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

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

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