Annotation of embedaddon/dnsmasq/src/forward.c, revision 1.1.1.3

1.1.1.3 ! misho       1: /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
1.1       misho       2: 
                      3:    This program is free software; you can redistribute it and/or modify
                      4:    it under the terms of the GNU General Public License as published by
                      5:    the Free Software Foundation; version 2 dated June, 1991, or
                      6:    (at your option) version 3 dated 29 June, 2007.
                      7:  
                      8:    This program is distributed in the hope that it will be useful,
                      9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     11:    GNU General Public License for more details.
                     12:      
                     13:    You should have received a copy of the GNU General Public License
                     14:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
                     15: */
                     16: 
                     17: #include "dnsmasq.h"
                     18: 
1.1.1.2   misho      19: static struct frec *lookup_frec(unsigned short id, void *hash);
1.1       misho      20: static struct frec *lookup_frec_by_sender(unsigned short id,
                     21:                                          union mysockaddr *addr,
1.1.1.2   misho      22:                                          void *hash);
                     23: static unsigned short get_id(void);
1.1       misho      24: static void free_frec(struct frec *f);
1.1.1.2   misho      25: 
1.1       misho      26: /* Send a UDP packet with its source address set as "source" 
                     27:    unless nowild is true, when we just send it with the kernel default */
                     28: int send_from(int fd, int nowild, char *packet, size_t len, 
                     29:              union mysockaddr *to, struct all_addr *source,
                     30:              unsigned int iface)
                     31: {
                     32:   struct msghdr msg;
                     33:   struct iovec iov[1]; 
                     34:   union {
                     35:     struct cmsghdr align; /* this ensures alignment */
                     36: #if defined(HAVE_LINUX_NETWORK)
                     37:     char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
                     38: #elif defined(IP_SENDSRCADDR)
                     39:     char control[CMSG_SPACE(sizeof(struct in_addr))];
                     40: #endif
                     41: #ifdef HAVE_IPV6
                     42:     char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
                     43: #endif
                     44:   } control_u;
                     45:   
                     46:   iov[0].iov_base = packet;
                     47:   iov[0].iov_len = len;
                     48: 
                     49:   msg.msg_control = NULL;
                     50:   msg.msg_controllen = 0;
                     51:   msg.msg_flags = 0;
                     52:   msg.msg_name = to;
                     53:   msg.msg_namelen = sa_len(to);
                     54:   msg.msg_iov = iov;
                     55:   msg.msg_iovlen = 1;
                     56:   
                     57:   if (!nowild)
                     58:     {
                     59:       struct cmsghdr *cmptr;
                     60:       msg.msg_control = &control_u;
                     61:       msg.msg_controllen = sizeof(control_u);
                     62:       cmptr = CMSG_FIRSTHDR(&msg);
                     63: 
                     64:       if (to->sa.sa_family == AF_INET)
                     65:        {
                     66: #if defined(HAVE_LINUX_NETWORK)
                     67:          struct in_pktinfo p;
                     68:          p.ipi_ifindex = 0;
                     69:          p.ipi_spec_dst = source->addr.addr4;
                     70:          memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
                     71:          msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
                     72:          cmptr->cmsg_level = IPPROTO_IP;
                     73:          cmptr->cmsg_type = IP_PKTINFO;
                     74: #elif defined(IP_SENDSRCADDR)
                     75:          memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
                     76:          msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
                     77:          cmptr->cmsg_level = IPPROTO_IP;
                     78:          cmptr->cmsg_type = IP_SENDSRCADDR;
                     79: #endif
                     80:        }
                     81:       else
                     82: #ifdef HAVE_IPV6
                     83:        {
                     84:          struct in6_pktinfo p;
                     85:          p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
                     86:          p.ipi6_addr = source->addr.addr6;
                     87:          memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
                     88:          msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
                     89:          cmptr->cmsg_type = daemon->v6pktinfo;
                     90:          cmptr->cmsg_level = IPPROTO_IPV6;
                     91:        }
                     92: #else
                     93:       (void)iface; /* eliminate warning */
                     94: #endif
                     95:     }
                     96:   
1.1.1.3 ! misho      97:   while (retry_send(sendmsg(fd, &msg, 0)));
        !            98: 
        !            99:   /* If interface is still in DAD, EINVAL results - ignore that. */
        !           100:   if (errno != 0 && errno != EINVAL)
1.1       misho     101:     {
                    102:       my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
                    103:       return 0;
                    104:     }
                    105:   
                    106:   return 1;
                    107: }
                    108:           
1.1.1.3 ! misho     109: static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
        !           110:                                   char *qdomain, int *type, char **domain, int *norebind)
1.1       misho     111:                              
                    112: {
                    113:   /* If the query ends in the domain in one of our servers, set
                    114:      domain to point to that name. We find the largest match to allow both
                    115:      domain.org and sub.domain.org to exist. */
                    116:   
                    117:   unsigned int namelen = strlen(qdomain);
                    118:   unsigned int matchlen = 0;
                    119:   struct server *serv;
                    120:   unsigned int flags = 0;
                    121:   
                    122:   for (serv = daemon->servers; serv; serv=serv->next)
                    123:     /* domain matches take priority over NODOTS matches */
                    124:     if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
                    125:       {
                    126:        unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; 
                    127:        *type = SERV_FOR_NODOTS;
                    128:        if (serv->flags & SERV_NO_ADDR)
                    129:          flags = F_NXDOMAIN;
                    130:        else if (serv->flags & SERV_LITERAL_ADDRESS) 
                    131:          { 
                    132:            if (sflag & qtype)
                    133:              {
                    134:                flags = sflag;
                    135:                if (serv->addr.sa.sa_family == AF_INET) 
                    136:                  *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
                    137: #ifdef HAVE_IPV6
                    138:                else
                    139:                  *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
                    140: #endif 
                    141:              }
                    142:            else if (!flags || (flags & F_NXDOMAIN))
                    143:              flags = F_NOERR;
                    144:          } 
                    145:       }
                    146:     else if (serv->flags & SERV_HAS_DOMAIN)
                    147:       {
                    148:        unsigned int domainlen = strlen(serv->domain);
                    149:        char *matchstart = qdomain + namelen - domainlen;
                    150:        if (namelen >= domainlen &&
                    151:            hostname_isequal(matchstart, serv->domain) &&
                    152:            (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
                    153:          {
1.1.1.3 ! misho     154:            if ((serv->flags & SERV_NO_REBIND) && norebind)     
1.1       misho     155:              *norebind = 1;
                    156:            else
                    157:              {
                    158:                unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
                    159:                /* implement priority rules for --address and --server for same domain.
                    160:                   --address wins if the address is for the correct AF
                    161:                   --server wins otherwise. */
                    162:                if (domainlen != 0 && domainlen == matchlen)
                    163:                  {
                    164:                    if ((serv->flags & SERV_LITERAL_ADDRESS))
                    165:                      {
                    166:                        if (!(sflag & qtype) && flags == 0)
                    167:                          continue;
                    168:                      }
                    169:                    else
                    170:                      {
                    171:                        if (flags & (F_IPV4 | F_IPV6))
                    172:                          continue;
                    173:                      }
                    174:                  }
                    175:                
                    176:                if (domainlen >= matchlen)
                    177:                  {
1.1.1.3 ! misho     178:                    *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
1.1       misho     179:                    *domain = serv->domain;
                    180:                    matchlen = domainlen;
                    181:                    if (serv->flags & SERV_NO_ADDR)
                    182:                      flags = F_NXDOMAIN;
                    183:                    else if (serv->flags & SERV_LITERAL_ADDRESS)
                    184:                      {
                    185:                        if (sflag & qtype)
                    186:                          {
                    187:                            flags = sflag;
                    188:                            if (serv->addr.sa.sa_family == AF_INET) 
                    189:                              *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
                    190: #ifdef HAVE_IPV6
                    191:                            else
                    192:                              *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
                    193: #endif
                    194:                          }
                    195:                        else if (!flags || (flags & F_NXDOMAIN))
                    196:                          flags = F_NOERR;
                    197:                      }
                    198:                    else
                    199:                      flags = 0;
                    200:                  } 
                    201:              }
                    202:          }
                    203:       }
                    204:   
                    205:   if (flags == 0 && !(qtype & F_QUERY) && 
                    206:       option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
                    207:     /* don't forward A or AAAA queries for simple names, except the empty name */
                    208:     flags = F_NOERR;
                    209:   
                    210:   if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
                    211:     flags = F_NOERR;
                    212: 
                    213:   if (flags)
                    214:     {
                    215:       int logflags = 0;
                    216:       
                    217:       if (flags == F_NXDOMAIN || flags == F_NOERR)
                    218:        logflags = F_NEG | qtype;
                    219:   
                    220:       log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
                    221:     }
                    222:   else if ((*type) & SERV_USE_RESOLV)
                    223:     {
                    224:       *type = 0; /* use normal servers for this domain */
                    225:       *domain = NULL;
                    226:     }
                    227:   return  flags;
                    228: }
                    229: 
                    230: static int forward_query(int udpfd, union mysockaddr *udpaddr,
                    231:                         struct all_addr *dst_addr, unsigned int dst_iface,
1.1.1.2   misho     232:                         struct dns_header *header, size_t plen, time_t now, 
                    233:                         struct frec *forward, int ad_reqd, int do_bit)
1.1       misho     234: {
                    235:   char *domain = NULL;
1.1.1.3 ! misho     236:   int type = SERV_DO_DNSSEC, norebind = 0;
1.1       misho     237:   struct all_addr *addrp = NULL;
                    238:   unsigned int flags = 0;
                    239:   struct server *start = NULL;
1.1.1.2   misho     240: #ifdef HAVE_DNSSEC
                    241:   void *hash = hash_questions(header, plen, daemon->namebuff);
1.1.1.3 ! misho     242:   int do_dnssec = 0;
1.1.1.2   misho     243: #else
                    244:   unsigned int crc = questions_crc(header, plen, daemon->namebuff);
                    245:   void *hash = &crc;
                    246: #endif
                    247:  unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
                    248: 
                    249:  (void)do_bit;
                    250: 
1.1       misho     251:   /* may be no servers available. */
1.1.1.3 ! misho     252:   if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
1.1       misho     253:     {
1.1.1.3 ! misho     254:       /* If we didn't get an answer advertising a maximal packet in EDNS,
        !           255:         fall back to 1280, which should work everywhere on IPv6.
        !           256:         If that generates an answer, it will become the new default
        !           257:         for this server */
        !           258:       forward->flags |= FREC_TEST_PKTSZ;
        !           259:       
1.1.1.2   misho     260: #ifdef HAVE_DNSSEC
                    261:       /* If we've already got an answer to this query, but we're awaiting keys for validation,
                    262:         there's no point retrying the query, retry the key query instead...... */
                    263:       if (forward->blocking_query)
                    264:        {
1.1.1.3 ! misho     265:          int fd, is_sign;
        !           266:          unsigned char *pheader;
        !           267:          
        !           268:          forward->flags &= ~FREC_TEST_PKTSZ;
        !           269:          
1.1.1.2   misho     270:          while (forward->blocking_query)
                    271:            forward = forward->blocking_query;
1.1.1.3 ! misho     272:           
        !           273:          forward->flags |= FREC_TEST_PKTSZ;
1.1.1.2   misho     274:          
                    275:          blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
                    276:          plen = forward->stash_len;
                    277:          
1.1.1.3 ! misho     278:          if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
        !           279:            PUTSHORT(SAFE_PKTSZ, pheader);
        !           280: 
1.1.1.2   misho     281:          if (forward->sentto->addr.sa.sa_family == AF_INET) 
1.1.1.3 ! misho     282:            log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
1.1.1.2   misho     283: #ifdef HAVE_IPV6
                    284:          else
1.1.1.3 ! misho     285:            log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
1.1.1.2   misho     286: #endif
                    287:   
                    288:          if (forward->sentto->sfd)
                    289:            fd = forward->sentto->sfd->fd;
                    290:          else
                    291:            {
                    292: #ifdef HAVE_IPV6
                    293:              if (forward->sentto->addr.sa.sa_family == AF_INET6)
                    294:                fd = forward->rfd6->fd;
                    295:              else
                    296: #endif
                    297:                fd = forward->rfd4->fd;
                    298:            }
                    299:          
1.1.1.3 ! misho     300:          while (retry_send( sendto(fd, (char *)header, plen, 0,
        !           301:                                    &forward->sentto->addr.sa,
        !           302:                                    sa_len(&forward->sentto->addr))));
1.1.1.2   misho     303:          
                    304:          return 1;
                    305:        }
                    306: #endif
                    307: 
1.1       misho     308:       /* retry on existing query, send to all available servers  */
                    309:       domain = forward->sentto->domain;
                    310:       forward->sentto->failed_queries++;
                    311:       if (!option_bool(OPT_ORDER))
                    312:        {
                    313:          forward->forwardall = 1;
                    314:          daemon->last_server = NULL;
                    315:        }
                    316:       type = forward->sentto->flags & SERV_TYPE;
1.1.1.3 ! misho     317: #ifdef HAVE_DNSSEC
        !           318:       do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
        !           319: #endif
        !           320: 
1.1       misho     321:       if (!(start = forward->sentto->next))
                    322:        start = daemon->servers; /* at end of list, recycle */
                    323:       header->id = htons(forward->new_id);
                    324:     }
                    325:   else 
                    326:     {
                    327:       if (gotname)
                    328:        flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
                    329:       
1.1.1.3 ! misho     330: #ifdef HAVE_DNSSEC
        !           331:       do_dnssec = type & SERV_DO_DNSSEC;
        !           332: #endif
        !           333:       type &= ~SERV_DO_DNSSEC;      
        !           334: 
        !           335:       if (daemon->servers && !flags)
        !           336:        forward = get_new_frec(now, NULL, 0);
        !           337:       /* table full - flags == 0, return REFUSED */
1.1       misho     338:       
                    339:       if (forward)
                    340:        {
                    341:          forward->source = *udpaddr;
                    342:          forward->dest = *dst_addr;
                    343:          forward->iface = dst_iface;
                    344:          forward->orig_id = ntohs(header->id);
1.1.1.2   misho     345:          forward->new_id = get_id();
1.1       misho     346:          forward->fd = udpfd;
1.1.1.2   misho     347:          memcpy(forward->hash, hash, HASH_SIZE);
1.1       misho     348:          forward->forwardall = 0;
1.1.1.2   misho     349:          forward->flags = 0;
1.1       misho     350:          if (norebind)
                    351:            forward->flags |= FREC_NOREBIND;
                    352:          if (header->hb4 & HB4_CD)
                    353:            forward->flags |= FREC_CHECKING_DISABLED;
1.1.1.2   misho     354:          if (ad_reqd)
                    355:            forward->flags |= FREC_AD_QUESTION;
                    356: #ifdef HAVE_DNSSEC
                    357:          forward->work_counter = DNSSEC_WORK;
                    358:          if (do_bit)
                    359:            forward->flags |= FREC_DO_QUESTION;
                    360: #endif
                    361:          
1.1       misho     362:          header->id = htons(forward->new_id);
                    363:          
                    364:          /* In strict_order mode, always try servers in the order 
                    365:             specified in resolv.conf, if a domain is given 
                    366:             always try all the available servers,
                    367:             otherwise, use the one last known to work. */
                    368:          
                    369:          if (type == 0)
                    370:            {
                    371:              if (option_bool(OPT_ORDER))
                    372:                start = daemon->servers;
                    373:              else if (!(start = daemon->last_server) ||
                    374:                       daemon->forwardcount++ > FORWARD_TEST ||
                    375:                       difftime(now, daemon->forwardtime) > FORWARD_TIME)
                    376:                {
                    377:                  start = daemon->servers;
                    378:                  forward->forwardall = 1;
                    379:                  daemon->forwardcount = 0;
                    380:                  daemon->forwardtime = now;
                    381:                }
                    382:            }
                    383:          else
                    384:            {
                    385:              start = daemon->servers;
                    386:              if (!option_bool(OPT_ORDER))
                    387:                forward->forwardall = 1;
                    388:            }
                    389:        }
                    390:     }
                    391: 
                    392:   /* check for send errors here (no route to host) 
                    393:      if we fail to send to all nameservers, send back an error
                    394:      packet straight away (helps modem users when offline)  */
                    395:   
                    396:   if (!flags && forward)
                    397:     {
                    398:       struct server *firstsentto = start;
1.1.1.3 ! misho     399:       int subnet, forwarded = 0;
        !           400:       size_t edns0_len;
        !           401: 
        !           402:       /* If a query is retried, use the log_id for the retry when logging the answer. */
        !           403:       forward->log_id = daemon->log_id;
1.1       misho     404:       
1.1.1.3 ! misho     405:       edns0_len  = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
1.1       misho     406:       
1.1.1.3 ! misho     407:       if (edns0_len != plen)
1.1.1.2   misho     408:        {
1.1.1.3 ! misho     409:          plen = edns0_len;
        !           410:          forward->flags |= FREC_ADDED_PHEADER;
        !           411:          
        !           412:          if (subnet)
        !           413:            forward->flags |= FREC_HAS_SUBNET;
1.1.1.2   misho     414:        }
1.1.1.3 ! misho     415:       
1.1.1.2   misho     416: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho     417:       if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
1.1.1.2   misho     418:        {
1.1.1.3 ! misho     419:          size_t new = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
1.1.1.2   misho     420:         
1.1.1.3 ! misho     421:          if (new != plen)
        !           422:            forward->flags |= FREC_ADDED_PHEADER;
        !           423: 
        !           424:          plen = new;
        !           425:              
1.1.1.2   misho     426:          /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
                    427:             this allows it to select auth servers when one is returning bad data. */
                    428:          if (option_bool(OPT_DNSSEC_DEBUG))
                    429:            header->hb4 |= HB4_CD;
                    430: 
                    431:        }
                    432: #endif
                    433: 
1.1.1.3 ! misho     434:       /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
        !           435:       if (find_pseudoheader(header, plen, &edns0_len, NULL, NULL, NULL) && edns0_len > 11)
        !           436:        forward->flags |= FREC_HAS_EXTRADATA;
        !           437:       
1.1       misho     438:       while (1)
                    439:        { 
                    440:          /* only send to servers dealing with our domain.
                    441:             domain may be NULL, in which case server->domain 
                    442:             must be NULL also. */
                    443:          
                    444:          if (type == (start->flags & SERV_TYPE) &&
                    445:              (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
1.1.1.3 ! misho     446:              !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1.1       misho     447:            {
                    448:              int fd;
                    449: 
                    450:              /* find server socket to use, may need to get random one. */
                    451:              if (start->sfd)
                    452:                fd = start->sfd->fd;
                    453:              else 
                    454:                {
                    455: #ifdef HAVE_IPV6
                    456:                  if (start->addr.sa.sa_family == AF_INET6)
                    457:                    {
                    458:                      if (!forward->rfd6 &&
                    459:                          !(forward->rfd6 = allocate_rfd(AF_INET6)))
                    460:                        break;
                    461:                      daemon->rfd_save = forward->rfd6;
                    462:                      fd = forward->rfd6->fd;
                    463:                    }
                    464:                  else
                    465: #endif
                    466:                    {
                    467:                      if (!forward->rfd4 &&
                    468:                          !(forward->rfd4 = allocate_rfd(AF_INET)))
                    469:                        break;
                    470:                      daemon->rfd_save = forward->rfd4;
                    471:                      fd = forward->rfd4->fd;
                    472:                    }
                    473: 
                    474: #ifdef HAVE_CONNTRACK
                    475:                  /* Copy connection mark of incoming query to outgoing connection. */
                    476:                  if (option_bool(OPT_CONNTRACK))
                    477:                    {
                    478:                      unsigned int mark;
1.1.1.2   misho     479:                      if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
1.1       misho     480:                        setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
                    481:                    }
                    482: #endif
                    483:                }
                    484:              
1.1.1.3 ! misho     485: #ifdef HAVE_DNSSEC
        !           486:              if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
1.1       misho     487:                {
1.1.1.3 ! misho     488:                  /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
        !           489:                     packet size to 512. But that won't provide space for the RRSIGS in many cases.
        !           490:                     The RRSIGS will be stripped out before the answer goes back, so the packet should
        !           491:                     shrink again. So, if we added a do-bit, bump the udp packet size to the value
        !           492:                     known to be OK for this server. We check returned size after stripping and set
        !           493:                     the truncated bit if it's still too big. */                  
        !           494:                  unsigned char *pheader;
        !           495:                  int is_sign;
        !           496:                  if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
        !           497:                    PUTSHORT(start->edns_pktsz, pheader);
1.1       misho     498:                }
1.1.1.3 ! misho     499: #endif
        !           500: 
        !           501:              if (retry_send(sendto(fd, (char *)header, plen, 0,
        !           502:                                    &start->addr.sa,
        !           503:                                    sa_len(&start->addr))))
        !           504:                continue;
        !           505:            
        !           506:              if (errno == 0)
1.1       misho     507:                {
                    508:                  /* Keep info in case we want to re-send this packet */
                    509:                  daemon->srv_save = start;
                    510:                  daemon->packet_len = plen;
                    511:                  
                    512:                  if (!gotname)
                    513:                    strcpy(daemon->namebuff, "query");
                    514:                  if (start->addr.sa.sa_family == AF_INET)
                    515:                    log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 
                    516:                              (struct all_addr *)&start->addr.in.sin_addr, NULL); 
                    517: #ifdef HAVE_IPV6
                    518:                  else
                    519:                    log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 
                    520:                              (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
                    521: #endif 
                    522:                  start->queries++;
                    523:                  forwarded = 1;
                    524:                  forward->sentto = start;
                    525:                  if (!forward->forwardall) 
                    526:                    break;
                    527:                  forward->forwardall++;
                    528:                }
                    529:            } 
                    530:          
                    531:          if (!(start = start->next))
                    532:            start = daemon->servers;
                    533:          
                    534:          if (start == firstsentto)
                    535:            break;
                    536:        }
                    537:       
                    538:       if (forwarded)
                    539:        return 1;
                    540:       
                    541:       /* could not send on, prepare to return */ 
                    542:       header->id = htons(forward->orig_id);
                    543:       free_frec(forward); /* cancel */
                    544:     }    
                    545:   
                    546:   /* could not send on, return empty answer or address if known for whole domain */
                    547:   if (udpfd != -1)
                    548:     {
                    549:       plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
                    550:       send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
                    551:     }
                    552: 
                    553:   return 0;
                    554: }
                    555: 
1.1.1.2   misho     556: static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind, 
1.1.1.3 ! misho     557:                            int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader, 
        !           558:                            int check_subnet, union mysockaddr *query_source)
1.1       misho     559: {
                    560:   unsigned char *pheader, *sizep;
                    561:   char **sets = 0;
                    562:   int munged = 0, is_sign;
                    563:   size_t plen; 
                    564: 
1.1.1.2   misho     565:   (void)ad_reqd;
1.1.1.3 ! misho     566:   (void)do_bit;
        !           567:   (void)bogusanswer;
1.1.1.2   misho     568: 
1.1       misho     569: #ifdef HAVE_IPSET
1.1.1.2   misho     570:   if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
1.1       misho     571:     {
1.1.1.2   misho     572:       /* Similar algorithm to search_servers. */
                    573:       struct ipsets *ipset_pos;
                    574:       unsigned int namelen = strlen(daemon->namebuff);
                    575:       unsigned int matchlen = 0;
                    576:       for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next) 
                    577:        {
                    578:          unsigned int domainlen = strlen(ipset_pos->domain);
                    579:          char *matchstart = daemon->namebuff + namelen - domainlen;
                    580:          if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
                    581:              (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
                    582:              domainlen >= matchlen) 
                    583:            {
                    584:              matchlen = domainlen;
                    585:              sets = ipset_pos->sets;
                    586:            }
                    587:        }
1.1       misho     588:     }
                    589: #endif
                    590:   
1.1.1.3 ! misho     591:   if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
1.1       misho     592:     {
1.1.1.2   misho     593:       if (check_subnet && !check_source(header, plen, pheader, query_source))
                    594:        {
                    595:          my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
                    596:          return 0;
                    597:        }
                    598:       
1.1.1.3 ! misho     599:       if (!is_sign)
1.1.1.2   misho     600:        {
1.1.1.3 ! misho     601:          if (added_pheader)
        !           602:            {
        !           603:              /* client didn't send EDNS0, we added one, strip it off before returning answer. */
        !           604:              n = rrfilter(header, n, 0);
        !           605:              pheader = NULL;
        !           606:            }
        !           607:          else
        !           608:            {
        !           609:              unsigned short udpsz;
        !           610: 
        !           611:              /* If upstream is advertising a larger UDP packet size
        !           612:                 than we allow, trim it so that we don't get overlarge
        !           613:                 requests for the client. We can't do this for signed packets. */
        !           614:              GETSHORT(udpsz, sizep);
        !           615:              if (udpsz > daemon->edns_pktsz)
        !           616:                {
        !           617:                  sizep -= 2;
        !           618:                  PUTSHORT(daemon->edns_pktsz, sizep);
        !           619:                }
        !           620: 
        !           621: #ifdef HAVE_DNSSEC
        !           622:              /* If the client didn't set the do bit, but we did, reset it. */
        !           623:              if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
        !           624:                {
        !           625:                  unsigned short flags;
        !           626:                  sizep += 2; /* skip RCODE */
        !           627:                  GETSHORT(flags, sizep);
        !           628:                  flags &= ~0x8000;
        !           629:                  sizep -= 2;
        !           630:                  PUTSHORT(flags, sizep);
        !           631:                }
        !           632: #endif
        !           633:            }
1.1.1.2   misho     634:        }
1.1       misho     635:     }
1.1.1.2   misho     636:   
1.1       misho     637:   /* RFC 4035 sect 4.6 para 3 */
1.1.1.2   misho     638:   if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
1.1       misho     639:      header->hb4 &= ~HB4_AD;
1.1.1.2   misho     640:   
1.1       misho     641:   if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
1.1.1.2   misho     642:     return resize_packet(header, n, pheader, plen);
1.1       misho     643:   
                    644:   /* Complain loudly if the upstream server is non-recursive. */
1.1.1.3 ! misho     645:   if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
1.1       misho     646:       server && !(server->flags & SERV_WARNED_RECURSIVE))
                    647:     {
                    648:       prettyprint_addr(&server->addr, daemon->namebuff);
                    649:       my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
                    650:       if (!option_bool(OPT_LOG))
                    651:        server->flags |= SERV_WARNED_RECURSIVE;
                    652:     }  
1.1.1.2   misho     653: 
1.1       misho     654:   if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
                    655:       check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
                    656:     {
                    657:       munged = 1;
                    658:       SET_RCODE(header, NXDOMAIN);
                    659:       header->hb3 &= ~HB3_AA;
1.1.1.2   misho     660:       cache_secure = 0;
1.1       misho     661:     }
                    662:   else 
                    663:     {
1.1.1.2   misho     664:       int doctored = 0;
                    665:       
1.1       misho     666:       if (RCODE(header) == NXDOMAIN && 
                    667:          extract_request(header, n, daemon->namebuff, NULL) &&
                    668:          check_for_local_domain(daemon->namebuff, now))
                    669:        {
                    670:          /* if we forwarded a query for a locally known name (because it was for 
                    671:             an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
                    672:             since we know that the domain exists, even if upstream doesn't */
                    673:          munged = 1;
                    674:          header->hb3 |= HB3_AA;
                    675:          SET_RCODE(header, NOERROR);
1.1.1.2   misho     676:          cache_secure = 0;
1.1       misho     677:        }
                    678:       
1.1.1.2   misho     679:       if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
1.1       misho     680:        {
                    681:          my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
                    682:          munged = 1;
1.1.1.2   misho     683:          cache_secure = 0;
                    684:        }
                    685: 
                    686:       if (doctored)
                    687:        cache_secure = 0;
                    688:     }
                    689:   
                    690: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho     691:   if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
1.1.1.2   misho     692:     {
1.1.1.3 ! misho     693:       /* Bogus reply, turn into SERVFAIL */
        !           694:       SET_RCODE(header, SERVFAIL);
        !           695:       munged = 1;
1.1       misho     696:     }
1.1.1.2   misho     697: 
                    698:   if (option_bool(OPT_DNSSEC_VALID))
1.1.1.3 ! misho     699:     {
        !           700:       header->hb4 &= ~HB4_AD;
        !           701:       
        !           702:       if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
        !           703:        header->hb4 |= HB4_AD;
        !           704:       
        !           705:       /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
        !           706:       if (!do_bit)
        !           707:        n = rrfilter(header, n, 1);
        !           708:     }
1.1.1.2   misho     709: #endif
                    710: 
1.1       misho     711:   /* do this after extract_addresses. Ensure NODATA reply and remove
                    712:      nameserver info. */
                    713:   
                    714:   if (munged)
                    715:     {
                    716:       header->ancount = htons(0);
                    717:       header->nscount = htons(0);
                    718:       header->arcount = htons(0);
1.1.1.3 ! misho     719:       header->hb3 &= ~HB3_TC;
1.1       misho     720:     }
                    721:   
                    722:   /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
                    723:      sections of the packet. Find the new length here and put back pseudoheader
                    724:      if it was removed. */
                    725:   return resize_packet(header, n, pheader, plen);
                    726: }
                    727: 
                    728: /* sets new last_server */
                    729: void reply_query(int fd, int family, time_t now)
                    730: {
                    731:   /* packet from peer server, extract data for cache, and send to
                    732:      original requester */
                    733:   struct dns_header *header;
                    734:   union mysockaddr serveraddr;
                    735:   struct frec *forward;
                    736:   socklen_t addrlen = sizeof(serveraddr);
1.1.1.2   misho     737:   ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
1.1       misho     738:   size_t nn;
                    739:   struct server *server;
1.1.1.2   misho     740:   void *hash;
                    741: #ifndef HAVE_DNSSEC
                    742:   unsigned int crc;
                    743: #endif
                    744: 
1.1       misho     745:   /* packet buffer overwritten */
                    746:   daemon->srv_save = NULL;
                    747:   
                    748:   /* Determine the address of the server replying  so that we can mark that as good */
                    749:   serveraddr.sa.sa_family = family;
                    750: #ifdef HAVE_IPV6
                    751:   if (serveraddr.sa.sa_family == AF_INET6)
                    752:     serveraddr.in6.sin6_flowinfo = 0;
                    753: #endif
                    754:   
1.1.1.2   misho     755:   header = (struct dns_header *)daemon->packet;
                    756:   
                    757:   if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
                    758:     return;
                    759:   
1.1       misho     760:   /* spoof check: answer must come from known server, */
                    761:   for (server = daemon->servers; server; server = server->next)
                    762:     if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
                    763:        sockaddr_isequal(&server->addr, &serveraddr))
                    764:       break;
                    765:   
1.1.1.2   misho     766:   if (!server)
                    767:     return;
                    768:   
                    769: #ifdef HAVE_DNSSEC
                    770:   hash = hash_questions(header, n, daemon->namebuff);
                    771: #else
                    772:   hash = &crc;
                    773:   crc = questions_crc(header, n, daemon->namebuff);
                    774: #endif
                    775:   
                    776:   if (!(forward = lookup_frec(ntohs(header->id), hash)))
1.1       misho     777:     return;
                    778:   
1.1.1.3 ! misho     779:   /* log_query gets called indirectly all over the place, so 
        !           780:      pass these in global variables - sorry. */
        !           781:   daemon->log_display_id = forward->log_id;
        !           782:   daemon->log_source_addr = &forward->source;
        !           783:   
        !           784:   if (daemon->ignore_addr && RCODE(header) == NOERROR &&
        !           785:       check_for_ignored_address(header, n, daemon->ignore_addr))
        !           786:     return;
        !           787: 
        !           788:   /* Note: if we send extra options in the EDNS0 header, we can't recreate
        !           789:      the query from the reply. */
        !           790:   if (RCODE(header) == REFUSED &&
1.1       misho     791:       !option_bool(OPT_ORDER) &&
1.1.1.3 ! misho     792:       forward->forwardall == 0 &&
        !           793:       !(forward->flags & FREC_HAS_EXTRADATA))
1.1       misho     794:     /* for broken servers, attempt to send to another one. */
                    795:     {
                    796:       unsigned char *pheader;
                    797:       size_t plen;
                    798:       int is_sign;
                    799:       
                    800:       /* recreate query from reply */
1.1.1.3 ! misho     801:       pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
1.1       misho     802:       if (!is_sign)
                    803:        {
                    804:          header->ancount = htons(0);
                    805:          header->nscount = htons(0);
                    806:          header->arcount = htons(0);
                    807:          if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
                    808:            {
1.1.1.3 ! misho     809:              header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
        !           810:              header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
        !           811:              if (forward->flags & FREC_CHECKING_DISABLED)
        !           812:                header->hb4 |= HB4_CD;
        !           813:              if (forward->flags & FREC_AD_QUESTION)
        !           814:                header->hb4 |= HB4_AD;
        !           815:              if (forward->flags & FREC_DO_QUESTION)
        !           816:                add_do_bit(header, nn,  (unsigned char *)pheader + plen);
        !           817:              forward_query(-1, NULL, NULL, 0, header, nn, now, forward, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION);
1.1       misho     818:              return;
                    819:            }
                    820:        }
                    821:     }   
1.1.1.2   misho     822:    
                    823:   server = forward->sentto;
1.1       misho     824:   if ((forward->sentto->flags & SERV_TYPE) == 0)
                    825:     {
1.1.1.2   misho     826:       if (RCODE(header) == REFUSED)
1.1       misho     827:        server = NULL;
                    828:       else
                    829:        {
                    830:          struct server *last_server;
                    831:          
                    832:          /* find good server by address if possible, otherwise assume the last one we sent to */ 
                    833:          for (last_server = daemon->servers; last_server; last_server = last_server->next)
                    834:            if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
                    835:                sockaddr_isequal(&last_server->addr, &serveraddr))
                    836:              {
                    837:                server = last_server;
                    838:                break;
                    839:              }
                    840:        } 
                    841:       if (!option_bool(OPT_ALL_SERVERS))
                    842:        daemon->last_server = server;
                    843:     }
1.1.1.3 ! misho     844:  
        !           845:   /* We tried resending to this server with a smaller maximum size and got an answer.
        !           846:      Make that permanent. To avoid reduxing the packet size for an single dropped packet,
        !           847:      only do this when we get a truncated answer, or one larger than the safe size. */
        !           848:   if (server && (forward->flags & FREC_TEST_PKTSZ) && 
        !           849:       ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
        !           850:     server->edns_pktsz = SAFE_PKTSZ;
        !           851:   
1.1       misho     852:   /* If the answer is an error, keep the forward record in place in case
                    853:      we get a good reply from another server. Kill it when we've
                    854:      had replies from all to avoid filling the forwarding table when
                    855:      everything is broken */
1.1.1.3 ! misho     856:   if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
1.1       misho     857:     {
1.1.1.3 ! misho     858:       int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
1.1.1.2   misho     859: 
                    860:       if (option_bool(OPT_NO_REBIND))
                    861:        check_rebind = !(forward->flags & FREC_NOREBIND);
                    862:       
                    863:       /*   Don't cache replies where DNSSEC validation was turned off, either
                    864:           the upstream server told us so, or the original query specified it.  */
                    865:       if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
                    866:        no_cache_dnssec = 1;
                    867:       
                    868: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho     869:       if (server && (server->flags & SERV_DO_DNSSEC) && 
        !           870:          option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
1.1.1.2   misho     871:        {
1.1.1.3 ! misho     872:          int status = 0;
1.1       misho     873: 
1.1.1.2   misho     874:          /* We've had a reply already, which we're validating. Ignore this duplicate */
                    875:          if (forward->blocking_query)
                    876:            return;
1.1.1.3 ! misho     877:          
        !           878:           /* Truncated answer can't be validated.
1.1.1.2   misho     879:                 If this is an answer to a DNSSEC-generated query, we still
                    880:                 need to get the client to retry over TCP, so return
                    881:                 an answer with the TC bit set, even if the actual answer fits.
                    882:              */
1.1.1.3 ! misho     883:          if (header->hb3 & HB3_TC)
        !           884:            status = STAT_TRUNCATED;
        !           885:          
        !           886:          while (1)
1.1.1.2   misho     887:            {
1.1.1.3 ! misho     888:              /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
        !           889:                 would invite infinite loops, since the answers to DNSKEY and DS queries
        !           890:                 will not be cached, so they'll be repeated. */
        !           891:              if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
1.1.1.2   misho     892:                {
1.1.1.3 ! misho     893:                  if (forward->flags & FREC_DNSKEY_QUERY)
        !           894:                    status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
        !           895:                  else if (forward->flags & FREC_DS_QUERY)
        !           896:                    status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1.1.1.2   misho     897:                  else
1.1.1.3 ! misho     898:                    status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, 
        !           899:                                                   option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
1.1.1.2   misho     900:                }
                    901:              
1.1.1.3 ! misho     902:              /* Can't validate, as we're missing key data. Put this
        !           903:                 answer aside, whilst we get that. */     
        !           904:              if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
1.1.1.2   misho     905:                {
1.1.1.3 ! misho     906:                  struct frec *new, *orig;
1.1.1.2   misho     907:                  
1.1.1.3 ! misho     908:                  /* Free any saved query */
        !           909:                  if (forward->stash)
        !           910:                    blockdata_free(forward->stash);
        !           911:                  
        !           912:                  /* Now save reply pending receipt of key data */
        !           913:                  if (!(forward->stash = blockdata_alloc((char *)header, n)))
        !           914:                    return;
        !           915:                  forward->stash_len = n;
1.1.1.2   misho     916:                  
1.1.1.3 ! misho     917:                  /* Find the original query that started it all.... */
        !           918:                  for (orig = forward; orig->dependent; orig = orig->dependent);
1.1.1.2   misho     919:                  
1.1.1.3 ! misho     920:                  if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
        !           921:                    status = STAT_ABANDONED;
1.1.1.2   misho     922:                  else
                    923:                    {
1.1.1.3 ! misho     924:                      int fd, type = SERV_DO_DNSSEC;
        !           925:                      struct frec *next = new->next;
        !           926:                      char *domain;
        !           927:                      
        !           928:                      *new = *forward; /* copy everything, then overwrite */
        !           929:                      new->next = next;
        !           930:                      new->blocking_query = NULL;
        !           931: 
        !           932:                      /* Find server to forward to. This will normally be the 
        !           933:                         same as for the original query, but may be another if
        !           934:                         servers for domains are involved. */                 
        !           935:                      if (search_servers(now, NULL, F_QUERY, daemon->keyname, &type, &domain, NULL) == 0)
        !           936:                        {
        !           937:                          struct server *start = server, *new_server = NULL;
        !           938:                           type &= ~SERV_DO_DNSSEC;
        !           939:                           
        !           940:                           while (1)
        !           941:                             {
        !           942:                               if (type == (start->flags & SERV_TYPE) &&
        !           943:                                   (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
        !           944:                                   !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
        !           945:                                 {
        !           946:                                   new_server = start;
        !           947:                                   if (server == start)
        !           948:                                     {
        !           949:                                       new_server = NULL;
        !           950:                                       break;
        !           951:                                     }
        !           952:                                 }
        !           953:                               
        !           954:                               if (!(start = start->next))
        !           955:                                 start = daemon->servers;
        !           956:                               if (start == server)
        !           957:                                 break;
        !           958:                             }
        !           959:                        
        !           960:                           if (new_server)
        !           961:                             server = new_server;
        !           962:                        }
        !           963: 
        !           964:                      new->sentto = server;
        !           965: 
        !           966:                      new->rfd4 = NULL;
1.1.1.2   misho     967: #ifdef HAVE_IPV6
1.1.1.3 ! misho     968:                      new->rfd6 = NULL;
        !           969: #endif
        !           970:                      new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
        !           971:                      
        !           972:                      new->dependent = forward; /* to find query awaiting new one. */
        !           973:                      forward->blocking_query = new; /* for garbage cleaning */
        !           974:                      /* validate routines leave name of required record in daemon->keyname */
        !           975:                      if (status == STAT_NEED_KEY)
        !           976:                        {
        !           977:                          new->flags |= FREC_DNSKEY_QUERY; 
        !           978:                          nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
        !           979:                                                     daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
        !           980:                        }
        !           981:                      else 
1.1.1.2   misho     982:                        {
1.1.1.3 ! misho     983:                          new->flags |= FREC_DS_QUERY;
        !           984:                          nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
        !           985:                                                     daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
1.1.1.2   misho     986:                        }
1.1.1.3 ! misho     987:                      if ((hash = hash_questions(header, nn, daemon->namebuff)))
        !           988:                        memcpy(new->hash, hash, HASH_SIZE);
        !           989:                      new->new_id = get_id();
        !           990:                      header->id = htons(new->new_id);
        !           991:                      /* Save query for retransmission */
        !           992:                      new->stash = blockdata_alloc((char *)header, nn);
        !           993:                      new->stash_len = nn;
        !           994:                      
        !           995:                      /* Don't resend this. */
        !           996:                      daemon->srv_save = NULL;
        !           997:                      
        !           998:                      if (server->sfd)
        !           999:                        fd = server->sfd->fd;
1.1.1.2   misho    1000:                      else
1.1.1.3 ! misho    1001:                        {
        !          1002:                          fd = -1;
        !          1003: #ifdef HAVE_IPV6
        !          1004:                          if (server->addr.sa.sa_family == AF_INET6)
        !          1005:                            {
        !          1006:                              if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
        !          1007:                                fd = new->rfd6->fd;
        !          1008:                            }
        !          1009:                          else
1.1.1.2   misho    1010: #endif
1.1.1.3 ! misho    1011:                            {
        !          1012:                              if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
        !          1013:                                fd = new->rfd4->fd;
        !          1014:                            }
        !          1015:                        }
        !          1016:                      
        !          1017:                      if (fd != -1)
1.1.1.2   misho    1018:                        {
1.1.1.3 ! misho    1019: #ifdef HAVE_CONNTRACK
        !          1020:                          /* Copy connection mark of incoming query to outgoing connection. */
        !          1021:                          if (option_bool(OPT_CONNTRACK))
        !          1022:                            {
        !          1023:                              unsigned int mark;
        !          1024:                              if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
        !          1025:                                setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
        !          1026:                            }
        !          1027: #endif
        !          1028:                          while (retry_send(sendto(fd, (char *)header, nn, 0, 
        !          1029:                                                   &server->addr.sa, 
        !          1030:                                                   sa_len(&server->addr)))); 
        !          1031:                          server->queries++;
1.1.1.2   misho    1032:                        }
1.1.1.3 ! misho    1033:                    }             
1.1.1.2   misho    1034:                  return;
                   1035:                }
                   1036:          
1.1.1.3 ! misho    1037:              /* Validated original answer, all done. */
        !          1038:              if (!forward->dependent)
        !          1039:                break;
        !          1040:              
        !          1041:              /* validated subsdiary query, (and cached result)
        !          1042:                 pop that and return to the previous query we were working on. */
1.1.1.2   misho    1043:              struct frec *prev = forward->dependent;
                   1044:              free_frec(forward);
                   1045:              forward = prev;
                   1046:              forward->blocking_query = NULL; /* already gone */
                   1047:              blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
                   1048:              n = forward->stash_len;
                   1049:            }
1.1.1.3 ! misho    1050:        
        !          1051:          
        !          1052:          no_cache_dnssec = 0;
1.1.1.2   misho    1053:          
                   1054:          if (status == STAT_TRUNCATED)
                   1055:            header->hb3 |= HB3_TC;
                   1056:          else
                   1057:            {
1.1.1.3 ! misho    1058:              char *result, *domain = "result";
1.1.1.2   misho    1059:              
1.1.1.3 ! misho    1060:              if (status == STAT_ABANDONED)
        !          1061:                {
        !          1062:                  result = "ABANDONED";
        !          1063:                  status = STAT_BOGUS;
        !          1064:                }
1.1.1.2   misho    1065:              else
                   1066:                result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
                   1067:              
1.1.1.3 ! misho    1068:              if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
        !          1069:                domain = daemon->namebuff;
        !          1070:              
        !          1071:              log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
1.1.1.2   misho    1072:            }
                   1073:          
                   1074:          if (status == STAT_SECURE)
                   1075:            cache_secure = 1;
                   1076:          else if (status == STAT_BOGUS)
1.1.1.3 ! misho    1077:            {
        !          1078:              no_cache_dnssec = 1;
        !          1079:              bogusanswer = 1;
        !          1080:            }
1.1.1.2   misho    1081:        }
                   1082: #endif     
1.1       misho    1083:       
1.1.1.2   misho    1084:       /* restore CD bit to the value in the query */
                   1085:       if (forward->flags & FREC_CHECKING_DISABLED)
                   1086:        header->hb4 |= HB4_CD;
                   1087:       else
                   1088:        header->hb4 &= ~HB4_CD;
                   1089:       
1.1.1.3 ! misho    1090:       if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer, 
1.1.1.2   misho    1091:                              forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION, 
                   1092:                              forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
1.1       misho    1093:        {
                   1094:          header->id = htons(forward->orig_id);
                   1095:          header->hb4 |= HB4_RA; /* recursion if available */
1.1.1.3 ! misho    1096: #ifdef HAVE_DNSSEC
        !          1097:          /* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
        !          1098:             greater than the no-EDNS0-implied 512 to have if space for the RRSIGS. If, having stripped them and the EDNS0
        !          1099:              header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
        !          1100:          if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
        !          1101:            {
        !          1102:              header->ancount = htons(0);
        !          1103:              header->nscount = htons(0);
        !          1104:              header->arcount = htons(0);
        !          1105:              header->hb3 |= HB3_TC;
        !          1106:              nn = resize_packet(header, nn, NULL, 0);
        !          1107:            }
        !          1108: #endif
1.1       misho    1109:          send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn, 
                   1110:                    &forward->source, &forward->dest, forward->iface);
                   1111:        }
                   1112:       free_frec(forward); /* cancel */
                   1113:     }
                   1114: }
                   1115: 
                   1116: 
                   1117: void receive_query(struct listener *listen, time_t now)
                   1118: {
                   1119:   struct dns_header *header = (struct dns_header *)daemon->packet;
                   1120:   union mysockaddr source_addr;
1.1.1.3 ! misho    1121:   unsigned char *pheader;
        !          1122:   unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
1.1       misho    1123:   struct all_addr dst_addr;
                   1124:   struct in_addr netmask, dst_addr_4;
                   1125:   size_t m;
                   1126:   ssize_t n;
1.1.1.3 ! misho    1127:   int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
1.1.1.2   misho    1128: #ifdef HAVE_AUTH
                   1129:   int local_auth = 0;
                   1130: #endif
1.1       misho    1131:   struct iovec iov[1];
                   1132:   struct msghdr msg;
                   1133:   struct cmsghdr *cmptr;
                   1134:   union {
                   1135:     struct cmsghdr align; /* this ensures alignment */
                   1136: #ifdef HAVE_IPV6
                   1137:     char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
                   1138: #endif
                   1139: #if defined(HAVE_LINUX_NETWORK)
                   1140:     char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
                   1141: #elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
                   1142:     char control[CMSG_SPACE(sizeof(struct in_addr)) +
                   1143:                 CMSG_SPACE(sizeof(unsigned int))];
                   1144: #elif defined(IP_RECVDSTADDR)
                   1145:     char control[CMSG_SPACE(sizeof(struct in_addr)) +
                   1146:                 CMSG_SPACE(sizeof(struct sockaddr_dl))];
                   1147: #endif
                   1148:   } control_u;
1.1.1.2   misho    1149: #ifdef HAVE_IPV6
                   1150:    /* Can always get recvd interface for IPv6 */
                   1151:   int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
                   1152: #else
                   1153:   int check_dst = !option_bool(OPT_NOWILD);
                   1154: #endif
                   1155: 
1.1       misho    1156:   /* packet buffer overwritten */
                   1157:   daemon->srv_save = NULL;
                   1158:   
1.1.1.3 ! misho    1159:   dst_addr_4.s_addr = dst_addr.addr.addr4.s_addr = 0;
1.1       misho    1160:   netmask.s_addr = 0;
                   1161:   
                   1162:   if (option_bool(OPT_NOWILD) && listen->iface)
                   1163:     {
                   1164:       auth_dns = listen->iface->dns_auth;
                   1165:      
                   1166:       if (listen->family == AF_INET)
                   1167:        {
1.1.1.3 ! misho    1168:          dst_addr_4 = dst_addr.addr.addr4 = listen->iface->addr.in.sin_addr;
1.1       misho    1169:          netmask = listen->iface->netmask;
                   1170:        }
                   1171:     }
                   1172:   
                   1173:   iov[0].iov_base = daemon->packet;
                   1174:   iov[0].iov_len = daemon->edns_pktsz;
                   1175:     
                   1176:   msg.msg_control = control_u.control;
                   1177:   msg.msg_controllen = sizeof(control_u);
                   1178:   msg.msg_flags = 0;
                   1179:   msg.msg_name = &source_addr;
                   1180:   msg.msg_namelen = sizeof(source_addr);
                   1181:   msg.msg_iov = iov;
                   1182:   msg.msg_iovlen = 1;
                   1183:   
                   1184:   if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
                   1185:     return;
                   1186:   
                   1187:   if (n < (int)sizeof(struct dns_header) || 
                   1188:       (msg.msg_flags & MSG_TRUNC) ||
                   1189:       (header->hb3 & HB3_QR))
                   1190:     return;
                   1191:   
                   1192:   source_addr.sa.sa_family = listen->family;
1.1.1.2   misho    1193:   
                   1194:   if (listen->family == AF_INET)
                   1195:     {
                   1196:        /* Source-port == 0 is an error, we can't send back to that. 
                   1197:          http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
                   1198:       if (source_addr.in.sin_port == 0)
                   1199:        return;
                   1200:     }
1.1       misho    1201: #ifdef HAVE_IPV6
1.1.1.2   misho    1202:   else
                   1203:     {
                   1204:       /* Source-port == 0 is an error, we can't send back to that. */
                   1205:       if (source_addr.in6.sin6_port == 0)
                   1206:        return;
                   1207:       source_addr.in6.sin6_flowinfo = 0;
                   1208:     }
1.1       misho    1209: #endif
1.1.1.2   misho    1210:   
                   1211:   /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
                   1212:   if (option_bool(OPT_LOCAL_SERVICE))
                   1213:     {
                   1214:       struct addrlist *addr;
                   1215: #ifdef HAVE_IPV6
                   1216:       if (listen->family == AF_INET6) 
                   1217:        {
                   1218:          for (addr = daemon->interface_addrs; addr; addr = addr->next)
                   1219:            if ((addr->flags & ADDRLIST_IPV6) &&
                   1220:                is_same_net6(&addr->addr.addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
                   1221:              break;
                   1222:        }
                   1223:       else
                   1224: #endif
                   1225:        {
                   1226:          struct in_addr netmask;
                   1227:          for (addr = daemon->interface_addrs; addr; addr = addr->next)
                   1228:            {
1.1.1.3 ! misho    1229:              netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
1.1.1.2   misho    1230:              if (!(addr->flags & ADDRLIST_IPV6) &&
                   1231:                  is_same_net(addr->addr.addr.addr4, source_addr.in.sin_addr, netmask))
                   1232:                break;
                   1233:            }
                   1234:        }
                   1235:       if (!addr)
                   1236:        {
                   1237:          static int warned = 0;
                   1238:          if (!warned)
                   1239:            {
                   1240:              my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
                   1241:              warned = 1;
                   1242:            }
                   1243:          return;
                   1244:        }
                   1245:     }
                   1246:                
                   1247:   if (check_dst)
1.1       misho    1248:     {
                   1249:       struct ifreq ifr;
                   1250: 
                   1251:       if (msg.msg_controllen < sizeof(struct cmsghdr))
                   1252:        return;
                   1253: 
                   1254: #if defined(HAVE_LINUX_NETWORK)
                   1255:       if (listen->family == AF_INET)
                   1256:        for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
                   1257:          if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
                   1258:            {
                   1259:              union {
                   1260:                unsigned char *c;
                   1261:                struct in_pktinfo *p;
                   1262:              } p;
                   1263:              p.c = CMSG_DATA(cmptr);
                   1264:              dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
                   1265:              if_index = p.p->ipi_ifindex;
                   1266:            }
                   1267: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
                   1268:       if (listen->family == AF_INET)
                   1269:        {
                   1270:          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
                   1271:            {
                   1272:              union {
                   1273:                unsigned char *c;
                   1274:                unsigned int *i;
                   1275:                struct in_addr *a;
                   1276: #ifndef HAVE_SOLARIS_NETWORK
                   1277:                struct sockaddr_dl *s;
                   1278: #endif
                   1279:              } p;
                   1280:               p.c = CMSG_DATA(cmptr);
                   1281:               if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
                   1282:                 dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
                   1283:               else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
                   1284: #ifdef HAVE_SOLARIS_NETWORK
                   1285:                 if_index = *(p.i);
                   1286: #else
                   1287:                 if_index = p.s->sdl_index;
                   1288: #endif
                   1289:            }
                   1290:        }
                   1291: #endif
                   1292:       
                   1293: #ifdef HAVE_IPV6
                   1294:       if (listen->family == AF_INET6)
                   1295:        {
                   1296:          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
                   1297:            if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
                   1298:              {
                   1299:                union {
                   1300:                  unsigned char *c;
                   1301:                  struct in6_pktinfo *p;
                   1302:                } p;
                   1303:                p.c = CMSG_DATA(cmptr);
                   1304:                  
                   1305:                dst_addr.addr.addr6 = p.p->ipi6_addr;
                   1306:                if_index = p.p->ipi6_ifindex;
                   1307:              }
                   1308:        }
                   1309: #endif
                   1310:       
                   1311:       /* enforce available interface configuration */
                   1312:       
                   1313:       if (!indextoname(listen->fd, if_index, ifr.ifr_name))
                   1314:        return;
                   1315:       
                   1316:       if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
                   1317:        {
                   1318:           if (!option_bool(OPT_CLEVERBIND))
1.1.1.2   misho    1319:             enumerate_interfaces(0); 
                   1320:           if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
                   1321:               !label_exception(if_index, listen->family, &dst_addr))
1.1       misho    1322:             return;
                   1323:        }
                   1324: 
                   1325:       if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
                   1326:        {
                   1327:          struct irec *iface;
                   1328:          
                   1329:          /* get the netmask of the interface whch has the address we were sent to.
                   1330:             This is no neccessarily the interface we arrived on. */
                   1331:          
                   1332:          for (iface = daemon->interfaces; iface; iface = iface->next)
                   1333:            if (iface->addr.sa.sa_family == AF_INET &&
                   1334:                iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
                   1335:              break;
                   1336:          
                   1337:          /* interface may be new */
                   1338:          if (!iface && !option_bool(OPT_CLEVERBIND))
1.1.1.2   misho    1339:            enumerate_interfaces(0)1.1       misho    1340:          
                   1341:          for (iface = daemon->interfaces; iface; iface = iface->next)
                   1342:            if (iface->addr.sa.sa_family == AF_INET &&
                   1343:                iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
                   1344:              break;
                   1345:          
                   1346:          /* If we failed, abandon localisation */
                   1347:          if (iface)
                   1348:            netmask = iface->netmask;
                   1349:          else
                   1350:            dst_addr_4.s_addr = 0;
                   1351:        }
                   1352:     }
1.1.1.3 ! misho    1353:    
        !          1354:   /* log_query gets called indirectly all over the place, so 
        !          1355:      pass these in global variables - sorry. */
        !          1356:   daemon->log_display_id = ++daemon->log_id;
        !          1357:   daemon->log_source_addr = &source_addr;
1.1       misho    1358:   
                   1359:   if (extract_request(header, (size_t)n, daemon->namebuff, &type))
                   1360:     {
1.1.1.2   misho    1361: #ifdef HAVE_AUTH
                   1362:       struct auth_zone *zone;
                   1363: #endif
                   1364:       char *types = querystr(auth_dns ? "auth" : "query", type);
                   1365:       
1.1       misho    1366:       if (listen->family == AF_INET) 
                   1367:        log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
                   1368:                  (struct all_addr *)&source_addr.in.sin_addr, types);
                   1369: #ifdef HAVE_IPV6
                   1370:       else
                   1371:        log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
                   1372:                  (struct all_addr *)&source_addr.in6.sin6_addr, types);
                   1373: #endif
                   1374: 
                   1375: #ifdef HAVE_AUTH
1.1.1.2   misho    1376:       /* find queries for zones we're authoritative for, and answer them directly */
1.1.1.3 ! misho    1377:       if (!auth_dns && !option_bool(OPT_LOCALISE))
1.1.1.2   misho    1378:        for (zone = daemon->auth_zones; zone; zone = zone->next)
                   1379:          if (in_zone(zone, daemon->namebuff, NULL))
                   1380:            {
                   1381:              auth_dns = 1;
                   1382:              local_auth = 1;
                   1383:              break;
                   1384:            }
                   1385: #endif
1.1.1.3 ! misho    1386:       
        !          1387: #ifdef HAVE_LOOP
        !          1388:       /* Check for forwarding loop */
        !          1389:       if (detect_loop(daemon->namebuff, type))
        !          1390:        return;
        !          1391: #endif
1.1.1.2   misho    1392:     }
                   1393:   
1.1.1.3 ! misho    1394:   if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
        !          1395:     { 
        !          1396:       unsigned short flags;
        !          1397:       
        !          1398:       have_pseudoheader = 1;
        !          1399:       GETSHORT(udp_size, pheader);
        !          1400:       pheader += 2; /* ext_rcode */
        !          1401:       GETSHORT(flags, pheader);
        !          1402:       
        !          1403:       if (flags & 0x8000)
        !          1404:        do_bit = 1;/* do bit */ 
        !          1405:        
        !          1406:       /* If the client provides an EDNS0 UDP size, use that to limit our reply.
        !          1407:         (bounded by the maximum configured). If no EDNS0, then it
        !          1408:         defaults to 512 */
        !          1409:       if (udp_size > daemon->edns_pktsz)
        !          1410:        udp_size = daemon->edns_pktsz;
        !          1411:     }
        !          1412: 
1.1.1.2   misho    1413: #ifdef HAVE_AUTH
1.1       misho    1414:   if (auth_dns)
                   1415:     {
1.1.1.3 ! misho    1416:       m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr, 
        !          1417:                      local_auth, do_bit, have_pseudoheader);
1.1       misho    1418:       if (m >= 1)
1.1.1.2   misho    1419:        {
                   1420:          send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
                   1421:                    (char *)header, m, &source_addr, &dst_addr, if_index);
                   1422:          daemon->auth_answer++;
                   1423:        }
1.1       misho    1424:     }
                   1425:   else
                   1426: #endif
                   1427:     {
1.1.1.3 ! misho    1428:       int ad_reqd = do_bit;
        !          1429:        /* RFC 6840 5.7 */
        !          1430:       if (header->hb4 & HB4_AD)
        !          1431:        ad_reqd = 1;
        !          1432: 
        !          1433:       m = answer_request(header, ((char *) header) + udp_size, (size_t)n, 
        !          1434:                         dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
1.1       misho    1435:       
                   1436:       if (m >= 1)
                   1437:        {
                   1438:          send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
                   1439:                    (char *)header, m, &source_addr, &dst_addr, if_index);
                   1440:          daemon->local_answer++;
                   1441:        }
                   1442:       else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
1.1.1.2   misho    1443:                             header, (size_t)n, now, NULL, ad_reqd, do_bit))
1.1       misho    1444:        daemon->queries_forwarded++;
                   1445:       else
                   1446:        daemon->local_answer++;
                   1447:     }
                   1448: }
                   1449: 
1.1.1.2   misho    1450: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho    1451: /* Recurse up the key heirarchy */
        !          1452: static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n, 
        !          1453:                           int class, char *name, char *keyname, struct server *server, 
        !          1454:                           int have_mark, unsigned int mark, int *keycount)
1.1.1.2   misho    1455: {
1.1.1.3 ! misho    1456:   int new_status;
        !          1457:   unsigned char *packet = NULL;
        !          1458:   unsigned char *payload = NULL;
        !          1459:   struct dns_header *new_header = NULL;
        !          1460:   u16 *length = NULL;
1.1.1.2   misho    1461: 
                   1462:   while (1)
                   1463:     {
1.1.1.3 ! misho    1464:       int type = SERV_DO_DNSSEC;
        !          1465:       char *domain;
        !          1466:       size_t m; 
1.1.1.2   misho    1467:       unsigned char c1, c2;
1.1.1.3 ! misho    1468:             
        !          1469:       /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1.1.1.2   misho    1470:       if (--(*keycount) == 0)
1.1.1.3 ! misho    1471:        new_status = STAT_ABANDONED;
        !          1472:       else if (status == STAT_NEED_KEY)
        !          1473:        new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
        !          1474:       else if (status == STAT_NEED_DS)
        !          1475:        new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
        !          1476:       else 
        !          1477:        new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
        !          1478:       
        !          1479:       if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
        !          1480:        break;
1.1.1.2   misho    1481: 
1.1.1.3 ! misho    1482:       /* Can't validate because we need a key/DS whose name now in keyname.
        !          1483:         Make query for same, and recurse to validate */
        !          1484:       if (!packet)
1.1.1.2   misho    1485:        {
1.1.1.3 ! misho    1486:          packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
        !          1487:          payload = &packet[2];
        !          1488:          new_header = (struct dns_header *)payload;
        !          1489:          length = (u16 *)packet;
1.1.1.2   misho    1490:        }
                   1491:       
1.1.1.3 ! misho    1492:       if (!packet)
1.1.1.2   misho    1493:        {
1.1.1.3 ! misho    1494:          new_status = STAT_ABANDONED;
        !          1495:          break;
1.1.1.2   misho    1496:        }
1.1.1.3 ! misho    1497:         
        !          1498:       m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class, 
        !          1499:                                new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
        !          1500:       
        !          1501:       *length = htons(m);
1.1.1.2   misho    1502: 
1.1.1.3 ! misho    1503:       /* Find server to forward to. This will normally be the 
        !          1504:         same as for the original query, but may be another if
        !          1505:         servers for domains are involved. */                 
        !          1506:       if (search_servers(now, NULL, F_QUERY, keyname, &type, &domain, NULL) == 0)
        !          1507:        {
        !          1508:          struct server *start = server, *new_server = NULL;
        !          1509:          type &= ~SERV_DO_DNSSEC;
        !          1510:                           
        !          1511:          while (1)
        !          1512:            {
        !          1513:              if (type == (start->flags & SERV_TYPE) &&
        !          1514:                  (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
        !          1515:                  !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
        !          1516:                {
        !          1517:                  new_server = start;
        !          1518:                  if (server == start)
        !          1519:                    {
        !          1520:                      new_server = NULL;
        !          1521:                      break;
        !          1522:                    }
        !          1523:                }
        !          1524:                               
        !          1525:              if (!(start = start->next))
        !          1526:                start = daemon->servers;
        !          1527:              if (start == server)
        !          1528:                break;
        !          1529:            }
        !          1530:        
1.1.1.2   misho    1531: 
1.1.1.3 ! misho    1532:          if (new_server)
1.1.1.2   misho    1533:            {
1.1.1.3 ! misho    1534:              server = new_server;
        !          1535:              /* may need to make new connection. */
        !          1536:              if (server->tcpfd == -1)
1.1.1.2   misho    1537:                {
1.1.1.3 ! misho    1538:                  if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1.1.1.2   misho    1539:                    {
1.1.1.3 ! misho    1540:                      new_status = STAT_ABANDONED;
        !          1541:                      break;
1.1.1.2   misho    1542:                    }
1.1.1.3 ! misho    1543: 
        !          1544: #ifdef HAVE_CONNTRACK
        !          1545:                  /* Copy connection mark of incoming query to outgoing connection. */
        !          1546:                  if (have_mark)
        !          1547:                    setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
        !          1548: #endif 
        !          1549:                          
        !          1550:                  if (!local_bind(server->tcpfd,  &server->source_addr, server->interface, 1) ||
        !          1551:                      connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
1.1.1.2   misho    1552:                    {
1.1.1.3 ! misho    1553:                      close(server->tcpfd);
        !          1554:                      server->tcpfd = -1;
        !          1555:                      new_status = STAT_ABANDONED;
        !          1556:                      break;
1.1.1.2   misho    1557:                    }
1.1.1.3 ! misho    1558: 
1.1.1.2   misho    1559:                }
                   1560:            }
                   1561:        }
                   1562: 
                   1563:       
                   1564:       if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
                   1565:          !read_write(server->tcpfd, &c1, 1, 1) ||
                   1566:          !read_write(server->tcpfd, &c2, 1, 1) ||
                   1567:          !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
                   1568:        {
1.1.1.3 ! misho    1569:          new_status = STAT_ABANDONED;
        !          1570:          break;
1.1.1.2   misho    1571:        }
                   1572: 
1.1.1.3 ! misho    1573:       m = (c1 << 8) | c2;
        !          1574:       
        !          1575:       new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
        !          1576:       
        !          1577:       if (new_status != STAT_OK)
        !          1578:        break;
1.1.1.2   misho    1579:     }
1.1.1.3 ! misho    1580: 
        !          1581:   if (packet)
        !          1582:     free(packet);
        !          1583:     
1.1.1.2   misho    1584:   return new_status;
                   1585: }
                   1586: #endif
                   1587: 
                   1588: 
1.1       misho    1589: /* The daemon forks before calling this: it should deal with one connection,
                   1590:    blocking as neccessary, and then return. Note, need to be a bit careful
                   1591:    about resources for debug mode, when the fork is suppressed: that's
                   1592:    done by the caller. */
                   1593: unsigned char *tcp_request(int confd, time_t now,
                   1594:                           union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
                   1595: {
                   1596:   size_t size = 0;
                   1597:   int norebind = 0;
1.1.1.2   misho    1598: #ifdef HAVE_AUTH
                   1599:   int local_auth = 0;
                   1600: #endif
1.1.1.3 ! misho    1601:   int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
        !          1602:   int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
1.1       misho    1603:   size_t m;
                   1604:   unsigned short qtype;
                   1605:   unsigned int gotname;
                   1606:   unsigned char c1, c2;
1.1.1.2   misho    1607:   /* Max TCP packet + slop + size */
                   1608:   unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
                   1609:   unsigned char *payload = &packet[2];
                   1610:   /* largest field in header is 16-bits, so this is still sufficiently aligned */
                   1611:   struct dns_header *header = (struct dns_header *)payload;
                   1612:   u16 *length = (u16 *)packet;
1.1       misho    1613:   struct server *last_server;
                   1614:   struct in_addr dst_addr_4;
                   1615:   union mysockaddr peer_addr;
                   1616:   socklen_t peer_len = sizeof(union mysockaddr);
1.1.1.3 ! misho    1617:   int query_count = 0;
        !          1618:   unsigned char *pheader;
        !          1619:   unsigned int mark = 0;
        !          1620:   int have_mark = 0;
        !          1621: 
        !          1622:   (void)mark;
        !          1623:   (void)have_mark;
        !          1624: 
1.1       misho    1625:   if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
                   1626:     return packet;
1.1.1.3 ! misho    1627: 
        !          1628: #ifdef HAVE_CONNTRACK
        !          1629:   /* Get connection mark of incoming query to set on outgoing connections. */
        !          1630:   if (option_bool(OPT_CONNTRACK))
        !          1631:     {
        !          1632:       struct all_addr local;
        !          1633: #ifdef HAVE_IPV6                     
        !          1634:       if (local_addr->sa.sa_family == AF_INET6)
        !          1635:        local.addr.addr6 = local_addr->in6.sin6_addr;
        !          1636:       else
        !          1637: #endif
        !          1638:        local.addr.addr4 = local_addr->in.sin_addr;
        !          1639:       
        !          1640:       have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
        !          1641:     }
        !          1642: #endif 
        !          1643: 
1.1.1.2   misho    1644:   /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
                   1645:   if (option_bool(OPT_LOCAL_SERVICE))
                   1646:     {
                   1647:       struct addrlist *addr;
                   1648: #ifdef HAVE_IPV6
                   1649:       if (peer_addr.sa.sa_family == AF_INET6) 
                   1650:        {
                   1651:          for (addr = daemon->interface_addrs; addr; addr = addr->next)
                   1652:            if ((addr->flags & ADDRLIST_IPV6) &&
                   1653:                is_same_net6(&addr->addr.addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
                   1654:              break;
                   1655:        }
                   1656:       else
                   1657: #endif
                   1658:        {
                   1659:          struct in_addr netmask;
                   1660:          for (addr = daemon->interface_addrs; addr; addr = addr->next)
                   1661:            {
1.1.1.3 ! misho    1662:              netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
1.1.1.2   misho    1663:              if (!(addr->flags & ADDRLIST_IPV6) && 
                   1664:                  is_same_net(addr->addr.addr.addr4, peer_addr.in.sin_addr, netmask))
                   1665:                break;
                   1666:            }
                   1667:        }
                   1668:       if (!addr)
                   1669:        {
                   1670:          my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
                   1671:          return packet;
                   1672:        }
                   1673:     }
1.1       misho    1674: 
                   1675:   while (1)
                   1676:     {
1.1.1.3 ! misho    1677:       if (query_count == TCP_MAX_QUERIES ||
        !          1678:          !packet ||
1.1       misho    1679:          !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
                   1680:          !(size = c1 << 8 | c2) ||
1.1.1.2   misho    1681:          !read_write(confd, payload, size, 1))
1.1       misho    1682:                return packet; 
                   1683:   
                   1684:       if (size < (int)sizeof(struct dns_header))
                   1685:        continue;
                   1686:       
1.1.1.3 ! misho    1687:       query_count++;
1.1       misho    1688: 
1.1.1.3 ! misho    1689:       /* log_query gets called indirectly all over the place, so 
        !          1690:         pass these in global variables - sorry. */
        !          1691:       daemon->log_display_id = ++daemon->log_id;
        !          1692:       daemon->log_source_addr = &peer_addr;
        !          1693:       
1.1       misho    1694:       /* save state of "cd" flag in query */
1.1.1.2   misho    1695:       if ((checking_disabled = header->hb4 & HB4_CD))
                   1696:        no_cache_dnssec = 1;
1.1       misho    1697:        
                   1698:       if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
                   1699:        {
1.1.1.2   misho    1700: #ifdef HAVE_AUTH
                   1701:          struct auth_zone *zone;
                   1702: #endif
                   1703:          char *types = querystr(auth_dns ? "auth" : "query", qtype);
1.1       misho    1704:          
                   1705:          if (peer_addr.sa.sa_family == AF_INET) 
                   1706:            log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
                   1707:                      (struct all_addr *)&peer_addr.in.sin_addr, types);
                   1708: #ifdef HAVE_IPV6
                   1709:          else
                   1710:            log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
                   1711:                      (struct all_addr *)&peer_addr.in6.sin6_addr, types);
                   1712: #endif
1.1.1.2   misho    1713:          
                   1714: #ifdef HAVE_AUTH
                   1715:          /* find queries for zones we're authoritative for, and answer them directly */
1.1.1.3 ! misho    1716:          if (!auth_dns && !option_bool(OPT_LOCALISE))
1.1.1.2   misho    1717:            for (zone = daemon->auth_zones; zone; zone = zone->next)
                   1718:              if (in_zone(zone, daemon->namebuff, NULL))
                   1719:                {
                   1720:                  auth_dns = 1;
                   1721:                  local_auth = 1;
                   1722:                  break;
                   1723:                }
                   1724: #endif
1.1       misho    1725:        }
                   1726:       
                   1727:       if (local_addr->sa.sa_family == AF_INET)
                   1728:        dst_addr_4 = local_addr->in.sin_addr;
                   1729:       else
                   1730:        dst_addr_4.s_addr = 0;
                   1731:       
1.1.1.3 ! misho    1732:       do_bit = 0;
        !          1733: 
        !          1734:       if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
        !          1735:        { 
        !          1736:          unsigned short flags;
        !          1737:          
        !          1738:          have_pseudoheader = 1;
        !          1739:          pheader += 4; /* udp_size, ext_rcode */
        !          1740:          GETSHORT(flags, pheader);
        !          1741:       
        !          1742:          if (flags & 0x8000)
        !          1743:            do_bit = 1; /* do bit */ 
        !          1744:        }
        !          1745: 
1.1       misho    1746: #ifdef HAVE_AUTH
                   1747:       if (auth_dns)
1.1.1.3 ! misho    1748:        m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, 
        !          1749:                        local_auth, do_bit, have_pseudoheader);
1.1       misho    1750:       else
                   1751: #endif
                   1752:        {
1.1.1.3 ! misho    1753:           int ad_reqd = do_bit;
        !          1754:           /* RFC 6840 5.7 */
        !          1755:           if (header->hb4 & HB4_AD)
        !          1756:             ad_reqd = 1;
        !          1757:           
        !          1758:           /* m > 0 if answered from cache */
        !          1759:           m = answer_request(header, ((char *) header) + 65536, (size_t)size, 
        !          1760:                              dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
1.1       misho    1761:          
                   1762:          /* Do this by steam now we're not in the select() loop */
1.1.1.3 ! misho    1763:          check_log_writer(1)1.1       misho    1764:          
                   1765:          if (m == 0)
                   1766:            {
                   1767:              unsigned int flags = 0;
                   1768:              struct all_addr *addrp = NULL;
1.1.1.3 ! misho    1769:              int type = SERV_DO_DNSSEC;
1.1       misho    1770:              char *domain = NULL;
1.1.1.3 ! misho    1771:              size_t new_size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
        !          1772: 
        !          1773:              if (size != new_size)
1.1.1.2   misho    1774:                {
1.1.1.3 ! misho    1775:                  added_pheader = 1;
        !          1776:                  size = new_size;
1.1.1.2   misho    1777:                }
1.1.1.3 ! misho    1778:              
1.1       misho    1779:              if (gotname)
                   1780:                flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
                   1781:              
1.1.1.3 ! misho    1782:              type &= ~SERV_DO_DNSSEC;
        !          1783:              
1.1       misho    1784:              if (type != 0  || option_bool(OPT_ORDER) || !daemon->last_server)
                   1785:                last_server = daemon->servers;
                   1786:              else
                   1787:                last_server = daemon->last_server;
                   1788:              
                   1789:              if (!flags && last_server)
                   1790:                {
                   1791:                  struct server *firstsendto = NULL;
1.1.1.2   misho    1792: #ifdef HAVE_DNSSEC
                   1793:                  unsigned char *newhash, hash[HASH_SIZE];
                   1794:                  if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
                   1795:                    memcpy(hash, newhash, HASH_SIZE);
                   1796:                  else
                   1797:                    memset(hash, 0, HASH_SIZE);
                   1798: #else
1.1       misho    1799:                  unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
1.1.1.2   misho    1800: #endif           
1.1       misho    1801:                  /* Loop round available servers until we succeed in connecting to one.
                   1802:                     Note that this code subtley ensures that consecutive queries on this connection
                   1803:                     which can go to the same server, do so. */
                   1804:                  while (1) 
                   1805:                    {
                   1806:                      if (!firstsendto)
                   1807:                        firstsendto = last_server;
                   1808:                      else
                   1809:                        {
                   1810:                          if (!(last_server = last_server->next))
                   1811:                            last_server = daemon->servers;
                   1812:                          
                   1813:                          if (last_server == firstsendto)
                   1814:                            break;
                   1815:                        }
                   1816:                      
                   1817:                      /* server for wrong domain */
                   1818:                      if (type != (last_server->flags & SERV_TYPE) ||
1.1.1.3 ! misho    1819:                          (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
        !          1820:                          (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1.1       misho    1821:                        continue;
                   1822:                      
                   1823:                      if (last_server->tcpfd == -1)
                   1824:                        {
                   1825:                          if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
                   1826:                            continue;
                   1827:                          
1.1.1.3 ! misho    1828: #ifdef HAVE_CONNTRACK
        !          1829:                          /* Copy connection mark of incoming query to outgoing connection. */
        !          1830:                          if (have_mark)
        !          1831:                            setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
        !          1832: #endif 
        !          1833:                      
1.1       misho    1834:                          if ((!local_bind(last_server->tcpfd,  &last_server->source_addr, last_server->interface, 1) ||
                   1835:                               connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
                   1836:                            {
                   1837:                              close(last_server->tcpfd);
                   1838:                              last_server->tcpfd = -1;
                   1839:                              continue;
                   1840:                            }
                   1841:                          
1.1.1.2   misho    1842: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho    1843:                          if (option_bool(OPT_DNSSEC_VALID) && (last_server->flags & SERV_DO_DNSSEC))
1.1.1.2   misho    1844:                            {
1.1.1.3 ! misho    1845:                              new_size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
        !          1846:                              
        !          1847:                              if (size != new_size)
        !          1848:                                {
        !          1849:                                  added_pheader = 1;
        !          1850:                                  size = new_size;
        !          1851:                                }
1.1.1.2   misho    1852:                              
                   1853:                              /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
                   1854:                                 this allows it to select auth servers when one is returning bad data. */
                   1855:                              if (option_bool(OPT_DNSSEC_DEBUG))
                   1856:                                header->hb4 |= HB4_CD;
                   1857:                            }
                   1858: #endif
1.1       misho    1859:                        }
                   1860:                      
1.1.1.2   misho    1861:                      *length = htons(size);
                   1862: 
                   1863:                      /* get query name again for logging - may have been overwritten */
                   1864:                      if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
                   1865:                        strcpy(daemon->namebuff, "query");
1.1       misho    1866:                      
1.1.1.2   misho    1867:                      if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
1.1       misho    1868:                          !read_write(last_server->tcpfd, &c1, 1, 1) ||
1.1.1.2   misho    1869:                          !read_write(last_server->tcpfd, &c2, 1, 1) ||
                   1870:                          !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
1.1       misho    1871:                        {
                   1872:                          close(last_server->tcpfd);
                   1873:                          last_server->tcpfd = -1;
                   1874:                          continue;
                   1875:                        } 
                   1876:                      
                   1877:                      m = (c1 << 8) | c2;
                   1878:                      
                   1879:                      if (last_server->addr.sa.sa_family == AF_INET)
                   1880:                        log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 
                   1881:                                  (struct all_addr *)&last_server->addr.in.sin_addr, NULL); 
                   1882: #ifdef HAVE_IPV6
                   1883:                      else
                   1884:                        log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 
                   1885:                                  (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
                   1886: #endif 
1.1.1.2   misho    1887: 
                   1888: #ifdef HAVE_DNSSEC
1.1.1.3 ! misho    1889:                      if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
1.1.1.2   misho    1890:                        {
                   1891:                          int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
1.1.1.3 ! misho    1892:                          int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, 
        !          1893:                                                       last_server, have_mark, mark, &keycount);
        !          1894:                          char *result, *domain = "result";
        !          1895:                          
        !          1896:                          if (status == STAT_ABANDONED)
        !          1897:                            {
        !          1898:                              result = "ABANDONED";
        !          1899:                              status = STAT_BOGUS;
        !          1900:                            }
1.1.1.2   misho    1901:                          else
                   1902:                            result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
                   1903:                          
1.1.1.3 ! misho    1904:                          if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
        !          1905:                            domain = daemon->namebuff;
        !          1906: 
        !          1907:                          log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
1.1.1.2   misho    1908:                          
                   1909:                          if (status == STAT_BOGUS)
1.1.1.3 ! misho    1910:                            {
        !          1911:                              no_cache_dnssec = 1;
        !          1912:                              bogusanswer = 1;
        !          1913:                            }
        !          1914: 
1.1.1.2   misho    1915:                          if (status == STAT_SECURE)
                   1916:                            cache_secure = 1;
                   1917:                        }
                   1918: #endif
                   1919: 
                   1920:                      /* restore CD bit to the value in the query */
                   1921:                      if (checking_disabled)
                   1922:                        header->hb4 |= HB4_CD;
                   1923:                      else
                   1924:                        header->hb4 &= ~HB4_CD;
1.1       misho    1925:                      
                   1926:                      /* There's no point in updating the cache, since this process will exit and
                   1927:                         lose the information after a few queries. We make this call for the alias and 
                   1928:                         bogus-nxdomain side-effects. */
                   1929:                      /* If the crc of the question section doesn't match the crc we sent, then
                   1930:                         someone might be attempting to insert bogus values into the cache by 
                   1931:                         sending replies containing questions and bogus answers. */
1.1.1.2   misho    1932: #ifdef HAVE_DNSSEC
                   1933:                      newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
                   1934:                      if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
                   1935:                        { 
                   1936:                          m = 0;
                   1937:                          break;
                   1938:                        }
                   1939: #else                    
                   1940:                      if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
                   1941:                        {
                   1942:                          m = 0;
                   1943:                          break;
                   1944:                        }
                   1945: #endif
                   1946: 
                   1947:                      m = process_reply(header, now, last_server, (unsigned int)m, 
1.1.1.3 ! misho    1948:                                        option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
        !          1949:                                        ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr); 
1.1       misho    1950:                      
                   1951:                      break;
                   1952:                    }
                   1953:                }
                   1954:        
                   1955:              /* In case of local answer or no connections made. */
                   1956:              if (m == 0)
                   1957:                m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
                   1958:            }
                   1959:        }
                   1960:          
1.1.1.3 ! misho    1961:       check_log_writer(1);
1.1       misho    1962:       
1.1.1.2   misho    1963:       *length = htons(m);
                   1964:            
                   1965:       if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
1.1       misho    1966:        return packet;
                   1967:     }
                   1968: }
                   1969: 
                   1970: static struct frec *allocate_frec(time_t now)
                   1971: {
                   1972:   struct frec *f;
                   1973:   
                   1974:   if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
                   1975:     {
                   1976:       f->next = daemon->frec_list;
                   1977:       f->time = now;
                   1978:       f->sentto = NULL;
                   1979:       f->rfd4 = NULL;
                   1980:       f->flags = 0;
                   1981: #ifdef HAVE_IPV6
                   1982:       f->rfd6 = NULL;
                   1983: #endif
1.1.1.2   misho    1984: #ifdef HAVE_DNSSEC
                   1985:       f->dependent = NULL;
                   1986:       f->blocking_query = NULL;
                   1987:       f->stash = NULL;
                   1988: #endif
1.1       misho    1989:       daemon->frec_list = f;
                   1990:     }
                   1991: 
                   1992:   return f;
                   1993: }
                   1994: 
1.1.1.3 ! misho    1995: struct randfd *allocate_rfd(int family)
1.1       misho    1996: {
                   1997:   static int finger = 0;
                   1998:   int i;
                   1999: 
                   2000:   /* limit the number of sockets we have open to avoid starvation of 
                   2001:      (eg) TFTP. Once we have a reasonable number, randomness should be OK */
                   2002: 
                   2003:   for (i = 0; i < RANDOM_SOCKS; i++)
                   2004:     if (daemon->randomsocks[i].refcount == 0)
                   2005:       {
                   2006:        if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
                   2007:          break;
                   2008:       
                   2009:        daemon->randomsocks[i].refcount = 1;
                   2010:        daemon->randomsocks[i].family = family;
                   2011:        return &daemon->randomsocks[i];
                   2012:       }
                   2013: 
                   2014:   /* No free ones or cannot get new socket, grab an existing one */
                   2015:   for (i = 0; i < RANDOM_SOCKS; i++)
                   2016:     {
                   2017:       int j = (i+finger) % RANDOM_SOCKS;
                   2018:       if (daemon->randomsocks[j].refcount != 0 &&
                   2019:          daemon->randomsocks[j].family == family && 
                   2020:          daemon->randomsocks[j].refcount != 0xffff)
                   2021:        {
                   2022:          finger = j;
                   2023:          daemon->randomsocks[j].refcount++;
                   2024:          return &daemon->randomsocks[j];
                   2025:        }
                   2026:     }
                   2027: 
                   2028:   return NULL; /* doom */
                   2029: }
1.1.1.3 ! misho    2030: 
        !          2031: void free_rfd(struct randfd *rfd)
        !          2032: {
        !          2033:   if (rfd && --(rfd->refcount) == 0)
        !          2034:     close(rfd->fd);
        !          2035: }
        !          2036: 
1.1       misho    2037: static void free_frec(struct frec *f)
                   2038: {
1.1.1.3 ! misho    2039:   free_rfd(f->rfd4);
1.1       misho    2040:   f->rfd4 = NULL;
                   2041:   f->sentto = NULL;
                   2042:   f->flags = 0;
                   2043:   
                   2044: #ifdef HAVE_IPV6
1.1.1.3 ! misho    2045:   free_rfd(f->rfd6);
1.1       misho    2046:   f->rfd6 = NULL;
                   2047: #endif
1.1.1.2   misho    2048: 
                   2049: #ifdef HAVE_DNSSEC
                   2050:   if (f->stash)
                   2051:     {
                   2052:       blockdata_free(f->stash);
                   2053:       f->stash = NULL;
                   2054:     }
                   2055: 
                   2056:   /* Anything we're waiting on is pointless now, too */
                   2057:   if (f->blocking_query)
                   2058:     free_frec(f->blocking_query);
                   2059:   f->blocking_query = NULL;
                   2060:   f->dependent = NULL;
                   2061: #endif
1.1       misho    2062: }
                   2063: 
                   2064: /* if wait==NULL return a free or older than TIMEOUT record.
                   2065:    else return *wait zero if one available, or *wait is delay to
                   2066:    when the oldest in-use record will expire. Impose an absolute
1.1.1.2   misho    2067:    limit of 4*TIMEOUT before we wipe things (for random sockets).
                   2068:    If force is set, always return a result, even if we have
                   2069:    to allocate above the limit. */
                   2070: struct frec *get_new_frec(time_t now, int *wait, int force)
1.1       misho    2071: {
                   2072:   struct frec *f, *oldest, *target;
                   2073:   int count;
                   2074:   
                   2075:   if (wait)
                   2076:     *wait = 0;
                   2077: 
                   2078:   for (f = daemon->frec_list, oldest = NULL, target =  NULL, count = 0; f; f = f->next, count++)
                   2079:     if (!f->sentto)
                   2080:       target = f;
                   2081:     else 
                   2082:       {
1.1.1.3 ! misho    2083: #ifdef HAVE_DNSSEC
        !          2084:            /* Don't free DNSSEC sub-queries here, as we may end up with
        !          2085:               dangling references to them. They'll go when their "real" query 
        !          2086:               is freed. */
        !          2087:            if (!f->dependent)
        !          2088: #endif
        !          2089:              {
        !          2090:                if (difftime(now, f->time) >= 4*TIMEOUT)
        !          2091:                  {
        !          2092:                    free_frec(f);
        !          2093:                    target = f;
        !          2094:                  }
        !          2095:             
        !          2096:            
        !          2097:                if (!oldest || difftime(f->time, oldest->time) <= 0)
        !          2098:                  oldest = f;
        !          2099:              }
1.1       misho    2100:       }
                   2101: 
                   2102:   if (target)
                   2103:     {
                   2104:       target->time = now;
                   2105:       return target;
                   2106:     }
                   2107:   
                   2108:   /* can't find empty one, use oldest if there is one
                   2109:      and it's older than timeout */
                   2110:   if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
                   2111:     { 
                   2112:       /* keep stuff for twice timeout if we can by allocating a new
                   2113:         record instead */
                   2114:       if (difftime(now, oldest->time) < 2*TIMEOUT && 
                   2115:          count <= daemon->ftabsize &&
                   2116:          (f = allocate_frec(now)))
                   2117:        return f;
                   2118: 
                   2119:       if (!wait)
                   2120:        {
                   2121:          free_frec(oldest);
                   2122:          oldest->time = now;
                   2123:        }
                   2124:       return oldest;
                   2125:     }
                   2126:   
                   2127:   /* none available, calculate time 'till oldest record expires */
1.1.1.2   misho    2128:   if (!force && count > daemon->ftabsize)
1.1       misho    2129:     {
1.1.1.2   misho    2130:       static time_t last_log = 0;
                   2131:       
1.1       misho    2132:       if (oldest && wait)
                   2133:        *wait = oldest->time + (time_t)TIMEOUT - now;
1.1.1.2   misho    2134:       
                   2135:       if ((int)difftime(now, last_log) > 5)
                   2136:        {
                   2137:          last_log = now;
                   2138:          my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
                   2139:        }
                   2140: 
1.1       misho    2141:       return NULL;
                   2142:     }
                   2143:   
                   2144:   if (!(f = allocate_frec(now)) && wait)
                   2145:     /* wait one second on malloc failure */
                   2146:     *wait = 1;
                   2147: 
                   2148:   return f; /* OK if malloc fails and this is NULL */
                   2149: }
                   2150:  
                   2151: /* crc is all-ones if not known. */
1.1.1.2   misho    2152: static struct frec *lookup_frec(unsigned short id, void *hash)
1.1       misho    2153: {
                   2154:   struct frec *f;
                   2155: 
                   2156:   for(f = daemon->frec_list; f; f = f->next)
                   2157:     if (f->sentto && f->new_id == id && 
1.1.1.2   misho    2158:        (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
1.1       misho    2159:       return f;
                   2160:       
                   2161:   return NULL;
                   2162: }
                   2163: 
                   2164: static struct frec *lookup_frec_by_sender(unsigned short id,
                   2165:                                          union mysockaddr *addr,
1.1.1.2   misho    2166:                                          void *hash)
1.1       misho    2167: {
                   2168:   struct frec *f;
                   2169:   
                   2170:   for(f = daemon->frec_list; f; f = f->next)
                   2171:     if (f->sentto &&
                   2172:        f->orig_id == id && 
1.1.1.2   misho    2173:        memcmp(hash, f->hash, HASH_SIZE) == 0 &&
1.1       misho    2174:        sockaddr_isequal(&f->source, addr))
                   2175:       return f;
                   2176:    
                   2177:   return NULL;
1.1.1.3 ! misho    2178: }
        !          2179:  
        !          2180: /* Send query packet again, if we can. */
        !          2181: void resend_query()
        !          2182: {
        !          2183:   if (daemon->srv_save)
        !          2184:     {
        !          2185:       int fd;
        !          2186:       
        !          2187:       if (daemon->srv_save->sfd)
        !          2188:        fd = daemon->srv_save->sfd->fd;
        !          2189:       else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
        !          2190:        fd = daemon->rfd_save->fd;
        !          2191:       else
        !          2192:        return;
        !          2193:       
        !          2194:       while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
        !          2195:                              &daemon->srv_save->addr.sa, 
        !          2196:                              sa_len(&daemon->srv_save->addr)))); 
        !          2197:     }
1.1       misho    2198: }
                   2199: 
                   2200: /* A server record is going away, remove references to it */
                   2201: void server_gone(struct server *server)
                   2202: {
                   2203:   struct frec *f;
                   2204:   
                   2205:   for (f = daemon->frec_list; f; f = f->next)
                   2206:     if (f->sentto && f->sentto == server)
                   2207:       free_frec(f);
                   2208:   
                   2209:   if (daemon->last_server == server)
                   2210:     daemon->last_server = NULL;
                   2211: 
                   2212:   if (daemon->srv_save == server)
                   2213:     daemon->srv_save = NULL;
                   2214: }
                   2215: 
                   2216: /* return unique random ids. */
1.1.1.2   misho    2217: static unsigned short get_id(void)
1.1       misho    2218: {
                   2219:   unsigned short ret = 0;
                   2220:   
                   2221:   do 
                   2222:     ret = rand16();
1.1.1.2   misho    2223:   while (lookup_frec(ret, NULL));
1.1       misho    2224:   
                   2225:   return ret;
                   2226: }
                   2227: 
                   2228: 
                   2229: 
                   2230: 
                   2231: 

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