diff --git a/CHANGELOG b/CHANGELOG index d3cf909..bc1e930 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,9 @@ version 2.76 Return REFUSED when running out of forwarding table slots, not SERVFAIL. + Add --max-port configuration. Thanks to Hans Dedecker for + the patch. + version 2.75 Fix reversion on 2.74 which caused 100% CPU use when a diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 69acdae..103a813 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= +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= 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 5451c6c..91ac40a 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, "[=]", gettext_noop("Use alternative ports for DHCP."), NULL }, { LOPT_NAPTR, ARG_DUP, ",", gettext_noop("Specify NAPTR DNS record."), NULL }, { LOPT_MINPORT, ARG_ONE, "", gettext_noop("Specify lowest port available for DNS query transmission."), NULL }, + { LOPT_MAXPORT, ARG_ONE, "", 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:]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL}, { LOPT_PROXY, ARG_DUP, "[=]...", 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);