]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Add --ignore-address option.
authorGlen Huang <curvedmark@gmail.com>
Sat, 27 Dec 2014 15:28:12 +0000 (15:28 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Sat, 27 Dec 2014 15:28:12 +0000 (15:28 +0000)
CHANGELOG
man/dnsmasq.8
src/dnsmasq.h
src/forward.c
src/option.c
src/rfc1035.c

index 956b71a151dbc0a3bcd28ab958a9b050f38b674b..2b6356bcfb0280dcf38db1d25eb88f606a467b30 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,6 +22,14 @@ version 2.73
 
            Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids
            for the bug report.
+           
+           Add --ignore-address option. Ignore replies to A-record 
+           queries which include the specified address. No error is
+           generated, dnsmasq simply continues to listen for another 
+           reply. This is useful to defeat blocking strategies which
+           rely on quickly supplying a forged answer to a DNS 
+           request for certain domains, before the correct answer can
+            arrive. Thanks to Glen Huang for the patch.
        
 
 version 2.72
index 0b8e04f0a8971238993f360d2f809a62320d803e..4236ba307df393f46ce7f632eb6d6117614a5f32 100644 (file)
@@ -293,6 +293,12 @@ an advertising web page in response to queries for unregistered names,
 instead of the correct NXDOMAIN response. This option tells dnsmasq to
 fake the correct response when it sees this behaviour. As at Sept 2003
 the IP address being returned by Verisign is 64.94.110.11
+.TP 
+.B \-B, --ignore-address=<ipaddr>
+Ignore replies to A-record queries which include the specified address. 
+No error is generated, dnsmasq simply continues to listen for another reply. 
+This is useful to defeat blocking strategies which rely on quickly supplying a
+forged answer to a DNS request for certain domain, before the correct answer can arrive.
 .TP
 .B \-f, --filterwin2k
 Later versions of windows make periodic DNS requests which don't get sensible answers from
index 1dd61c5edba3d73a6f0051ae8687519f35379201..7bc982ddf73c8fc2d2485116316d8b8611d8e9ef 100644 (file)
@@ -930,7 +930,7 @@ extern struct daemon {
   char *runfile; 
   char *lease_change_command;
   struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
-  struct bogus_addr *bogus_addr;
+  struct bogus_addr *bogus_addr, *ignore_addr;
   struct server *servers;
   struct ipsets *ipsets;
   int log_fac; /* log facility */
@@ -1093,6 +1093,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                      time_t now, int *ad_reqd, int *do_bit);
 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
                             struct bogus_addr *addr, time_t now);
+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
 unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
                                 size_t *len, unsigned char **p, int *is_sign);
 int check_for_local_domain(char *name, time_t now);
index 408a179a20f4194818a169b8c67c8d53d5b755de..f28c7d51f708e49caccebaa51da1fc169be10e52 100644 (file)
@@ -724,6 +724,10 @@ void reply_query(int fd, int family, time_t now)
   if (!(forward = lookup_frec(ntohs(header->id), hash)))
     return;
   
+  if (daemon->ignore_addr && RCODE(header) == NOERROR &&
+      check_for_ignored_address(header, n, daemon->ignore_addr))
+    return;
+
   if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
       !option_bool(OPT_ORDER) &&
       forward->forwardall == 0)
index 209fa697660902dfdd4d8b711005ebdad8c7dc47..907d0cf88de9820018f00b926b16c35b50bce87b 100644 (file)
@@ -147,6 +147,7 @@ struct myoption {
 #define LOPT_LOCAL_SERVICE 335
 #define LOPT_DNSSEC_TIME   336
 #define LOPT_LOOP_DETECT   337
+#define LOPT_IGNORE_ADDR   338
 
 #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =  
@@ -181,6 +182,7 @@ static const struct myoption opts[] =
     { "local-service", 0, 0, LOPT_LOCAL_SERVICE },
     { "bogus-priv", 0, 0, 'b' },
     { "bogus-nxdomain", 1, 0, 'B' },
+    { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
     { "selfmx", 0, 0, 'e' },
     { "filterwin2k", 0, 0, 'f' },
     { "pid-file", 2, 0, 'x' },
@@ -457,6 +459,7 @@ static struct {
   { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
   { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL },
   { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL },
+  { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL }, 
   { 0, 0, NULL, NULL, NULL }
 }; 
 
@@ -2119,14 +2122,23 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
       break;
       
     case 'B':  /* --bogus-nxdomain */
-      {
+    case LOPT_IGNORE_ADDR: /* --ignore-address */
+     {
        struct in_addr addr;
        unhide_metas(arg);
        if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
          {
            struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
-           baddr->next = daemon->bogus_addr;
-           daemon->bogus_addr = baddr;
+           if (option == 'B')
+             {
+               baddr->next = daemon->bogus_addr;
+               daemon->bogus_addr = baddr;
+             }
+           else
+             {
+               baddr->next = daemon->ignore_addr;
+               daemon->ignore_addr = baddr;
+             }
            baddr->addr = addr;
          }
        else
index bdeb3fb10e6835ed4c9abfbec320ab927d7a1fb4..75c4266b47dd3a709a93e6479a109140f54aaab3 100644 (file)
@@ -1328,6 +1328,43 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
   return 0;
 }
 
+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr)
+{
+  unsigned char *p;
+  int i, qtype, qclass, rdlen;
+  struct bogus_addr *baddrp;
+
+  /* skip over questions */
+  if (!(p = skip_questions(header, qlen)))
+    return 0; /* bad packet */
+
+  for (i = ntohs(header->ancount); i != 0; i--)
+    {
+      if (!(p = skip_name(p, header, qlen, 10)))
+       return 0; /* bad packet */
+      
+      GETSHORT(qtype, p); 
+      GETSHORT(qclass, p);
+      p += 4; /* TTL */
+      GETSHORT(rdlen, p);
+      
+      if (qclass == C_IN && qtype == T_A)
+       {
+         if (!CHECK_LEN(header, p, qlen, INADDRSZ))
+           return 0;
+         
+         for (baddrp = baddr; baddrp; baddrp = baddrp->next)
+           if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
+             return 1;
+       }
+      
+      if (!ADD_RDLEN(header, p, qlen, rdlen))
+       return 0;
+    }
+  
+  return 0;
+}
+
 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, ...)
 {