Diff for /embedaddon/dnsmasq/src/auth.c between versions 1.1.1.3 and 1.1.1.5

version 1.1.1.3, 2016/11/02 09:57:01 version 1.1.1.5, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     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     it under the terms of the GNU General Public License as published by
Line 18 Line 18
   
 #ifdef HAVE_AUTH  #ifdef HAVE_AUTH
   
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)static struct addrlist *find_addrlist(struct addrlist *list, int flag, union all_addr *addr_u)
 {  {
  struct addrlist *subnet;  do {
     if (!(list->flags & ADDRLIST_IPV6))
       {
         struct in_addr netmask, addr = addr_u->addr4;
         
         if (!(flag & F_IPV4))
           continue;
         
         netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
         
         if  (is_same_net(addr, list->addr.addr4, netmask))
           return list;
       }
     else if (is_same_net6(&(addr_u->addr6), &list->addr.addr6, list->prefixlen))
       return list;
     
   } while ((list = list->next));
   
   return NULL;
 }
   
  for (subnet = zone->subnet; subnet; subnet = subnet->next)static struct addrlist *find_subnet(struct auth_zone *zone, int flag, union all_addr *addr_u)
    {{
      if (!(subnet->flags & ADDRLIST_IPV6))  if (!zone->subnet)
        {    return NULL;
          struct in_addr netmask, addr = addr_u->addr.addr4;  
   return find_addrlist(zone->subnet, flag, addr_u);
 }
   
          if (!(flag & F_IPV4))static struct addrlist *find_exclude(struct auth_zone *zone, int flag, union all_addr *addr_u)
            continue;{
            if (!zone->exclude)
          netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen));    return NULL;
            
          if  (is_same_net(addr, subnet->addr.addr.addr4, netmask))  return find_addrlist(zone->exclude, flag, addr_u);
            return subnet; 
        } 
#ifdef HAVE_IPV6 
      else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen)) 
        return subnet; 
#endif 
 
    } 
  return NULL; 
 }  }
   
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)static int filter_zone(struct auth_zone *zone, int flag, union all_addr *addr_u)
 {  {
  /* No zones specified, no filter */  if (find_exclude(zone, flag, addr_u))
     return 0;
 
   /* No subnets specified, no filter */
   if (!zone->subnet)    if (!zone->subnet)
     return 1;      return 1;
       
Line 86  size_t answer_auth(struct dns_header *header, char *li Line 101  size_t answer_auth(struct dns_header *header, char *li
 {  {
   char *name = daemon->namebuff;    char *name = daemon->namebuff;
   unsigned char *p, *ansp;    unsigned char *p, *ansp;
  int qtype, qclass;  int qtype, qclass, rc;
   int nameoffset, axfroffset = 0;    int nameoffset, axfroffset = 0;
   int q, anscount = 0, authcount = 0;    int q, anscount = 0, authcount = 0;
   struct crec *crecp;    struct crec *crecp;
  int  auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;  int  auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0, out_of_zone = 0;
   struct auth_zone *zone = NULL;    struct auth_zone *zone = NULL;
   struct addrlist *subnet = NULL;    struct addrlist *subnet = NULL;
   char *cut;    char *cut;
Line 98  size_t answer_auth(struct dns_header *header, char *li Line 113  size_t answer_auth(struct dns_header *header, char *li
   struct txt_record *txt;    struct txt_record *txt;
   struct interface_name *intr;    struct interface_name *intr;
   struct naptr *na;    struct naptr *na;
  struct all_addr addr;  union all_addr addr;
  struct cname *a;  struct cname *a, *candidate;
   unsigned int wclen;
       
   if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )    if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
     return 0;      return 0;
Line 113  size_t answer_auth(struct dns_header *header, char *li Line 129  size_t answer_auth(struct dns_header *header, char *li
   
   for (q = ntohs(header->qdcount); q != 0; q--)    for (q = ntohs(header->qdcount); q != 0; q--)
     {      {
      unsigned short flag = 0;      unsigned int flag = 0;
       int found = 0;        int found = 0;
         int cname_wildcard = 0;
       
       /* save pointer to name for copying into answers */        /* save pointer to name for copying into answers */
       nameoffset = p - (unsigned char *)header;        nameoffset = p - (unsigned char *)header;
Line 129  size_t answer_auth(struct dns_header *header, char *li Line 146  size_t answer_auth(struct dns_header *header, char *li
       if (qclass != C_IN)        if (qclass != C_IN)
         {          {
           auth = 0;            auth = 0;
             out_of_zone = 1;
           continue;            continue;
         }          }
   
Line 142  size_t answer_auth(struct dns_header *header, char *li Line 160  size_t answer_auth(struct dns_header *header, char *li
                       
           if (!zone)            if (!zone)
             {              {
                 out_of_zone = 1;
               auth = 0;                auth = 0;
               continue;                continue;
             }              }
Line 161  size_t answer_auth(struct dns_header *header, char *li Line 180  size_t answer_auth(struct dns_header *header, char *li
                 struct addrlist *addrlist;                  struct addrlist *addrlist;
                                   
                 for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)                  for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
                  if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)                  if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr4.s_addr == addrlist->addr.addr4.s_addr)
                     break;                      break;
                                   
                 if (addrlist)                  if (addrlist)
Line 170  size_t answer_auth(struct dns_header *header, char *li Line 189  size_t answer_auth(struct dns_header *header, char *li
                   while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)                    while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
                     intr = intr->next;                      intr = intr->next;
               }                }
 #ifdef HAVE_IPV6  
           else if (flag == F_IPV6)            else if (flag == F_IPV6)
             for (intr = daemon->int_names; intr; intr = intr->next)              for (intr = daemon->int_names; intr; intr = intr->next)
               {                {
                 struct addrlist *addrlist;                  struct addrlist *addrlist;
                                   
                 for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)                  for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
                  if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))                  if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr6, &addrlist->addr.addr6))
                     break;                      break;
                                   
                 if (addrlist)                  if (addrlist)
Line 186  size_t answer_auth(struct dns_header *header, char *li Line 204  size_t answer_auth(struct dns_header *header, char *li
                   while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)                    while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
                     intr = intr->next;                      intr = intr->next;
               }                }
 #endif  
                       
           if (intr)            if (intr)
             {              {
               if (local_query || in_zone(zone, intr->name, NULL))                if (local_query || in_zone(zone, intr->name, NULL))
                 {                         {       
                   found = 1;                    found = 1;
                  log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);                  log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
                   if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                           daemon->auth_ttl, NULL,                                            daemon->auth_ttl, NULL,
                                           T_PTR, C_IN, "d", intr->name))                                            T_PTR, C_IN, "d", intr->name))
Line 217  size_t answer_auth(struct dns_header *header, char *li Line 234  size_t answer_auth(struct dns_header *header, char *li
                       strcat(name, ".");                        strcat(name, ".");
                       strcat(name, zone->domain);                        strcat(name, zone->domain);
                     }                      }
                  log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));                  log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid), 0);
                   found = 1;                    found = 1;
                   if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                           daemon->auth_ttl, NULL,                                            daemon->auth_ttl, NULL,
Line 226  size_t answer_auth(struct dns_header *header, char *li Line 243  size_t answer_auth(struct dns_header *header, char *li
                 }                  }
               else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))                else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
                 {                  {
                  log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));                  log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid), 0);
                   found = 1;                    found = 1;
                   if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                           daemon->auth_ttl, NULL,                                            daemon->auth_ttl, NULL,
Line 238  size_t answer_auth(struct dns_header *header, char *li Line 255  size_t answer_auth(struct dns_header *header, char *li
                                           
             } while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));              } while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
   
             if (!found && is_rev_synth(flag, &addr, name) && (local_query || in_zone(zone, name, NULL)))
               {
                 log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL, 0);
                 found = 1;
                 
                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                         daemon->auth_ttl, NULL,
                                         T_PTR, C_IN, "d", name))
                   anscount++;
               }
   
           if (found)            if (found)
             nxdomain = 0;              nxdomain = 0;
           else            else
            log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);            log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL, 0);
   
           continue;            continue;
         }          }
Line 258  size_t answer_auth(struct dns_header *header, char *li Line 286  size_t answer_auth(struct dns_header *header, char *li
                       
           if (!zone)            if (!zone)
             {              {
                 out_of_zone = 1;
               auth = 0;                auth = 0;
               continue;                continue;
             }              }
         }          }
   
       for (rec = daemon->mxnames; rec; rec = rec->next)        for (rec = daemon->mxnames; rec; rec = rec->next)
        if (!rec->issrv && hostname_isequal(name, rec->name))        if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
           {            {
             nxdomain = 0;              nxdomain = 0;
                                     
            if (qtype == T_MX)            if (rc == 2 && qtype == T_MX)
               {                {
                 found = 1;                  found = 1;
                log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");                 log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                                         NULL, T_MX, C_IN, "sd", rec->weight, rec->target))                                          NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
                   anscount++;                    anscount++;
Line 279  size_t answer_auth(struct dns_header *header, char *li Line 308  size_t answer_auth(struct dns_header *header, char *li
           }            }
               
       for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)        for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
        if (rec->issrv && hostname_isequal(name, rec->name))        if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
           {            {
             nxdomain = 0;              nxdomain = 0;
                           
            if (qtype == T_SRV)            if (rc == 2 && qtype == T_SRV)
               {                {
                 found = 1;                  found = 1;
                log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");                 log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                                         NULL, T_SRV, C_IN, "sssd",                                           NULL, T_SRV, C_IN, "sssd", 
                                         rec->priority, rec->weight, rec->srvport, rec->target))                                          rec->priority, rec->weight, rec->srvport, rec->target))
Line 314  size_t answer_auth(struct dns_header *header, char *li Line 343  size_t answer_auth(struct dns_header *header, char *li
         }          }
   
       for (txt = daemon->rr; txt; txt = txt->next)        for (txt = daemon->rr; txt; txt = txt->next)
        if (hostname_isequal(name, txt->name))        if ((rc = hostname_issubdomain(name, txt->name)))
           {            {
             nxdomain = 0;              nxdomain = 0;
            if (txt->class == qtype)            if (rc == 2 && txt->class == qtype)
               {                {
                 found = 1;                  found = 1;
                log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");                 log_query(F_CONFIG | F_RRNAME, name, NULL, NULL, txt->class);
                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                                         NULL, txt->class, C_IN, "t", txt->len, txt->txt))                                          NULL, txt->class, C_IN, "t", txt->len, txt->txt))
                   anscount++;                    anscount++;
Line 328  size_t answer_auth(struct dns_header *header, char *li Line 357  size_t answer_auth(struct dns_header *header, char *li
           }            }
               
       for (txt = daemon->txt; txt; txt = txt->next)        for (txt = daemon->txt; txt; txt = txt->next)
        if (txt->class == C_IN && hostname_isequal(name, txt->name))        if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
           {            {
             nxdomain = 0;              nxdomain = 0;
            if (qtype == T_TXT)            if (rc == 2 && qtype == T_TXT)
               {                {
                 found = 1;                  found = 1;
                log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");                 log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                                         NULL, T_TXT, C_IN, "t", txt->len, txt->txt))                                          NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
                   anscount++;                    anscount++;
Line 342  size_t answer_auth(struct dns_header *header, char *li Line 371  size_t answer_auth(struct dns_header *header, char *li
           }            }
   
        for (na = daemon->naptr; na; na = na->next)         for (na = daemon->naptr; na; na = na->next)
         if (hostname_isequal(name, na->name))         if ((rc = hostname_issubdomain(name, na->name)))
            {             {
              nxdomain = 0;               nxdomain = 0;
             if (qtype == T_NAPTR)             if (rc == 2 && qtype == T_NAPTR)
                {                 {
                  found = 1;                   found = 1;
                 log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");                 log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,                    if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl, 
                                          NULL, T_NAPTR, C_IN, "sszzzd",                                            NULL, T_NAPTR, C_IN, "sszzzd", 
                                          na->order, na->pref, na->flags, na->services, na->regexp, na->replace))                                           na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
Line 359  size_t answer_auth(struct dns_header *header, char *li Line 388  size_t answer_auth(struct dns_header *header, char *li
        if (qtype == T_A)         if (qtype == T_A)
          flag = F_IPV4;           flag = F_IPV4;
                 
 #ifdef HAVE_IPV6  
        if (qtype == T_AAAA)         if (qtype == T_AAAA)
          flag = F_IPV6;           flag = F_IPV6;
 #endif  
                 
        for (intr = daemon->int_names; intr; intr = intr->next)         for (intr = daemon->int_names; intr; intr = intr->next)
         if (hostname_isequal(name, intr->name))         if ((rc = hostname_issubdomain(name, intr->name)))
            {             {
              struct addrlist *addrlist;               struct addrlist *addrlist;
                             
              nxdomain = 0;               nxdomain = 0;
                             
             if (flag)             if (rc == 2 && flag)
                for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)                   for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)  
                  if (((addrlist->flags & ADDRLIST_IPV6)  ? T_AAAA : T_A) == qtype &&                   if (((addrlist->flags & ADDRLIST_IPV6)  ? T_AAAA : T_A) == qtype &&
                      (local_query || filter_zone(zone, flag, &addrlist->addr)))                       (local_query || filter_zone(zone, flag, &addrlist->addr)))
                    {                     {
 #ifdef HAVE_IPV6  
                      if (addrlist->flags & ADDRLIST_REVONLY)                       if (addrlist->flags & ADDRLIST_REVONLY)
                        continue;                         continue;
#endif
                      found = 1;                       found = 1;
                     log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);                     log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,                        if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                              daemon->auth_ttl, NULL, qtype, C_IN,                                                daemon->auth_ttl, NULL, qtype, C_IN, 
                                              qtype == T_A ? "4" : "6", &addrlist->addr))                                               qtype == T_A ? "4" : "6", &addrlist->addr))
                        anscount++;                         anscount++;
                    }                     }
              }               }
          
        for (a = daemon->cnames; a; a = a->next)  
          if (hostname_isequal(name, a->alias) )  
            {  
              log_query(F_CONFIG | F_CNAME, name, NULL, NULL);  
              strcpy(name, a->target);  
              if (!strchr(name, '.'))  
                {  
                  strcat(name, ".");  
                  strcat(name, zone->domain);  
                }  
              found = 1;  
              if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,   
                                      daemon->auth_ttl, &nameoffset,  
                                      T_CNAME, C_IN, "d", name))  
                anscount++;  
                
              goto cname_restart;  
            }  
   
          if (!found && is_name_synthetic(flag, name, &addr) )
            {
              nxdomain = 0;
              
              log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
              if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                      daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
                anscount++;
            }
          
       if (!cut)        if (!cut)
         {          {
           nxdomain = 0;            nxdomain = 0;
Line 415  size_t answer_auth(struct dns_header *header, char *li Line 432  size_t answer_auth(struct dns_header *header, char *li
           if (qtype == T_SOA)            if (qtype == T_SOA)
             {              {
               auth = soa = 1; /* inhibits auth section */                auth = soa = 1; /* inhibits auth section */
              found = 1;              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>", 0);
              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>"); 
             }              }
           else if (qtype == T_AXFR)            else if (qtype == T_AXFR)
             {              {
Line 424  size_t answer_auth(struct dns_header *header, char *li Line 440  size_t answer_auth(struct dns_header *header, char *li
                               
               if (peer_addr->sa.sa_family == AF_INET)                if (peer_addr->sa.sa_family == AF_INET)
                 peer_addr->in.sin_port = 0;                  peer_addr->in.sin_port = 0;
 #ifdef HAVE_IPV6  
               else                else
                 {                  {
                   peer_addr->in6.sin6_port = 0;                     peer_addr->in6.sin6_port = 0; 
                   peer_addr->in6.sin6_scope_id = 0;                    peer_addr->in6.sin6_scope_id = 0;
                 }                  }
 #endif  
                               
               for (peers = daemon->auth_peers; peers; peers = peers->next)                for (peers = daemon->auth_peers; peers; peers = peers->next)
                 if (sockaddr_isequal(peer_addr, &peers->addr))                  if (sockaddr_isequal(peer_addr, &peers->addr))
                   break;                    break;
                               
              /* Refuse all AXFR unless --auth-sec-servers is set */              /* Refuse all AXFR unless --auth-sec-servers or auth-peers is set */
              if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)              if ((!daemon->secondary_forward_server && !daemon->auth_peers) ||
                   (daemon->auth_peers && !peers)) 
                 {                  {
                   if (peer_addr->sa.sa_family == AF_INET)                    if (peer_addr->sa.sa_family == AF_INET)
                     inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);                      inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
 #ifdef HAVE_IPV6  
                   else                    else
                     inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);                       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);                    my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
                   return 0;                    return 0;
Line 454  size_t answer_auth(struct dns_header *header, char *li Line 467  size_t answer_auth(struct dns_header *header, char *li
               soa = 1; /* inhibits auth section */                soa = 1; /* inhibits auth section */
               ns = 1; /* ensure we include NS records! */                ns = 1; /* ensure we include NS records! */
               axfr = 1;                axfr = 1;
               found = 1;  
               axfroffset = nameoffset;                axfroffset = nameoffset;
              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>", 0);
             }              }
           else if (qtype == T_NS)            else if (qtype == T_NS)
             {              {
               auth = 1;                auth = 1;
               ns = 1; /* inhibits auth section */                ns = 1; /* inhibits auth section */
              found = 1;              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>", 0);
              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");  
             }              }
         }          }
               
Line 478  size_t answer_auth(struct dns_header *header, char *li Line 489  size_t answer_auth(struct dns_header *header, char *li
                   {                     { 
                     nxdomain = 0;                      nxdomain = 0;
                     if ((crecp->flags & flag) &&                       if ((crecp->flags & flag) && 
                        (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))                        (local_query || filter_zone(zone, flag, &(crecp->addr))))
                       {                        {
                         *cut = '.'; /* restore domain part */                          *cut = '.'; /* restore domain part */
                        log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));                        log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
                         *cut  = 0; /* remove domain part */                          *cut  = 0; /* remove domain part */
                         found = 1;  
                         if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,                           if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                                 daemon->auth_ttl, NULL, qtype, C_IN,                                                   daemon->auth_ttl, NULL, qtype, C_IN, 
                                                 qtype == T_A ? "4" : "6", &crecp->addr))                                                  qtype == T_A ? "4" : "6", &crecp->addr))
Line 501  size_t answer_auth(struct dns_header *header, char *li Line 511  size_t answer_auth(struct dns_header *header, char *li
             do              do
               {                 { 
                  nxdomain = 0;                   nxdomain = 0;
                 if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))                 if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
                    {                     {
                     log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));                     log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
                     found = 1; 
                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,                        if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                              daemon->auth_ttl, NULL, qtype, C_IN,                                                daemon->auth_ttl, NULL, qtype, C_IN, 
                                              qtype == T_A ? "4" : "6", &crecp->addr))                                               qtype == T_A ? "4" : "6", &crecp->addr))
Line 513  size_t answer_auth(struct dns_header *header, char *li Line 522  size_t answer_auth(struct dns_header *header, char *li
               } while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));                } while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
         }          }
               
      if (!found)      /* Only supply CNAME if no record for any type is known. */
        log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);      if (nxdomain)
         {
           /* Check for possible wildcard match against *.domain 
              return length of match, to get longest.
              Note that if return length of wildcard section, so
              we match b.simon to _both_ *.simon and b.simon
              but return a longer (better) match to b.simon.
           */  
           for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
             if (a->alias[0] == '*')
               {
                 char *test = name;
                 
                 while ((test = strchr(test+1, '.')))
                   {
                     if (hostname_isequal(test, &(a->alias[1])))
                       {
                         if (strlen(test) > wclen && !cname_wildcard)
                           {
                             wclen = strlen(test);
                             candidate = a;
                             cname_wildcard = 1;
                           }
                         break;
                       }
                   }
                 
               }
             else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
               {
                 /* Simple case, no wildcard */
                 wclen = strlen(a->alias);
                 candidate = a;
               }
           
           if (candidate)
             {
               log_query(F_CONFIG | F_CNAME, name, NULL, NULL, 0);
               strcpy(name, candidate->target);
               if (!strchr(name, '.'))
                 {
                   strcat(name, ".");
                   strcat(name, zone->domain);
                 }
               found = 1;
               if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                       daemon->auth_ttl, &nameoffset,
                                       T_CNAME, C_IN, "d", name))
                 anscount++;
               
               goto cname_restart;
             }
           else if (cache_find_non_terminal(name, now))
             nxdomain = 0;
 
           log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL, 0);
         }
               
     }      }
       
Line 534  size_t answer_auth(struct dns_header *header, char *li Line 599  size_t answer_auth(struct dns_header *header, char *li
   
           if (!(subnet->flags & ADDRLIST_IPV6))            if (!(subnet->flags & ADDRLIST_IPV6))
             {              {
              in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;              in_addr_t a = ntohl(subnet->addr.addr4.s_addr) >> 8;
               char *p = name;                char *p = name;
                               
               if (subnet->prefixlen >= 24)                if (subnet->prefixlen >= 24)
                p += sprintf(p, "%d.", a & 0xff);                p += sprintf(p, "%u.", a & 0xff);
               a = a >> 8;                a = a >> 8;
               if (subnet->prefixlen >= 16 )                if (subnet->prefixlen >= 16 )
                p += sprintf(p, "%d.", a & 0xff);                p += sprintf(p, "%u.", a & 0xff);
               a = a >> 8;                a = a >> 8;
              p += sprintf(p, "%d.in-addr.arpa", a & 0xff);              sprintf(p, "%u.in-addr.arpa", a & 0xff);
                               
             }              }
 #ifdef HAVE_IPV6  
           else            else
             {              {
               char *p = name;                char *p = name;
Line 554  size_t answer_auth(struct dns_header *header, char *li Line 618  size_t answer_auth(struct dns_header *header, char *li
                               
               for (i = subnet->prefixlen-1; i >= 0; i -= 4)                for (i = subnet->prefixlen-1; i >= 0; i -= 4)
                 {                   { 
                  int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];                  int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
                   p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);                    p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
                 }                  }
              p += sprintf(p, "ip6.arpa");              sprintf(p, "ip6.arpa");
                               
             }              }
 #endif  
         }          }
               
       /* handle NS and SOA in auth section or for explicit queries */        /* handle NS and SOA in auth section or for explicit queries */
Line 584  size_t answer_auth(struct dns_header *header, char *li Line 647  size_t answer_auth(struct dns_header *header, char *li
         {          {
           struct name_list *secondary;            struct name_list *secondary;
                       
          newoffset = ansp - (unsigned char *)header;          /* Only include the machine running dnsmasq if it's acting as an auth server */
          if (add_resource_record(header, limit, &trunc, -offset, &ansp,           if (daemon->authinterface)
                                  daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver)) 
             {              {
              if (offset == 0)               newoffset = ansp - (unsigned char *)header;
                offset = newoffset;              if (add_resource_record(header, limit, &trunc, -offset, &ansp, 
              if (ns)                                       daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
                anscount++;                {
              else                  if (offset == 0) 
                authcount++;                    offset = newoffset;
                   if (ns) 
                     anscount++;
                   else
                     authcount++;
                 }
             }              }
   
           if (!subnet)            if (!subnet)
Line 697  size_t answer_auth(struct dns_header *header, char *li Line 764  size_t answer_auth(struct dns_header *header, char *li
                                           daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))                                            daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
                     anscount++;                      anscount++;
                                   
 #ifdef HAVE_IPV6  
                 for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)                   for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) 
                   if ((addrlist->flags & ADDRLIST_IPV6) &&                     if ((addrlist->flags & ADDRLIST_IPV6) && 
                       (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&                        (local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
                       add_resource_record(header, limit, &trunc, -axfroffset, &ansp,                         add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                                           daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))                                            daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
                     anscount++;                      anscount++;
 #endif                
                                   
                 /* restore config data */                  /* restore config data */
                 if (cut)                  if (cut)
Line 741  size_t answer_auth(struct dns_header *header, char *li Line 806  size_t answer_auth(struct dns_header *header, char *li
                     {                      {
                       char *cache_name = cache_get_name(crecp);                        char *cache_name = cache_get_name(crecp);
                       if (!strchr(cache_name, '.') &&                         if (!strchr(cache_name, '.') && 
                          (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))                          (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr))) &&
                        {                          add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                          qtype = T_A;                                              daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN, 
#ifdef HAVE_IPV6                                              (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
                          if (crecp->flags & F_IPV6)                        anscount++;
                            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++; 
                        } 
                     }                      }
                                       
                   if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))                    if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
                     {                      {
                       strcpy(name, cache_get_name(crecp));                        strcpy(name, cache_get_name(crecp));
                       if (in_zone(zone, name, &cut) &&                         if (in_zone(zone, name, &cut) && 
                          (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))                          (local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr))))
                         {                          {
                          qtype = T_A;                          if (cut)
#ifdef HAVE_IPV6                            *cut = 0;
                          if (crecp->flags & F_IPV6) 
                            qtype = T_AAAA; 
#endif 
                           if (cut) 
                             *cut = 0; 
   
                           if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,                           if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                                                   daemon->auth_ttl, NULL, qtype, C_IN,                                                   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))                                                  (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
                             anscount++;                            anscount++;
                         }                          }
                     }                      }
                 }                  }
Line 806  size_t answer_auth(struct dns_header *header, char *li Line 859  size_t answer_auth(struct dns_header *header, char *li
       header->hb4 &= ~HB4_RA;        header->hb4 &= ~HB4_RA;
     }      }
   
  /* authoritive */  /* data is never DNSSEC signed. */
   header->hb4 &= ~HB4_AD;
 
   /* authoritative */
   if (auth)    if (auth)
     header->hb3 |= HB3_AA;      header->hb3 |= HB3_AA;
       
Line 818  size_t answer_auth(struct dns_header *header, char *li Line 874  size_t answer_auth(struct dns_header *header, char *li
     SET_RCODE(header, NXDOMAIN);      SET_RCODE(header, NXDOMAIN);
   else    else
     SET_RCODE(header, NOERROR); /* no error */      SET_RCODE(header, NOERROR); /* no error */
     
   header->ancount = htons(anscount);    header->ancount = htons(anscount);
   header->nscount = htons(authcount);    header->nscount = htons(authcount);
   header->arcount = htons(0);    header->arcount = htons(0);
   
     if (!local_query && out_of_zone)
       {
         SET_RCODE(header, REFUSED); 
         header->ancount = htons(0);
         header->nscount = htons(0);
         addr.log.rcode = REFUSED;
         addr.log.ede = EDE_NOT_AUTH;
         log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL, 0);
         return resize_packet(header,  ansp - (unsigned char *)header, NULL, 0);
       }
     
   /* Advertise our packet size limit in our reply */    /* Advertise our packet size limit in our reply */
   if (have_pseudoheader)    if (have_pseudoheader)
     return add_pseudoheader(header,  ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);      return add_pseudoheader(header,  ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
Line 830  size_t answer_auth(struct dns_header *header, char *li Line 898  size_t answer_auth(struct dns_header *header, char *li
 }  }
       
 #endif    #endif  
     
   
   

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.5


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>