[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