Split EDNS0 stuff into its own source file.
diff --git a/Makefile b/Makefile
index b664160..dfb0347 100644
--- a/Makefile
+++ b/Makefile
@@ -74,7 +74,7 @@
        helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
        dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
        domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
-       poll.o rrfilter.o
+       poll.o rrfilter.o edns0.o
 
 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
        dns-protocol.h radv-protocol.h ip6addr.h
diff --git a/bld/Android.mk b/bld/Android.mk
index 67b9c4b..87966d2 100644
--- a/bld/Android.mk
+++ b/bld/Android.mk
@@ -10,7 +10,7 @@
 		    dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
 		    radv.c slaac.c auth.c ipset.c domain.c \
 	            dnssec.c dnssec-openssl.c blockdata.c tables.c \
-		    loop.c inotify.c poll.c rrfilter.c
+		    loop.c inotify.c poll.c rrfilter.c edns0.c
 
 LOCAL_MODULE := dnsmasq
 
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index abb34c5..a41c8cc 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1123,14 +1123,6 @@
 unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
 size_t resize_packet(struct dns_header *header, size_t plen, 
 		  unsigned char *pheader, size_t hlen);
-size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
-			unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do);
-size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
-size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source);
-#ifdef HAVE_DNSSEC
-size_t add_do_bit(struct dns_header *header, size_t plen, char *limit);
-#endif
-int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
 int add_resource_record(struct dns_header *header, char *limit, int *truncp,
 			int nameoffset, unsigned char **pp, unsigned long ttl, 
 			int *offset, unsigned short type, unsigned short class, char *format, ...);
@@ -1521,3 +1513,12 @@
 u16 *rrfilter_desc(int type);
 int expand_workspace(unsigned char ***wkspc, int *szp, int new);
 
+/* edns0.c */
+size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
+			unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do);
+size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
+size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source);
+#ifdef HAVE_DNSSEC
+size_t add_do_bit(struct dns_header *header, size_t plen, char *limit);
+#endif
+int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
diff --git a/src/edns0.c b/src/edns0.c
new file mode 100644
index 0000000..f348b01
--- /dev/null
+++ b/src/edns0.c
@@ -0,0 +1,351 @@
+/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t  *len, unsigned char **p, int *is_sign)
+{
+  /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 
+     also return length of pseudoheader in *len and pointer to the UDP size in *p
+     Finally, check to see if a packet is signed. If it is we cannot change a single bit before
+     forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
+  
+  int i, arcount = ntohs(header->arcount);
+  unsigned char *ansp = (unsigned char *)(header+1);
+  unsigned short rdlen, type, class;
+  unsigned char *ret = NULL;
+
+  if (is_sign)
+    {
+      *is_sign = 0;
+
+      if (OPCODE(header) == QUERY)
+	{
+	  for (i = ntohs(header->qdcount); i != 0; i--)
+	    {
+	      if (!(ansp = skip_name(ansp, header, plen, 4)))
+		return NULL;
+	      
+	      GETSHORT(type, ansp); 
+	      GETSHORT(class, ansp);
+	      
+	      if (class == C_IN && type == T_TKEY)
+		*is_sign = 1;
+	    }
+	}
+    }
+  else
+    {
+      if (!(ansp = skip_questions(header, plen)))
+	return NULL;
+    }
+    
+  if (arcount == 0)
+    return NULL;
+  
+  if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
+    return NULL; 
+  
+  for (i = 0; i < arcount; i++)
+    {
+      unsigned char *save, *start = ansp;
+      if (!(ansp = skip_name(ansp, header, plen, 10)))
+	return NULL; 
+
+      GETSHORT(type, ansp);
+      save = ansp;
+      GETSHORT(class, ansp);
+      ansp += 4; /* TTL */
+      GETSHORT(rdlen, ansp);
+      if (!ADD_RDLEN(header, ansp, plen, rdlen))
+	return NULL;
+      if (type == T_OPT)
+	{
+	  if (len)
+	    *len = ansp - start;
+	  if (p)
+	    *p = save;
+	  ret = start;
+	}
+      else if (is_sign && 
+	       i == arcount - 1 && 
+	       class == C_ANY && 
+	       type == T_TSIG)
+	*is_sign = 1;
+    }
+  
+  return ret;
+}
+
+struct macparm {
+  unsigned char *limit;
+  struct dns_header *header;
+  size_t plen;
+  union mysockaddr *l3;
+};
+ 
+size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
+			unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do)
+{ 
+  unsigned char *lenp, *datap, *p;
+  int rdlen, is_sign;
+  
+  if (!(p = find_pseudoheader(header, plen, NULL, NULL, &is_sign)))
+    {
+      if (is_sign)
+	return plen;
+
+      /* We are adding the pseudoheader */
+      if (!(p = skip_questions(header, plen)) ||
+	  !(p = skip_section(p, 
+			     ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
+			     header, plen)))
+	return plen;
+      *p++ = 0; /* empty name */
+      PUTSHORT(T_OPT, p);
+      PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
+      PUTSHORT(0, p);    /* extended RCODE and version */
+      PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
+      lenp = p;
+      PUTSHORT(0, p);    /* RDLEN */
+      rdlen = 0;
+      if (((ssize_t)optlen) > (limit - (p + 4)))
+	return plen; /* Too big */
+      header->arcount = htons(ntohs(header->arcount) + 1);
+      datap = p;
+    }
+  else
+    {
+      int i;
+      unsigned short code, len, flags;
+      
+      /* Must be at the end, if exists */
+      if (ntohs(header->arcount) != 1 ||
+	  is_sign ||
+	  (!(p = skip_name(p, header, plen, 10))))
+	return plen;
+      
+      p += 6; /* skip UDP length and RCODE */
+      GETSHORT(flags, p);
+      if (set_do)
+	{
+	  p -=2;
+	  PUTSHORT(flags | 0x8000, p);
+	}
+
+      lenp = p;
+      GETSHORT(rdlen, p);
+      if (!CHECK_LEN(header, p, plen, rdlen))
+	return plen; /* bad packet */
+      datap = p;
+
+       /* no option to add */
+      if (optno == 0)
+	return plen;
+      	  
+      /* check if option already there */
+      for (i = 0; i + 4 < rdlen; i += len + 4)
+	{
+	  GETSHORT(code, p);
+	  GETSHORT(len, p);
+	  if (code == optno)
+	    return plen;
+	  p += len;
+	}
+      
+      if (((ssize_t)optlen) > (limit - (p + 4)))
+	return plen; /* Too big */
+    }
+  
+  if (optno != 0)
+    {
+      PUTSHORT(optno, p);
+      PUTSHORT(optlen, p);
+      memcpy(p, opt, optlen);
+      p += optlen;  
+    }
+
+  PUTSHORT(p - datap, lenp);
+  return p - (unsigned char *)header;
+  
+}
+
+static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
+{
+  struct macparm *parm = parmv;
+  int match = 0;
+    
+  if (family == parm->l3->sa.sa_family)
+    {
+      if (family == AF_INET && memcmp(&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
+	match = 1;
+#ifdef HAVE_IPV6
+      else
+	if (family == AF_INET6 && memcmp(&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
+	  match = 1;
+#endif
+    }
+ 
+  if (!match)
+    return 1; /* continue */
+
+  parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, PACKETSZ, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0);
+  
+  return 0; /* done */
+}	      
+     
+size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3)
+{
+  struct macparm parm;
+     
+  parm.header = header;
+  parm.limit = (unsigned char *)limit;
+  parm.plen = plen;
+  parm.l3 = l3;
+
+  iface_enumerate(AF_UNSPEC, &parm, filter_mac);
+  
+  return parm.plen; 
+}
+
+struct subnet_opt {
+  u16 family;
+  u8 source_netmask, scope_netmask;
+#ifdef HAVE_IPV6 
+  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;
+}
+
+static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
+{
+  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
+  
+  int len;
+  void *addrp;
+  int sa_family = source->sa.sa_family;
+
+#ifdef HAVE_IPV6
+  if (source->sa.sa_family == AF_INET6)
+    {
+      opt->source_netmask = daemon->add_subnet6->mask;
+      if (daemon->add_subnet6->addr_used) 
+	{
+	  sa_family = daemon->add_subnet6->addr.sa.sa_family;
+	  addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
+	} 
+      else 
+	addrp = &source->in6.sin6_addr;
+    }
+  else
+#endif
+    {
+      opt->source_netmask = daemon->add_subnet4->mask;
+      if (daemon->add_subnet4->addr_used)
+	{
+	  sa_family = daemon->add_subnet4->addr.sa.sa_family;
+	  addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
+	} 
+      else 
+	addrp = &source->in.sin_addr;
+    }
+  
+  opt->scope_netmask = 0;
+  len = 0;
+  
+  if (opt->source_netmask != 0)
+    {
+#ifdef HAVE_IPV6
+      opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
+#else
+      opt->family = htons(1);
+#endif
+      len = ((opt->source_netmask - 1) >> 3) + 1;
+      memcpy(opt->addr, addrp, len);
+      if (opt->source_netmask & 7)
+	opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
+    }
+
+  return len + 4;
+}
+ 
+size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source)
+{
+  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
+  
+  int len;
+  struct subnet_opt opt;
+  
+  len = calc_subnet_opt(&opt, source);
+  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0);
+}
+
+#ifdef HAVE_DNSSEC
+size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
+{
+  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1);
+}
+#endif
+
+int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
+{
+  /* Section 9.2, Check that subnet option in reply matches. */
+
+
+ int len, calc_len;
+  struct subnet_opt opt;
+  unsigned char *p;
+  int code, i, rdlen;
+  
+   calc_len = calc_subnet_opt(&opt, peer);
+   
+   if (!(p = skip_name(pseudoheader, header, plen, 10)))
+     return 1;
+   
+   p += 8; /* skip UDP length and RCODE */
+   
+   GETSHORT(rdlen, p);
+   if (!CHECK_LEN(header, p, plen, rdlen))
+     return 1; /* bad packet */
+   
+   /* check if option there */
+   for (i = 0; i + 4 < rdlen; i += len + 4)
+     {
+       GETSHORT(code, p);
+       GETSHORT(len, p);
+       if (code == EDNS0_OPTION_CLIENT_SUBNET)
+	 {
+	   /* make sure this doesn't mismatch. */
+	   opt.scope_netmask = p[3];
+	   if (len != calc_len || memcmp(p, &opt, len) != 0)
+	     return 0;
+	 }
+       p += len;
+     }
+   
+   return 1;
+}
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 18858a8..5d89287 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -408,340 +408,6 @@
   return ansp - (unsigned char *)header;
 }
 
-unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t  *len, unsigned char **p, int *is_sign)
-{
-  /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 
-     also return length of pseudoheader in *len and pointer to the UDP size in *p
-     Finally, check to see if a packet is signed. If it is we cannot change a single bit before
-     forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
-  
-  int i, arcount = ntohs(header->arcount);
-  unsigned char *ansp = (unsigned char *)(header+1);
-  unsigned short rdlen, type, class;
-  unsigned char *ret = NULL;
-
-  if (is_sign)
-    {
-      *is_sign = 0;
-
-      if (OPCODE(header) == QUERY)
-	{
-	  for (i = ntohs(header->qdcount); i != 0; i--)
-	    {
-	      if (!(ansp = skip_name(ansp, header, plen, 4)))
-		return NULL;
-	      
-	      GETSHORT(type, ansp); 
-	      GETSHORT(class, ansp);
-	      
-	      if (class == C_IN && type == T_TKEY)
-		*is_sign = 1;
-	    }
-	}
-    }
-  else
-    {
-      if (!(ansp = skip_questions(header, plen)))
-	return NULL;
-    }
-    
-  if (arcount == 0)
-    return NULL;
-  
-  if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
-    return NULL; 
-  
-  for (i = 0; i < arcount; i++)
-    {
-      unsigned char *save, *start = ansp;
-      if (!(ansp = skip_name(ansp, header, plen, 10)))
-	return NULL; 
-
-      GETSHORT(type, ansp);
-      save = ansp;
-      GETSHORT(class, ansp);
-      ansp += 4; /* TTL */
-      GETSHORT(rdlen, ansp);
-      if (!ADD_RDLEN(header, ansp, plen, rdlen))
-	return NULL;
-      if (type == T_OPT)
-	{
-	  if (len)
-	    *len = ansp - start;
-	  if (p)
-	    *p = save;
-	  ret = start;
-	}
-      else if (is_sign && 
-	       i == arcount - 1 && 
-	       class == C_ANY && 
-	       type == T_TSIG)
-	*is_sign = 1;
-    }
-  
-  return ret;
-}
-
-struct macparm {
-  unsigned char *limit;
-  struct dns_header *header;
-  size_t plen;
-  union mysockaddr *l3;
-};
- 
-size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
-			unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do)
-{ 
-  unsigned char *lenp, *datap, *p;
-  int rdlen, is_sign;
-  
-  if (!(p = find_pseudoheader(header, plen, NULL, NULL, &is_sign)))
-    {
-      if (is_sign)
-	return plen;
-
-      /* We are adding the pseudoheader */
-      if (!(p = skip_questions(header, plen)) ||
-	  !(p = skip_section(p, 
-			     ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
-			     header, plen)))
-	return plen;
-      *p++ = 0; /* empty name */
-      PUTSHORT(T_OPT, p);
-      PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
-      PUTSHORT(0, p);    /* extended RCODE and version */
-      PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
-      lenp = p;
-      PUTSHORT(0, p);    /* RDLEN */
-      rdlen = 0;
-      if (((ssize_t)optlen) > (limit - (p + 4)))
-	return plen; /* Too big */
-      header->arcount = htons(ntohs(header->arcount) + 1);
-      datap = p;
-    }
-  else
-    {
-      int i;
-      unsigned short code, len, flags;
-      
-      /* Must be at the end, if exists */
-      if (ntohs(header->arcount) != 1 ||
-	  is_sign ||
-	  (!(p = skip_name(p, header, plen, 10))))
-	return plen;
-      
-      p += 6; /* skip UDP length and RCODE */
-      GETSHORT(flags, p);
-      if (set_do)
-	{
-	  p -=2;
-	  PUTSHORT(flags | 0x8000, p);
-	}
-
-      lenp = p;
-      GETSHORT(rdlen, p);
-      if (!CHECK_LEN(header, p, plen, rdlen))
-	return plen; /* bad packet */
-      datap = p;
-
-       /* no option to add */
-      if (optno == 0)
-	return plen;
-      	  
-      /* check if option already there */
-      for (i = 0; i + 4 < rdlen; i += len + 4)
-	{
-	  GETSHORT(code, p);
-	  GETSHORT(len, p);
-	  if (code == optno)
-	    return plen;
-	  p += len;
-	}
-      
-      if (((ssize_t)optlen) > (limit - (p + 4)))
-	return plen; /* Too big */
-    }
-  
-  if (optno != 0)
-    {
-      PUTSHORT(optno, p);
-      PUTSHORT(optlen, p);
-      memcpy(p, opt, optlen);
-      p += optlen;  
-    }
-
-  PUTSHORT(p - datap, lenp);
-  return p - (unsigned char *)header;
-  
-}
-
-static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
-{
-  struct macparm *parm = parmv;
-  int match = 0;
-    
-  if (family == parm->l3->sa.sa_family)
-    {
-      if (family == AF_INET && memcmp(&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
-	match = 1;
-#ifdef HAVE_IPV6
-      else
-	if (family == AF_INET6 && memcmp(&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
-	  match = 1;
-#endif
-    }
- 
-  if (!match)
-    return 1; /* continue */
-
-  parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, PACKETSZ, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0);
-  
-  return 0; /* done */
-}	      
-     
-size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3)
-{
-  struct macparm parm;
-     
-  parm.header = header;
-  parm.limit = (unsigned char *)limit;
-  parm.plen = plen;
-  parm.l3 = l3;
-
-  iface_enumerate(AF_UNSPEC, &parm, filter_mac);
-  
-  return parm.plen; 
-}
-
-struct subnet_opt {
-  u16 family;
-  u8 source_netmask, scope_netmask;
-#ifdef HAVE_IPV6 
-  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;
-}
-
-static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
-{
-  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
-  
-  int len;
-  void *addrp;
-  int sa_family = source->sa.sa_family;
-
-#ifdef HAVE_IPV6
-  if (source->sa.sa_family == AF_INET6)
-    {
-      opt->source_netmask = daemon->add_subnet6->mask;
-      if (daemon->add_subnet6->addr_used) 
-	{
-	  sa_family = daemon->add_subnet6->addr.sa.sa_family;
-	  addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
-	} 
-      else 
-	addrp = &source->in6.sin6_addr;
-    }
-  else
-#endif
-    {
-      opt->source_netmask = daemon->add_subnet4->mask;
-      if (daemon->add_subnet4->addr_used)
-	{
-	  sa_family = daemon->add_subnet4->addr.sa.sa_family;
-	  addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
-	} 
-      else 
-	addrp = &source->in.sin_addr;
-    }
-  
-  opt->scope_netmask = 0;
-  len = 0;
-  
-  if (opt->source_netmask != 0)
-    {
-#ifdef HAVE_IPV6
-      opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
-#else
-      opt->family = htons(1);
-#endif
-      len = ((opt->source_netmask - 1) >> 3) + 1;
-      memcpy(opt->addr, addrp, len);
-      if (opt->source_netmask & 7)
-	opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
-    }
-
-  return len + 4;
-}
- 
-size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source)
-{
-  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
-  
-  int len;
-  struct subnet_opt opt;
-  
-  len = calc_subnet_opt(&opt, source);
-  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0);
-}
-
-#ifdef HAVE_DNSSEC
-size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
-{
-  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1);
-}
-#endif
-
-int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
-{
-  /* Section 9.2, Check that subnet option in reply matches. */
-
-
- int len, calc_len;
-  struct subnet_opt opt;
-  unsigned char *p;
-  int code, i, rdlen;
-  
-   calc_len = calc_subnet_opt(&opt, peer);
-   
-   if (!(p = skip_name(pseudoheader, header, plen, 10)))
-     return 1;
-   
-   p += 8; /* skip UDP length and RCODE */
-   
-   GETSHORT(rdlen, p);
-   if (!CHECK_LEN(header, p, plen, rdlen))
-     return 1; /* bad packet */
-   
-   /* check if option there */
-   for (i = 0; i + 4 < rdlen; i += len + 4)
-     {
-       GETSHORT(code, p);
-       GETSHORT(len, p);
-       if (code == EDNS0_OPTION_CLIENT_SUBNET)
-	 {
-	   /* make sure this doesn't mismatch. */
-	   opt.scope_netmask = p[3];
-	   if (len != calc_len || memcmp(p, &opt, len) != 0)
-	     return 0;
-	 }
-       p += len;
-     }
-   
-   return 1;
-}
-
 /* is addr in the non-globally-routed IP space? */ 
 int private_net(struct in_addr addr, int ban_localhost) 
 {