Commit 4e7694d7 authored by Kristian Evensen's avatar Kristian Evensen Committed by Simon Kelley

Allow binding to both source address and interface in server specs.

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: default avatarKristian Evensen <kristian.evensen@gmail.com>
parent e33b4870
...@@ -467,14 +467,14 @@ to make configuration files clearer in this case. ...@@ -467,14 +467,14 @@ to make configuration files clearer in this case.
IPv6 addresses may include a %interface scope-id, eg IPv6 addresses may include a %interface scope-id, eg
fe80::202:a412:4512:7bbf%eth0. fe80::202:a412:4512:7bbf%eth0.
The optional string after the @ character tells The optional string after the @ character tells dnsmasq how to set the source of
dnsmasq how to set the source of the queries to this the queries to this nameserver. It can either be an ip-address, an interface
nameserver. It should be an ip-address, which should belong to the machine on which name or both. The ip-address should belong to the machine on which dnsmasq is
dnsmasq is running otherwise this server line will be logged and then running, otherwise this server line will be logged and then ignored. If an
ignored, or an interface name. If an interface name is given, then interface name is given, then queries to the server will be forced via that
queries to the server will be forced via that interface; if an interface; if an ip-address is given then the source address of the queries will
ip-address is given then the source address of the queries will be set be set to that address; and if both are given then a combination of ip-address
to that 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 The query-port flag is ignored for any servers which have a
source address specified but the port may be specified directly as source address specified but the port may be specified directly as
part of the source address. Forcing queries to an interface is not part of the source address. Forcing queries to an interface is not
......
...@@ -757,6 +757,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a ...@@ -757,6 +757,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
{ {
int source_port = 0, serv_port = NAMESERVER_PORT; int source_port = 0, serv_port = NAMESERVER_PORT;
char *portno, *source; char *portno, *source;
char *interface_opt = NULL;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
int scope_index = 0; int scope_index = 0;
char *scope_id; char *scope_id;
...@@ -782,6 +783,19 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a ...@@ -782,6 +783,19 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
scope_id = split_chr(arg, '%'); scope_id = split_chr(arg, '%');
#endif #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) if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
{ {
addr->in.sin_port = htons(serv_port); addr->in.sin_port = htons(serv_port);
...@@ -800,6 +814,9 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a ...@@ -800,6 +814,9 @@ 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 (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
{ {
#if defined(SO_BINDTODEVICE) #if defined(SO_BINDTODEVICE)
if (interface_opt)
return _("interface can only be specified once");
source_addr->in.sin_addr.s_addr = INADDR_ANY; source_addr->in.sin_addr.s_addr = INADDR_ANY;
strncpy(interface, source, IF_NAMESIZE - 1); strncpy(interface, source, IF_NAMESIZE - 1);
#else #else
...@@ -832,6 +849,9 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a ...@@ -832,6 +849,9 @@ 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 (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
{ {
#if defined(SO_BINDTODEVICE) #if defined(SO_BINDTODEVICE)
if (interface_opt)
return _("interface can only be specified once");
source_addr->in6.sin6_addr = in6addr_any; source_addr->in6.sin6_addr = in6addr_any;
strncpy(interface, source, IF_NAMESIZE - 1); strncpy(interface, source, IF_NAMESIZE - 1);
#else #else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment