View | Details | Raw Unified | Return to bug 54101
Collapse All | Expand All

(-)httpd-2.4.4/modules/proxy/mod_proxy.h (-2 / +3 lines)
Lines 232-237 Link Here
232
                                * that is used over the backend connection. */
232
                                * that is used over the backend connection. */
233
    proxy_worker *worker;      /* Connection pool this connection belongs to */
233
    proxy_worker *worker;      /* Connection pool this connection belongs to */
234
    apr_pool_t   *pool;        /* Subpool for hostname and addr data */
234
    apr_pool_t   *pool;        /* Subpool for hostname and addr data */
235
    const char   *uds_path;    /* Unix domain socket path */
235
    const char   *hostname;
236
    const char   *hostname;
236
    apr_sockaddr_t *addr;      /* Preparsed remote address info */
237
    apr_sockaddr_t *addr;      /* Preparsed remote address info */
237
    apr_pool_t   *scpool;      /* Subpool used for socket and connection data */
238
    apr_pool_t   *scpool;      /* Subpool used for socket and connection data */
Lines 303-311 Link Here
303
#define PROXY_WORKER_MAX_SCHEME_SIZE    16
304
#define PROXY_WORKER_MAX_SCHEME_SIZE    16
304
#define PROXY_WORKER_MAX_ROUTE_SIZE     64
305
#define PROXY_WORKER_MAX_ROUTE_SIZE     64
305
#define PROXY_BALANCER_MAX_ROUTE_SIZE PROXY_WORKER_MAX_ROUTE_SIZE
306
#define PROXY_BALANCER_MAX_ROUTE_SIZE PROXY_WORKER_MAX_ROUTE_SIZE
306
#define PROXY_WORKER_MAX_NAME_SIZE      96
307
#define PROXY_WORKER_MAX_NAME_SIZE      368
307
#define PROXY_BALANCER_MAX_NAME_SIZE PROXY_WORKER_MAX_NAME_SIZE
308
#define PROXY_BALANCER_MAX_NAME_SIZE PROXY_WORKER_MAX_NAME_SIZE
308
#define PROXY_WORKER_MAX_HOSTNAME_SIZE  64
309
#define PROXY_WORKER_MAX_HOSTNAME_SIZE  336
309
#define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE
310
#define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE
310
#define PROXY_BALANCER_MAX_STICKY_SIZE  64
311
#define PROXY_BALANCER_MAX_STICKY_SIZE  64
311
312
(-)httpd-2.4.4/modules/proxy/proxy_util.c (-84 / +200 lines)
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

Return to bug 54101