[Dnsmasq-discuss] [PATCH] dnsmasq: max-port support for outbound dns queries

Hans Dedecker dedeckeh at gmail.com
Thu Jan 14 14:25:48 GMT 2016


By default dnsmasq selects random ports for outbound dns queries;
when max-port option is specified the ports used will be lower
than the specified value. This is usefull for systems behind
firewalls which clamp the maximum allowed port value.
If max-port is specified min-port is set to 1024 if unset
to prevent clashes with the system ports; fatal error is
generated when max-port is smaller than min-port

Signed-off-by: Hans Dedecker <dedeckeh at gmail.com>
---
 man/dnsmasq.8      | 7 +++++++
 src/dns-protocol.h | 1 +
 src/dnsmasq.c      | 8 +++++++-
 src/dnsmasq.h      | 2 +-
 src/network.c      | 6 +++---
 src/option.c       | 9 +++++++++
 6 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index d51b10f..8dcb656 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -174,6 +174,13 @@ queries. Dnsmasq picks random ports as source for outbound queries:
 when this option is given, the ports used will always to larger
 than that specified. Useful for systems behind firewalls. 
 .TP
+.B --max-port=<port>
+Use ports lower than that given as source for outbound DNS queries.
+Dnsmasq picks random ports as source for outbound queries:
+when this option is given, the ports used will always be lower
+than that specified. Useful for systems behind firewalls.
+.TP
+
 .B \-i, --interface=<interface name>
 Listen only on the specified interface(s). Dnsmasq automatically adds
 the loopback (local) interface to the list of interfaces to use when
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index 95c55f2..75d8ffb 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -16,6 +16,7 @@
 
 #define NAMESERVER_PORT 53
 #define TFTP_PORT       69
+#define MAX_PORT        65535u
 
 #define IN6ADDRSZ       16
 #define INADDRSZ        4
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index e993629..0bb3e03 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -219,7 +219,13 @@ int main (int argc, char **argv)
   if (option_bool(OPT_LOOP_DETECT))
     die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
 #endif
-  
+
+  if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
+    daemon->min_port = 1024u;
+
+  if (daemon->max_port < daemon->min_port)
+    die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
+
   now = dnsmasq_time();
 
   /* Create a serial at startup if not configured. */
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 543481c..fd483a6 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -950,7 +950,7 @@ extern struct daemon {
   char *log_file; /* optional log file */
   int max_logs;  /* queue limit */
   int cachesize, ftabsize;
-  int port, query_port, min_port;
+  int port, query_port, min_port, max_port;
   unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl;
   char *dns_client_id;
   struct hostsfile *addn_hosts;
diff --git a/src/network.c b/src/network.c
index 303ae50..23f81ca 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1119,7 +1119,7 @@ int random_sock(int family)
   if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
     {
       union mysockaddr addr;
-      unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
+      unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
       int tries = ports_avail < 30 ? 3 * ports_avail : 100;
 
       memset(&addr, 0, sizeof(addr));
@@ -1132,8 +1132,8 @@ int random_sock(int family)
 	  {
 	    unsigned short port = rand16();
 	    
-	    if (daemon->min_port != 0)
-	      port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
+            if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
+              port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
 	    
 	    if (family == AF_INET) 
 	      {
diff --git a/src/option.c b/src/option.c
index 0e126f2..f40e9e2 100644
--- a/src/option.c
+++ b/src/option.c
@@ -154,6 +154,7 @@ struct myoption {
 #define LOPT_HOST_INOTIFY  342
 #define LOPT_DNSSEC_STAMP  343
 #define LOPT_TFTP_NO_FAIL  344
+#define LOPT_MAXPORT       345
 #define LOPT_DNS_CLIENT_ID 355
 
 #ifdef HAVE_GETOPT_LONG
@@ -271,6 +272,7 @@ static const struct myoption opts[] =
     { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
     { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
     { "min-port", 1, 0, LOPT_MINPORT },
+    { "max-port", 1, 0, LOPT_MAXPORT },
     { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
     { "cname", 1, 0, LOPT_CNAME },
     { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
@@ -438,6 +440,7 @@ static struct {
   { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
   { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
   { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
+  { LOPT_MAXPORT, ARG_ONE, "<port>", gettext_noop("Specify highest port available for DNS query transmission."), NULL },
   { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
   { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
   { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
@@ -2512,6 +2515,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	ret_err(gen_err);
       break;
 
+    case LOPT_MAXPORT:  /* --max-port */
+      if (!atoi_check16(arg, &daemon->max_port))
+	ret_err(gen_err);
+      break;
+
     case '0':  /* --dns-forward-max */
       if (!atoi_check(arg, &daemon->ftabsize))
 	ret_err(gen_err);
@@ -4462,6 +4470,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
   daemon->soa_refresh = SOA_REFRESH;
   daemon->soa_retry = SOA_RETRY;
   daemon->soa_expiry = SOA_EXPIRY;
+  daemon->max_port = MAX_PORT;
 
   add_txt("version.bind", "dnsmasq-" VERSION, 0 );
   add_txt("authors.bind", "Simon Kelley", 0);
-- 
1.9.1




More information about the Dnsmasq-discuss mailing list