Patch to enable SO_BINDTODEVICE

Ben Greear greearb at candelatech.com
Wed Jan 9 23:19:57 UTC 2013


In order to play some tricks and send requests to myself
over external network interfaces, I need to enable the
SO_BINDTODEVICE socket option.

Here's the patch that I'm trying out.  If there is a better patch format
or place to send this, please let me know.

Thanks,
Ben


 From fe7226036848bd1f4f74dd8186a176b17f974614 Mon Sep 17 00:00:00 2001
From: Ben Greear <greearb at candelatech.com>
Date: Wed, 9 Jan 2013 15:01:35 -0800
Subject: [PATCH] Support bind_dev=[ifname] in accept configuration clause.

If this option is enabled, nginx will call SO_BINDTODEVICE
on the particular device name.  This can be helpful for
some types of firewalling, and routing setups.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
  src/core/ngx_connection.c       | 21 +++++++++++++++++++++
  src/core/ngx_connection.h       |  1 +
  src/http/ngx_http.c             | 13 +++++++++++++
  src/http/ngx_http_core_module.c |  6 ++++++
  src/http/ngx_http_core_module.h |  1 +
  5 files changed, 42 insertions(+)

diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index c818114..a3a8101 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -397,6 +397,27 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
                  continue;
              }

+            if (ls[i].dev_name[0]) {
+#ifdef SO_BINDTODEVICE
+                if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
+                               ls[i].dev_name, strlen(ls[i].dev_name))) {
+                   ngx_log_error(NGX_LOG_EMERG, log, errno, "setsockopt (%i, BINDTODEVICE, %s) failed",
+                                 s, ls[i].dev_name);
+                   return NGX_ERROR;
+                }
+                else {
+                   ngx_log_error(NGX_LOG_EMERG, log, 0, "setsockopt (%i, BINDTODEVICE, %s) succeeded!",
+                                 s, ls[i].dev_name);
+                }
+#else
+                ngx_log_error(NGX_LOG_EMERG, log, 0,
+                              "setsockopt (%i, BINDTODEVICE, %s) not supported on this platform.  Please remove the bind_dev= option for 'listen' directive.",
+                              s, ls[i].dev_name);
+                return NGX_ERROR;
+#endif
+            }
+
+
  #if (NGX_HAVE_UNIX_DOMAIN)

              if (ls[i].sockaddr->sa_family == AF_UNIX) {
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 87fd087..e5c030c 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -18,6 +18,7 @@ typedef struct ngx_listening_s  ngx_listening_t;
  struct ngx_listening_s {
      ngx_socket_t        fd;

+    char                dev_name[32]; /* Use SO_BINDTODEVICE if this is not zero-length */
      struct sockaddr    *sockaddr;
      socklen_t           socklen;    /* size of sockaddr */
      size_t              addr_text_max_len;
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index f1f8a48..9aa732b 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1618,6 +1618,16 @@ ngx_http_cmp_conf_addrs(const void *one, const void *two)
          return -1;
      }

+    if (first->opt.dev_name[0] && !second->opt.dev_name[0]) {
+        /* shift explicit bind_dev()ed addresses to the start */
+        return -1;
+    }
+
+    if (!first->opt.dev_name[0] && second->opt.dev_name[0]) {
+        /* shift explicit bind_dev()ed addresses to the start */
+        return 1;
+    }
+
      if (first->opt.bind && !second->opt.bind) {
          /* shift explicit bind()ed addresses to the start */
          return -1;
@@ -1768,6 +1778,9 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
      ls->rcvbuf = addr->opt.rcvbuf;
      ls->sndbuf = addr->opt.sndbuf;

+    strncpy(ls->dev_name, addr->opt.dev_name, sizeof(ls->dev_name));
+    ls->dev_name[sizeof(ls->dev_name) - 1] = 0;
+
      ls->keepalive = addr->opt.so_keepalive;
  #if (NGX_HAVE_KEEPALIVE_TUNABLE)
      ls->keepidle = addr->opt.tcp_keepidle;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 27f082e..664f9b7 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -3937,6 +3937,12 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
              continue;
          }

+        if (ngx_strncmp(value[n].data, "bind_dev=", 9) == 0) {
+            strncpy(lsopt.dev_name, (char*)(value[n].data + 9), sizeof(lsopt.dev_name));
+            lsopt.dev_name[sizeof(lsopt.dev_name) - 1] = 0;
+            continue;
+        }
+
  #if (NGX_HAVE_SETFIB)
          if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
              lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index ff1c2df..8ac0a7a 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -67,6 +67,7 @@ typedef struct {
      } u;

      socklen_t                  socklen;
+    char                       dev_name[32]; /* for use with bind_dev */

      unsigned                   set:1;
      unsigned                   default_server:1;
-- 
1.7.11.7

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



More information about the nginx-devel mailing list