Lines 31-36
Link Here
|
31 |
#define apr_socket_create apr_socket_create_ex |
31 |
#define apr_socket_create apr_socket_create_ex |
32 |
#endif |
32 |
#endif |
33 |
|
33 |
|
|
|
34 |
#define HAVE_AF_UNIX 1 |
35 |
#if HAVE_AF_UNIX |
36 |
#include <sys/un.h> |
37 |
#include "apr_support.h" /* for apr_wait_for_io_or_timeout() */ |
38 |
#endif |
39 |
|
34 |
APLOG_USE_MODULE(proxy); |
40 |
APLOG_USE_MODULE(proxy); |
35 |
|
41 |
|
36 |
/* |
42 |
/* |
Lines 2015-2020
Link Here
|
2015 |
(*conn)->worker = worker; |
2021 |
(*conn)->worker = worker; |
2016 |
(*conn)->close = 0; |
2022 |
(*conn)->close = 0; |
2017 |
(*conn)->inreslist = 0; |
2023 |
(*conn)->inreslist = 0; |
|
|
2024 |
(*conn)->uds_path = NULL; |
2018 |
|
2025 |
|
2019 |
return OK; |
2026 |
return OK; |
2020 |
} |
2027 |
} |
Lines 2031-2036
Link Here
|
2031 |
return OK; |
2038 |
return OK; |
2032 |
} |
2039 |
} |
2033 |
|
2040 |
|
|
|
2041 |
/* |
2042 |
* Decodes a '%' escaped string, and returns the number of characters |
2043 |
*/ |
2044 |
static int decodeenc(char *x) |
2045 |
{ |
2046 |
int i, j, ch; |
2047 |
|
2048 |
if (x[0] == '\0') { |
2049 |
/* special case for no characters */ |
2050 |
return 0; |
2051 |
} |
2052 |
for (i = 0, j = 0; x[i] != '\0'; i++, j++) { |
2053 |
/* decode it if not already done */ |
2054 |
ch = x[i]; |
2055 |
if (ch == '%' && apr_isxdigit(x[i + 1]) && apr_isxdigit(x[i + 2])) { |
2056 |
ch = ap_proxy_hex2c(&x[i + 1]); |
2057 |
i += 2; |
2058 |
} |
2059 |
x[j] = ch; |
2060 |
} |
2061 |
x[j] = '\0'; |
2062 |
return j; |
2063 |
} |
2064 |
|
2034 |
PROXY_DECLARE(int) |
2065 |
PROXY_DECLARE(int) |
2035 |
ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, |
2066 |
ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, |
2036 |
proxy_server_conf *conf, |
2067 |
proxy_server_conf *conf, |
Lines 2125-2134
Link Here
|
2125 |
conn->port = uri->port; |
2156 |
conn->port = uri->port; |
2126 |
} |
2157 |
} |
2127 |
socket_cleanup(conn); |
2158 |
socket_cleanup(conn); |
2128 |
err = apr_sockaddr_info_get(&(conn->addr), |
2159 |
if (strncmp(conn->hostname, "socket=", 7) == 0) { |
2129 |
conn->hostname, APR_UNSPEC, |
2160 |
char *uds_path = apr_pstrdup(conn->pool, conn->hostname + 7); |
2130 |
conn->port, 0, |
2161 |
decodeenc(uds_path); |
2131 |
conn->pool); |
2162 |
conn->uds_path = uds_path; |
|
|
2163 |
} |
2164 |
else { |
2165 |
err = apr_sockaddr_info_get(&(conn->addr), |
2166 |
conn->hostname, APR_UNSPEC, |
2167 |
conn->port, 0, |
2168 |
conn->pool); |
2169 |
} |
2132 |
} |
2170 |
} |
2133 |
else if (!worker->cp->addr) { |
2171 |
else if (!worker->cp->addr) { |
2134 |
if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) { |
2172 |
if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) { |
Lines 2353-2358
Link Here
|
2353 |
} |
2391 |
} |
2354 |
|
2392 |
|
2355 |
|
2393 |
|
|
|
2394 |
/* lifted from mod_proxy_fdpass.c; tweaked addrlen in connect() call */ |
2395 |
static apr_status_t socket_connect_un(apr_socket_t *sock, |
2396 |
struct sockaddr_un *sa) |
2397 |
{ |
2398 |
apr_status_t rv; |
2399 |
apr_os_sock_t rawsock; |
2400 |
apr_interval_time_t t; |
2401 |
|
2402 |
rv = apr_os_sock_get(&rawsock, sock); |
2403 |
if (rv != APR_SUCCESS) { |
2404 |
return rv; |
2405 |
} |
2406 |
|
2407 |
rv = apr_socket_timeout_get(sock, &t); |
2408 |
if (rv != APR_SUCCESS) { |
2409 |
return rv; |
2410 |
} |
2411 |
|
2412 |
do { |
2413 |
const socklen_t addrlen = APR_OFFSETOF(struct sockaddr_un, sun_path) |
2414 |
+ strlen(sa->sun_path) + 1; |
2415 |
rv = connect(rawsock, (struct sockaddr*)sa, addrlen); |
2416 |
} while (rv == -1 && errno == EINTR); |
2417 |
|
2418 |
if ((rv == -1) && (errno == EINPROGRESS || errno == EALREADY) |
2419 |
&& (t > 0)) { |
2420 |
#if APR_MAJOR_VERSION < 2 |
2421 |
rv = apr_wait_for_io_or_timeout(NULL, sock, 0); |
2422 |
#else |
2423 |
rv = apr_socket_wait(sock, APR_WAIT_WRITE); |
2424 |
#endif |
2425 |
|
2426 |
if (rv != APR_SUCCESS) { |
2427 |
return rv; |
2428 |
} |
2429 |
} |
2430 |
|
2431 |
if (rv == -1 && errno != EISCONN) { |
2432 |
return errno; |
2433 |
} |
2434 |
|
2435 |
return APR_SUCCESS; |
2436 |
} |
2437 |
|
2356 |
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, |
2438 |
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, |
2357 |
proxy_conn_rec *conn, |
2439 |
proxy_conn_rec *conn, |
2358 |
proxy_worker *worker, |
2440 |
proxy_worker *worker, |
Lines 2377-2469
Link Here
|
2377 |
proxy_function); |
2459 |
proxy_function); |
2378 |
} |
2460 |
} |
2379 |
} |
2461 |
} |
2380 |
while (backend_addr && !connected) { |
2462 |
while ((backend_addr || conn->uds_path) && !connected) { |
2381 |
if ((rv = apr_socket_create(&newsock, backend_addr->family, |
2463 |
if (conn->uds_path) { |
2382 |
SOCK_STREAM, APR_PROTO_TCP, |
2464 |
struct sockaddr_un sa; |
2383 |
conn->scpool)) != APR_SUCCESS) { |
|
|
2384 |
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; |
2385 |
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00952) |
2386 |
"%s: error creating fam %d socket for target %s", |
2387 |
proxy_function, |
2388 |
backend_addr->family, |
2389 |
worker->s->hostname); |
2390 |
/* |
2391 |
* this could be an IPv6 address from the DNS but the |
2392 |
* local machine won't give us an IPv6 socket; hopefully the |
2393 |
* DNS returned an additional address to try |
2394 |
*/ |
2395 |
backend_addr = backend_addr->next; |
2396 |
continue; |
2397 |
} |
2398 |
conn->connection = NULL; |
2399 |
|
2465 |
|
2400 |
if (worker->s->recv_buffer_size > 0 && |
2466 |
rv = apr_socket_create(&newsock, AF_UNIX, SOCK_STREAM, 0, |
2401 |
(rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF, |
2467 |
conn->scpool); |
2402 |
worker->s->recv_buffer_size))) { |
2468 |
if (rv != APR_SUCCESS) { |
2403 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00953) |
2469 |
loglevel = APLOG_ERR; |
2404 |
"apr_socket_opt_set(SO_RCVBUF): Failed to set " |
2470 |
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO() |
2405 |
"ProxyReceiveBufferSize, using default"); |
2471 |
"%s: error creating Unix domain socket for " |
2406 |
} |
2472 |
"target %s", |
|
|
2473 |
proxy_function, |
2474 |
worker->s->hostname); |
2475 |
break; |
2476 |
} |
2477 |
conn->connection = NULL; |
2407 |
|
2478 |
|
2408 |
rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1); |
2479 |
sa.sun_family = AF_UNIX; |
2409 |
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) { |
2480 |
apr_cpystrn(sa.sun_path, conn->uds_path, sizeof(sa.sun_path)); |
2410 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00954) |
|
|
2411 |
"apr_socket_opt_set(APR_TCP_NODELAY): " |
2412 |
"Failed to set"); |
2413 |
} |
2414 |
|
2481 |
|
2415 |
/* Set a timeout for connecting to the backend on the socket */ |
2482 |
rv = socket_connect_un(newsock, &sa); |
2416 |
if (worker->s->conn_timeout_set) { |
|
|
2417 |
apr_socket_timeout_set(newsock, worker->s->conn_timeout); |
2418 |
} |
2419 |
else if (worker->s->timeout_set) { |
2420 |
apr_socket_timeout_set(newsock, worker->s->timeout); |
2421 |
} |
2422 |
else if (conf->timeout_set) { |
2423 |
apr_socket_timeout_set(newsock, conf->timeout); |
2424 |
} |
2425 |
else { |
2426 |
apr_socket_timeout_set(newsock, s->timeout); |
2427 |
} |
2428 |
/* Set a keepalive option */ |
2429 |
if (worker->s->keepalive) { |
2430 |
if ((rv = apr_socket_opt_set(newsock, |
2431 |
APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) { |
2432 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00955) |
2433 |
"apr_socket_opt_set(SO_KEEPALIVE): Failed to set" |
2434 |
" Keepalive"); |
2435 |
} |
2436 |
} |
2437 |
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s, |
2438 |
"%s: fam %d socket created to connect to %s", |
2439 |
proxy_function, backend_addr->family, worker->s->hostname); |
2440 |
|
2441 |
if (conf->source_address_set) { |
2442 |
local_addr = apr_pmemdup(conn->pool, conf->source_address, |
2443 |
sizeof(apr_sockaddr_t)); |
2444 |
local_addr->pool = conn->pool; |
2445 |
rv = apr_socket_bind(newsock, local_addr); |
2446 |
if (rv != APR_SUCCESS) { |
2483 |
if (rv != APR_SUCCESS) { |
2447 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00956) |
2484 |
apr_socket_close(newsock); |
2448 |
"%s: failed to bind socket to local address", |
2485 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO() |
2449 |
proxy_function); |
2486 |
"%s: attempt to connect to Unix domain socket " |
|
|
2487 |
"%s (%s) failed", |
2488 |
proxy_function, |
2489 |
conn->uds_path, |
2490 |
worker->s->hostname); |
2491 |
break; |
2450 |
} |
2492 |
} |
2451 |
} |
2493 |
} |
|
|
2494 |
else { |
2495 |
if ((rv = apr_socket_create(&newsock, backend_addr->family, |
2496 |
SOCK_STREAM, APR_PROTO_TCP, |
2497 |
conn->scpool)) != APR_SUCCESS) { |
2498 |
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; |
2499 |
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00952) |
2500 |
"%s: error creating fam %d socket for " |
2501 |
"target %s", |
2502 |
proxy_function, |
2503 |
backend_addr->family, |
2504 |
worker->s->hostname); |
2505 |
/* |
2506 |
* this could be an IPv6 address from the DNS but the |
2507 |
* local machine won't give us an IPv6 socket; hopefully the |
2508 |
* DNS returned an additional address to try |
2509 |
*/ |
2510 |
backend_addr = backend_addr->next; |
2511 |
continue; |
2512 |
} |
2513 |
conn->connection = NULL; |
2452 |
|
2514 |
|
2453 |
/* make the connection out of the socket */ |
2515 |
if (worker->s->recv_buffer_size > 0 && |
2454 |
rv = apr_socket_connect(newsock, backend_addr); |
2516 |
(rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF, |
|
|
2517 |
worker->s->recv_buffer_size))) { |
2518 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00953) |
2519 |
"apr_socket_opt_set(SO_RCVBUF): Failed to set " |
2520 |
"ProxyReceiveBufferSize, using default"); |
2521 |
} |
2455 |
|
2522 |
|
2456 |
/* if an error occurred, loop round and try again */ |
2523 |
rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1); |
2457 |
if (rv != APR_SUCCESS) { |
2524 |
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) { |
2458 |
apr_socket_close(newsock); |
2525 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00954) |
2459 |
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; |
2526 |
"apr_socket_opt_set(APR_TCP_NODELAY): " |
2460 |
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00957) |
2527 |
"Failed to set"); |
2461 |
"%s: attempt to connect to %pI (%s) failed", |
2528 |
} |
2462 |
proxy_function, |
2529 |
|
2463 |
backend_addr, |
2530 |
/* Set a timeout for connecting to the backend on the socket */ |
2464 |
worker->s->hostname); |
2531 |
if (worker->s->conn_timeout_set) { |
2465 |
backend_addr = backend_addr->next; |
2532 |
apr_socket_timeout_set(newsock, worker->s->conn_timeout); |
2466 |
continue; |
2533 |
} |
|
|
2534 |
else if (worker->s->timeout_set) { |
2535 |
apr_socket_timeout_set(newsock, worker->s->timeout); |
2536 |
} |
2537 |
else if (conf->timeout_set) { |
2538 |
apr_socket_timeout_set(newsock, conf->timeout); |
2539 |
} |
2540 |
else { |
2541 |
apr_socket_timeout_set(newsock, s->timeout); |
2542 |
} |
2543 |
/* Set a keepalive option */ |
2544 |
if (worker->s->keepalive) { |
2545 |
if ((rv = apr_socket_opt_set(newsock, |
2546 |
APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) { |
2547 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00955) |
2548 |
"apr_socket_opt_set(SO_KEEPALIVE): Failed to set" |
2549 |
" Keepalive"); |
2550 |
} |
2551 |
} |
2552 |
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s, |
2553 |
"%s: fam %d socket created to connect to %s", |
2554 |
proxy_function, backend_addr->family, worker->s->hostname); |
2555 |
|
2556 |
if (conf->source_address_set) { |
2557 |
local_addr = apr_pmemdup(conn->pool, conf->source_address, |
2558 |
sizeof(apr_sockaddr_t)); |
2559 |
local_addr->pool = conn->pool; |
2560 |
rv = apr_socket_bind(newsock, local_addr); |
2561 |
if (rv != APR_SUCCESS) { |
2562 |
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00956) |
2563 |
"%s: failed to bind socket to local address", |
2564 |
proxy_function); |
2565 |
} |
2566 |
} |
2567 |
|
2568 |
/* make the connection out of the socket */ |
2569 |
rv = apr_socket_connect(newsock, backend_addr); |
2570 |
|
2571 |
/* if an error occurred, loop round and try again */ |
2572 |
if (rv != APR_SUCCESS) { |
2573 |
apr_socket_close(newsock); |
2574 |
loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; |
2575 |
ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00957) |
2576 |
"%s: attempt to connect to %pI (%s) failed", |
2577 |
proxy_function, |
2578 |
backend_addr, |
2579 |
worker->s->hostname); |
2580 |
backend_addr = backend_addr->next; |
2581 |
continue; |
2582 |
} |
2467 |
} |
2583 |
} |
2468 |
|
2584 |
|
2469 |
/* Set a timeout on the socket */ |
2585 |
/* Set a timeout on the socket */ |
Lines 2479-2485
Link Here
|
2479 |
|
2595 |
|
2480 |
conn->sock = newsock; |
2596 |
conn->sock = newsock; |
2481 |
|
2597 |
|
2482 |
if (conn->forward) { |
2598 |
if (!conn->uds_path && conn->forward) { |
2483 |
forward_info *forward = (forward_info *)conn->forward; |
2599 |
forward_info *forward = (forward_info *)conn->forward; |
2484 |
/* |
2600 |
/* |
2485 |
* For HTTP CONNECT we need to prepend CONNECT request before |
2601 |
* For HTTP CONNECT we need to prepend CONNECT request before |