The current --server syntax allows for binding to interface or address. However,
in some (admittedly special) cases it is useful to be able to specify both. This
commit introduces the following syntax to support binding to both interface and
address:

--server X.X.X.X@IP@interface#port

Based on my tests, the syntax is backwards compatible with the current
@IP/interface#port. The code will fail if two interface names are given.

v1->v2:
* Add man page description of the extended server syntax (thanks Simon Kelley)

Signed-off-by: Kristian Evensen <kristian.even...@gmail.com>
---
 man/dnsmasq.8 | 16 ++++++++--------
 src/option.c  | 36 ++++++++++++++++++++++++++++++++----
 2 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 059eafc..2e5ef21 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -467,14 +467,14 @@ to make configuration files clearer in this case.
 IPv6 addresses may include a %interface scope-id, eg
 fe80::202:a412:4512:7bbf%eth0.
 
-The optional string after the @ character tells
-dnsmasq how to set the source of the queries to this
-nameserver. It should be an ip-address, which should belong to the machine on 
which
-dnsmasq is running otherwise this server line will be logged and then
-ignored, or an interface name. If an interface name is given, then
-queries to the server will be forced via that interface; if an
-ip-address is given then the source address of the queries will be set
-to that address.
+The optional string after the @ character tells dnsmasq how to set the source 
of
+the queries to this nameserver. It can either be an ip-address, an interface
+name or both. The ip-address should belong to the machine on which dnsmasq is
+running, otherwise this server line will be logged and then ignored. If an
+interface name is given, then queries to the server will be forced via that
+interface; if an ip-address is given then the source address of the queries 
will
+be set to that address; and if both are given then a combination of ip-address
+and interface name will be used to steer requests to the server.
 The query-port flag is ignored for any servers which have a
 source address specified but the port may be specified directly as
 part of the source address. Forcing queries to an interface is not
diff --git a/src/option.c b/src/option.c
index 31c8cb9..45bd34d 100644
--- a/src/option.c
+++ b/src/option.c
@@ -757,6 +757,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union 
mysockaddr *source_a
 {
   int source_port = 0, serv_port = NAMESERVER_PORT;
   char *portno, *source;
+  char *interface_opt = NULL;
 #ifdef HAVE_IPV6
   int scope_index = 0;
   char *scope_id;
@@ -782,6 +783,19 @@ char *parse_server(char *arg, union mysockaddr *addr, 
union mysockaddr *source_a
   scope_id = split_chr(arg, '%');
 #endif
   
+  if (source) {
+    interface_opt = split_chr(source, '@');
+
+    if (interface_opt)
+      {
+#if defined(SO_BINDTODEVICE)
+       strncpy(interface, interface_opt, IF_NAMESIZE - 1);
+#else
+       return _("interface binding not supported");
+#endif
+      }
+  }
+
   if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
     {
       addr->in.sin_port = htons(serv_port);    
@@ -800,8 +814,15 @@ char *parse_server(char *arg, union mysockaddr *addr, 
union mysockaddr *source_a
          if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
            {
 #if defined(SO_BINDTODEVICE)
-             source_addr->in.sin_addr.s_addr = INADDR_ANY;
-             strncpy(interface, source, IF_NAMESIZE - 1);
+             if (interface_opt)
+               {
+                 return _("interface can only be specified once");
+               }
+             else
+               {
+                 source_addr->in.sin_addr.s_addr = INADDR_ANY;
+                 strncpy(interface, source, IF_NAMESIZE - 1);
+               }
 #else
              return _("interface binding not supported");
 #endif
@@ -832,8 +853,15 @@ char *parse_server(char *arg, union mysockaddr *addr, 
union mysockaddr *source_a
          if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
            {
 #if defined(SO_BINDTODEVICE)
-             source_addr->in6.sin6_addr = in6addr_any; 
-             strncpy(interface, source, IF_NAMESIZE - 1);
+             if (interface_opt)
+               {
+                 return _("interface can only be specified once");
+               }
+             else
+               {
+                 source_addr->in6.sin6_addr = in6addr_any;
+                 strncpy(interface, source, IF_NAMESIZE - 1);
+               }
 #else
              return _("interface binding not supported");
 #endif
-- 
2.9.3


_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to