From fca008d8d486b3071eb2c1e00dba2d8d963b19dd Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sun, 19 Feb 2017 18:50:41 +0000 Subject: [PATCH] Make --bogus-priv apply to IPv6. --- CHANGELOG | 3 +++ man/dnsmasq.8 | 3 ++- src/rfc1035.c | 25 ++++++++++++++++++++----- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 86cec72..7fa39b8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -77,6 +77,9 @@ version 2.77 Implement RFC 6842. Thanks to Reddeiah Raju Konduru for pointing out that this was missing. + Make --bogus-priv apply to IPv6, for the prefixes specified + in RFC6303. Thanks to Kevin Darbyshire-Bryant for work on this. + version 2.76 Include 0.0.0.0/8 in DNS rebind checks. This range diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 4ba788f..9f0e3a2 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -301,7 +301,8 @@ attached to. Currently this facility is limited to IPv4. .B \-b, --bogus-priv Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc) which are not found in /etc/hosts or the DHCP leases file are answered -with "no such domain" rather than being forwarded upstream. +with "no such domain" rather than being forwarded upstream. The +set of prefixes affected is the list given in RFC6303, for IPv4 and IPv6. .TP .B \-V, --alias=[]|[-],[,] Modify IPv4 addresses returned from upstream nameservers; old-ip is diff --git a/src/rfc1035.c b/src/rfc1035.c index 3a238f0..3462a7b 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -426,6 +426,19 @@ int private_net(struct in_addr addr, int ban_localhost) ((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ; } +#ifdef HAVE_IPV6 +static int private_net6(struct in6_addr *a) +{ + return + IN6_IS_ADDR_UNSPECIFIED(a) || /* RFC 6303 4.3 */ + IN6_IS_ADDR_LOOPBACK(a) || /* RFC 6303 4.3 */ + IN6_IS_ADDR_LINKLOCAL(a) || /* RFC 6303 4.5 */ + ((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) { int i, qtype, qclass, rdlen; @@ -1440,20 +1453,22 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, anscount++; } } - else if (is_arpa == F_IPV4 && - option_bool(OPT_BOGUSPRIV) && - private_net(addr.addr.addr4, 1)) + 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)))) { /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */ ans = 1; sec_data = 0; nxdomain = 1; if (!dryrun) - log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, + log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN, name, &addr, NULL); } } - + for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) { unsigned short type = T_A;