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

(-)modules/proxy/proxy_util.c (+43 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_bind_addr *bind, server_rec *s)
2272
{
2273
    int i;
2274
    const int idx = bind->idx;
2275
    const int range = bind->range;
2276
    const int start = 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
            bind->idx = (idx + i + 1) % range; /* alternatively (port - start +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",
2374
                     "proxy: %s: fam %d socket created to connect to %s",
2350
                     proxy_function, backend_addr->family, worker->hostname);
2375
                     proxy_function, backend_addr->family, worker->hostname);
2351
2376
2377
        proxy_bind_addr* bind = (worker->bind ? worker->bind : conf->bind);
2378
        if (bind) {
2379
            rv = APR_EINVAL;
2380
            apr_sockaddr_t *addr;
2381
            for(addr = bind->addr; addr; addr = addr->next) {
2382
                if (addr->family != backend_addr->family) continue;
2383
                rv = bind_to_addr(newsock, addr, proxy_function, bind, s);
2384
                if (rv == APR_SUCCESS) break;
2385
            }
2386
            if (rv != APR_SUCCESS) {
2387
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "proxy: %s: can not bind to %s:%u+%u",
2388
                        proxy_function,bind->addr, bind->port, bind->range - 1, NULL);
2389
                return DECLINED;
2390
            }
2391
        } else {
2392
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: Not using bind ",proxy_function);
2393
        }
2394
2352
        /* make the connection out of the socket */
2395
        /* make the connection out of the socket */
2353
        rv = apr_socket_connect(newsock, backend_addr);
2396
        rv = apr_socket_connect(newsock, backend_addr);
2354
2397
(-)modules/proxy/mod_proxy.c (+76 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 70-75 Link Here
70
        (w)->io_buffer_size_set   = (c)->io_buffer_size_set;    \
76
        (w)->io_buffer_size_set   = (c)->io_buffer_size_set;    \
71
    } while (0)
77
    } while (0)
72
78
79
static int parse_bind_address(char* val,proxy_bind_addr *bind, apr_pool_t *p);
80
73
static const char *set_worker_param(apr_pool_t *p,
81
static const char *set_worker_param(apr_pool_t *p,
74
                                    proxy_worker *worker,
82
                                    proxy_worker *worker,
75
                                    const char *key,
83
                                    const char *key,
Lines 281-292 Link Here
281
            return "lbset must be between 0 and 99";
289
            return "lbset must be between 0 and 99";
282
        worker->lbset = ival;
290
        worker->lbset = ival;
283
    }
291
    }
292
    else if (!strcasecmp(key, "bind")) {
293
        worker->bind = (proxy_bind_addr*) apr_pcalloc(p, sizeof(proxy_bind_addr));
294
        switch (parse_bind_address((char*)val, worker->bind, p)) {
295
            case -1:
296
                return "ProxySet bind:  Invalid address -"
297
                    " format is <addr>[:<port>+<range>]";
298
            case -2:
299
                return "ProxySet bind: Hostname did not resolve.";
300
        }
301
    }
284
    else {
302
    else {
285
        return "unknown Worker parameter";
303
        return "unknown Worker parameter";
286
    }
304
    }
287
    return NULL;
305
    return NULL;
288
}
306
}
289
307
308
static int parse_bind_address(char* val, proxy_bind_addr* bind, apr_pool_t *p) {
309
    char* s_range, *host, *scope_id;
310
    s_range = ap_strrchr((char*)val,'+');
311
    if (s_range) {
312
        *s_range++ = 0;
313
        bind->range = atoi(s_range);
314
        if (bind->range < MIN_RANGE_HINT)
315
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
316
                    "range %u is too low, consider increasing the bind range.", bind->range, NULL);
317
    }
318
    /* We dont accept a single port with out a range as it would be same
319
    * as a single threaded single process http-client
320
    *
321
    * We do not allow ip:0+0 or ip:0 as it can be specified more clearly
322
    * as just ip.
323
    *
324
    * we dont accept a range without a port either.
325
    */
326
    if((apr_parse_addr_port(&host, &scope_id, &bind->port, val, p) != APR_SUCCESS)
327
          || scope_id               /* we dont know how to use scope_id */
328
          || (!bind->port && s_range)       /* only a combo [port+range] is valid */
329
          || (bind->port && (!s_range || bind->range < 0)) /* Let admin specify r=0 if he wants to */
330
          || ((bind->port + bind->range) >= PORT_MAX_PORTS)
331
    )
332
        return -1;
333
334
    /* Preparse the address */
335
    if((apr_sockaddr_info_get(&bind->addr, host, APR_UNSPEC, bind->port, 0, p)
336
                != APR_SUCCESS) || !bind->addr)
337
        return -2;
338
339
    bind->range++; /* update range before passing it back. */
340
    bind->idx = 0;
341
342
    return 0;
343
}
344
290
static const char *set_balancer_param(proxy_server_conf *conf,
345
static const char *set_balancer_param(proxy_server_conf *conf,
291
                                      apr_pool_t *p,
346
                                      apr_pool_t *p,
292
                                      proxy_balancer *balancer,
347
                                      proxy_balancer *balancer,
Lines 1066-1071 Link Here
1066
    ps->timeout_set = 0;
1121
    ps->timeout_set = 0;
1067
    ps->badopt = bad_error;
1122
    ps->badopt = bad_error;
1068
    ps->badopt_set = 0;
1123
    ps->badopt_set = 0;
1124
    ps->bind = NULL;
1069
    ps->pool = p;
1125
    ps->pool = p;
1070
1126
1071
    return ps;
1127
    return ps;
Lines 1109-1114 Link Here
1109
    ps->badopt_set = overrides->badopt_set || base->badopt_set;
1165
    ps->badopt_set = overrides->badopt_set || base->badopt_set;
1110
    ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;
1166
    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;
1167
    ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set;
1168
    ps->bind = (overrides->bind ? overrides->bind : base->bind);
1112
    ps->pool = p;
1169
    ps->pool = p;
1113
    return ps;
1170
    return ps;
1114
}
1171
}
Lines 1706-1711 Link Here
1706
    return NULL;
1763
    return NULL;
1707
}
1764
}
1708
1765
1766
static const char*
1767
    set_proxy_bindaddr(cmd_parms *parms, void *dummy, const char *addr)
1768
{
1769
    proxy_server_conf *psf =
1770
        ap_get_module_config(parms->server->module_config, &proxy_module);
1771
    
1772
    psf->bind = (proxy_bind_addr*) apr_pcalloc(parms->pool, sizeof(proxy_bind_addr));
1773
    switch (parse_bind_address((char*)addr, psf->bind, parms->pool)) {
1774
        case -1:
1775
            return "ProxyBindAddress:  Invalid address -"
1776
                " format is <addr>[:<port>+<range>]";
1777
        case -2:
1778
            return "ProxyBindAddress: Hostname did not resolve.";
1779
    }
1780
    return NULL;
1781
}
1782
1709
static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
1783
static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
1710
{
1784
{
1711
    server_rec *s = cmd->server;
1785
    server_rec *s = cmd->server;
Lines 2088-2093 Link Here
2088
     "A balancer or worker name with list of params"),
2162
     "A balancer or worker name with list of params"),
2089
    AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
2163
    AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
2090
     RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
2164
     RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
2165
    AP_INIT_TAKE1("ProxyBindAddress", set_proxy_bindaddr, NULL, RSRC_CONF,
2166
            "Set the source address for a proxied connection."),
2091
    {NULL}
2167
    {NULL}
2092
};
2168
};
2093
2169
(-)modules/proxy/mod_proxy.h (+16 lines)
Lines 133-139 Link Here
133
typedef struct proxy_conn_pool proxy_conn_pool;
133
typedef struct proxy_conn_pool proxy_conn_pool;
134
typedef struct proxy_balancer_method proxy_balancer_method;
134
typedef struct proxy_balancer_method proxy_balancer_method;
135
135
136
/*bind to local ports*/
136
typedef struct {
137
typedef struct {
138
    apr_sockaddr_t *addr;
139
    apr_port_t port;
140
    apr_port_t range;             /* restrict the source ports used by mod_proxy */
141
    int idx;                      /* pointer to port to try on next call */
142
} proxy_bind_addr;
143
144
typedef struct {
137
    apr_array_header_t *proxies;
145
    apr_array_header_t *proxies;
138
    apr_array_header_t *sec_proxy;
146
    apr_array_header_t *sec_proxy;
139
    apr_array_header_t *aliases;
147
    apr_array_header_t *aliases;
Lines 190-195 Link Here
190
        status_full
198
        status_full
191
    } proxy_status;             /* Status display options */
199
    } proxy_status;             /* Status display options */
192
    char proxy_status_set;
200
    char proxy_status_set;
201
202
    /*bind to local ports*/
203
    proxy_bind_addr* bind;
204
193
    apr_pool_t *pool;           /* Pool used for allocating this struct */
205
    apr_pool_t *pool;           /* Pool used for allocating this struct */
194
} proxy_server_conf;
206
} proxy_server_conf;
195
207
Lines 352-357 Link Here
352
    char            retry_set;
364
    char            retry_set;
353
    char            disablereuse;
365
    char            disablereuse;
354
    char            disablereuse_set;
366
    char            disablereuse_set;
367
368
    /*bind to local ports*/
369
    proxy_bind_addr* bind;
370
355
};
371
};
356
372
357
/*
373
/*

Return to bug 45405