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

(-)modules/proxy/proxy_util.c (+40 lines)
Lines 2267-2272 Link Here
2267
}
2267
}
2268
#endif /* USE_ALTERNATE_IS_CONNECTED */
2268
#endif /* USE_ALTERNATE_IS_CONNECTED */
2269
2269
2270
apr_status_t bind_to_addr(apr_socket_t *newsock, apr_sockaddr_t *laddr,
2271
        const char *proxy_function, proxy_server_conf *conf, server_rec *s)
2272
{
2273
    int i;
2274
    const int idx = conf->bind_idx;
2275
    const int range = conf->bind_range;
2276
    const int start = conf->bind_port;
2277
    for(i = 0; i < range; ++i) { /* loop until we can bind correctly*/
2278
        int port = start + ((idx + i) % range);
2279
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: trying to bind to %s:%u",
2280
                proxy_function, laddr,port, NULL);
2281
2282
        laddr->sa.sin.sin_port = htons(port);
2283
        laddr->port = port;
2284
        if (apr_socket_bind(newsock, laddr) == APR_SUCCESS) {
2285
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: bound to %s:%u",
2286
                    proxy_function, laddr, laddr->port, NULL);
2287
            conf->bind_idx = i + 1;
2288
            return APR_SUCCESS;
2289
        }
2290
    }
2291
    return APR_EINVAL;
2292
}
2293
2294
2270
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
2295
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
2271
                                            proxy_conn_rec *conn,
2296
                                            proxy_conn_rec *conn,
2272
                                            proxy_worker *worker,
2297
                                            proxy_worker *worker,
Lines 2349-2354 Link Here
2349
                     "proxy: %s: fam %d socket created to connect to %s",
2373
                     "proxy: %s: fam %d socket created to connect to %s",
2350
                     proxy_function, backend_addr->family, worker->hostname);
2374
                     proxy_function, backend_addr->family, worker->hostname);
2351
2375
2376
        if (conf->bindopt_set) {
2377
            rv = APR_EINVAL;
2378
            apr_sockaddr_t *addr;
2379
            for(*addr = conf->bind_addr; addr; addr = addr->next) {
2380
                if (addr->family != backend_addr->family) continue;
2381
                rv = bind_to_addr(newsock, addr, proxy_function, conf, s);
2382
                if (rv == APR_SUCCESS) break;
2383
            }
2384
            if (rv != APR_SUCCESS) {
2385
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "proxy: %s: could not bind to %s:%u+%u",
2386
                        proxy_function,conf->bind_addr, conf->bind_port, conf->bind_range, NULL);
2387
                return DECLINED;
2388
            }
2389
        }
2390
2352
        /* make the connection out of the socket */
2391
        /* make the connection out of the socket */
2353
        rv = apr_socket_connect(newsock, backend_addr);
2392
        rv = apr_socket_connect(newsock, backend_addr);
2354
2393
(-)modules/proxy/mod_proxy.c (+64 lines)
Lines 35-40 Link Here
35
#define MAX(x,y) ((x) >= (y) ? (x) : (y))
35
#define MAX(x,y) ((x) >= (y) ? (x) : (y))
36
#endif
36
#endif
37
37
38
/* Value from /usr/sys/port_kernel.h is it exposed in any portable header? */
39
#define PORT_MAX_PORTS 0x10000
40
41
/* a sane value for RANGE of bind */
42
#define MIN_RANGE_HINT 8
43
38
/* return the sizeof of one lb_worker in scoreboard. */
44
/* return the sizeof of one lb_worker in scoreboard. */
39
static int ap_proxy_lb_worker_size(void)
45
static int ap_proxy_lb_worker_size(void)
40
{
46
{
Lines 1066-1071 Link Here
1066
    ps->timeout_set = 0;
1072
    ps->timeout_set = 0;
1067
    ps->badopt = bad_error;
1073
    ps->badopt = bad_error;
1068
    ps->badopt_set = 0;
1074
    ps->badopt_set = 0;
1075
    ps->bindopt_set = 0;
1076
    ps->bind_idx = 0;
1077
    ps->bind_addr = 0;
1069
    ps->pool = p;
1078
    ps->pool = p;
1070
1079
1071
    return ps;
1080
    return ps;
Lines 1109-1114 Link Here
1109
    ps->badopt_set = overrides->badopt_set || base->badopt_set;
1118
    ps->badopt_set = overrides->badopt_set || base->badopt_set;
1110
    ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;
1119
    ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;
1111
    ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set;
1120
    ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set;
1121
    ps->bindopt_set = overrides->bindopt_set || base->bindopt_set;
1112
    ps->pool = p;
1122
    ps->pool = p;
1113
    return ps;
1123
    return ps;
1114
}
1124
}
Lines 1706-1711 Link Here
1706
    return NULL;
1716
    return NULL;
1707
}
1717
}
1708
1718
1719
static const char*
1720
    set_proxy_bindaddr(cmd_parms *parms, void *dummy, const char *addr)
1721
{
1722
    char *range, *host, *scope_id;
1723
    apr_port_t port;
1724
    int r = 0;
1725
1726
    proxy_server_conf *psf =
1727
    ap_get_module_config(parms->server->module_config, &proxy_module);
1728
1729
    range = ap_strrchr((char*)addr, '+');
1730
    if (range) {
1731
        *range++ = 0;
1732
        r = atoi(range);
1733
        if (r < MIN_RANGE_HINT)
1734
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
1735
                    "range %u is too low, consider increasing the bind range.", r, NULL);
1736
    }
1737
1738
    /* We dont accept a single port with out a range as it would be same
1739
     * as a single threaded single process http-client
1740
     *
1741
     * We do not allow ip:0+0 or ip:0 as it can be specified more clearly
1742
     * as just ip.
1743
     *
1744
     * we dont accept a range with out a port either.
1745
     */
1746
    if((apr_parse_addr_port(&host, &scope_id, &port, addr, parms->pool)
1747
                != APR_SUCCESS)
1748
            || scope_id               /* we dont know how to use scope_id */
1749
            || (!port && range)       /* only a combo [port+range] is valid */
1750
            || (port && (!range || r < 0)) /* Let admin specify r=0 if he wants to */
1751
            || ((port + r) >= PORT_MAX_PORTS)
1752
      )
1753
        return "ProxyBindAddress:  Invalid address -"
1754
               " format is <addr>[:<port>+<range>]";
1755
1756
    /* Preparse the address */
1757
    if((apr_sockaddr_info_get(&(psf->bind_addr), host, APR_UNSPEC, port, 0, parms->pool)
1758
            != APR_SUCCESS) || !psf->bind_addr)
1759
        return "ProxyBindAddress: Hostname did not resolve.";
1760
1761
    psf->bind_port = port;
1762
    /* If there didn't exist a port then there was no range either. so we have the
1763
     * starting value 0 for r when no port was specified.*/
1764
    psf->bind_range = r + 1;
1765
    psf->bind_idx = 0;
1766
    psf->bindopt_set = 1;
1767
1768
    return NULL;
1769
}
1770
1709
static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
1771
static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
1710
{
1772
{
1711
    server_rec *s = cmd->server;
1773
    server_rec *s = cmd->server;
Lines 2088-2093 Link Here
2088
     "A balancer or worker name with list of params"),
2150
     "A balancer or worker name with list of params"),
2089
    AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
2151
    AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
2090
     RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
2152
     RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
2153
    AP_INIT_TAKE1("ProxyBindAddress", set_proxy_bindaddr, NULL, RSRC_CONF,
2154
     "Set the source address for a proxied connection. "),
2091
    {NULL}
2155
    {NULL}
2092
};
2156
};
2093
2157
(-)modules/proxy/mod_proxy.h (+6 lines)
Lines 190-195 Link Here
190
        status_full
190
        status_full
191
    } proxy_status;             /* Status display options */
191
    } proxy_status;             /* Status display options */
192
    char proxy_status_set;
192
    char proxy_status_set;
193
    /*bind to local ports*/
194
    apr_sockaddr_t *bind_addr;
195
    apr_port_t bind_port;
196
    apr_port_t bind_range;             /* restrict the source ports used by mod_proxy */
197
    int bind_idx;
198
    char bindopt_set;
193
    apr_pool_t *pool;           /* Pool used for allocating this struct */
199
    apr_pool_t *pool;           /* Pool used for allocating this struct */
194
} proxy_server_conf;
200
} proxy_server_conf;
195
201

Return to bug 44806