diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index 10537d711f..85c43505e0 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq PKG_VERSION:=2.80 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq diff --git a/package/network/services/dnsmasq/patches/0001-Impove-cache-behaviour-for-TCP-connections.patch b/package/network/services/dnsmasq/patches/0001-Impove-cache-behaviour-for-TCP-connections.patch new file mode 100644 index 0000000000..453c2924b2 --- /dev/null +++ b/package/network/services/dnsmasq/patches/0001-Impove-cache-behaviour-for-TCP-connections.patch @@ -0,0 +1,495 @@ +From a799ca0c6314ad73a97bc6c89382d2712a9c0b0e Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Thu, 18 Oct 2018 19:35:29 +0100 +Subject: [PATCH 01/11] Impove cache behaviour for TCP connections. + +For ease of implementaion, dnsmasq has always forked a new process to +handle each incoming TCP connection. A side-effect of this is that any +DNS queries answered from TCP connections are not cached: when TCP +connections were rare, this was not a problem. With the coming of +DNSSEC, it's now the case that some DNSSEC queries have answers which +spill to TCP, and if, for instance, this applies to the keys for the +root then those never get cached, and performance is very bad. This +fix passes cache entries back from the TCP child process to the main +server process, and fixes the problem. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + CHANGELOG | 14 ++++ + src/blockdata.c | 37 ++++++++- + src/cache.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++-- + src/dnsmasq.c | 58 ++++++++++++-- + src/dnsmasq.h | 5 ++ + 5 files changed, 291 insertions(+), 19 deletions(-) + +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -1,3 +1,17 @@ ++version 2.81 ++ Impove cache behaviour for TCP connections. For ease of ++ implementaion, dnsmasq has always forked a new process to handle ++ each incoming TCP connection. A side-effect of this is that ++ any DNS queries answered from TCP connections are not cached: ++ when TCP connections were rare, this was not a problem. ++ With the coming of DNSSEC, it's now the case that some ++ DNSSEC queries have answers which spill to TCP, and if, ++ for instance, this applies to the keys for the root then ++ those never get cached, and performance is very bad. ++ This fix passes cache entries back from the TCP child process to ++ the main server process, and fixes the problem. ++ ++ + version 2.80 + Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method + for the initial patch and motivation. +--- a/src/blockdata.c ++++ b/src/blockdata.c +@@ -61,7 +61,7 @@ void blockdata_report(void) + blockdata_alloced * sizeof(struct blockdata)); + } + +-struct blockdata *blockdata_alloc(char *data, size_t len) ++static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len) + { + struct blockdata *block, *ret = NULL; + struct blockdata **prev = &ret; +@@ -89,8 +89,17 @@ struct blockdata *blockdata_alloc(char * + blockdata_hwm = blockdata_count; + + blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; +- memcpy(block->key, data, blen); +- data += blen; ++ if (data) ++ { ++ memcpy(block->key, data, blen); ++ data += blen; ++ } ++ else if (!read_write(fd, block->key, blen, 1)) ++ { ++ /* failed read free partial chain */ ++ blockdata_free(ret); ++ return NULL; ++ } + len -= blen; + *prev = block; + prev = &block->next; +@@ -100,6 +109,10 @@ struct blockdata *blockdata_alloc(char * + return ret; + } + ++struct blockdata *blockdata_alloc(char *data, size_t len) ++{ ++ return blockdata_alloc_real(0, data, len); ++} + + void blockdata_free(struct blockdata *blocks) + { +@@ -148,5 +161,21 @@ void *blockdata_retrieve(struct blockdat + + return data; + } +- ++ ++ ++void blockdata_write(struct blockdata *block, size_t len, int fd) ++{ ++ for (; len > 0 && block; block = block->next) ++ { ++ size_t blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len; ++ read_write(fd, block->key, blen, 0); ++ len -= blen; ++ } ++} ++ ++struct blockdata *blockdata_read(int fd, size_t len) ++{ ++ return blockdata_alloc_real(fd, NULL, len); ++} ++ + #endif +--- a/src/cache.c ++++ b/src/cache.c +@@ -26,6 +26,8 @@ static union bigname *big_free = NULL; + static int bignames_left, hash_size; + + static void make_non_terminals(struct crec *source); ++static struct crec *really_insert(char *name, struct all_addr *addr, ++ time_t now, unsigned long ttl, unsigned short flags); + + /* type->string mapping: this is also used by the name-hash function as a mixing table. */ + static const struct { +@@ -464,16 +466,10 @@ void cache_start_insert(void) + new_chain = NULL; + insert_error = 0; + } +- ++ + struct crec *cache_insert(char *name, struct all_addr *addr, + time_t now, unsigned long ttl, unsigned short flags) + { +- struct crec *new, *target_crec = NULL; +- union bigname *big_name = NULL; +- int freed_all = flags & F_REVERSE; +- int free_avail = 0; +- unsigned int target_uid; +- + /* Don't log DNSSEC records here, done elsewhere */ + if (flags & (F_IPV4 | F_IPV6 | F_CNAME)) + { +@@ -484,7 +480,20 @@ struct crec *cache_insert(char *name, st + if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl) + ttl = daemon->min_cache_ttl; + } ++ ++ return really_insert(name, addr, now, ttl, flags); ++} + ++ ++static struct crec *really_insert(char *name, struct all_addr *addr, ++ time_t now, unsigned long ttl, unsigned short flags) ++{ ++ struct crec *new, *target_crec = NULL; ++ union bigname *big_name = NULL; ++ int freed_all = flags & F_REVERSE; ++ int free_avail = 0; ++ unsigned int target_uid; ++ + /* if previous insertion failed give up now. */ + if (insert_error) + return NULL; +@@ -645,12 +654,185 @@ void cache_end_insert(void) + cache_hash(new_chain); + cache_link(new_chain); + daemon->metrics[METRIC_DNS_CACHE_INSERTED]++; ++ ++ /* If we're a child process, send this cache entry up the pipe to the master. ++ The marshalling process is rather nasty. */ ++ if (daemon->pipe_to_parent != -1) ++ { ++ char *name = cache_get_name(new_chain); ++ ssize_t m = strlen(name); ++ unsigned short flags = new_chain->flags; ++#ifdef HAVE_DNSSEC ++ u16 class = new_chain->uid; ++#endif ++ ++ read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)name, m, 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0); ++ ++ if (flags & (F_IPV4 | F_IPV6)) ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0); ++#ifdef HAVE_DNSSEC ++ else if (flags & F_DNSKEY) ++ { ++ read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.algo, sizeof(new_chain->addr.key.algo), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keytag, sizeof(new_chain->addr.key.keytag), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.flags, sizeof(new_chain->addr.key.flags), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keylen, sizeof(new_chain->addr.key.keylen), 0); ++ blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent); ++ } ++ else if (flags & F_DS) ++ { ++ read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0); ++ /* A negative DS entry is possible and has no data, obviously. */ ++ if (!(flags & F_NEG)) ++ { ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.algo, sizeof(new_chain->addr.ds.algo), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keytag, sizeof(new_chain->addr.ds.keytag), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.digest, sizeof(new_chain->addr.ds.digest), 0); ++ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keylen, sizeof(new_chain->addr.ds.keylen), 0); ++ blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent); ++ } ++ } ++#endif ++ ++ } + } ++ + new_chain = tmp; + } ++ ++ /* signal end of cache insert in master process */ ++ if (daemon->pipe_to_parent != -1) ++ { ++ ssize_t m = -1; ++ read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0); ++ } ++ + new_chain = NULL; + } + ++ ++/* A marshalled cache entry arrives on fd, read, unmarshall and insert into cache of master process. */ ++int cache_recv_insert(time_t now, int fd) ++{ ++ ssize_t m; ++ struct all_addr addr; ++ unsigned long ttl; ++ time_t ttd; ++ unsigned short flags; ++ struct crec *crecp = NULL; ++ ++ cache_start_insert(); ++ ++ while(1) ++ { ++ ++ if (!read_write(fd, (unsigned char *)&m, sizeof(m), 1)) ++ return 0; ++ ++ if (m == -1) ++ { ++ cache_end_insert(); ++ return 1; ++ } ++ ++ if (!read_write(fd, (unsigned char *)daemon->namebuff, m, 1) || ++ !read_write(fd, (unsigned char *)&ttd, sizeof(ttd), 1) || ++ !read_write(fd, (unsigned char *)&flags, sizeof(flags), 1)) ++ return 0; ++ ++ daemon->namebuff[m] = 0; ++ ++ ttl = difftime(ttd, now); ++ ++ if (flags & (F_IPV4 | F_IPV6)) ++ { ++ if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1)) ++ return 0; ++ crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags); ++ } ++ else if (flags & F_CNAME) ++ { ++ struct crec *newc = really_insert(daemon->namebuff, NULL, now, ttl, flags); ++ /* This relies on the fact the the target of a CNAME immediately preceeds ++ it because of the order of extraction in extract_addresses, and ++ the order reversal on the new_chain. */ ++ if (newc) ++ { ++ if (!crecp) ++ { ++ newc->addr.cname.target.cache = NULL; ++ /* anything other than zero, to avoid being mistaken for CNAME to interface-name */ ++ newc->addr.cname.uid = 1; ++ } ++ else ++ { ++ next_uid(crecp); ++ newc->addr.cname.target.cache = crecp; ++ newc->addr.cname.uid = crecp->uid; ++ } ++ } ++ } ++#ifdef HAVE_DNSSEC ++ else if (flags & (F_DNSKEY | F_DS)) ++ { ++ unsigned short class, keylen, keyflags, keytag; ++ unsigned char algo, digest; ++ struct blockdata *keydata; ++ ++ if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1)) ++ return 0; ++ /* Cache needs to known class for DNSSEC stuff */ ++ addr.addr.dnssec.class = class; ++ ++ crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags); ++ ++ if (flags & F_DNSKEY) ++ { ++ if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) || ++ !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) || ++ !read_write(fd, (unsigned char *)&keyflags, sizeof(keyflags), 1) || ++ !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) || ++ !(keydata = blockdata_read(fd, keylen))) ++ return 0; ++ } ++ else if (!(flags & F_NEG)) ++ { ++ if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) || ++ !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) || ++ !read_write(fd, (unsigned char *)&digest, sizeof(digest), 1) || ++ !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) || ++ !(keydata = blockdata_read(fd, keylen))) ++ return 0; ++ } ++ ++ if (crecp) ++ { ++ if (flags & F_DNSKEY) ++ { ++ crecp->addr.key.algo = algo; ++ crecp->addr.key.keytag = keytag; ++ crecp->addr.key.flags = flags; ++ crecp->addr.key.keylen = keylen; ++ crecp->addr.key.keydata = keydata; ++ } ++ else if (!(flags & F_NEG)) ++ { ++ crecp->addr.ds.algo = algo; ++ crecp->addr.ds.keytag = keytag; ++ crecp->addr.ds.digest = digest; ++ crecp->addr.ds.keylen = keylen; ++ crecp->addr.ds.keydata = keydata; ++ } ++ } ++ } ++#endif ++ } ++} ++ + int cache_find_non_terminal(char *name, time_t now) + { + struct crec *crecp; +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -930,6 +930,10 @@ int main (int argc, char **argv) + check_servers(); + + pid = getpid(); ++ ++ daemon->pipe_to_parent = -1; ++ for (i = 0; i < MAX_PROCS; i++) ++ daemon->tcp_pipes[i] = -1; + + #ifdef HAVE_INOTIFY + /* Using inotify, have to select a resolv file at startup */ +@@ -1611,7 +1615,7 @@ static int set_dns_listeners(time_t now) + we don't need to explicitly arrange to wake up here */ + if (listener->tcpfd != -1) + for (i = 0; i < MAX_PROCS; i++) +- if (daemon->tcp_pids[i] == 0) ++ if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) + { + poll_listen(listener->tcpfd, POLLIN); + break; +@@ -1624,6 +1628,13 @@ static int set_dns_listeners(time_t now) + + } + ++#ifndef NO_FORK ++ if (!option_bool(OPT_DEBUG)) ++ for (i = 0; i < MAX_PROCS; i++) ++ if (daemon->tcp_pipes[i] != -1) ++ poll_listen(daemon->tcp_pipes[i], POLLIN); ++#endif ++ + return wait; + } + +@@ -1632,7 +1643,10 @@ static void check_dns_listeners(time_t n + struct serverfd *serverfdp; + struct listener *listener; + int i; +- ++#ifndef NO_FORK ++ int pipefd[2]; ++#endif ++ + for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) + if (poll_check(serverfdp->fd, POLLIN)) + reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now); +@@ -1642,7 +1656,26 @@ static void check_dns_listeners(time_t n + if (daemon->randomsocks[i].refcount != 0 && + poll_check(daemon->randomsocks[i].fd, POLLIN)) + reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); +- ++ ++#ifndef NO_FORK ++ /* Races. The child process can die before we read all of the data from the ++ pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the ++ process, and tcp_pipes to -1 and close the FD when we read the last ++ of the data - indicated by cache_recv_insert returning zero. ++ The order of these events is indeterminate, and both are needed ++ to free the process slot. Once the child process has gone, poll() ++ returns POLLHUP, not POLLIN, so have to check for both here. */ ++ if (!option_bool(OPT_DEBUG)) ++ for (i = 0; i < MAX_PROCS; i++) ++ if (daemon->tcp_pipes[i] != -1 && ++ poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) && ++ !cache_recv_insert(now, daemon->tcp_pipes[i])) ++ { ++ close(daemon->tcp_pipes[i]); ++ daemon->tcp_pipes[i] = -1; ++ } ++#endif ++ + for (listener = daemon->listeners; listener; listener = listener->next) + { + if (listener->fd != -1 && poll_check(listener->fd, POLLIN)) +@@ -1736,15 +1769,20 @@ static void check_dns_listeners(time_t n + while (retry_send(close(confd))); + } + #ifndef NO_FORK +- else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0) ++ else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0) + { +- if (p != -1) ++ close(pipefd[1]); /* parent needs read pipe end. */ ++ if (p == -1) ++ close(pipefd[0]); ++ else + { + int i; ++ + for (i = 0; i < MAX_PROCS; i++) +- if (daemon->tcp_pids[i] == 0) ++ if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) + { + daemon->tcp_pids[i] = p; ++ daemon->tcp_pipes[i] = pipefd[0]; + break; + } + } +@@ -1761,7 +1799,7 @@ static void check_dns_listeners(time_t n + int flags; + struct in_addr netmask; + int auth_dns; +- ++ + if (iface) + { + netmask = iface->netmask; +@@ -1777,7 +1815,11 @@ static void check_dns_listeners(time_t n + /* Arrange for SIGALRM after CHILD_LIFETIME seconds to + terminate the process. */ + if (!option_bool(OPT_DEBUG)) +- alarm(CHILD_LIFETIME); ++ { ++ alarm(CHILD_LIFETIME); ++ close(pipefd[0]); /* close read end in child. */ ++ daemon->pipe_to_parent = pipefd[1]; ++ } + #endif + + /* start with no upstream connections. */ +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1091,6 +1091,8 @@ extern struct daemon { + size_t packet_len; /* " " */ + struct randfd *rfd_save; /* " " */ + pid_t tcp_pids[MAX_PROCS]; ++ int tcp_pipes[MAX_PROCS]; ++ int pipe_to_parent; + struct randfd randomsocks[RANDOM_SOCKS]; + int v6pktinfo; + struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */ +@@ -1152,6 +1154,7 @@ struct crec *cache_find_by_name(struct c + char *name, time_t now, unsigned int prot); + void cache_end_insert(void); + void cache_start_insert(void); ++int cache_recv_insert(time_t now, int fd); + struct crec *cache_insert(char *name, struct all_addr *addr, + time_t now, unsigned long ttl, unsigned short flags); + void cache_reload(void); +@@ -1174,6 +1177,8 @@ void blockdata_init(void); + void blockdata_report(void); + struct blockdata *blockdata_alloc(char *data, size_t len); + void *blockdata_retrieve(struct blockdata *block, size_t len, void *data); ++struct blockdata *blockdata_read(int fd, size_t len); ++void blockdata_write(struct blockdata *block, size_t len, int fd); + void blockdata_free(struct blockdata *blocks); + #endif + diff --git a/package/network/services/dnsmasq/patches/0002-Ensure-that-AD-bit-is-reset-on-answers-from-address-.patch b/package/network/services/dnsmasq/patches/0002-Ensure-that-AD-bit-is-reset-on-answers-from-address-.patch new file mode 100644 index 0000000000..e3178b8dfd --- /dev/null +++ b/package/network/services/dnsmasq/patches/0002-Ensure-that-AD-bit-is-reset-on-answers-from-address-.patch @@ -0,0 +1,26 @@ +From a220545c4277cba534be5ef4638b5076fc7d2cf4 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Mon, 22 Oct 2018 18:21:48 +0100 +Subject: [PATCH 02/11] Ensure that AD bit is reset on answers from + --address=//
. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/rfc1035.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -938,9 +938,9 @@ size_t setup_reply(struct dns_header *he + return 0; + + /* clear authoritative and truncated flags, set QR flag */ +- header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR; +- /* set RA flag */ +- header->hb4 |= HB4_RA; ++ header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC )) | HB3_QR; ++ /* clear AD flag, set RA flag */ ++ header->hb4 = (header->hb4 & ~HB4_AD) | HB4_RA; + + header->nscount = htons(0); + header->arcount = htons(0); diff --git a/package/network/services/dnsmasq/patches/0003-Remove-ability-to-compile-without-IPv6-support.patch b/package/network/services/dnsmasq/patches/0003-Remove-ability-to-compile-without-IPv6-support.patch new file mode 100644 index 0000000000..be3c4116b6 --- /dev/null +++ b/package/network/services/dnsmasq/patches/0003-Remove-ability-to-compile-without-IPv6-support.patch @@ -0,0 +1,2192 @@ +From ee8750451b49d27b180517a4e35b636be0fae575 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Tue, 23 Oct 2018 22:10:17 +0100 +Subject: [PATCH 03/11] Remove ability to compile without IPv6 support. + +This was the source of a large number of #ifdefs, originally +included for use with old embedded libc versions. I'm +sure no-one wants or needs IPv6-free code these days, so this +is a move towards more maintainable code. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/arp.c | 13 ---------- + src/auth.c | 53 ++++++++++---------------------------- + src/bpf.c | 10 ++------ + src/cache.c | 31 ++++------------------ + src/config.h | 30 +++------------------- + src/conntrack.c | 2 -- + src/dbus.c | 4 --- + src/dnsmasq.c | 6 ++--- + src/dnsmasq.h | 20 ++------------- + src/domain.c | 28 +++----------------- + src/dump.c | 4 --- + src/edns0.c | 14 +--------- + src/forward.c | 68 ++++--------------------------------------------- + src/helper.c | 8 ------ + src/ipset.c | 9 +------ + src/netlink.c | 5 +--- + src/network.c | 54 +++------------------------------------ + src/option.c | 34 ------------------------- + src/rfc1035.c | 50 +++++++----------------------------- + src/tables.c | 3 +-- + src/tftp.c | 17 ++----------- + src/util.c | 13 +--------- + 22 files changed, 57 insertions(+), 419 deletions(-) + +--- a/src/arp.c ++++ b/src/arp.c +@@ -44,11 +44,6 @@ static int filter_mac(int family, char * + if (maclen > DHCP_CHADDR_MAX) + return 1; + +-#ifndef HAVE_IPV6 +- if (family != AF_INET) +- return 1; +-#endif +- + /* Look for existing entry */ + for (arp = arps; arp; arp = arp->next) + { +@@ -60,13 +55,11 @@ static int filter_mac(int family, char * + if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr) + continue; + } +-#ifdef HAVE_IPV6 + else + { + if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp)) + continue; + } +-#endif + + if (arp->status == ARP_EMPTY) + { +@@ -103,10 +96,8 @@ static int filter_mac(int family, char * + memcpy(arp->hwaddr, mac, maclen); + if (family == AF_INET) + arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr; +-#ifdef HAVE_IPV6 + else + memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ); +-#endif + } + + return 1; +@@ -136,11 +127,9 @@ int find_mac(union mysockaddr *addr, uns + arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr) + continue; + +-#ifdef HAVE_IPV6 + if (arp->family == AF_INET6 && + !IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr)) + continue; +-#endif + + /* Only accept positive entries unless in lazy mode. */ + if (arp->status != ARP_EMPTY || lazy || updated) +@@ -203,10 +192,8 @@ int find_mac(union mysockaddr *addr, uns + + if (addr->sa.sa_family == AF_INET) + arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr; +-#ifdef HAVE_IPV6 + else + memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ); +-#endif + } + + return 0; +--- a/src/auth.c ++++ b/src/auth.c +@@ -33,10 +33,8 @@ static struct addrlist *find_addrlist(st + if (is_same_net(addr, list->addr.addr.addr4, netmask)) + return list; + } +-#ifdef HAVE_IPV6 + else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen)) + return list; +-#endif + + } while ((list = list->next)); + +@@ -189,7 +187,6 @@ size_t answer_auth(struct dns_header *he + while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) + intr = intr->next; + } +-#ifdef HAVE_IPV6 + else if (flag == F_IPV6) + for (intr = daemon->int_names; intr; intr = intr->next) + { +@@ -205,7 +202,6 @@ size_t answer_auth(struct dns_header *he + while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) + intr = intr->next; + } +-#endif + + if (intr) + { +@@ -378,10 +374,8 @@ size_t answer_auth(struct dns_header *he + if (qtype == T_A) + flag = F_IPV4; + +-#ifdef HAVE_IPV6 + if (qtype == T_AAAA) + flag = F_IPV6; +-#endif + + for (intr = daemon->int_names; intr; intr = intr->next) + if ((rc = hostname_issubdomain(name, intr->name))) +@@ -395,10 +389,9 @@ size_t answer_auth(struct dns_header *he + if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype && + (local_query || filter_zone(zone, flag, &addrlist->addr))) + { +-#ifdef HAVE_IPV6 + if (addrlist->flags & ADDRLIST_REVONLY) + continue; +-#endif ++ + found = 1; + log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, +@@ -424,13 +417,11 @@ size_t answer_auth(struct dns_header *he + + if (peer_addr->sa.sa_family == AF_INET) + peer_addr->in.sin_port = 0; +-#ifdef HAVE_IPV6 + else + { + peer_addr->in6.sin6_port = 0; + peer_addr->in6.sin6_scope_id = 0; + } +-#endif + + for (peers = daemon->auth_peers; peers; peers = peers->next) + if (sockaddr_isequal(peer_addr, &peers->addr)) +@@ -442,10 +433,8 @@ size_t answer_auth(struct dns_header *he + { + if (peer_addr->sa.sa_family == AF_INET) + inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN); +-#ifdef HAVE_IPV6 + else + inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN); +-#endif + + my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff); + return 0; +@@ -603,7 +592,6 @@ size_t answer_auth(struct dns_header *he + p += sprintf(p, "%u.in-addr.arpa", a & 0xff); + + } +-#ifdef HAVE_IPV6 + else + { + char *p = name; +@@ -617,7 +605,6 @@ size_t answer_auth(struct dns_header *he + p += sprintf(p, "ip6.arpa"); + + } +-#endif + } + + /* handle NS and SOA in auth section or for explicit queries */ +@@ -754,14 +741,12 @@ size_t answer_auth(struct dns_header *he + daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr)) + anscount++; + +-#ifdef HAVE_IPV6 + for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) + if ((addrlist->flags & ADDRLIST_IPV6) && + (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) && + add_resource_record(header, limit, &trunc, -axfroffset, &ansp, + daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr)) + anscount++; +-#endif + + /* restore config data */ + if (cut) +@@ -798,18 +783,11 @@ size_t answer_auth(struct dns_header *he + { + char *cache_name = cache_get_name(crecp); + if (!strchr(cache_name, '.') && +- (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))) +- { +- qtype = T_A; +-#ifdef HAVE_IPV6 +- if (crecp->flags & F_IPV6) +- qtype = T_AAAA; +-#endif +- if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, +- daemon->auth_ttl, NULL, qtype, C_IN, +- (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr)) +- anscount++; +- } ++ (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))) && ++ add_resource_record(header, limit, &trunc, -axfroffset, &ansp, ++ daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN, ++ (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr)) ++ anscount++; + } + + if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN)))) +@@ -818,18 +796,13 @@ size_t answer_auth(struct dns_header *he + if (in_zone(zone, name, &cut) && + (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))) + { +- qtype = T_A; +-#ifdef HAVE_IPV6 +- if (crecp->flags & F_IPV6) +- qtype = T_AAAA; +-#endif +- if (cut) +- *cut = 0; +- +- if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, +- daemon->auth_ttl, NULL, qtype, C_IN, +- (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr)) +- anscount++; ++ if (cut) ++ *cut = 0; ++ ++ if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, ++ daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN, ++ (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr)) ++ anscount++; + } + } + } +--- a/src/bpf.c ++++ b/src/bpf.c +@@ -31,9 +31,7 @@ + # include + #endif + #include +-#ifdef HAVE_IPV6 +-# include +-#endif ++#include + + #ifndef SA_SIZE + #define SA_SIZE(sa) \ +@@ -121,7 +119,7 @@ int iface_enumerate(int family, void *pa + if (getifaddrs(&head) == -1) + return 0; + +-#if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6) ++#if defined(HAVE_BSD_NETWORK) + if (family == AF_INET6) + fd = socket(PF_INET6, SOCK_DGRAM, 0); + #endif +@@ -152,7 +150,6 @@ int iface_enumerate(int family, void *pa + if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm))) + goto err; + } +-#ifdef HAVE_IPV6 + else if (family == AF_INET6) + { + struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr; +@@ -219,7 +216,6 @@ int iface_enumerate(int family, void *pa + (int) preferred, (int)valid, parm))) + goto err; + } +-#endif /* HAVE_IPV6 */ + + #ifdef HAVE_DHCP6 + else if (family == AF_LINK) +@@ -427,10 +423,8 @@ void route_sock(void) + del_family = sa->sa_family; + if (del_family == AF_INET) + del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr; +-#ifdef HAVE_IPV6 + else if (del_family == AF_INET6) + del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr; +-#endif + else + del_family = 0; + } +--- a/src/cache.c ++++ b/src/cache.c +@@ -410,11 +410,8 @@ static struct crec *cache_scan_free(char + else + { + int i; +-#ifdef HAVE_IPV6 + int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ; +-#else +- int addrlen = INADDRSZ; +-#endif ++ + for (i = 0; i < hash_size; i++) + for (crecp = hash_table[i], up = &hash_table[i]; + crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL)); +@@ -512,11 +509,9 @@ static struct crec *really_insert(char * + if ((flags & F_IPV4) && (new->flags & F_IPV4) && + new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr) + return new; +-#ifdef HAVE_IPV6 + else if ((flags & F_IPV6) && (new->flags & F_IPV6) && + IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6)) + return new; +-#endif + } + + insert_error = 1; +@@ -938,11 +933,7 @@ struct crec *cache_find_by_addr(struct c + time_t now, unsigned int prot) + { + struct crec *ans; +-#ifdef HAVE_IPV6 + int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ; +-#else +- int addrlen = INADDRSZ; +-#endif + + if (crecp) /* iterating */ + ans = crecp->next; +@@ -1171,14 +1162,12 @@ int read_hostsfile(char *filename, unsig + addrlen = INADDRSZ; + domain_suffix = get_domain(addr.addr.addr4); + } +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, token, &addr) > 0) + { + flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; + addrlen = IN6ADDRSZ; + domain_suffix = get_domain6(&addr.addr.addr6); + } +-#endif + else + { + my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno); +@@ -1343,7 +1332,7 @@ void cache_reload(void) + cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG; + add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); + } +-#ifdef HAVE_IPV6 ++ + if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) && + (cache = whine_malloc(SIZEOF_POINTER_CREC))) + { +@@ -1352,7 +1341,6 @@ void cache_reload(void) + cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG; + add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); + } +-#endif + } + + if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts) +@@ -1451,13 +1439,11 @@ void cache_add_dhcp_entry(char *host_nam + int in_hosts = 0; + size_t addrlen = sizeof(struct in_addr); + +-#ifdef HAVE_IPV6 + if (prot == AF_INET6) + { + flags = F_IPV6; + addrlen = sizeof(struct in6_addr); + } +-#endif + + inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN); + +@@ -1810,10 +1796,8 @@ void dump_cache(time_t now) + a = daemon->addrbuff; + if (cache->flags & F_IPV4) + inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN); +-#ifdef HAVE_IPV6 + else if (cache->flags & F_IPV6) + inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN); +-#endif + } + + if (cache->flags & F_IPV4) +@@ -1954,14 +1938,9 @@ void log_query(unsigned int flags, char + sprintf(daemon->addrbuff, "%u", rcode); + } + else +- { +-#ifdef HAVE_IPV6 +- inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, +- addr, daemon->addrbuff, ADDRSTRLEN); +-#else +- strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN); +-#endif +- } ++ inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, ++ addr, daemon->addrbuff, ADDRSTRLEN); ++ + } + else + dest = arg; +--- a/src/config.h ++++ b/src/config.h +@@ -131,7 +131,6 @@ HAVE_INOTIFY + + NO_ID + Don't report *.bind CHAOS info to clients, forward such requests upstream instead. +-NO_IPV6 + NO_TFTP + NO_DHCP + NO_DHCP6 +@@ -141,8 +140,8 @@ NO_AUTH + NO_DUMPFILE + NO_INOTIFY + these are available to explicitly disable compile time options which would +- otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or +- which are enabled by default in the distributed source tree. Building dnsmasq ++ otherwise be enabled automatically or which are enabled by default ++ in the distributed source tree. Building dnsmasq + with something like "make COPTS=-DNO_SCRIPT" will do the trick. + NO_GMP + Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp. +@@ -308,29 +307,9 @@ HAVE_SOCKADDR_SA_LEN + + #endif + +-/* Decide if we're going to support IPv6 */ +-/* We assume that systems which don't have IPv6 +- headers don't have ntop and pton either */ +- +-#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) +-# define HAVE_IPV6 +-# define ADDRSTRLEN INET6_ADDRSTRLEN +-#else +-# if !defined(INET_ADDRSTRLEN) +-# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */ +-# endif +-# undef HAVE_IPV6 +-# define ADDRSTRLEN INET_ADDRSTRLEN +-#endif +- +- + /* rules to implement compile-time option dependencies and + the NO_XXX flags */ + +-#ifdef NO_IPV6 +-#undef HAVE_IPV6 +-#endif +- + #ifdef NO_TFTP + #undef HAVE_TFTP + #endif +@@ -340,7 +319,7 @@ HAVE_SOCKADDR_SA_LEN + #undef HAVE_DHCP6 + #endif + +-#if defined(NO_DHCP6) || !defined(HAVE_IPV6) ++#if defined(NO_DHCP6) + #undef HAVE_DHCP6 + #endif + +@@ -385,9 +364,6 @@ HAVE_SOCKADDR_SA_LEN + #ifdef DNSMASQ_COMPILE_OPTS + + static char *compile_opts = +-#ifndef HAVE_IPV6 +-"no-" +-#endif + "IPv6 " + #ifndef HAVE_GETOPT_LONG + "no-" +--- a/src/conntrack.c ++++ b/src/conntrack.c +@@ -36,7 +36,6 @@ int get_incoming_mark(union mysockaddr * + nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port)); + +-#ifdef HAVE_IPV6 + if (peer_addr->sa.sa_family == AF_INET6) + { + nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6); +@@ -45,7 +44,6 @@ int get_incoming_mark(union mysockaddr * + nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr.addr6.s6_addr); + } + else +-#endif + { + nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr); +--- a/src/dbus.c ++++ b/src/dbus.c +@@ -185,9 +185,6 @@ static void dbus_read_servers(DBusMessag + } + } + +-#ifndef HAVE_IPV6 +- my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support")); +-#else + if (i == sizeof(struct in6_addr)) + { + memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr)); +@@ -202,7 +199,6 @@ static void dbus_read_servers(DBusMessag + source_addr.in6.sin6_port = htons(daemon->query_port); + skip = 0; + } +-#endif + } + else + /* At the end */ +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -1730,11 +1730,11 @@ static void check_dns_listeners(time_t n + indextoname(listener->tcpfd, if_index, intr_name)) + { + struct all_addr addr; +- addr.addr.addr4 = tcp_addr.in.sin_addr; +-#ifdef HAVE_IPV6 ++ + if (tcp_addr.sa.sa_family == AF_INET6) + addr.addr.addr6 = tcp_addr.in6.sin6_addr; +-#endif ++ else ++ addr.addr.addr4 = tcp_addr.in.sin_addr; + + for (iface = daemon->interfaces; iface; iface = iface->next) + if (iface->index == if_index) +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -126,9 +126,7 @@ typedef unsigned long long u64; + #include + #include + #include +-#ifdef HAVE_IPV6 + #include +-#endif + #include + #include + #include +@@ -159,6 +157,8 @@ extern int capget(cap_user_header_t head + /* daemon is function in the C library.... */ + #define daemon dnsmasq_daemon + ++#define ADDRSTRLEN INET6_ADDRSTRLEN ++ + /* Async event queue */ + struct event_desc { + int event, data, msg_sz; +@@ -273,9 +273,7 @@ struct event_desc { + struct all_addr { + union { + struct in_addr addr4; +-#ifdef HAVE_IPV6 + struct in6_addr addr6; +-#endif + /* for log_query */ + struct { + unsigned short keytag, algo, digest; +@@ -383,9 +381,7 @@ struct host_record { + struct name_list *next; + } *names; + struct in_addr addr; +-#ifdef HAVE_IPV6 + struct in6_addr addr6; +-#endif + struct host_record *next; + }; + +@@ -496,9 +492,7 @@ struct crec { + union mysockaddr { + struct sockaddr sa; + struct sockaddr_in in; +-#if defined(HAVE_IPV6) + struct sockaddr_in6 in6; +-#endif + }; + + /* bits in flag param to IPv6 callbacks from iface_enumerate() */ +@@ -660,9 +654,7 @@ struct frec { + struct all_addr dest; + struct server *sentto; /* NULL means free */ + struct randfd *rfd4; +-#ifdef HAVE_IPV6 + struct randfd *rfd6; +-#endif + unsigned int iface; + unsigned short orig_id, new_id; + int log_id, fd, forwardall, flags; +@@ -877,9 +869,7 @@ struct dhcp_bridge { + struct cond_domain { + char *domain, *prefix; + struct in_addr start, end; +-#ifdef HAVE_IPV6 + struct in6_addr start6, end6; +-#endif + int is6, indexed; + struct cond_domain *next; + }; +@@ -1184,9 +1174,7 @@ void blockdata_free(struct blockdata *bl + + /* domain.c */ + char *get_domain(struct in_addr addr); +-#ifdef HAVE_IPV6 + char *get_domain6(struct in6_addr *addr); +-#endif + int is_name_synthetic(int flags, char *name, struct all_addr *addr); + int is_rev_synth(int flag, struct all_addr *addr, char *name); + +@@ -1270,11 +1258,9 @@ int hostname_issubdomain(char *a, char * + time_t dnsmasq_time(void); + int netmask_length(struct in_addr mask); + int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask); +-#ifdef HAVE_IPV6 + int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen); + u64 addr6part(struct in6_addr *addr); + void setaddr6part(struct in6_addr *addr, u64 host); +-#endif + int retry_send(ssize_t rc); + void prettyprint_time(char *buf, unsigned int t); + int prettyprint_addr(union mysockaddr *addr, char *buf); +@@ -1353,9 +1339,7 @@ int loopback_exception(int fd, int famil + int label_exception(int index, int family, struct all_addr *addr); + int fix_fd(int fd); + int tcp_interface(int fd, int af); +-#ifdef HAVE_IPV6 + int set_ipv6pktinfo(int fd); +-#endif + #ifdef HAVE_DHCP6 + void join_multicast(int dienow); + #endif +--- a/src/domain.c ++++ b/src/domain.c +@@ -18,21 +18,14 @@ + + + static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c); +-#ifdef HAVE_IPV6 + static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c); +-#endif + + + int is_name_synthetic(int flags, char *name, struct all_addr *addr) + { + char *p; + struct cond_domain *c = NULL; +- int prot = AF_INET; +- +-#ifdef HAVE_IPV6 +- if (flags & F_IPV6) +- prot = AF_INET6; +-#endif ++ int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET; + + for (c = daemon->synth_domains; c; c = c->next) + { +@@ -83,8 +76,7 @@ int is_name_synthetic(int flags, char *n + addr->addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index); + found = 1; + } +- } +-#ifdef HAVE_IPV6 ++ } + else + { + u64 index = atoll(tail); +@@ -98,7 +90,6 @@ int is_name_synthetic(int flags, char *n + found = 1; + } + } +-#endif + } + } + else +@@ -111,10 +102,8 @@ int is_name_synthetic(int flags, char *n + if ((c >='0' && c <= '9') || c == '-') + continue; + +-#ifdef HAVE_IPV6 + if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f'))) + continue; +-#endif + + break; + } +@@ -124,7 +113,6 @@ int is_name_synthetic(int flags, char *n + + *p = 0; + +-#ifdef HAVE_IPV6 + if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail) + { + /* special hack for v4-mapped. */ +@@ -134,7 +122,6 @@ int is_name_synthetic(int flags, char *n + *p = '.'; + } + else +-#endif + { + /* swap . or : for - */ + for (p = tail; *p; p++) +@@ -142,10 +129,8 @@ int is_name_synthetic(int flags, char *n + { + if (prot == AF_INET) + *p = '.'; +-#ifdef HAVE_IPV6 + else + *p = ':'; +-#endif + } + } + +@@ -158,7 +143,6 @@ int is_name_synthetic(int flags, char *n + ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr)) + found = 1; + } +-#ifdef HAVE_IPV6 + else + { + u64 addrpart = addr6part(&addr->addr.addr6); +@@ -169,7 +153,6 @@ int is_name_synthetic(int flags, char *n + addrpart <= addr6part(&c->end6)) + found = 1; + } +-#endif + } + + } +@@ -221,8 +204,7 @@ int is_rev_synth(int flag, struct all_ad + return 1; + } + +-#ifdef HAVE_IPV6 +- if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains))) ++ if ((flag & F_IPV6) && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains))) + { + char *p; + +@@ -259,7 +241,6 @@ int is_rev_synth(int flag, struct all_ad + + return 1; + } +-#endif + + return 0; + } +@@ -286,7 +267,7 @@ char *get_domain(struct in_addr addr) + return daemon->domain_suffix; + } + +-#ifdef HAVE_IPV6 ++ + static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c) + { + u64 addrpart = addr6part(addr); +@@ -310,4 +291,3 @@ char *get_domain6(struct in6_addr *addr) + + return daemon->domain_suffix; + } +-#endif +--- a/src/dump.c ++++ b/src/dump.c +@@ -82,10 +82,8 @@ void dump_init(void) + void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst) + { + struct ip ip; +-#ifdef HAVE_IPV6 + struct ip6_hdr ip6; + int family; +-#endif + struct udphdr { + u16 uh_sport; /* source port */ + u16 uh_dport; /* destination port */ +@@ -105,7 +103,6 @@ void dump_packet(int mask, void *packet, + /* So wireshark can Id the packet. */ + udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT); + +-#ifdef HAVE_IPV6 + if (src) + family = src->sa.sa_family; + else +@@ -139,7 +136,6 @@ void dump_packet(int mask, void *packet, + sum += ((u16 *)&ip6.ip6_src)[i]; + } + else +-#endif + { + iphdr = &ip; + ipsz = sizeof(ip); +--- a/src/edns0.c ++++ b/src/edns0.c +@@ -301,20 +301,14 @@ static size_t add_mac(struct dns_header + + struct subnet_opt { + u16 family; +- u8 source_netmask, scope_netmask; +-#ifdef HAVE_IPV6 ++ u8 source_netmask, scope_netmask; + u8 addr[IN6ADDRSZ]; +-#else +- u8 addr[INADDRSZ]; +-#endif + }; + + static void *get_addrp(union mysockaddr *addr, const short family) + { +-#ifdef HAVE_IPV6 + if (family == AF_INET6) + return &addr->in6.sin6_addr; +-#endif + + return &addr->in.sin_addr; + } +@@ -330,7 +324,6 @@ static size_t calc_subnet_opt(struct sub + opt->source_netmask = 0; + opt->scope_netmask = 0; + +-#ifdef HAVE_IPV6 + if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6) + { + opt->source_netmask = daemon->add_subnet6->mask; +@@ -342,7 +335,6 @@ static size_t calc_subnet_opt(struct sub + else + addrp = &source->in6.sin6_addr; + } +-#endif + + if (source->sa.sa_family == AF_INET && daemon->add_subnet4) + { +@@ -356,11 +348,7 @@ static size_t calc_subnet_opt(struct sub + addrp = &source->in.sin_addr; + } + +-#ifdef HAVE_IPV6 + opt->family = htons(sa_family == AF_INET6 ? 2 : 1); +-#else +- opt->family = htons(1); +-#endif + + len = 0; + +--- a/src/forward.c ++++ b/src/forward.c +@@ -38,9 +38,7 @@ int send_from(int fd, int nowild, char * + #elif defined(IP_SENDSRCADDR) + char control[CMSG_SPACE(sizeof(struct in_addr))]; + #endif +-#ifdef HAVE_IPV6 + char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +-#endif + } control_u; + + iov[0].iov_base = packet; +@@ -79,7 +77,6 @@ int send_from(int fd, int nowild, char * + #endif + } + else +-#ifdef HAVE_IPV6 + { + struct in6_pktinfo p; + p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */ +@@ -89,9 +86,6 @@ int send_from(int fd, int nowild, char * + cmptr->cmsg_type = daemon->v6pktinfo; + cmptr->cmsg_level = IPPROTO_IPV6; + } +-#else +- (void)iface; /* eliminate warning */ +-#endif + } + + while (retry_send(sendmsg(fd, &msg, 0))); +@@ -144,10 +138,8 @@ static unsigned int search_servers(time_ + flags = sflag; + if (serv->addr.sa.sa_family == AF_INET) + *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; +-#ifdef HAVE_IPV6 + else + *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; +-#endif + } + else if (!flags || (flags & F_NXDOMAIN)) + flags = F_NOERR; +@@ -204,10 +196,8 @@ static unsigned int search_servers(time_ + flags = sflag; + if (serv->addr.sa.sa_family == AF_INET) + *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; +-#ifdef HAVE_IPV6 + else + *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; +-#endif + } + else if (!flags || (flags & F_NXDOMAIN)) + flags = F_NOERR; +@@ -236,10 +226,8 @@ static unsigned int search_servers(time_ + /* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */ + if (flags & F_IPV4) + log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL); +-#ifdef HAVE_IPV6 + if (flags & F_IPV6) + log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL); +-#endif + } + } + else if ((*type) & SERV_USE_RESOLV) +@@ -302,20 +290,17 @@ static int forward_query(int udpfd, unio + + if (forward->sentto->addr.sa.sa_family == AF_INET) + log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); +-#ifdef HAVE_IPV6 + else + log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec"); +-#endif ++ + + if (forward->sentto->sfd) + fd = forward->sentto->sfd->fd; + else + { +-#ifdef HAVE_IPV6 + if (forward->sentto->addr.sa.sa_family == AF_INET6) + fd = forward->rfd6->fd; + else +-#endif + fd = forward->rfd4->fd; + } + +@@ -475,7 +460,6 @@ static int forward_query(int udpfd, unio + fd = start->sfd->fd; + else + { +-#ifdef HAVE_IPV6 + if (start->addr.sa.sa_family == AF_INET6) + { + if (!forward->rfd6 && +@@ -485,7 +469,6 @@ static int forward_query(int udpfd, unio + fd = forward->rfd6->fd; + } + else +-#endif + { + if (!forward->rfd4 && + !(forward->rfd4 = allocate_rfd(AF_INET))) +@@ -541,11 +524,9 @@ static int forward_query(int udpfd, unio + if (start->addr.sa.sa_family == AF_INET) + log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&start->addr.in.sin_addr, NULL); +-#ifdef HAVE_IPV6 + else + log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&start->addr.in6.sin6_addr, NULL); +-#endif + start->queries++; + forwarded = 1; + forward->sentto = start; +@@ -788,11 +769,8 @@ void reply_query(int fd, int family, tim + daemon->srv_save = NULL; + + /* Determine the address of the server replying so that we can mark that as good */ +- serveraddr.sa.sa_family = family; +-#ifdef HAVE_IPV6 +- if (serveraddr.sa.sa_family == AF_INET6) ++ if ((serveraddr.sa.sa_family = family) == AF_INET6) + serveraddr.in6.sin6_flowinfo = 0; +-#endif + + header = (struct dns_header *)daemon->packet; + +@@ -878,7 +856,6 @@ void reply_query(int fd, int family, tim + fd = start->sfd->fd; + else + { +-#ifdef HAVE_IPV6 + if (start->addr.sa.sa_family == AF_INET6) + { + /* may have changed family */ +@@ -887,7 +864,6 @@ void reply_query(int fd, int family, tim + fd = forward->rfd6->fd; + } + else +-#endif + { + /* may have changed family */ + if (!forward->rfd4) +@@ -902,10 +878,8 @@ void reply_query(int fd, int family, tim + + if (start->addr.sa.sa_family == AF_INET) + log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&start->addr.in.sin_addr, "dnssec"); +-#ifdef HAVE_IPV6 + else + log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&start->addr.in6.sin6_addr, "dnssec"); +-#endif + + return; + } +@@ -1099,9 +1073,7 @@ void reply_query(int fd, int family, tim + + new->sentto = server; + new->rfd4 = NULL; +-#ifdef HAVE_IPV6 + new->rfd6 = NULL; +-#endif + new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA); + new->forwardall = 0; + +@@ -1125,11 +1097,9 @@ void reply_query(int fd, int family, tim + if (server->addr.sa.sa_family == AF_INET) + log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (struct all_addr *)&(server->addr.in.sin_addr), + querystr("dnssec-query", querytype)); +-#ifdef HAVE_IPV6 + else + log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (struct all_addr *)&(server->addr.in6.sin6_addr), + querystr("dnssec-query", querytype)); +-#endif + + if ((hash = hash_questions(header, nn, daemon->namebuff))) + memcpy(new->hash, hash, HASH_SIZE); +@@ -1147,14 +1117,12 @@ void reply_query(int fd, int family, tim + else + { + fd = -1; +-#ifdef HAVE_IPV6 + if (server->addr.sa.sa_family == AF_INET6) + { + if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6))) + fd = new->rfd6->fd; + } + else +-#endif + { + if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET))) + fd = new->rfd4->fd; +@@ -1290,9 +1258,7 @@ void receive_query(struct listener *list + struct cmsghdr *cmptr; + union { + struct cmsghdr align; /* this ensures alignment */ +-#ifdef HAVE_IPV6 + char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +-#endif + #if defined(HAVE_LINUX_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; + #elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK) +@@ -1303,12 +1269,8 @@ void receive_query(struct listener *list + CMSG_SPACE(sizeof(struct sockaddr_dl))]; + #endif + } control_u; +-#ifdef HAVE_IPV6 + /* Can always get recvd interface for IPv6 */ + int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6; +-#else +- int check_dst = !option_bool(OPT_NOWILD); +-#endif + + /* packet buffer overwritten */ + daemon->srv_save = NULL; +@@ -1359,7 +1321,6 @@ void receive_query(struct listener *list + if (source_addr.in.sin_port == 0) + return; + } +-#ifdef HAVE_IPV6 + else + { + /* Source-port == 0 is an error, we can't send back to that. */ +@@ -1367,13 +1328,12 @@ void receive_query(struct listener *list + return; + source_addr.in6.sin6_flowinfo = 0; + } +-#endif + + /* We can be configured to only accept queries from at-most-one-hop-away addresses. */ + if (option_bool(OPT_LOCAL_SERVICE)) + { + struct addrlist *addr; +-#ifdef HAVE_IPV6 ++ + if (listen->family == AF_INET6) + { + for (addr = daemon->interface_addrs; addr; addr = addr->next) +@@ -1382,7 +1342,6 @@ void receive_query(struct listener *list + break; + } + else +-#endif + { + struct in_addr netmask; + for (addr = daemon->interface_addrs; addr; addr = addr->next) +@@ -1451,7 +1410,6 @@ void receive_query(struct listener *list + } + #endif + +-#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + { + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) +@@ -1467,7 +1425,6 @@ void receive_query(struct listener *list + if_index = p.p->ipi6_ifindex; + } + } +-#endif + + /* enforce available interface configuration */ + +@@ -1531,11 +1488,9 @@ void receive_query(struct listener *list + if (listen->family == AF_INET) + log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&source_addr.in.sin_addr, types); +-#ifdef HAVE_IPV6 + else + log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&source_addr.in6.sin6_addr, types); +-#endif + + #ifdef HAVE_AUTH + /* find queries for zones we're authoritative for, and answer them directly */ +@@ -1744,11 +1699,9 @@ static int tcp_key_recurse(time_t now, i + if (server->addr.sa.sa_family == AF_INET) + log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (struct all_addr *)&(server->addr.in.sin_addr), + querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS)); +-#ifdef HAVE_IPV6 + else + log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (struct all_addr *)&(server->addr.in6.sin6_addr), + querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS)); +-#endif + + server->flags |= SERV_GOT_TCP; + +@@ -1813,11 +1766,10 @@ unsigned char *tcp_request(int confd, ti + if (option_bool(OPT_CONNTRACK)) + { + struct all_addr local; +-#ifdef HAVE_IPV6 ++ + if (local_addr->sa.sa_family == AF_INET6) + local.addr.addr6 = local_addr->in6.sin6_addr; + else +-#endif + local.addr.addr4 = local_addr->in.sin_addr; + + have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark); +@@ -1828,7 +1780,7 @@ unsigned char *tcp_request(int confd, ti + if (option_bool(OPT_LOCAL_SERVICE)) + { + struct addrlist *addr; +-#ifdef HAVE_IPV6 ++ + if (peer_addr.sa.sa_family == AF_INET6) + { + for (addr = daemon->interface_addrs; addr; addr = addr->next) +@@ -1837,7 +1789,6 @@ unsigned char *tcp_request(int confd, ti + break; + } + else +-#endif + { + struct in_addr netmask; + for (addr = daemon->interface_addrs; addr; addr = addr->next) +@@ -1892,11 +1843,9 @@ unsigned char *tcp_request(int confd, ti + if (peer_addr.sa.sa_family == AF_INET) + log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&peer_addr.in.sin_addr, types); +-#ifdef HAVE_IPV6 + else + log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&peer_addr.in6.sin6_addr, types); +-#endif + + #ifdef HAVE_AUTH + /* find queries for zones we're authoritative for, and answer them directly */ +@@ -2072,11 +2021,9 @@ unsigned char *tcp_request(int confd, ti + if (last_server->addr.sa.sa_family == AF_INET) + log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&last_server->addr.in.sin_addr, NULL); +-#ifdef HAVE_IPV6 + else + log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL); +-#endif + + #ifdef HAVE_DNSSEC + if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC)) +@@ -2175,9 +2122,7 @@ static struct frec *allocate_frec(time_t + f->sentto = NULL; + f->rfd4 = NULL; + f->flags = 0; +-#ifdef HAVE_IPV6 + f->rfd6 = NULL; +-#endif + #ifdef HAVE_DNSSEC + f->dependent = NULL; + f->blocking_query = NULL; +@@ -2237,11 +2182,8 @@ static void free_frec(struct frec *f) + f->rfd4 = NULL; + f->sentto = NULL; + f->flags = 0; +- +-#ifdef HAVE_IPV6 + free_rfd(f->rfd6); + f->rfd6 = NULL; +-#endif + + #ifdef HAVE_DNSSEC + if (f->stash) +--- a/src/helper.c ++++ b/src/helper.c +@@ -64,9 +64,7 @@ struct script_data + #ifdef HAVE_TFTP + off_t file_len; + #endif +-#ifdef HAVE_IPV6 + struct in6_addr addr6; +-#endif + #ifdef HAVE_DHCP6 + int iaid, vendorclass_count; + #endif +@@ -302,10 +300,8 @@ int create_helper(int event_fd, int err_ + + if (!is6) + inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN); +-#ifdef HAVE_IPV6 + else + inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN); +-#endif + + #ifdef HAVE_TFTP + /* file length */ +@@ -826,10 +822,8 @@ void queue_tftp(off_t file_len, char *fi + + if ((buf->flags = peer->sa.sa_family) == AF_INET) + buf->addr = peer->in.sin_addr; +-#ifdef HAVE_IPV6 + else + buf->addr6 = peer->in6.sin6_addr; +-#endif + + memcpy((unsigned char *)(buf+1), filename, filename_len); + +@@ -851,10 +845,8 @@ void queue_arp(int action, unsigned char + buf->hwaddr_type = ARPHRD_ETHER; + if ((buf->flags = family) == AF_INET) + buf->addr = addr->addr.addr4; +-#ifdef HAVE_IPV6 + else + buf->addr6 = addr->addr.addr6; +-#endif + + memcpy(buf->hwaddr, mac, maclen); + +--- a/src/ipset.c ++++ b/src/ipset.c +@@ -120,13 +120,8 @@ static int new_add_to_ipset(const char * + struct my_nfgenmsg *nfg; + struct my_nlattr *nested[2]; + uint8_t proto; +- int addrsz = INADDRSZ; ++ int addrsz = (af == AF_INET6) ? INADDRSZ : IN6ADDRSZ; + +-#ifdef HAVE_IPV6 +- if (af == AF_INET6) +- addrsz = IN6ADDRSZ; +-#endif +- + if (strlen(setname) >= IPSET_MAXNAMELEN) + { + errno = ENAMETOOLONG; +@@ -213,7 +208,6 @@ int add_to_ipset(const char *setname, co + { + int ret = 0, af = AF_INET; + +-#ifdef HAVE_IPV6 + if (flags & F_IPV6) + { + af = AF_INET6; +@@ -224,7 +218,6 @@ int add_to_ipset(const char *setname, co + ret = -1; + } + } +-#endif + + if (ret != -1) + ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove); +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -51,11 +51,10 @@ void netlink_init(void) + addr.nl_groups = RTMGRP_IPV4_ROUTE; + if (option_bool(OPT_CLEVERBIND)) + addr.nl_groups |= RTMGRP_IPV4_IFADDR; +-#ifdef HAVE_IPV6 + addr.nl_groups |= RTMGRP_IPV6_ROUTE; + if (option_bool(OPT_CLEVERBIND)) + addr.nl_groups |= RTMGRP_IPV6_IFADDR; +-#endif ++ + #ifdef HAVE_DHCP6 + if (daemon->doing_ra || daemon->doing_dhcp6) + addr.nl_groups |= RTMGRP_IPV6_IFADDR; +@@ -235,7 +234,6 @@ int iface_enumerate(int family, void *pa + if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm))) + callback_ok = 0; + } +-#ifdef HAVE_IPV6 + else if (ifa->ifa_family == AF_INET6) + { + struct in6_addr *addrp = NULL; +@@ -270,7 +268,6 @@ int iface_enumerate(int family, void *pa + (int) preferred, (int)valid, parm))) + callback_ok = 0; + } +-#endif + } + } + else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC) +--- a/src/network.c ++++ b/src/network.c +@@ -137,12 +137,10 @@ int iface_check(int family, struct all_a + if (family == AF_INET && + tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) + ret = match_addr = tmp->used = 1; +-#ifdef HAVE_IPV6 + else if (family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, + &addr->addr.addr6)) + ret = match_addr = tmp->used = 1; +-#endif + } + } + +@@ -162,11 +160,9 @@ int iface_check(int family, struct all_a + else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET && + tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) + break; +-#ifdef HAVE_IPV6 + else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6)) + break; +-#endif + + if (tmp && auth) + { +@@ -200,11 +196,8 @@ int loopback_exception(int fd, int famil + if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) + return 1; + } +-#ifdef HAVE_IPV6 + else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6)) + return 1; +-#endif +- + } + } + return 0; +@@ -292,19 +285,15 @@ static int iface_allowed(struct iface_pa + al->addr.addr.addr4 = addr->in.sin_addr; + al->flags = 0; + } +-#ifdef HAVE_IPV6 + else + { + al->addr.addr.addr6 = addr->in6.sin6_addr; + al->flags = ADDRLIST_IPV6; + } +-#endif + } + } + +-#ifdef HAVE_IPV6 + if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr)) +-#endif + { + struct interface_name *int_name; + struct addrlist *al; +@@ -337,7 +326,6 @@ static int iface_allowed(struct iface_pa + } + } + +-#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6)) + { + if (param->spare) +@@ -357,8 +345,6 @@ static int iface_allowed(struct iface_pa + al->flags = ADDRLIST_IPV6; + } + } +-#endif +- + } + #endif + +@@ -386,7 +372,6 @@ static int iface_allowed(struct iface_pa + al->addr.addr.addr4 = addr->in.sin_addr; + al->flags = 0; + } +-#ifdef HAVE_IPV6 + else + { + al->addr.addr.addr6 = addr->in6.sin6_addr; +@@ -396,7 +381,6 @@ static int iface_allowed(struct iface_pa + if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE))) + al->flags |= ADDRLIST_REVONLY; + } +-#endif + } + } + } +@@ -438,11 +422,9 @@ static int iface_allowed(struct iface_pa + !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns)) + return 1; + +-#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6 && + !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns)) + return 1; +-#endif + + #ifdef HAVE_DHCP + /* No DHCP where we're doing auth DNS. */ +@@ -501,7 +483,6 @@ static int iface_allowed(struct iface_pa + return 0; + } + +-#ifdef HAVE_IPV6 + static int iface_allowed_v6(struct in6_addr *local, int prefix, + int scope, int if_index, int flags, + int preferred, int valid, void *vparam) +@@ -529,7 +510,6 @@ static int iface_allowed_v6(struct in6_a + + return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags); + } +-#endif + + static int iface_allowed_v4(struct in_addr local, int if_index, char *label, + struct in_addr netmask, struct in_addr broadcast, void *vparam) +@@ -633,9 +613,7 @@ int enumerate_interfaces(int reset) + + param.spare = spare; + +-#ifdef HAVE_IPV6 + ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6); +-#endif + + if (ret) + ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4); +@@ -740,10 +718,8 @@ static int make_sock(union mysockaddr *a + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd)) + goto err; + +-#ifdef HAVE_IPV6 + if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) + goto err; +-#endif + + if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1) + goto err; +@@ -767,15 +743,12 @@ static int make_sock(union mysockaddr *a + #endif + } + } +-#ifdef HAVE_IPV6 + else if (!set_ipv6pktinfo(fd)) + goto err; +-#endif + + return fd; + } + +-#ifdef HAVE_IPV6 + int set_ipv6pktinfo(int fd) + { + int opt = 1; +@@ -802,7 +775,6 @@ int set_ipv6pktinfo(int fd) + + return 0; + } +-#endif + + + /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */ +@@ -842,7 +814,6 @@ int tcp_interface(int fd, int af) + } + } + } +-#ifdef HAVE_IPV6 + else + { + /* Only the RFC-2292 API has the ability to find the interface for TCP connections, +@@ -874,7 +845,6 @@ int tcp_interface(int fd, int af) + } + } + } +-#endif /* IPV6 */ + #endif /* Linux */ + + return if_index; +@@ -904,7 +874,6 @@ static struct listener *create_listeners + tftpfd = make_sock(addr, SOCK_DGRAM, dienow); + addr->in.sin_port = save; + } +-# ifdef HAVE_IPV6 + else + { + short save = addr->in6.sin6_port; +@@ -912,7 +881,6 @@ static struct listener *create_listeners + tftpfd = make_sock(addr, SOCK_DGRAM, dienow); + addr->in6.sin6_port = save; + } +-# endif + } + #endif + +@@ -945,11 +913,10 @@ void create_wildcard_listeners(void) + + l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1); + +-#ifdef HAVE_IPV6 + memset(&addr, 0, sizeof(addr)); +-# ifdef HAVE_SOCKADDR_SA_LEN ++#ifdef HAVE_SOCKADDR_SA_LEN + addr.in6.sin6_len = sizeof(addr.in6); +-# endif ++#endif + addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_addr = in6addr_any; + addr.in6.sin6_port = htons(daemon->port); +@@ -959,7 +926,6 @@ void create_wildcard_listeners(void) + l->next = l6; + else + l = l6; +-#endif + + daemon->listeners = l; + } +@@ -1159,7 +1125,6 @@ int random_sock(int family) + addr.in.sin_len = sizeof(struct sockaddr_in); + #endif + } +-#ifdef HAVE_IPV6 + else + { + addr.in6.sin6_addr = in6addr_any; +@@ -1168,7 +1133,6 @@ int random_sock(int family) + addr.in6.sin6_len = sizeof(struct sockaddr_in6); + #endif + } +-#endif + + if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0) + return fd; +@@ -1193,10 +1157,8 @@ int local_bind(int fd, union mysockaddr + { + if (addr_copy.sa.sa_family == AF_INET) + addr_copy.in.sin_port = 0; +-#ifdef HAVE_IPV6 + else + addr_copy.in6.sin6_port = 0; +-#endif + } + + if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) +@@ -1211,7 +1173,7 @@ int local_bind(int fd, union mysockaddr + return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0; + } + #endif +-#if defined(HAVE_IPV6) && defined (IPV6_UNICAST_IF) ++#if defined (IPV6_UNICAST_IF) + if (addr_copy.sa.sa_family == AF_INET6) + { + uint32_t ifindex_opt = htonl(ifindex); +@@ -1247,12 +1209,10 @@ static struct serverfd *allocate_sfd(uni + addr->in.sin_port == htons(0)) + return NULL; + +-#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6 && + memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 && + addr->in6.sin6_port == htons(0)) + return NULL; +-#endif + } + + if (intname && strlen(intname) != 0) +@@ -1315,7 +1275,7 @@ void pre_allocate_sfds(void) + #endif + if ((sfd = allocate_sfd(&addr, ""))) + sfd->preallocated = 1; +-#ifdef HAVE_IPV6 ++ + memset(&addr, 0, sizeof(addr)); + addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_addr = in6addr_any; +@@ -1325,7 +1285,6 @@ void pre_allocate_sfds(void) + #endif + if ((sfd = allocate_sfd(&addr, ""))) + sfd->preallocated = 1; +-#endif + } + + for (srv = daemon->servers; srv; srv = srv->next) +@@ -1658,7 +1617,6 @@ int reload_servers(char *fname) + source_addr.in.sin_addr.s_addr = INADDR_ANY; + source_addr.in.sin_port = htons(daemon->query_port); + } +-#ifdef HAVE_IPV6 + else + { + int scope_index = 0; +@@ -1686,10 +1644,6 @@ int reload_servers(char *fname) + else + continue; + } +-#else /* IPV6 */ +- else +- continue; +-#endif + + add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL); + gotone = 1; +--- a/src/option.c ++++ b/src/option.c +@@ -764,10 +764,8 @@ static char *parse_mysockaddr(char *arg, + { + if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0) + addr->sa.sa_family = AF_INET; +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) + addr->sa.sa_family = AF_INET6; +-#endif + else + return _("bad address"); + +@@ -779,10 +777,8 @@ char *parse_server(char *arg, union myso + 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; +-#endif + + if (!arg || strlen(arg) == 0) + { +@@ -800,9 +796,7 @@ char *parse_server(char *arg, union myso + !atoi_check16(portno, &serv_port)) + return _("bad port"); + +-#ifdef HAVE_IPV6 + scope_id = split_chr(arg, '%'); +-#endif + + if (source) { + interface_opt = split_chr(source, '@'); +@@ -846,7 +840,6 @@ char *parse_server(char *arg, union myso + } + } + } +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) + { + if (scope_id && (scope_index = if_nametoindex(scope_id)) == 0) +@@ -881,7 +874,6 @@ char *parse_server(char *arg, union myso + } + } + } +-#endif + else + return _("bad address"); + +@@ -1914,10 +1906,8 @@ static int one_opt(int option, char *arg + unhide_metas(arg); + if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0) + new->addr.sa.sa_family = AF_INET; +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) + new->addr.sa.sa_family = AF_INET6; +-#endif + else + { + char *fam = split_chr(arg, '/'); +@@ -1927,10 +1917,8 @@ static int one_opt(int option, char *arg + { + if (strcmp(fam, "4") == 0) + new->addr.sa.sa_family = AF_INET; +-#ifdef HAVE_IPV6 + else if (strcmp(fam, "6") == 0) + new->addr.sa.sa_family = AF_INET6; +-#endif + else + ret_err(gen_err); + } +@@ -1996,14 +1984,12 @@ static int one_opt(int option, char *arg + subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen; + subnet->flags = ADDRLIST_LITERAL; + } +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &addr.addr.addr6)) + { + subnet = opt_malloc(sizeof(struct addrlist)); + subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen; + subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6; + } +-#endif + else + { + struct auth_name_list *name = opt_malloc(sizeof(struct auth_name_list)); +@@ -2015,10 +2001,8 @@ static int one_opt(int option, char *arg + { + if (prefixlen == 4) + name->flags &= ~AUTH6; +-#ifdef HAVE_IPV6 + else if (prefixlen == 6) + name->flags &= ~AUTH4; +-#endif + else + ret_err(gen_err); + } +@@ -2139,7 +2123,6 @@ static int one_opt(int option, char *arg + } + } + } +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, comma, &new->start6)) + { + u64 mask = (1LLU << (128 - msize)) - 1LLU; +@@ -2183,7 +2166,6 @@ static int one_opt(int option, char *arg + } + } + } +-#endif + else + ret_err(gen_err); + } +@@ -2201,7 +2183,6 @@ static int one_opt(int option, char *arg + else if (!inet_pton(AF_INET, arg, &new->end)) + ret_err(gen_err); + } +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, comma, &new->start6)) + { + new->is6 = 1; +@@ -2210,7 +2191,6 @@ static int one_opt(int option, char *arg + else if (!inet_pton(AF_INET6, arg, &new->end6)) + ret_err(gen_err); + } +-#endif + else + ret_err(gen_err); + +@@ -2369,7 +2349,6 @@ static int one_opt(int option, char *arg + new->addr.in.sin_len = sizeof(new->addr.in); + #endif + } +-#ifdef HAVE_IPV6 + else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) + { + new->addr.sa.sa_family = AF_INET6; +@@ -2380,7 +2359,6 @@ static int one_opt(int option, char *arg + new->addr.in6.sin6_len = sizeof(new->addr.in6); + #endif + } +-#endif + else + ret_err(gen_err); + +@@ -2493,9 +2471,7 @@ static int one_opt(int option, char *arg + int size; + struct server *serv; + struct in_addr addr4; +-#ifdef HAVE_IPV6 + struct in6_addr addr6; +-#endif + + unhide_metas(arg); + if (!arg || !(comma=split(arg)) || !(string = split_chr(arg, '/')) || !atoi_check(string, &size)) +@@ -2507,10 +2483,8 @@ static int one_opt(int option, char *arg + if (!serv) + ret_err(_("bad prefix")); + } +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &addr6)) + serv = add_rev6(&addr6, size); +-#endif + else + ret_err(gen_err); + +@@ -3863,10 +3837,8 @@ err: + { + if (strcmp(arg, "4") == 0) + new->family = AF_INET; +-#ifdef HAVE_IPV6 + else if (strcmp(arg, "6") == 0) + new->family = AF_INET6; +-#endif + else + ret_err(gen_err); + } +@@ -4156,10 +4128,8 @@ err: + new->ttl = atoi(arg); + else if (inet_pton(AF_INET, arg, &addr)) + new->addr = addr.addr.addr4; +-#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &addr)) + new->addr6 = addr.addr.addr6; +-#endif + else + { + int nomem; +@@ -4866,10 +4836,8 @@ void read_opts(int argc, char **argv, ch + { + if (tmp->source_addr.sa.sa_family == AF_INET) + tmp->source_addr.in.sin_port = htons(daemon->query_port); +-#ifdef HAVE_IPV6 + else if (tmp->source_addr.sa.sa_family == AF_INET6) + tmp->source_addr.in6.sin6_port = htons(daemon->query_port); +-#endif + } + } + +@@ -4930,10 +4898,8 @@ void read_opts(int argc, char **argv, ch + for(tmp = daemon->if_addrs; tmp; tmp = tmp->next) + if (tmp->addr.sa.sa_family == AF_INET) + tmp->addr.in.sin_port = htons(daemon->port); +-#ifdef HAVE_IPV6 + else if (tmp->addr.sa.sa_family == AF_INET6) + tmp->addr.in6.sin6_port = htons(daemon->port); +-#endif /* IPv6 */ + } + + /* create default, if not specified */ +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -198,7 +198,6 @@ int in_arpa_name_2_addr(char *namein, st + + return F_IPV4; + } +-#ifdef HAVE_IPV6 + else if (hostname_isequal(penchunk, "ip6") && + (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa"))) + { +@@ -243,7 +242,6 @@ int in_arpa_name_2_addr(char *namein, st + return F_IPV6; + } + } +-#endif + + return 0; + } +@@ -426,7 +424,6 @@ int private_net(struct in_addr addr, int + ((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ; + } + +-#ifdef HAVE_IPV6 + static int private_net6(struct in6_addr *a) + { + return +@@ -436,8 +433,6 @@ static int private_net6(struct in6_addr + ((unsigned char *)a)[0] == 0xfd || /* RFC 6303 4.4 */ + ((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */ + } +-#endif +- + + static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored) + { +@@ -738,13 +733,11 @@ int extract_addresses(struct dns_header + addrlen = INADDRSZ; + flags |= F_IPV4; + } +-#ifdef HAVE_IPV6 + else if (qtype == T_AAAA) + { + addrlen = IN6ADDRSZ; + flags |= F_IPV6; + } +-#endif + else + continue; + +@@ -818,7 +811,6 @@ int extract_addresses(struct dns_header + private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND))) + return 1; + +-#ifdef HAVE_IPV6 + if ((flags & F_IPV6) && + IN6_IS_ADDR_V4MAPPED(&addr.addr.addr6)) + { +@@ -827,7 +819,6 @@ int extract_addresses(struct dns_header + if (private_net(v4, !option_bool(OPT_LOCAL_REBIND))) + return 1; + } +-#endif + } + + #ifdef HAVE_IPSET +@@ -966,7 +957,6 @@ size_t setup_reply(struct dns_header *he + add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp); + } + +-#ifdef HAVE_IPV6 + if (flags & F_IPV6) + { + SET_RCODE(header, NOERROR); +@@ -974,7 +964,6 @@ size_t setup_reply(struct dns_header *he + header->hb3 |= HB3_AA; + add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp); + } +-#endif + } + else /* nowhere to forward to */ + { +@@ -1164,14 +1153,12 @@ int add_resource_record(struct dns_heade + for (; *format; format++) + switch (*format) + { +-#ifdef HAVE_IPV6 + case '6': + CHECK_LIMIT(IN6ADDRSZ); + sval = va_arg(ap, char *); + memcpy(p, sval, IN6ADDRSZ); + p += IN6ADDRSZ; + break; +-#endif + + case '4': + CHECK_LIMIT(INADDRSZ); +@@ -1413,7 +1400,6 @@ size_t answer_request(struct dns_header + while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) + intr = intr->next; + } +-#ifdef HAVE_IPV6 + else if (is_arpa == F_IPV6) + for (intr = daemon->int_names; intr; intr = intr->next) + { +@@ -1429,7 +1415,6 @@ size_t answer_request(struct dns_header + while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) + intr = intr->next; + } +-#endif + + if (intr) + { +@@ -1521,9 +1506,7 @@ size_t answer_request(struct dns_header + } + } + else if (option_bool(OPT_BOGUSPRIV) && ( +-#ifdef HAVE_IPV6 + (is_arpa == F_IPV6 && private_net6(&addr.addr.addr6)) || +-#endif + (is_arpa == F_IPV4 && private_net(addr.addr.addr4, 1)))) + { + struct server *serv; +@@ -1564,16 +1547,9 @@ size_t answer_request(struct dns_header + + for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) + { +- unsigned short type = T_A; ++ unsigned short type = (flag == F_IPV6) ? T_AAAA : T_A; + struct interface_name *intr; + +- if (flag == F_IPV6) +-#ifdef HAVE_IPV6 +- type = T_AAAA; +-#else +- break; +-#endif +- + if (qtype != type && qtype != T_ANY) + continue; + +@@ -1596,31 +1572,26 @@ size_t answer_request(struct dns_header + for (intr = daemon->int_names; intr; intr = intr->next) + if (hostname_isequal(name, intr->name)) + for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) +-#ifdef HAVE_IPV6 +- if (!(addrlist->flags & ADDRLIST_IPV6)) +-#endif +- if (is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask)) +- { +- localise = 1; +- break; +- } ++ if (!(addrlist->flags & ADDRLIST_IPV6) && ++ is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask)) ++ { ++ localise = 1; ++ break; ++ } + + for (intr = daemon->int_names; intr; intr = intr->next) + if (hostname_isequal(name, intr->name)) + { + for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) +-#ifdef HAVE_IPV6 + if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type) +-#endif + { + if (localise && + !is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask)) + continue; + +-#ifdef HAVE_IPV6 + if (addrlist->flags & ADDRLIST_REVONLY) + continue; +-#endif ++ + ans = 1; + sec_data = 0; + if (!dryrun) +@@ -1904,11 +1875,8 @@ size_t answer_request(struct dns_header + crecp = NULL; + while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6))) + { +-#ifdef HAVE_IPV6 + int type = crecp->flags & F_IPV4 ? T_A : T_AAAA; +-#else +- int type = T_A; +-#endif ++ + if (crecp->flags & F_NEG) + continue; + +--- a/src/tables.c ++++ b/src/tables.c +@@ -108,7 +108,7 @@ int add_to_ipset(const char *setname, co + my_syslog(LOG_INFO, _("info: table created")); + + bzero(&addr, sizeof(addr)); +-#ifdef HAVE_IPV6 ++ + if (flags & F_IPV6) + { + addr.pfra_af = AF_INET6; +@@ -116,7 +116,6 @@ int add_to_ipset(const char *setname, co + memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr)); + } + else +-#endif + { + addr.pfra_af = AF_INET; + addr.pfra_net = 0x20; +--- a/src/tftp.c ++++ b/src/tftp.c +@@ -60,17 +60,11 @@ void tftp_request(struct listener *liste + char *prefix = daemon->tftp_prefix; + struct tftp_prefix *pref; + struct all_addr addra; +-#ifdef HAVE_IPV6 + /* Can always get recvd interface for IPv6 */ + int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6; +-#else +- int check_dest = !option_bool(OPT_NOWILD); +-#endif + union { + struct cmsghdr align; /* this ensures alignment */ +-#ifdef HAVE_IPV6 + char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +-#endif + #if defined(HAVE_LINUX_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; + #elif defined(HAVE_SOLARIS_NETWORK) +@@ -174,7 +168,6 @@ void tftp_request(struct listener *liste + + #endif + +-#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + { + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) +@@ -190,7 +183,6 @@ void tftp_request(struct listener *liste + if_index = p.p->ipi6_ifindex; + } + } +-#endif + + if (!indextoname(listen->tftpfd, if_index, namebuff)) + return; +@@ -199,10 +191,8 @@ void tftp_request(struct listener *liste + + addra.addr.addr4 = addr.in.sin_addr; + +-#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + addra.addr.addr6 = addr.in6.sin6_addr; +-#endif + + if (daemon->tftp_interfaces) + { +@@ -262,7 +252,6 @@ void tftp_request(struct listener *liste + addr.in.sin_len = sizeof(addr.in); + #endif + } +-#ifdef HAVE_IPV6 + else + { + addr.in6.sin6_port = htons(port); +@@ -272,7 +261,6 @@ void tftp_request(struct listener *liste + addr.in6.sin6_len = sizeof(addr.in6); + #endif + } +-#endif + + if (!(transfer = whine_malloc(sizeof(struct tftp_transfer)))) + return; +@@ -310,10 +298,9 @@ void tftp_request(struct listener *liste + { + if (listen->family == AF_INET) + addr.in.sin_port = htons(port); +-#ifdef HAVE_IPV6 + else +- addr.in6.sin6_port = htons(port); +-#endif ++ addr.in6.sin6_port = htons(port); ++ + continue; + } + my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP")); +--- a/src/util.c ++++ b/src/util.c +@@ -320,13 +320,12 @@ int sockaddr_isequal(union mysockaddr *s + s1->in.sin_port == s2->in.sin_port && + s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr) + return 1; +-#ifdef HAVE_IPV6 ++ + if (s1->sa.sa_family == AF_INET6 && + s1->in6.sin6_port == s2->in6.sin6_port && + s1->in6.sin6_scope_id == s2->in6.sin6_scope_id && + IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr)) + return 1; +-#endif + } + return 0; + } +@@ -336,11 +335,9 @@ int sa_len(union mysockaddr *addr) + #ifdef HAVE_SOCKADDR_SA_LEN + return addr->sa.sa_len; + #else +-#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6) + return sizeof(addr->in6); + else +-#endif + return sizeof(addr->in); + #endif + } +@@ -437,7 +434,6 @@ int is_same_net(struct in_addr a, struct + return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); + } + +-#ifdef HAVE_IPV6 + int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen) + { + int pfbytes = prefixlen >> 3; +@@ -476,15 +472,12 @@ void setaddr6part(struct in6_addr *addr, + } + } + +-#endif +- + + /* returns port number from address */ + int prettyprint_addr(union mysockaddr *addr, char *buf) + { + int port = 0; + +-#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET) + { + inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN); +@@ -503,10 +496,6 @@ int prettyprint_addr(union mysockaddr *a + } + port = ntohs(addr->in6.sin6_port); + } +-#else +- strcpy(buf, inet_ntoa(addr->in.sin_addr)); +- port = ntohs(addr->in.sin_port); +-#endif + + return port; + } diff --git a/package/network/services/dnsmasq/patches/0004-Don-t-forward-.bind-.server-queries-upstream.patch b/package/network/services/dnsmasq/patches/0004-Don-t-forward-.bind-.server-queries-upstream.patch new file mode 100644 index 0000000000..497b4c3df2 --- /dev/null +++ b/package/network/services/dnsmasq/patches/0004-Don-t-forward-.bind-.server-queries-upstream.patch @@ -0,0 +1,52 @@ +From cf5984367bc6a949e3803a576512c5a7bc48ebab Mon Sep 17 00:00:00 2001 +From: Vladislav Grishenko +Date: Thu, 18 Oct 2018 04:55:21 +0500 +Subject: [PATCH 04/11] Don't forward *.bind/*.server queries upstream + +Chaos .bind and .server (RFC4892) zones are local, therefore +don't forward queries upstream to avoid mixing with supported +locally and false replies with NO_ID enabled. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/rfc1035.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1276,7 +1276,7 @@ size_t answer_request(struct dns_header + int q, ans, anscount = 0, addncount = 0; + int dryrun = 0; + struct crec *crecp; +- int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1; ++ int nxdomain = 0, notimp = 0, auth = 1, trunc = 0, sec_data = 1; + struct mx_srv_record *rec; + size_t len; + +@@ -1355,6 +1355,17 @@ size_t answer_request(struct dns_header + } + } + ++ if (qclass == C_CHAOS) ++ { ++ /* don't forward *.bind and *.server chaos queries */ ++ if (hostname_issubdomain("bind", name) || hostname_issubdomain("server", name)) ++ { ++ if (!ans) ++ notimp = 1, auth = 0; ++ ans = 1; ++ } ++ } ++ + if (qclass == C_IN) + { + struct txt_record *t; +@@ -1903,6 +1914,8 @@ size_t answer_request(struct dns_header + + if (nxdomain) + SET_RCODE(header, NXDOMAIN); ++ else if (notimp) ++ SET_RCODE(header, NOTIMP); + else + SET_RCODE(header, NOERROR); /* no error */ + header->ancount = htons(anscount); diff --git a/package/network/services/dnsmasq/patches/0005-Fix-logging-in-cf5984367bc6a949e3803a576512c5a7bc48e.patch b/package/network/services/dnsmasq/patches/0005-Fix-logging-in-cf5984367bc6a949e3803a576512c5a7bc48e.patch new file mode 100644 index 0000000000..b9be306118 --- /dev/null +++ b/package/network/services/dnsmasq/patches/0005-Fix-logging-in-cf5984367bc6a949e3803a576512c5a7bc48e.patch @@ -0,0 +1,63 @@ +From cbb5b17ad8e03e08ade62376a4f6a2066e55960d Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Tue, 23 Oct 2018 23:45:57 +0100 +Subject: [PATCH 05/11] Fix logging in cf5984367bc6a949e3803a576512c5a7bc48ebab + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/rfc1035.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1335,7 +1335,6 @@ size_t answer_request(struct dns_header + { + unsigned long ttl = daemon->local_ttl; + int ok = 1; +- log_query(F_CONFIG | F_RRNAME, name, NULL, ""); + #ifndef NO_ID + /* Dynamically generate stat record */ + if (t->stat != 0) +@@ -1345,11 +1344,14 @@ size_t answer_request(struct dns_header + ok = 0; + } + #endif +- if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp, +- ttl, NULL, +- T_TXT, t->class, "t", t->len, t->txt)) +- anscount++; +- ++ if (ok) ++ { ++ log_query(F_CONFIG | F_RRNAME, name, NULL, ""); ++ if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ++ ttl, NULL, ++ T_TXT, t->class, "t", t->len, t->txt)) ++ anscount++; ++ } + } + } + } +@@ -1357,12 +1359,19 @@ size_t answer_request(struct dns_header + + if (qclass == C_CHAOS) + { +- /* don't forward *.bind and *.server chaos queries */ ++ /* don't forward *.bind and *.server chaos queries - always reply with NOTIMP */ + if (hostname_issubdomain("bind", name) || hostname_issubdomain("server", name)) + { + if (!ans) +- notimp = 1, auth = 0; +- ans = 1; ++ { ++ notimp = 1, auth = 0; ++ if (!dryrun) ++ { ++ addr.addr.rcode.rcode = NOTIMP; ++ log_query(F_CONFIG | F_RCODE, name, &addr, NULL); ++ } ++ ans = 1; ++ } + } + } + diff --git a/package/network/services/dnsmasq/patches/0006-Fix-spurious-AD-flags-in-some-DNS-replies-from-local.patch b/package/network/services/dnsmasq/patches/0006-Fix-spurious-AD-flags-in-some-DNS-replies-from-local.patch new file mode 100644 index 0000000000..3271a5f3af --- /dev/null +++ b/package/network/services/dnsmasq/patches/0006-Fix-spurious-AD-flags-in-some-DNS-replies-from-local.patch @@ -0,0 +1,120 @@ +From 6f7812d97bc8f87004c0a5069c6c94c64af78106 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Tue, 23 Oct 2018 23:54:44 +0100 +Subject: [PATCH 06/11] Fix spurious AD flags in some DNS replies from local + config. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/rfc1035.c | 42 ++++++++++++++++++++++++------------------ + 1 file changed, 24 insertions(+), 18 deletions(-) + +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1330,7 +1330,7 @@ size_t answer_request(struct dns_header + { + if (t->class == qclass && hostname_isequal(name, t->name)) + { +- ans = 1; ++ ans = 1, sec_data = 0; + if (!dryrun) + { + unsigned long ttl = daemon->local_ttl; +@@ -1370,7 +1370,7 @@ size_t answer_request(struct dns_header + addr.addr.rcode.rcode = NOTIMP; + log_query(F_CONFIG | F_RCODE, name, &addr, NULL); + } +- ans = 1; ++ ans = 1, sec_data = 0; + } + } + } +@@ -1725,7 +1725,7 @@ size_t answer_request(struct dns_header + } + else if (is_name_synthetic(flag, name, &addr)) + { +- ans = 1; ++ ans = 1, sec_data = 0; + if (!dryrun) + { + log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL); +@@ -1763,25 +1763,27 @@ size_t answer_request(struct dns_header + for (rec = daemon->mxnames; rec; rec = rec->next) + if (!rec->issrv && hostname_isequal(name, rec->name)) + { +- ans = found = 1; +- if (!dryrun) +- { +- int offset; +- log_query(F_CONFIG | F_RRNAME, name, NULL, ""); +- if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, +- &offset, T_MX, C_IN, "sd", rec->weight, rec->target)) +- { +- anscount++; +- if (rec->target) +- rec->offset = offset; +- } +- } ++ ans = found = 1; ++ sec_data = 0; ++ if (!dryrun) ++ { ++ int offset; ++ log_query(F_CONFIG | F_RRNAME, name, NULL, ""); ++ if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, ++ &offset, T_MX, C_IN, "sd", rec->weight, rec->target)) ++ { ++ anscount++; ++ if (rec->target) ++ rec->offset = offset; ++ } ++ } + } + + if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && + cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR)) + { + ans = 1; ++ sec_data = 0; + if (!dryrun) + { + log_query(F_CONFIG | F_RRNAME, name, NULL, ""); +@@ -1802,6 +1804,7 @@ size_t answer_request(struct dns_header + if (rec->issrv && hostname_isequal(name, rec->name)) + { + found = ans = 1; ++ sec_data = 0; + if (!dryrun) + { + int offset; +@@ -1838,6 +1841,7 @@ size_t answer_request(struct dns_header + if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_')))) + { + ans = 1; ++ sec_data = 0; + if (!dryrun) + log_query(F_CONFIG | F_NEG, name, NULL, NULL); + } +@@ -1850,6 +1854,7 @@ size_t answer_request(struct dns_header + if (hostname_isequal(name, na->name)) + { + ans = 1; ++ sec_data = 0; + if (!dryrun) + { + log_query(F_CONFIG | F_RRNAME, name, NULL, ""); +@@ -1862,11 +1867,12 @@ size_t answer_request(struct dns_header + } + + if (qtype == T_MAILB) +- ans = 1, nxdomain = 1; ++ ans = 1, nxdomain = 1, sec_data = 0; + + if (qtype == T_SOA && option_bool(OPT_FILTER)) + { +- ans = 1; ++ ans = 1; ++ sec_data = 0; + if (!dryrun) + log_query(F_CONFIG | F_NEG, name, &addr, NULL); + } diff --git a/package/network/services/dnsmasq/patches/0007-Do-not-rely-on-dead-code-elimination-use-array-inste.patch b/package/network/services/dnsmasq/patches/0007-Do-not-rely-on-dead-code-elimination-use-array-inste.patch new file mode 100644 index 0000000000..55ea917c39 --- /dev/null +++ b/package/network/services/dnsmasq/patches/0007-Do-not-rely-on-dead-code-elimination-use-array-inste.patch @@ -0,0 +1,71 @@ +From 24b87607c1353e94689e8a2190571ab3f3b36f31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 24 Oct 2018 22:30:18 +0100 +Subject: [PATCH 07/11] Do not rely on dead code elimination, use array + instead. Make options bits derived from size and count. Use size of option + bits and last supported bit in computation. No new change would be required + when new options are added. Just change OPT_LAST constant. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/dnsmasq.h | 11 +++++++---- + src/option.c | 10 ++-------- + 2 files changed, 9 insertions(+), 12 deletions(-) + +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -200,9 +200,6 @@ struct event_desc { + #define EC_MISC 5 + #define EC_INIT_OFFSET 10 + +-/* Trust the compiler dead-code eliminator.... */ +-#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32))) +- + #define OPT_BOGUSPRIV 0 + #define OPT_FILTER 1 + #define OPT_LOG 2 +@@ -264,6 +261,12 @@ struct event_desc { + #define OPT_UBUS 58 + #define OPT_LAST 59 + ++#define OPTION_BITS (sizeof(unsigned int)*8) ++#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) ++#define option_var(x) (daemon->options[(x) / OPTION_BITS]) ++#define option_val(x) ((1u) << ((x) % OPTION_BITS)) ++#define option_bool(x) (option_var(x) & option_val(x)) ++ + /* extra flags for my_syslog, we use a couple of facilities since they are known + not to occupy the same bits as priorities, no matter how syslog.h is set up. */ + #define MS_TFTP LOG_USER +@@ -978,7 +981,7 @@ extern struct daemon { + config file arguments. All set (including defaults) + in option.c */ + +- unsigned int options, options2; ++ unsigned int options[OPTION_SIZE]; + struct resolvc default_resolv, *resolv_files; + time_t last_resolv; + char *servers_file; +--- a/src/option.c ++++ b/src/option.c +@@ -1490,18 +1490,12 @@ static int parse_dhcp_opt(char *errstr, + + void set_option_bool(unsigned int opt) + { +- if (opt < 32) +- daemon->options |= 1u << opt; +- else +- daemon->options2 |= 1u << (opt - 32); ++ option_var(opt) |= option_val(opt); + } + + void reset_option_bool(unsigned int opt) + { +- if (opt < 32) +- daemon->options &= ~(1u << opt); +- else +- daemon->options2 &= ~(1u << (opt - 32)); ++ option_var(opt) &= ~(option_val(opt)); + } + + static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only) diff --git a/package/network/services/dnsmasq/patches/0008-Fix-Makefile-lines-generating-UBUS-linker-config.patch b/package/network/services/dnsmasq/patches/0008-Fix-Makefile-lines-generating-UBUS-linker-config.patch new file mode 100644 index 0000000000..91b465fd1c --- /dev/null +++ b/package/network/services/dnsmasq/patches/0008-Fix-Makefile-lines-generating-UBUS-linker-config.patch @@ -0,0 +1,63 @@ +From 3a5a84cdd1488bad118eeac72d09a60299bca744 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Wed, 31 Oct 2018 21:30:13 +0000 +Subject: [PATCH 08/11] Fix Makefile lines generating UBUS linker config. + +If arg2 of pkg-wrapper is "--copy", then arg1 is NOT the name of +the package manager (--copy doesn't invoke it) it's a secondary +config string that inhibts the copy if found. This patch allows that +to be the empty string, for unconditional copy, and modifies the +ubus linker config to use it. It worked by coincidence before, because +there was no config string called "pkg-config". + +Signed-off-by: Kevin Darbyshire-Bryant +--- + Makefile | 2 +- + bld/pkg-wrapper | 14 ++++++++------ + 2 files changed, 9 insertions(+), 7 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -53,7 +53,7 @@ top?=$(CURDIR) + + dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1` + dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1` +-ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS $(PKG_CONFIG) --copy -lubox -lubus` ++ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS "" --copy -lubox -lubus` + idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn` + idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn` + idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2` +--- a/bld/pkg-wrapper ++++ b/bld/pkg-wrapper +@@ -11,23 +11,25 @@ in=`cat` + + if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \ + echo $in | grep $search >/dev/null 2>&1; then +-# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP ++# Nasty, nasty, in --copy, arg 2 (if non-empty) is another config to search for, used with NO_GMP + if [ $op = "--copy" ]; then +- if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \ +- echo $in | grep $pkg >/dev/null 2>&1; then ++ if [ -z "$pkg" ]; then ++ pkg="$*" ++ elif grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \ ++ echo $in | grep $pkg >/dev/null 2>&1; then + pkg="" + else + pkg="$*" + fi + elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \ +- echo $in | grep ${search}_STATIC >/dev/null 2>&1; then ++ echo $in | grep ${search}_STATIC >/dev/null 2>&1; then + pkg=`$pkg --static $op $*` + else + pkg=`$pkg $op $*` + fi +- ++ + if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \ +- echo $in | grep ${search}_STATIC >/dev/null 2>&1; then ++ echo $in | grep ${search}_STATIC >/dev/null 2>&1; then + if [ $op = "--libs" ] || [ $op = "--copy" ]; then + echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic" + else diff --git a/package/network/services/dnsmasq/patches/0009-Revert-68f6312d4bae30b78daafcd6f51dc441b8685b1e.patch b/package/network/services/dnsmasq/patches/0009-Revert-68f6312d4bae30b78daafcd6f51dc441b8685b1e.patch new file mode 100644 index 0000000000..ff9ddd842c --- /dev/null +++ b/package/network/services/dnsmasq/patches/0009-Revert-68f6312d4bae30b78daafcd6f51dc441b8685b1e.patch @@ -0,0 +1,41 @@ +From 122392e0b352507cabb9e982208d35d2e56902e0 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Wed, 31 Oct 2018 22:24:02 +0000 +Subject: [PATCH 09/11] Revert 68f6312d4bae30b78daafcd6f51dc441b8685b1e + +The above is intended to increase robustness, but actually does the +opposite. The problem is that by ignoring SERVFAIL messages and hoping +for a better answer from another of the servers we've forwarded to, +we become vulnerable in the case that one or more of the configured +servers is down or not responding. + +Consider the case that a domain is indeed BOGUS, and we've send the +query to n servers. With 68f6312d4bae30b78daafcd6f51dc441b8685b1e +we ignore the first n-1 SERVFAIL replies, and only return the +final n'th answer to the client. Now, if one of the servers we are +forwarding to is down, then we won't get all n replies, and the +client will never get an answer! This is a far more likely scenario +than a temporary SERVFAIL from only one of a set of notionally identical +servers, so, on the ground of robustness, we have to believe +any SERVFAIL answers we get, and return them to the client. + +The client could be using the same recursive servers we are, +so it should, in theory, retry on SERVFAIL anyway. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/forward.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/src/forward.c ++++ b/src/forward.c +@@ -957,8 +957,7 @@ void reply_query(int fd, int family, tim + we get a good reply from another server. Kill it when we've + had replies from all to avoid filling the forwarding table when + everything is broken */ +- if (forward->forwardall == 0 || --forward->forwardall == 1 || +- (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL)) ++ if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED) + { + int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; + diff --git a/package/network/services/dnsmasq/patches/0010-Remove-the-NO_FORK-compile-time-option-and-support-f.patch b/package/network/services/dnsmasq/patches/0010-Remove-the-NO_FORK-compile-time-option-and-support-f.patch new file mode 100644 index 0000000000..1110d4c5fa --- /dev/null +++ b/package/network/services/dnsmasq/patches/0010-Remove-the-NO_FORK-compile-time-option-and-support-f.patch @@ -0,0 +1,199 @@ +From 48d12f14c9c0fc8cf943b52774c3892517dd72d4 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Fri, 2 Nov 2018 21:55:04 +0000 +Subject: [PATCH 10/11] Remove the NO_FORK compile-time option, and support for + uclinux. + +In an era where everything has an MMU, this looks like +an anachronism, and it adds to (Ok, multiplies!) the +combinatorial explosion of compile-time options. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + CHANGELOG | 6 ++++++ + src/config.h | 21 ++------------------- + src/dnsmasq.c | 14 -------------- + src/option.c | 4 +--- + 4 files changed, 9 insertions(+), 36 deletions(-) + +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -11,6 +11,12 @@ version 2.81 + This fix passes cache entries back from the TCP child process to + the main server process, and fixes the problem. + ++ Remove the NO_FORK compile-time option, and support for uclinux. ++ In an era where everything has an MMU, this looks like ++ an anachronism, and it adds to (Ok, multiplies!) the ++ combinatorial explosion of compile-time options. Thanks to ++ Kevin Darbyshire-Bryant for the patch. ++ + + version 2.80 + Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method +--- a/src/config.h ++++ b/src/config.h +@@ -239,27 +239,13 @@ HAVE_SOCKADDR_SA_LEN + defined if struct sockaddr has sa_len field (*BSD) + */ + +-/* Must precede __linux__ since uClinux defines __linux__ too. */ +-#if defined(__uClinux__) +-#define HAVE_LINUX_NETWORK +-#define HAVE_GETOPT_LONG +-#undef HAVE_SOCKADDR_SA_LEN +-/* Never use fork() on uClinux. Note that this is subtly different from the +- --keep-in-foreground option, since it also suppresses forking new +- processes for TCP connections and disables the call-a-script on leasechange +- system. It's intended for use on MMU-less kernels. */ +-#define NO_FORK +- +-#elif defined(__UCLIBC__) ++#if defined(__UCLIBC__) + #define HAVE_LINUX_NETWORK + #if defined(__UCLIBC_HAS_GNU_GETOPT__) || \ + ((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21)) + # define HAVE_GETOPT_LONG + #endif + #undef HAVE_SOCKADDR_SA_LEN +-#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__) +-# define NO_FORK +-#endif + #if defined(__UCLIBC_HAS_IPV6__) + # ifndef IPV6_V6ONLY + # define IPV6_V6ONLY 26 +@@ -328,7 +314,7 @@ HAVE_SOCKADDR_SA_LEN + #define HAVE_DHCP + #endif + +-#if defined(NO_SCRIPT) || defined(NO_FORK) ++#if defined(NO_SCRIPT) + #undef HAVE_SCRIPT + #undef HAVE_LUASCRIPT + #endif +@@ -372,9 +358,6 @@ static char *compile_opts = + #ifdef HAVE_BROKEN_RTC + "no-RTC " + #endif +-#ifdef NO_FORK +-"no-MMU " +-#endif + #ifndef HAVE_DBUS + "no-" + #endif +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -485,7 +485,6 @@ int main (int argc, char **argv) + if (chdir("/") != 0) + die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC); + +-#ifndef NO_FORK + if (!option_bool(OPT_NO_FORK)) + { + pid_t pid; +@@ -525,7 +524,6 @@ int main (int argc, char **argv) + if (pid != 0) + _exit(0); + } +-#endif + + /* write pidfile _after_ forking ! */ + if (daemon->runfile) +@@ -1628,12 +1626,10 @@ static int set_dns_listeners(time_t now) + + } + +-#ifndef NO_FORK + if (!option_bool(OPT_DEBUG)) + for (i = 0; i < MAX_PROCS; i++) + if (daemon->tcp_pipes[i] != -1) + poll_listen(daemon->tcp_pipes[i], POLLIN); +-#endif + + return wait; + } +@@ -1643,9 +1639,7 @@ static void check_dns_listeners(time_t n + struct serverfd *serverfdp; + struct listener *listener; + int i; +-#ifndef NO_FORK + int pipefd[2]; +-#endif + + for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) + if (poll_check(serverfdp->fd, POLLIN)) +@@ -1657,7 +1651,6 @@ static void check_dns_listeners(time_t n + poll_check(daemon->randomsocks[i].fd, POLLIN)) + reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); + +-#ifndef NO_FORK + /* Races. The child process can die before we read all of the data from the + pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the + process, and tcp_pipes to -1 and close the FD when we read the last +@@ -1674,7 +1667,6 @@ static void check_dns_listeners(time_t n + close(daemon->tcp_pipes[i]); + daemon->tcp_pipes[i] = -1; + } +-#endif + + for (listener = daemon->listeners; listener; listener = listener->next) + { +@@ -1768,7 +1760,6 @@ static void check_dns_listeners(time_t n + shutdown(confd, SHUT_RDWR); + while (retry_send(close(confd))); + } +-#ifndef NO_FORK + else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0) + { + close(pipefd[1]); /* parent needs read pipe end. */ +@@ -1791,7 +1782,6 @@ static void check_dns_listeners(time_t n + /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */ + daemon->log_id += TCP_MAX_QUERIES; + } +-#endif + else + { + unsigned char *buff; +@@ -1811,7 +1801,6 @@ static void check_dns_listeners(time_t n + auth_dns = 0; + } + +-#ifndef NO_FORK + /* Arrange for SIGALRM after CHILD_LIFETIME seconds to + terminate the process. */ + if (!option_bool(OPT_DEBUG)) +@@ -1820,7 +1809,6 @@ static void check_dns_listeners(time_t n + close(pipefd[0]); /* close read end in child. */ + daemon->pipe_to_parent = pipefd[1]; + } +-#endif + + /* start with no upstream connections. */ + for (s = daemon->servers; s; s = s->next) +@@ -1846,13 +1834,11 @@ static void check_dns_listeners(time_t n + shutdown(s->tcpfd, SHUT_RDWR); + while (retry_send(close(s->tcpfd))); + } +-#ifndef NO_FORK + if (!option_bool(OPT_DEBUG)) + { + flush_log(); + _exit(0); + } +-#endif + } + } + } +--- a/src/option.c ++++ b/src/option.c +@@ -1828,9 +1828,7 @@ static int one_opt(int option, char *arg + /* Sorry about the gross pre-processor abuse */ + case '6': /* --dhcp-script */ + case LOPT_LUASCRIPT: /* --dhcp-luascript */ +-# if defined(NO_FORK) +- ret_err(_("cannot run scripts under uClinux")); +-# elif !defined(HAVE_SCRIPT) ++# if !defined(HAVE_SCRIPT) + ret_err(_("recompile with HAVE_SCRIPT defined to enable lease-change scripts")); + # else + if (option == LOPT_LUASCRIPT) diff --git a/package/network/services/dnsmasq/patches/0011-Free-config-file-values-on-parsing-errors.patch b/package/network/services/dnsmasq/patches/0011-Free-config-file-values-on-parsing-errors.patch new file mode 100644 index 0000000000..3ba971fe72 --- /dev/null +++ b/package/network/services/dnsmasq/patches/0011-Free-config-file-values-on-parsing-errors.patch @@ -0,0 +1,1199 @@ +From 59e470381f84f2fdf0640c7bc67827f3f0c64784 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 2 Nov 2018 22:39:39 +0000 +Subject: [PATCH 11/11] Free config file values on parsing errors. + +This time I have a little bit more controversal patches. But I think +still useful. They fixes memory leaks that might occur in some cases. +Most dnsmasq errors is fatal, so it does not matter. But some are not. +Some parts are reloaded on SIGHUP signal, so it might leak more than once. + +Some example when it changes the failures. Use dhcp-options file with +this content: + +tag:error,vendor:redhat +option:ntp-server,1.2.3.4.5 +option6:ntp-server,[:::] + +Is not fatal and dnsmasq will start. On each reload command, it would +leak some memory. I validated it using valgrind --leak-check=full +dnsmasq -d. This patch fixes it. It introduces something that might be +considered constructor and destructor of selected structures. + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/option.c | 533 ++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 352 insertions(+), 181 deletions(-) + +--- a/src/option.c ++++ b/src/option.c +@@ -577,14 +577,15 @@ static void *opt_malloc(size_t size) + return ret; + } + +-static char *opt_string_alloc(char *cp) ++static char *opt_string_alloc(const char *cp) + { + char *ret = NULL; ++ size_t len; + +- if (cp && strlen(cp) != 0) ++ if (cp && (len = strlen(cp)) != 0) + { +- ret = opt_malloc(strlen(cp)+1); +- strcpy(ret, cp); ++ ret = opt_malloc(len+1); ++ memcpy(ret, cp, len+1); + + /* restore hidden metachars */ + unhide_metas(ret); +@@ -759,6 +760,8 @@ static void do_usage(void) + } + + #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0) ++#define ret_err_free(x,m) do { strcpy(errstr, (x)); free((m)); return 0; } while (0) ++#define goto_err(x) do { strcpy(errstr, (x)); goto on_error; } while (0) + + static char *parse_mysockaddr(char *arg, union mysockaddr *addr) + { +@@ -904,6 +907,8 @@ static struct server *add_rev4(struct in + p += sprintf(p, "%d.", (a >> 24) & 0xff); + break; + default: ++ free(serv->domain); ++ free(serv); + return NULL; + } + +@@ -958,6 +963,97 @@ static char *set_prefix(char *arg) + return arg; + } + ++static struct dhcp_netid * ++dhcp_netid_create(const char *net, struct dhcp_netid *next) ++{ ++ struct dhcp_netid *tt; ++ tt = opt_malloc(sizeof (struct dhcp_netid)); ++ tt->net = opt_string_alloc(net); ++ tt->next = next; ++ return tt; ++} ++ ++static void dhcp_netid_free(struct dhcp_netid *nid) ++{ ++ while (nid) ++ { ++ struct dhcp_netid *tmp = nid; ++ nid = nid->next; ++ free(tmp->net); ++ free(tmp); ++ } ++} ++ ++/* Parse one or more tag:s before parameters. ++ * Moves arg to the end of tags. */ ++static struct dhcp_netid * dhcp_tags(char **arg) ++{ ++ struct dhcp_netid *id = NULL; ++ ++ while (is_tag_prefix(*arg)) ++ { ++ char *comma = split(*arg); ++ id = dhcp_netid_create((*arg)+4, id); ++ *arg = comma; ++ }; ++ if (!*arg) ++ { ++ dhcp_netid_free(id); ++ id = NULL; ++ } ++ return id; ++} ++ ++static void dhcp_netid_list_free(struct dhcp_netid_list *netid) ++{ ++ while (netid) ++ { ++ struct dhcp_netid_list *tmplist = netid; ++ netid = netid->next; ++ dhcp_netid_free(tmplist->list); ++ free(tmplist); ++ } ++} ++ ++static void dhcp_config_free(struct dhcp_config *config) ++{ ++ if (config) ++ { ++ struct hwaddr_config *hwaddr = config->hwaddr; ++ while (hwaddr) ++ { ++ struct hwaddr_config *tmp = hwaddr; ++ hwaddr = hwaddr->next; ++ free(tmp); ++ } ++ dhcp_netid_list_free(config->netid); ++ if (config->flags & CONFIG_CLID) ++ free(config->clid); ++ free(config); ++ } ++} ++ ++static void dhcp_context_free(struct dhcp_context *ctx) ++{ ++ if (ctx) ++ { ++ dhcp_netid_free(ctx->filter); ++ free(ctx->netid.net); ++ free(ctx->template_interface); ++ free(ctx); ++ } ++} ++ ++static void dhcp_opt_free(struct dhcp_opt *opt) ++{ ++ if (opt->flags & DHOPT_VENDOR) ++ free(opt->u.vendor_class); ++ dhcp_netid_free(opt->netid); ++ free(opt->val); ++ free(opt); ++} ++ ++ + /* This is too insanely large to keep in-line in the switch */ + static int parse_dhcp_opt(char *errstr, char *arg, int flags) + { +@@ -965,7 +1061,6 @@ static int parse_dhcp_opt(char *errstr, + char lenchar = 0, *cp; + int addrs, digs, is_addr, is_addr6, is_hex, is_dec, is_string, dots; + char *comma = NULL; +- struct dhcp_netid *np = NULL; + u16 opt_len = 0; + int is6 = 0; + int option_ok = 0; +@@ -1052,14 +1147,9 @@ static int parse_dhcp_opt(char *errstr, + } + else + { +- new->netid = opt_malloc(sizeof (struct dhcp_netid)); + /* allow optional "net:" or "tag:" for consistency */ +- if (is_tag_prefix(arg)) +- new->netid->net = opt_string_alloc(arg+4); +- else +- new->netid->net = opt_string_alloc(set_prefix(arg)); +- new->netid->next = np; +- np = new->netid; ++ const char *name = (is_tag_prefix(arg)) ? arg+4 : set_prefix(arg); ++ new->netid = dhcp_netid_create(name, new->netid); + } + + arg = comma; +@@ -1069,7 +1159,7 @@ static int parse_dhcp_opt(char *errstr, + if (is6) + { + if (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE)) +- ret_err(_("unsupported encapsulation for IPv6 option")); ++ goto_err(_("unsupported encapsulation for IPv6 option")); + + if (opt_len == 0 && + !(new->flags & DHOPT_RFC3925)) +@@ -1083,7 +1173,7 @@ static int parse_dhcp_opt(char *errstr, + + /* option may be missing with rfc3925 match */ + if (!option_ok) +- ret_err(_("bad dhcp-option")); ++ goto_err(_("bad dhcp-option")); + + if (comma) + { +@@ -1151,10 +1241,10 @@ static int parse_dhcp_opt(char *errstr, + is_string = is_dec = is_hex = 0; + + if (!is6 && (!is_addr || dots == 0)) +- ret_err(_("bad IP address")); ++ goto_err(_("bad IP address")); + + if (is6 && !is_addr6) +- ret_err(_("bad IPv6 address")); ++ goto_err(_("bad IPv6 address")); + } + /* or names */ + else if (opt_len & (OT_NAME | OT_RFC1035_NAME | OT_CSTRING)) +@@ -1247,7 +1337,7 @@ static int parse_dhcp_opt(char *errstr, + comma = split(cp); + slash = split_chr(cp, '/'); + if (!inet_pton(AF_INET, cp, &in)) +- ret_err(_("bad IPv4 address")); ++ goto_err(_("bad IPv4 address")); + if (!slash) + { + memcpy(op, &in, INADDRSZ); +@@ -1292,8 +1382,8 @@ static int parse_dhcp_opt(char *errstr, + op += IN6ADDRSZ; + continue; + } +- +- ret_err(_("bad IPv6 address")); ++ ++ goto_err(_("bad IPv6 address")); + } + new->len = op - new->val; + } +@@ -1320,7 +1410,7 @@ static int parse_dhcp_opt(char *errstr, + if (strcmp (arg, ".") != 0) + { + if (!(dom = canonicalise_opt(arg))) +- ret_err(_("bad domain in dhcp-option")); ++ goto_err(_("bad domain in dhcp-option")); + + domlen = strlen(dom) + 2; + } +@@ -1414,7 +1504,7 @@ static int parse_dhcp_opt(char *errstr, + { + char *dom = canonicalise_opt(arg); + if (!dom) +- ret_err(_("bad domain in dhcp-option")); ++ goto_err(_("bad domain in dhcp-option")); + + newp = opt_malloc(len + strlen(dom) + 2); + +@@ -1452,14 +1542,14 @@ static int parse_dhcp_opt(char *errstr, + ((new->len > 255) || + (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) || + (new->len > 250 && (new->flags & DHOPT_RFC3925)))) +- ret_err(_("dhcp-option too long")); ++ goto_err(_("dhcp-option too long")); + + if (flags == DHOPT_MATCH) + { + if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) || + !new->netid || + new->netid->next) +- ret_err(_("illegal dhcp-match")); ++ goto_err(_("illegal dhcp-match")); + + if (is6) + { +@@ -1484,6 +1574,9 @@ static int parse_dhcp_opt(char *errstr, + } + + return 1; ++on_error: ++ dhcp_opt_free(new); ++ return 0; + } + + #endif +@@ -1498,6 +1591,16 @@ void reset_option_bool(unsigned int opt) + option_var(opt) &= ~(option_val(opt)); + } + ++static void server_list_free(struct server *list) ++{ ++ while (list) ++ { ++ struct server *tmp = list; ++ list = list->next; ++ free(tmp); ++ } ++} ++ + static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only) + { + int i; +@@ -1679,13 +1782,13 @@ static int one_opt(int option, char *arg + /* has subnet+len */ + err = parse_mysockaddr(arg, &new->addr); + if (err) +- ret_err(err); ++ ret_err_free(err, new); + if (!atoi_check(end, &new->mask)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + new->addr_used = 1; + } + else if (!atoi_check(arg, &new->mask)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + + daemon->add_subnet4 = new; + +@@ -1697,15 +1800,15 @@ static int one_opt(int option, char *arg + /* has subnet+len */ + err = parse_mysockaddr(comma, &new->addr); + if (err) +- ret_err(err); ++ ret_err_free(err, new); + if (!atoi_check(end, &new->mask)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + new->addr_used = 1; + } + else + { + if (!atoi_check(comma, &new->mask)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + } + + daemon->add_subnet6 = new; +@@ -1912,7 +2015,10 @@ static int one_opt(int option, char *arg + else if (strcmp(fam, "6") == 0) + new->addr.sa.sa_family = AF_INET6; + else +- ret_err(gen_err); ++ { ++ free(new->name); ++ ret_err_free(gen_err, new); ++ } + } + } + new->next = daemon->authinterface; +@@ -2077,7 +2183,7 @@ static int one_opt(int option, char *arg + + arg = split(netpart); + if (!atoi_check(netpart, &msize)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + else if (inet_pton(AF_INET, comma, &new->start)) + { + int mask = (1 << (32 - msize)) - 1; +@@ -2090,18 +2196,18 @@ static int one_opt(int option, char *arg + { + if (!(new->prefix = canonicalise_opt(arg)) || + strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN) +- ret_err(_("bad prefix")); ++ ret_err_free(_("bad prefix"), new); + } + else if (strcmp(arg, "local") != 0 || + (msize != 8 && msize != 16 && msize != 24)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + else + { + /* generate the equivalent of + local=/xxx.yyy.zzz.in-addr.arpa/ */ + struct server *serv = add_rev4(new->start, msize); + if (!serv) +- ret_err(_("bad prefix")); ++ ret_err_free(_("bad prefix"), new); + + serv->flags |= SERV_NO_ADDR; + +@@ -2130,17 +2236,17 @@ static int one_opt(int option, char *arg + setaddr6part(&new->end6, addrpart | mask); + + if (msize < 64) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + else if (arg) + { + if (option != 's') + { + if (!(new->prefix = canonicalise_opt(arg)) || + strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN) +- ret_err(_("bad prefix")); ++ ret_err_free(_("bad prefix"), new); + } + else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + else + { + /* generate the equivalent of +@@ -2159,7 +2265,7 @@ static int one_opt(int option, char *arg + } + } + else +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + } + else + { +@@ -2173,7 +2279,7 @@ static int one_opt(int option, char *arg + if (!arg) + new->end.s_addr = new->start.s_addr; + else if (!inet_pton(AF_INET, arg, &new->end)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + } + else if (inet_pton(AF_INET6, comma, &new->start6)) + { +@@ -2181,16 +2287,16 @@ static int one_opt(int option, char *arg + if (!arg) + memcpy(&new->end6, &new->start6, IN6ADDRSZ); + else if (!inet_pton(AF_INET6, arg, &new->end6)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + } + else +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + + if (option != 's' && prefstr) + { + if (!(new->prefix = canonicalise_opt(prefstr)) || + strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN) +- ret_err(_("bad prefix")); ++ ret_err_free(_("bad prefix"), new); + } + } + +@@ -2352,7 +2458,7 @@ static int one_opt(int option, char *arg + #endif + } + else +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + + new->used = 0; + if (option == 'a') +@@ -2423,7 +2529,10 @@ static int one_opt(int option, char *arg + { + newlist->flags |= SERV_LITERAL_ADDRESS; + if (!(newlist->flags & SERV_TYPE)) +- ret_err(gen_err); ++ { ++ server_list_free(newlist); ++ ret_err(gen_err); ++ } + } + else if (option == LOPT_NO_REBIND) + newlist->flags |= SERV_NO_REBIND; +@@ -2440,7 +2549,10 @@ static int one_opt(int option, char *arg + { + char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags); + if (err) +- ret_err(err); ++ { ++ server_list_free(newlist); ++ ret_err(err); ++ } + } + + serv = newlist; +@@ -2776,21 +2888,19 @@ static int one_opt(int option, char *arg + { + if (is_tag_prefix(arg)) + { +- struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid)); +- tt->net = opt_string_alloc(arg+4); +- tt->next = new->filter; + /* ignore empty tag */ +- if (tt->net) +- new->filter = tt; ++ if (arg[4]) ++ new->filter = dhcp_netid_create(arg+4, new->filter); + } + else + { + if (new->netid.net) +- ret_err(_("only one tag allowed")); +- else if (strstr(arg, "set:") == arg) +- new->netid.net = opt_string_alloc(arg+4); ++ { ++ dhcp_context_free(new); ++ ret_err(_("only one tag allowed")); ++ } + else +- new->netid.net = opt_string_alloc(arg); ++ new->netid.net = opt_string_alloc(set_prefix(arg)); + } + arg = comma; + } +@@ -2806,7 +2916,10 @@ static int one_opt(int option, char *arg + break; + + if (k < 2) +- ret_err(_("bad dhcp-range")); ++ { ++ dhcp_context_free(new); ++ ret_err(_("bad dhcp-range")); ++ } + + if (inet_pton(AF_INET, a[0], &new->start)) + { +@@ -2818,7 +2931,10 @@ static int one_opt(int option, char *arg + else if (strcmp(a[1], "proxy") == 0) + new->flags |= CONTEXT_PROXY; + else if (!inet_pton(AF_INET, a[1], &new->end)) +- ret_err(_("bad dhcp-range")); ++ { ++ dhcp_context_free(new); ++ ret_err(_("bad dhcp-range")); ++ } + + if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) + { +@@ -2833,7 +2949,10 @@ static int one_opt(int option, char *arg + new->flags |= CONTEXT_NETMASK; + leasepos = 3; + if (!is_same_net(new->start, new->end, new->netmask)) +- ret_err(_("inconsistent DHCP range")); ++ { ++ dhcp_context_free(new); ++ ret_err(_("inconsistent DHCP range")); ++ } + + + if (k >= 4 && strchr(a[3], '.') && +@@ -2847,6 +2966,8 @@ static int one_opt(int option, char *arg + #ifdef HAVE_DHCP6 + else if (inet_pton(AF_INET6, a[0], &new->start6)) + { ++ const char *err = NULL; ++ + new->flags |= CONTEXT_V6; + new->prefix = 64; /* default */ + new->end6 = new->start6; +@@ -2892,19 +3013,24 @@ static int one_opt(int option, char *arg + } + } + +- if (new->prefix != 64) ++ if (new->prefix > 64) + { + if (new->flags & CONTEXT_RA) +- ret_err(_("prefix length must be exactly 64 for RA subnets")); ++ err=(_("prefix length must be exactly 64 for RA subnets")); + else if (new->flags & CONTEXT_TEMPLATE) +- ret_err(_("prefix length must be exactly 64 for subnet constructors")); ++ err=(_("prefix length must be exactly 64 for subnet constructors")); + } +- +- if (new->prefix < 64) +- ret_err(_("prefix length must be at least 64")); ++ else if (new->prefix < 64) ++ err=(_("prefix length must be at least 64")); + +- if (!is_same_net6(&new->start6, &new->end6, new->prefix)) +- ret_err(_("inconsistent DHCPv6 range")); ++ if (!err && !is_same_net6(&new->start6, &new->end6, new->prefix)) ++ err=(_("inconsistent DHCPv6 range")); ++ ++ if (err) ++ { ++ dhcp_context_free(new); ++ ret_err(err); ++ } + + /* dhcp-range=:: enables DHCP stateless on any interface */ + if (IN6_IS_ADDR_UNSPECIFIED(&new->start6) && !(new->flags & CONTEXT_TEMPLATE)) +@@ -2915,7 +3041,10 @@ static int one_opt(int option, char *arg + struct in6_addr zero; + memset(&zero, 0, sizeof(zero)); + if (!is_same_net6(&zero, &new->start6, new->prefix)) +- ret_err(_("prefix must be zero with \"constructor:\" argument")); ++ { ++ dhcp_context_free(new); ++ ret_err(_("prefix must be zero with \"constructor:\" argument")); ++ } + } + + if (addr6part(&new->start6) > addr6part(&new->end6)) +@@ -2927,12 +3056,18 @@ static int one_opt(int option, char *arg + } + #endif + else +- ret_err(_("bad dhcp-range")); ++ { ++ dhcp_context_free(new); ++ ret_err(_("bad dhcp-range")); ++ } + + if (leasepos < k) + { + if (leasepos != k-1) +- ret_err(_("bad dhcp-range")); ++ { ++ dhcp_context_free(new); ++ ret_err(_("bad dhcp-range")); ++ } + + if (strcmp(a[leasepos], "infinite") == 0) + new->lease_time = 0xffffffff; +@@ -2971,7 +3106,7 @@ static int one_opt(int option, char *arg + break; + + if (*cp || (leasepos+1 < k)) +- ret_err(_("bad dhcp-range")); ++ ret_err_free(_("bad dhcp-range"), new); + + new->lease_time = atoi(a[leasepos]) * fac; + /* Leases of a minute or less confuse +@@ -2998,6 +3133,7 @@ static int one_opt(int option, char *arg + new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0; + new->hwaddr = NULL; + new->netid = NULL; ++ new->clid = NULL; + + if ((a[0] = arg)) + for (k = 1; k < 7; k++) +@@ -3028,7 +3164,10 @@ static int one_opt(int option, char *arg + } + + if (len == -1) +- ret_err(_("bad hex constant")); ++ { ++ dhcp_config_free(new); ++ ret_err(_("bad hex constant")); ++ } + else if ((new->clid = opt_malloc(len))) + { + new->flags |= CONFIG_CLID; +@@ -3040,17 +3179,17 @@ static int one_opt(int option, char *arg + /* dhcp-host has strange backwards-compat needs. */ + else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg) + { +- struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)); + struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list)); +- newtag->net = opt_malloc(strlen(arg + 4) + 1); + newlist->next = new->netid; + new->netid = newlist; +- newlist->list = newtag; +- strcpy(newtag->net, arg+4); +- unhide_metas(newtag->net); ++ newlist->list = dhcp_netid_create(arg+4, NULL); + } + else if (strstr(arg, "tag:") == arg) +- ret_err(_("cannot match tags in --dhcp-host")); ++ { ++ ++ dhcp_config_free(new); ++ ret_err(_("cannot match tags in --dhcp-host")); ++ } + #ifdef HAVE_DHCP6 + else if (arg[0] == '[' && arg[strlen(arg)-1] == ']') + { +@@ -3058,7 +3197,10 @@ static int one_opt(int option, char *arg + arg++; + + if (!inet_pton(AF_INET6, arg, &new->addr6)) +- ret_err(_("bad IPv6 address")); ++ { ++ dhcp_config_free(new); ++ ret_err(_("bad IPv6 address")); ++ } + + for (i= 0; i < 8; i++) + if (new->addr6.s6_addr[i] != 0) +@@ -3076,10 +3218,13 @@ static int one_opt(int option, char *arg + struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config)); + if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX, + &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1) +- ret_err(_("bad hex constant")); ++ { ++ free(newhw); ++ dhcp_config_free(new); ++ ret_err(_("bad hex constant")); ++ } + else + { +- + newhw->next = new->hwaddr; + new->hwaddr = newhw; + } +@@ -3156,7 +3301,10 @@ static int one_opt(int option, char *arg + { + if (!(new->hostname = canonicalise_opt(a[j])) || + !legal_hostname(new->hostname)) +- ret_err(_("bad DHCP host name")); ++ { ++ dhcp_config_free(new); ++ ret_err(_("bad DHCP host name")); ++ } + + new->flags |= CONFIG_NAME; + new->domain = strip_hostname(new->hostname); +@@ -3209,10 +3357,7 @@ static int one_opt(int option, char *arg + } + else + { +- struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)); +- newtag->net = opt_malloc(len - 3); +- strcpy(newtag->net, arg+4); +- unhide_metas(newtag->net); ++ struct dhcp_netid *newtag = dhcp_netid_create(arg+4, NULL); + + if (strstr(arg, "set:") == arg) + { +@@ -3229,7 +3374,7 @@ static int one_opt(int option, char *arg + else + { + new->set = NULL; +- free(newtag); ++ dhcp_netid_free(newtag); + break; + } + } +@@ -3238,7 +3383,11 @@ static int one_opt(int option, char *arg + } + + if (!new->set) +- ret_err(_("bad tag-if")); ++ { ++ dhcp_netid_free(new->tag); ++ dhcp_netid_list_free(new->set); ++ ret_err_free(_("bad tag-if"), new); ++ } + + break; + } +@@ -3281,19 +3430,12 @@ static int one_opt(int option, char *arg + + case 'M': /* --dhcp-boot */ + { +- struct dhcp_netid *id = NULL; +- while (is_tag_prefix(arg)) +- { +- struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid)); +- newid->next = id; +- id = newid; +- comma = split(arg); +- newid->net = opt_string_alloc(arg+4); +- arg = comma; +- }; ++ struct dhcp_netid *id = dhcp_tags(&arg); + +- if (!arg) +- ret_err(gen_err); ++ if (!id) ++ { ++ ret_err(gen_err); ++ } + else + { + char *dhcp_file, *dhcp_sname = NULL, *tftp_sname = NULL; +@@ -3339,19 +3481,12 @@ static int one_opt(int option, char *arg + + case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */ + { +- struct dhcp_netid *id = NULL; +- while (is_tag_prefix(arg)) +- { +- struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid)); +- newid->next = id; +- id = newid; +- comma = split(arg); +- newid->net = opt_string_alloc(arg+4); +- arg = comma; +- }; ++ struct dhcp_netid *id = dhcp_tags(&arg); + +- if (!arg) +- ret_err(gen_err); ++ if (!id) ++ { ++ ret_err(gen_err); ++ } + else + { + struct delay_config *new; +@@ -3376,19 +3511,13 @@ static int one_opt(int option, char *arg + + new->netid = NULL; + new->opt = 10; /* PXE_MENU_PROMPT */ +- +- while (is_tag_prefix(arg)) +- { +- struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); +- comma = split(arg); +- nn->next = new->netid; +- new->netid = nn; +- nn->net = opt_string_alloc(arg+4); +- arg = comma; +- } ++ new->netid = dhcp_tags(&arg); + +- if (!arg) +- ret_err(gen_err); ++ if (!new->netid) ++ { ++ dhcp_opt_free(new); ++ ret_err(gen_err); ++ } + else + { + comma = split(arg); +@@ -3424,17 +3553,8 @@ static int one_opt(int option, char *arg + new->netid = NULL; + new->sname = NULL; + new->server.s_addr = 0; ++ new->netid = dhcp_tags(&arg); + +- while (is_tag_prefix(arg)) +- { +- struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); +- comma = split(arg); +- nn->next = new->netid; +- new->netid = nn; +- nn->net = opt_string_alloc(arg+4); +- arg = comma; +- } +- + if (arg && (comma = split(arg))) + { + for (i = 0; CSA[i]; i++) +@@ -3511,7 +3631,10 @@ static int one_opt(int option, char *arg + unhide_metas(comma); + new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type); + if (new->hwaddr_len == -1) +- ret_err(gen_err); ++ { ++ free(new->netid.net); ++ ret_err_free(gen_err, new); ++ } + else + { + new->next = daemon->dhcp_macs; +@@ -3528,7 +3651,7 @@ static int one_opt(int option, char *arg + + if (!(comma = split(arg)) || + !atoi_check16(comma, &new->class)) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + + new->tag.net = opt_string_alloc(set_prefix(arg)); + new->next = daemon->prefix_classes; +@@ -3550,7 +3673,7 @@ static int one_opt(int option, char *arg + struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor)); + + if (!(comma = split(arg))) +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + + new->netid.net = opt_string_alloc(set_prefix(arg)); + /* check for hex string - must digits may include : must not have nothing else, +@@ -3560,7 +3683,10 @@ static int one_opt(int option, char *arg + if ((comma = split(arg))) + { + if (option != 'U' || strstr(arg, "enterprise:") != arg) +- ret_err(gen_err); ++ { ++ free(new->netid.net); ++ ret_err_free(gen_err, new); ++ } + else + new->enterprise = atoi(arg+11); + } +@@ -3662,14 +3788,8 @@ static int one_opt(int option, char *arg + } + + while (arg) { +- struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid)); + comma = split(arg); +- member->next = list; +- list = member; +- if (is_tag_prefix(arg)) +- member->net = opt_string_alloc(arg+4); +- else +- member->net = opt_string_alloc(arg); ++ list = dhcp_netid_create(is_tag_prefix(arg) ? arg+4 :arg, list); + arg = comma; + } + +@@ -3683,7 +3803,7 @@ static int one_opt(int option, char *arg + struct addr_list *new = opt_malloc(sizeof(struct addr_list)); + comma = split(arg); + if (!(inet_pton(AF_INET, arg, &new->addr) > 0)) +- ret_err(_("bad dhcp-proxy address")); ++ ret_err_free(_("bad dhcp-proxy address"), new); + new->next = daemon->override_relays; + daemon->override_relays = new; + arg = comma; +@@ -3709,7 +3829,10 @@ static int one_opt(int option, char *arg + } + #endif + else +- ret_err(_("Bad dhcp-relay")); ++ { ++ free(new->interface); ++ ret_err_free(_("Bad dhcp-relay"), new); ++ } + + break; + } +@@ -3749,8 +3872,11 @@ static int one_opt(int option, char *arg + arg = split(comma); + if (!atoi_check(comma, &new->interval) || + (arg && !atoi_check(arg, &new->lifetime))) ++ { + err: +- ret_err(_("bad RA-params")); ++ free(new->name); ++ ret_err_free(_("bad RA-params"), new); ++ } + + new->next = daemon->ra_interfaces; + daemon->ra_interfaces = new; +@@ -3799,7 +3925,7 @@ err: + (!(inet_pton(AF_INET, dash, &new->end) > 0) || + !is_same_net(new->in, new->end, new->mask) || + ntohl(new->in.s_addr) > ntohl(new->end.s_addr))) +- ret_err(_("invalid alias range")); ++ ret_err_free(_("invalid alias range"), new); + + break; + } +@@ -3832,7 +3958,7 @@ err: + else if (strcmp(arg, "6") == 0) + new->family = AF_INET6; + else +- ret_err(gen_err); ++ ret_err_free(gen_err, new); + } + new->intr = opt_string_alloc(comma); + break; +@@ -3864,11 +3990,19 @@ err: + alias = canonicalise_opt(arg); + + if (!alias || !target) +- ret_err(_("bad CNAME")); ++ { ++ free(target); ++ free(alias); ++ ret_err(_("bad CNAME")); ++ } + + for (new = daemon->cnames; new; new = new->next) + if (hostname_isequal(new->alias, alias)) +- ret_err(_("duplicate CNAME")); ++ { ++ free(target); ++ free(alias); ++ ret_err(_("duplicate CNAME")); ++ } + new = opt_malloc(sizeof(struct cname)); + new->next = daemon->cnames; + daemon->cnames = new; +@@ -3891,7 +4025,11 @@ err: + + if (!(dom = canonicalise_opt(arg)) || + (comma && !(target = canonicalise_opt(comma)))) +- ret_err(_("bad PTR record")); ++ { ++ free(dom); ++ free(target); ++ ret_err(_("bad PTR record")); ++ } + else + { + new = opt_malloc(sizeof(struct ptr_record)); +@@ -3909,7 +4047,7 @@ err: + int k = 0; + struct naptr *new; + int order, pref; +- char *name, *replace = NULL; ++ char *name=NULL, *replace = NULL; + + if ((a[0] = arg)) + for (k = 1; k < 7; k++) +@@ -3922,7 +4060,11 @@ err: + !atoi_check16(a[1], &order) || + !atoi_check16(a[2], &pref) || + (k == 7 && !(replace = canonicalise_opt(a[6])))) +- ret_err(_("bad NAPTR record")); ++ { ++ free(name); ++ free(replace); ++ ret_err(_("bad NAPTR record")); ++ } + else + { + new = opt_malloc(sizeof(struct naptr)); +@@ -3944,22 +4086,26 @@ err: + struct txt_record *new; + size_t len = 0; + char *data; +- int val; ++ int class; + + comma = split(arg); + data = split(comma); + + new = opt_malloc(sizeof(struct txt_record)); +- new->next = daemon->rr; +- daemon->rr = new; ++ new->name = NULL; + +- if (!atoi_check(comma, &val) || ++ if (!atoi_check(comma, &class) || + !(new->name = canonicalise_opt(arg)) || + (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1U)) +- ret_err(_("bad RR record")); +- +- new->class = val; ++ { ++ free(new->name); ++ ret_err_free(_("bad RR record"), new); ++ } ++ + new->len = 0; ++ new->class = class; ++ new->next = daemon->rr; ++ daemon->rr = new; + + if (data) + { +@@ -4011,14 +4157,14 @@ err: + comma = split(arg); + + new = opt_malloc(sizeof(struct txt_record)); +- new->next = daemon->txt; +- daemon->txt = new; + new->class = C_IN; + new->stat = 0; + + if (!(new->name = canonicalise_opt(arg))) +- ret_err(_("bad TXT record")); ++ ret_err_free(_("bad TXT record"), new); + ++ new->next = daemon->txt; ++ daemon->txt = new; + len = comma ? strlen(comma) : 0; + len += (len/255) + 1; /* room for extra counts */ + new->txt = p = opt_malloc(len); +@@ -4065,24 +4211,32 @@ err: + arg = comma; + comma = split(arg); + if (!(target = canonicalise_opt(arg))) +- ret_err(_("bad SRV target")); ++ ret_err_free(_("bad SRV target"), name); + + if (comma) + { + arg = comma; + comma = split(arg); + if (!atoi_check16(arg, &port)) +- ret_err(_("invalid port number")); ++ { ++ free(name); ++ ret_err_free(_("invalid port number"), target); ++ } + + if (comma) + { + arg = comma; + comma = split(arg); + if (!atoi_check16(arg, &priority)) +- ret_err(_("invalid priority")); +- ++ { ++ free(name); ++ ret_err_free(_("invalid priority"), target); ++ } + if (comma && !atoi_check16(comma, &weight)) +- ret_err(_("invalid weight")); ++ { ++ free(name); ++ ret_err_free(_("invalid weight"), target); ++ } + } + } + } +@@ -4101,13 +4255,15 @@ err: + + case LOPT_HOST_REC: /* --host-record */ + { +- struct host_record *new = opt_malloc(sizeof(struct host_record)); +- memset(new, 0, sizeof(struct host_record)); +- new->ttl = -1; ++ struct host_record *new; + + if (!arg || !(comma = split(arg))) + ret_err(_("Bad host-record")); + ++ new = opt_malloc(sizeof(struct host_record)); ++ memset(new, 0, sizeof(struct host_record)); ++ new->ttl = -1; ++ + while (arg) + { + struct all_addr addr; +@@ -4126,10 +4282,19 @@ err: + { + int nomem; + char *canon = canonicalise(arg, &nomem); +- struct name_list *nl = opt_malloc(sizeof(struct name_list)); ++ struct name_list *nl; + if (!canon) +- ret_err(_("Bad name in host-record")); ++ { ++ struct name_list *tmp = new->names, *next; ++ for (tmp = new->names; tmp; tmp = next) ++ { ++ next = tmp->next; ++ free(tmp); ++ } ++ ret_err_free(_("Bad name in host-record"), new); ++ } + ++ nl = opt_malloc(sizeof(struct name_list)); + nl->name = canon; + /* keep order, so that PTR record goes to first name */ + nl->next = NULL; +@@ -4179,6 +4344,7 @@ err: + int len; + + new->class = C_IN; ++ new->name = NULL; + + if ((comma = split(arg)) && (algo = split(comma))) + { +@@ -4203,7 +4369,7 @@ err: + !atoi_check8(algo, &new->algo) || + !atoi_check8(digest, &new->digest_type) || + !(new->name = canonicalise_opt(arg))) +- ret_err(_("bad trust anchor")); ++ ret_err_free(_("bad trust anchor"), new); + + /* Upper bound on length */ + len = (2*strlen(keyhex))+1; +@@ -4217,7 +4383,10 @@ err: + else + cp++; + if ((new->digestlen = parse_hex(keyhex, (unsigned char *)new->digest, len, NULL, NULL)) == -1) +- ret_err(_("bad HEX in trust anchor")); ++ { ++ free(new->name); ++ ret_err_free(_("bad HEX in trust anchor"), new); ++ } + + new->next = daemon->ds; + daemon->ds = new; +@@ -4686,8 +4855,8 @@ void read_opts(int argc, char **argv, ch + size_t argbuf_size = MAXDNAME; + char *argbuf = opt_malloc(argbuf_size); + char *buff = opt_malloc(MAXDNAME); +- int option, conffile_opt = '7', testmode = 0; +- char *arg, *conffile = CONFFILE; ++ int option, testmode = 0; ++ char *arg, *conffile = NULL; + + opterr = 0; + +@@ -4796,7 +4965,8 @@ void read_opts(int argc, char **argv, ch + } + else if (option == 'C') + { +- conffile_opt = 0; /* file must exist */ ++ if (conffile) ++ free(conffile); + conffile = opt_string_alloc(arg); + } + else +@@ -4814,10 +4984,11 @@ void read_opts(int argc, char **argv, ch + + if (conffile) + { +- one_file(conffile, conffile_opt); +- if (conffile_opt == 0) +- free(conffile); ++ one_file(conffile, 0); ++ free(conffile); + } ++ else ++ one_file(CONFFILE, '7'); + + /* port might not be known when the address is parsed - fill in here */ + if (daemon->servers) diff --git a/package/network/services/dnsmasq/patches/0012-option-fix-non-DHCPv6-build-error.patch b/package/network/services/dnsmasq/patches/0012-option-fix-non-DHCPv6-build-error.patch new file mode 100644 index 0000000000..983cb1402e --- /dev/null +++ b/package/network/services/dnsmasq/patches/0012-option-fix-non-DHCPv6-build-error.patch @@ -0,0 +1,27 @@ +From 061eb8599636bb360e0b7fa5986935b86db39497 Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Mon, 10 Dec 2018 10:07:33 +0000 +Subject: [PATCH] option: fix non DHCPv6 build error + +option.c: In function 'dhcp_context_free': +option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface' + free(ctx->template_interface); + ^~ + +Signed-off-by: Kevin Darbyshire-Bryant +--- + src/option.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/src/option.c ++++ b/src/option.c +@@ -1039,7 +1039,9 @@ static void dhcp_context_free(struct dhc + { + dhcp_netid_free(ctx->filter); + free(ctx->netid.net); ++#ifdef HAVE_DHCP6 + free(ctx->template_interface); ++#endif + free(ctx); + } + } diff --git a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch index 88e334b0fc..f2681e3993 100644 --- a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch +++ b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch @@ -44,7 +44,7 @@ (buffer = safe_malloc(BUFF_SZ)) && (ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 && (bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1)) -@@ -217,17 +198,10 @@ int add_to_ipset(const char *setname, co +@@ -211,16 +192,9 @@ int add_to_ipset(const char *setname, co if (flags & F_IPV6) { af = AF_INET6; @@ -55,7 +55,6 @@ - ret = -1; - } } - #endif - if (ret != -1) - ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);