]> granicus.if.org Git - apache/commitdiff
Fix mod_proxy to support setting source address.
authorNick Kew <niq@apache.org>
Sun, 14 Nov 2010 00:01:43 +0000 (00:01 +0000)
committerNick Kew <niq@apache.org>
Sun, 14 Nov 2010 00:01:43 +0000 (00:01 +0000)
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

CHANGES
include/ap_mmn.h
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index 4d780b102b43051f0fa4f4608d66bf02ea1c6a38..6963dba9d69a06104c662426db4d6ef61e9e9fcb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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]
index 3c9250a850bcec360a45f1d7f9bcb212dca87b39..792c8cd837b88a3bc8a0ef09d160899765626626 100644 (file)
  *                         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
index b449d4a282a58bdd555b1f4e91bff9e9b2daa245..23eab0e65ec8309fc22c09393236034fdeb2b3ad 100644 (file)
@@ -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}
 };
 
index 28dedadd56fe6d8f8e315f6d082e723c7d070697..6da213cbca67e03b5ddd3e54670e78d582163bfa 100644 (file)
@@ -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;
 
 
index bb01a56ba23527b6bbf9f74d2d17e08d1887d69e..277c7d415576ddc269fca5d8bc82b7d4c5b1cd24 100644 (file)
@@ -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);