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

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

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