Discussion:
[Dnsmasq-discuss] [PATCH v2] Add support for binding to both interface and IP
Kristian Evensen
2017-03-20 19:44:33 UTC
Permalink
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 ***@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 <***@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
Simon Kelley
2017-03-22 21:34:37 UTC
Permalink
Good stuff.

Patch applied.


Cheers,

Simon.
Post by Kristian Evensen
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
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.
* Add man page description of the extended server syntax (thanks Simon Kelley)
Loading...