diff options
author | Nick Kew <niq@apache.org> | 2010-11-14 01:01:43 +0100 |
---|---|---|
committer | Nick Kew <niq@apache.org> | 2010-11-14 01:01:43 +0100 |
commit | 3bad5b17805e75f1b94c13dae70b9c989e417974 (patch) | |
tree | e940e44547fa03ac429cf4543643b4c3224b162d | |
parent | Updates. (diff) | |
download | apache2-3bad5b17805e75f1b94c13dae70b9c989e417974.tar.xz apache2-3bad5b17805e75f1b94c13dae70b9c989e417974.zip |
Fix mod_proxy to support setting source address.
PR 29404
Seems lots of users want this, and a couple of them have recenly asked nicely
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1034916 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | include/ap_mmn.h | 5 | ||||
-rw-r--r-- | modules/proxy/mod_proxy.c | 24 | ||||
-rw-r--r-- | modules/proxy/mod_proxy.h | 2 | ||||
-rw-r--r-- | modules/proxy/proxy_util.c | 23 |
5 files changed, 57 insertions, 2 deletions
@@ -243,6 +243,11 @@ Changes with Apache 2.3.9 and executing perl-style regexp ops (e.g s/foo/bar/i) and regexp memory [Nick Kew] + *) Proxy: support setting source address. PR 29404 + [Multiple contributors iterating through bugzilla, + Aron Ujvari <xanco nikhok.hu>, Aleksey Midenkov <asm uezku.kemsu.ru>, + <dan listening-station.net; trunk version Nick Kew] + Changes with Apache 2.3.8 *) suexec: Support large log files. PR 45856. [Stefan Fritsch] diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 3c9250a850..792c8cd837 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -283,14 +283,15 @@ * interface. * 20101106.1 (2.3.9-dev) Add ap_pool_cleanup_set_null() generic cleanup * 20101106.2 (2.3.9-dev) Add suexec_disabled_reason field to ap_unixd_config + * 20101113.0 (2.3.9-dev) Add source address to mod_proxy.h */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ #ifndef MODULE_MAGIC_NUMBER_MAJOR -#define MODULE_MAGIC_NUMBER_MAJOR 20101106 +#define MODULE_MAGIC_NUMBER_MAJOR 20101113 #endif -#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index b449d4a282..23eab0e65e 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -1150,6 +1150,8 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) ps->timeout_set = 0; ps->badopt = bad_error; ps->badopt_set = 0; + ps->source_address = NULL; + ps->source_address_set = 0; ps->pool = p; return ps; @@ -1188,9 +1190,29 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) ps->badopt_set = overrides->badopt_set || base->badopt_set; ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status; ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set; + ps->source_address = (overrides->source_address_set == 0) ? base->source_address : overrides->source_address; + ps->source_address_set = overrides->source_address_set || base->source_address_set; ps->pool = p; return ps; } +static const char *set_source_address(cmd_parms *parms, void *dummy, + const char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + struct apr_sockaddr_t *addr; + + if (APR_SUCCESS == apr_sockaddr_info_get(&addr, arg, APR_UNSPEC, 0, 0, + psf->pool)) { + psf->source_address = addr; + psf->source_address_set = 1; + } + else { + return "ProxySourceAddress invalid value"; + } + + return NULL; +} static void *create_proxy_dir_config(apr_pool_t *p, char *dummy) { @@ -2190,6 +2212,8 @@ static const command_rec proxy_cmds[] = "Configure Status: proxy status to one of: on | off | full"), AP_INIT_RAW_ARGS("ProxySet", set_proxy_param, NULL, RSRC_CONF|ACCESS_CONF, "A balancer or worker name with list of params"), + AP_INIT_TAKE1("ProxySourceAddress", set_source_address, NULL, RSRC_CONF, + "Configure local source IP used for request forward"), {NULL} }; diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 28dedadd56..6da213cbca 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -150,6 +150,7 @@ typedef struct { status_on, status_full } proxy_status; /* Status display options */ + apr_sockaddr_t *source_address; int req_set:1; int viaopt_set:1; @@ -159,6 +160,7 @@ typedef struct { int timeout_set:1; int badopt_set:1; int proxy_status_set:1; + int source_address_set:1; } proxy_server_conf; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index bb01a56ba2..277c7d4155 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1682,6 +1682,15 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock, "proxy: %s: fam %d socket created to connect to %s", proxy_function, backend_addr->family, backend_name); + if (conf->source_address) { + rv = apr_socket_bind(*newsock, conf->source_address); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: %s: failed to bind socket to local address", + proxy_function); + } + } + /* make the connection out of the socket */ rv = apr_socket_connect(*newsock, backend_addr); @@ -2453,6 +2462,8 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, int connected = 0; int loglevel; apr_sockaddr_t *backend_addr = conn->addr; + /* the local address to use for the outgoing connection */ + apr_sockaddr_t *local_addr; apr_socket_t *newsock; void *sconf = s->module_config; proxy_server_conf *conf = @@ -2527,6 +2538,18 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, "proxy: %s: fam %d socket created to connect to %s", proxy_function, backend_addr->family, worker->hostname); + if (conf->source_address_set == 1) { + local_addr = apr_pcalloc(conn->pool, sizeof(apr_sockaddr_t)); + memcpy(local_addr, conf->source_address, sizeof(apr_sockaddr_t)); + local_addr->pool = conn->pool; + rv = apr_socket_bind(newsock, local_addr); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "proxy: %s: failed to bind socket to local address", + proxy_function); + } + } + /* make the connection out of the socket */ rv = apr_socket_connect(newsock, backend_addr); |