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

(-)modules/proxy/proxy_util.c (+38 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_worker *worker, server_rec *s)
2272
{
2273
    const int idx = worker->bind_idx;
2274
    const int range = worker->bind_range;
2275
    const int start = worker->bind_port;
2276
    for(int i = 0; i < range; ++i) { /* loop until we can bind correctly*/
2277
        int port = start + ((idx + i) % range);
2278
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: trying to bind to %s:%u",
2279
                proxy_function, laddr,port, NULL);
2280
2281
        laddr->sa.sin.sin_port = htons(port);
2282
        laddr->port = port;
2283
        if (apr_socket_bind(newsock, laddr) == APR_SUCCESS) {
2284
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: bound to %s:%u",
2285
                    proxy_function, laddr, laddr->port, NULL);
2286
            worker->bind_idx = i + 1;
2287
            return APR_SUCCESS;
2288
        }
2289
    }
2290
    return APR_EINVAL;
2291
}
2292
2293
2270
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
2294
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
2271
                                            proxy_conn_rec *conn,
2295
                                            proxy_conn_rec *conn,
2272
                                            proxy_worker *worker,
2296
                                            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 (worker->bindopt_set) {
2377
            rv = APR_EINVAL;
2378
            for(apr_sockaddr_t *addr = worker->bind_addr; addr; addr = addr->next) {
2379
                if (addr->family != backend_addr->family) continue;
2380
                rv = bind_to_addr(newsock, addr, proxy_function, worker, s);
2381
                if (rv == APR_SUCCESS) break;
2382
            }
2383
            if (rv != APR_SUCCESS) {
2384
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "proxy: %s: can not bind to %s:%u+%u",
2385
                        proxy_function,worker->bind_addr, worker->bind_port, worker->bind_range, NULL);
2386
                return DECLINED;
2387
            }
2388
        }
2389
2352
        /* make the connection out of the socket */
2390
        /* make the connection out of the socket */
2353
        rv = apr_socket_connect(newsock, backend_addr);
2391
        rv = apr_socket_connect(newsock, backend_addr);
2354
2392
(-)modules/proxy/mod_proxy.c (+45 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 281-286 Link Here
281
            return "lbset must be between 0 and 99";
287
            return "lbset must be between 0 and 99";
282
        worker->lbset = ival;
288
        worker->lbset = ival;
283
    }
289
    }
290
    else if (!strcasecmp(key, "bind")) {
291
        char* range, *host, *scope_id;
292
        apr_port_t port;
293
        int r = 0;
294
        range = ap_strrchr((char*)val,'+');
295
        if (range) {
296
            *range++ = 0;
297
            r = atoi(range);
298
            if (r < MIN_RANGE_HINT)
299
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
300
                        "range %u is too low, consider increasing the bind range.", r, NULL);
301
            /* We dont accept a single port with out a range as it would be same
302
             * as a single threaded single process http-client
303
             *
304
             * We do not allow ip:0+0 or ip:0 as it can be specified more clearly
305
             * as just ip.
306
             *
307
             * we dont accept a range with out a port either.
308
             */
309
            if((apr_parse_addr_port(&host, &scope_id, &port, val, p) != APR_SUCCESS)
310
                    || scope_id               /* we dont know how to use scope_id */
311
                    || (!port && range)       /* only a combo [port+range] is valid */
312
                    || (port && (!range || r < 0)) /* Let admin specify r=0 if he wants to */
313
                    || ((port + r) >= PORT_MAX_PORTS)
314
              )
315
                return "ProxySet bind:  Invalid address -"
316
                    " format is <addr>[:<port>+<range>]";
317
        }
318
        /* Preparse the address */
319
        if((apr_sockaddr_info_get(&(worker->bind_addr), host, APR_UNSPEC, port, 0, p)
320
                    != APR_SUCCESS) || !worker->bind_addr)
321
            return "ProxySet bind: Hostname did not resolve.";
322
        worker->bind_port = port;
323
        /* If there didn't exist a port then there was no range either. so we have the
324
         * starting value 0 for r when no port was specified.*/
325
        worker->bind_range = r + 1;
326
        worker->bind_idx = 0;
327
        worker->bindopt_set = 1;
328
    }
284
    else {
329
    else {
285
        return "unknown Worker parameter";
330
        return "unknown Worker parameter";
286
    }
331
    }
(-)modules/proxy/mod_proxy.h (+8 lines)
Lines 352-357 Link Here
352
    char            retry_set;
352
    char            retry_set;
353
    char            disablereuse;
353
    char            disablereuse;
354
    char            disablereuse_set;
354
    char            disablereuse_set;
355
356
    /*bind to local ports*/
357
    apr_sockaddr_t *bind_addr;
358
    apr_port_t bind_port;
359
    apr_port_t bind_range;             /* restrict the source ports used by mod_proxy */
360
    int bind_idx;
361
    char bindopt_set;
362
355
};
363
};
356
364
357
/*
365
/*

Return to bug 45405