[MINOR] add support for bind interface name
By appending "interface <name>" to a "bind" line, it is now possible
to specifically bind to a physical interface name. Note that this
currently only works on Linux and requires root privileges.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 416e67c..10f7b2a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -782,6 +782,8 @@
/* Now let's parse the proxy-specific keywords */
if (!strcmp(args[0], "bind")) { /* new listen addresses */
struct listener *last_listen;
+ int cur_arg;
+
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
return -1;
@@ -799,24 +801,50 @@
curproxy->listen = str2listener(args[1], last_listen);
if (!curproxy->listen)
return -1;
- if (*args[2]) {
+
+ cur_arg = 2;
+ while (*(args[cur_arg])) {
+ if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
+#ifdef SO_BINDTODEVICE
+ struct listener *l;
+
+ if (!*args[cur_arg + 1]) {
+ Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
+ file, linenum, args[0]);
+ return -1;
+ }
+
+ for (l = curproxy->listen; l != last_listen; l = l->next)
+ l->interface = strdup(args[cur_arg + 1]);
+
+ global.last_checks |= LSTCHK_NETADM;
+
+ cur_arg += 2;
+ continue;
+#else
+ Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
+ file, linenum, args[0], args[cur_arg]);
+ return -1;
+#endif
+ }
+ if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
#ifdef CONFIG_HAP_LINUX_TPROXY
- if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
struct listener *l;
for (l = curproxy->listen; l != last_listen; l = l->next)
l->options |= LI_O_FOREIGN;
- }
- else {
- Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
- file, linenum, args[0]);
+
+ cur_arg ++;
+ continue;
+#else
+ Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
+ file, linenum, args[0], args[cur_arg]);
return -1;
+#endif
}
-#else
- Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
+ Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
file, linenum, args[0]);
return -1;
-#endif
}
global.maxsock++;
return 0;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 94907ec..78f63fc 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -241,6 +241,16 @@
err |= ERR_ALERT;
}
#endif
+#ifdef SO_BINDTODEVICE
+ /* Note: this might fail if not CAP_NET_RAW */
+ if (listener->interface) {
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
+ listener->interface, strlen(listener->interface)) == -1) {
+ msg = "cannot bind listener to device";
+ err |= ERR_WARN;
+ }
+ }
+#endif
if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
err |= ERR_RETRYABLE | ERR_ALERT;
msg = "cannot bind socket";