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

1.1.1.3 ! misho       1: /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
1.1       misho       2: 
                      3:    This program is free software; you can redistribute it and/or modify
                      4:    it under the terms of the GNU General Public License as published by
                      5:    the Free Software Foundation; version 2 dated June, 1991, or
                      6:    (at your option) version 3 dated 29 June, 2007.
                      7:  
                      8:    This program is distributed in the hope that it will be useful,
                      9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     11:    GNU General Public License for more details.
                     12:      
                     13:    You should have received a copy of the GNU General Public License
                     14:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
                     15: */
                     16: 
                     17: #include "dnsmasq.h"
                     18: 
                     19: #ifdef HAVE_LINUX_NETWORK
                     20: 
                     21: int indextoname(int fd, int index, char *name)
                     22: {
                     23:   struct ifreq ifr;
                     24:   
                     25:   if (index == 0)
                     26:     return 0;
                     27: 
                     28:   ifr.ifr_ifindex = index;
                     29:   if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
                     30:     return 0;
                     31: 
                     32:   strncpy(name, ifr.ifr_name, IF_NAMESIZE);
                     33: 
                     34:   return 1;
                     35: }
                     36: 
                     37: 
                     38: #elif defined(HAVE_SOLARIS_NETWORK)
                     39: 
                     40: #include <zone.h>
                     41: #include <alloca.h>
                     42: #ifndef LIFC_UNDER_IPMP
                     43: #  define LIFC_UNDER_IPMP 0
                     44: #endif
                     45: 
                     46: int indextoname(int fd, int index, char *name)
                     47: {
                     48:   int64_t lifc_flags;
                     49:   struct lifnum lifn;
                     50:   int numifs, bufsize, i;
                     51:   struct lifconf lifc;
                     52:   struct lifreq *lifrp;
                     53:   
                     54:   if (index == 0)
                     55:     return 0;
                     56:   
                     57:   if (getzoneid() == GLOBAL_ZONEID) 
                     58:     {
                     59:       if (!if_indextoname(index, name))
                     60:        return 0;
                     61:       return 1;
                     62:     }
                     63:   
                     64:   lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
                     65:   lifn.lifn_family = AF_UNSPEC;
                     66:   lifn.lifn_flags = lifc_flags;
                     67:   if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0) 
                     68:     return 0;
                     69:   
                     70:   numifs = lifn.lifn_count;
                     71:   bufsize = numifs * sizeof(struct lifreq);
                     72:   
                     73:   lifc.lifc_family = AF_UNSPEC;
                     74:   lifc.lifc_flags = lifc_flags;
                     75:   lifc.lifc_len = bufsize;
                     76:   lifc.lifc_buf = alloca(bufsize);
                     77:   
                     78:   if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)  
                     79:     return 0;
                     80:   
                     81:   lifrp = lifc.lifc_req;
                     82:   for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++) 
                     83:     {
                     84:       struct lifreq lifr;
                     85:       strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
                     86:       if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0) 
                     87:        return 0;
                     88:       
                     89:       if (lifr.lifr_index == index) {
                     90:        strncpy(name, lifr.lifr_name, IF_NAMESIZE);
                     91:        return 1;
                     92:       }
                     93:     }
                     94:   return 0;
                     95: }
                     96: 
                     97: 
                     98: #else
                     99: 
                    100: int indextoname(int fd, int index, char *name)
                    101: { 
1.1.1.2   misho     102:   (void)fd;
                    103: 
1.1       misho     104:   if (index == 0 || !if_indextoname(index, name))
                    105:     return 0;
                    106: 
                    107:   return 1;
                    108: }
                    109: 
                    110: #endif
                    111: 
                    112: int iface_check(int family, struct all_addr *addr, char *name, int *auth)
                    113: {
                    114:   struct iname *tmp;
1.1.1.2   misho     115:   int ret = 1, match_addr = 0;
1.1       misho     116: 
                    117:   /* Note: have to check all and not bail out early, so that we set the
1.1.1.2   misho     118:      "used" flags.
                    119: 
                    120:      May be called with family == AF_LOCALto check interface by name only. */
1.1       misho     121:   
                    122:   if (auth)
                    123:     *auth = 0;
                    124:   
                    125:   if (daemon->if_names || daemon->if_addrs)
                    126:     {
                    127:       ret = 0;
                    128: 
                    129:       for (tmp = daemon->if_names; tmp; tmp = tmp->next)
                    130:        if (tmp->name && wildcard_match(tmp->name, name))
                    131:          ret = tmp->used = 1;
                    132:                
                    133:       if (addr)
                    134:        for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
                    135:          if (tmp->addr.sa.sa_family == family)
                    136:            {
                    137:              if (family == AF_INET &&
                    138:                  tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
1.1.1.2   misho     139:                ret = match_addr = tmp->used = 1;
1.1       misho     140: #ifdef HAVE_IPV6
                    141:              else if (family == AF_INET6 &&
                    142:                       IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 
                    143:                                          &addr->addr.addr6))
1.1.1.2   misho     144:                ret = match_addr = tmp->used = 1;
1.1       misho     145: #endif
                    146:            }          
                    147:     }
                    148:   
1.1.1.2   misho     149:   if (!match_addr)
                    150:     for (tmp = daemon->if_except; tmp; tmp = tmp->next)
                    151:       if (tmp->name && wildcard_match(tmp->name, name))
                    152:        ret = 0;
1.1       misho     153:     
                    154: 
                    155:   for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
                    156:     if (tmp->name)
                    157:       {
1.1.1.2   misho     158:        if (strcmp(tmp->name, name) == 0 &&
                    159:            (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
1.1       misho     160:          break;
                    161:       }
                    162:     else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
                    163:             tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
                    164:       break;
                    165: #ifdef HAVE_IPV6
                    166:     else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
                    167:             IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
                    168:       break;
                    169: #endif      
                    170: 
                    171:   if (tmp && auth) 
                    172:     {
                    173:       *auth = 1;
                    174:       ret = 1;
                    175:     }
                    176: 
                    177:   return ret; 
                    178: }
                    179: 
                    180: 
                    181: /* Fix for problem that the kernel sometimes reports the loopback inerface as the
                    182:    arrival interface when a packet originates locally, even when sent to address of 
                    183:    an interface other than the loopback. Accept packet if it arrived via a loopback 
                    184:    interface, even when we're not accepting packets that way, as long as the destination
                    185:    address is one we're believing. Interface list must be up-to-date before calling. */
                    186: int loopback_exception(int fd, int family, struct all_addr *addr, char *name)    
                    187: {
                    188:   struct ifreq ifr;
                    189:   struct irec *iface;
                    190: 
                    191:   strncpy(ifr.ifr_name, name, IF_NAMESIZE);
                    192:   if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
                    193:       ifr.ifr_flags & IFF_LOOPBACK)
                    194:     {
                    195:       for (iface = daemon->interfaces; iface; iface = iface->next)
                    196:        if (iface->addr.sa.sa_family == family)
                    197:          {
                    198:            if (family == AF_INET)
                    199:              {
                    200:                if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
                    201:                  return 1;
                    202:              }
                    203: #ifdef HAVE_IPV6
                    204:            else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
                    205:              return 1;
                    206: #endif
                    207:            
                    208:          }
                    209:     }
                    210:   return 0;
                    211: }
                    212: 
1.1.1.2   misho     213: /* If we're configured with something like --interface=eth0:0 then we'll listen correctly
                    214:    on the relevant address, but the name of the arrival interface, derived from the
                    215:    index won't match the config. Check that we found an interface address for the arrival 
                    216:    interface: daemon->interfaces must be up-to-date. */
                    217: int label_exception(int index, int family, struct all_addr *addr)
1.1       misho     218: {
                    219:   struct irec *iface;
1.1.1.2   misho     220: 
                    221:   /* labels only supported on IPv4 addresses. */
                    222:   if (family != AF_INET)
                    223:     return 0;
                    224: 
                    225:   for (iface = daemon->interfaces; iface; iface = iface->next)
                    226:     if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
                    227:        iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
                    228:       return 1;
                    229: 
                    230:   return 0;
                    231: }
                    232: 
                    233: struct iface_param {
                    234:   struct addrlist *spare;
                    235:   int fd;
                    236: };
                    237: 
                    238: static int iface_allowed(struct iface_param *param, int if_index, char *label,
1.1.1.3 ! misho     239:                         union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags) 
1.1.1.2   misho     240: {
                    241:   struct irec *iface;
                    242:   int mtu = 0, loopback;
1.1       misho     243:   struct ifreq ifr;
                    244:   int tftp_ok = !!option_bool(OPT_TFTP);
                    245:   int dhcp_ok = 1;
                    246:   int auth_dns = 0;
1.1.1.2   misho     247: #if defined(HAVE_DHCP) || defined(HAVE_TFTP)
1.1       misho     248:   struct iname *tmp;
                    249: #endif
                    250: 
1.1.1.2   misho     251:   (void)prefixlen;
1.1       misho     252: 
1.1.1.2   misho     253:   if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
                    254:       ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
                    255:     return 0;
1.1       misho     256:    
                    257:   loopback = ifr.ifr_flags & IFF_LOOPBACK;
                    258:   
                    259:   if (loopback)
1.1.1.2   misho     260:     dhcp_ok = 0;
                    261:   
                    262:   if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
1.1       misho     263:     mtu = ifr.ifr_mtu;
                    264:   
1.1.1.2   misho     265:   if (!label)
                    266:     label = ifr.ifr_name;
                    267:  
                    268:   /* maintain a list of all addresses on all interfaces for --local-service option */
                    269:   if (option_bool(OPT_LOCAL_SERVICE))
                    270:     {
                    271:       struct addrlist *al;
                    272: 
                    273:       if (param->spare)
                    274:        {
                    275:          al = param->spare;
                    276:          param->spare = al->next;
                    277:        }
                    278:       else
                    279:        al = whine_malloc(sizeof(struct addrlist));
                    280:       
                    281:       if (al)
                    282:        {
                    283:          al->next = daemon->interface_addrs;
                    284:          daemon->interface_addrs = al;
                    285:          al->prefixlen = prefixlen;
                    286:          
                    287:          if (addr->sa.sa_family == AF_INET)
                    288:            {
                    289:              al->addr.addr.addr4 = addr->in.sin_addr;
                    290:              al->flags = 0;
                    291:            }
                    292: #ifdef HAVE_IPV6
                    293:          else
                    294:            {
                    295:              al->addr.addr.addr6 = addr->in6.sin6_addr;
                    296:              al->flags = ADDRLIST_IPV6;
                    297:            } 
                    298: #endif
                    299:        }
                    300:     }
1.1       misho     301:   
1.1.1.2   misho     302: #ifdef HAVE_IPV6
                    303:   if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
                    304: #endif
                    305:     {
                    306:       struct interface_name *int_name;
                    307:       struct addrlist *al;
                    308: #ifdef HAVE_AUTH
                    309:       struct auth_zone *zone;
                    310:       struct auth_name_list *name;
                    311: 
                    312:       /* Find subnets in auth_zones */
                    313:       for (zone = daemon->auth_zones; zone; zone = zone->next)
                    314:        for (name = zone->interface_names; name; name = name->next)
                    315:          if (wildcard_match(name->name, label))
                    316:            {
                    317:              if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
                    318:                {
                    319:                  if (param->spare)
                    320:                    {
                    321:                      al = param->spare;
                    322:                      param->spare = al->next;
                    323:                    }
                    324:                  else
                    325:                    al = whine_malloc(sizeof(struct addrlist));
                    326:                  
                    327:                  if (al)
                    328:                    {
                    329:                      al->next = zone->subnet;
                    330:                      zone->subnet = al;
                    331:                      al->prefixlen = prefixlen;
                    332:                      al->addr.addr.addr4 = addr->in.sin_addr;
                    333:                      al->flags = 0;
                    334:                    }
                    335:                }
                    336:              
                    337: #ifdef HAVE_IPV6
                    338:              if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
                    339:                {
                    340:                  if (param->spare)
                    341:                    {
                    342:                      al = param->spare;
                    343:                      param->spare = al->next;
                    344:                    }
                    345:                  else
                    346:                    al = whine_malloc(sizeof(struct addrlist));
                    347:                  
                    348:                  if (al)
                    349:                    {
                    350:                      al->next = zone->subnet;
                    351:                      zone->subnet = al;
                    352:                      al->prefixlen = prefixlen;
                    353:                      al->addr.addr.addr6 = addr->in6.sin6_addr;
                    354:                      al->flags = ADDRLIST_IPV6;
                    355:                    }
                    356:                } 
                    357: #endif
                    358:              
                    359:            }
                    360: #endif
                    361:        
                    362:       /* Update addresses from interface_names. These are a set independent
                    363:         of the set we're listening on. */  
                    364:       for (int_name = daemon->int_names; int_name; int_name = int_name->next)
                    365:        if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 && 
                    366:            (addr->sa.sa_family == int_name->family || int_name->family == 0))
                    367:          {
                    368:            if (param->spare)
                    369:              {
                    370:                al = param->spare;
                    371:                param->spare = al->next;
                    372:              }
                    373:            else
                    374:              al = whine_malloc(sizeof(struct addrlist));
                    375:            
                    376:            if (al)
                    377:              {
                    378:                al->next = int_name->addr;
                    379:                int_name->addr = al;
                    380:                
                    381:                if (addr->sa.sa_family == AF_INET)
                    382:                  {
                    383:                    al->addr.addr.addr4 = addr->in.sin_addr;
                    384:                    al->flags = 0;
                    385:                  }
                    386: #ifdef HAVE_IPV6
                    387:                else
                    388:                 {
                    389:                    al->addr.addr.addr6 = addr->in6.sin6_addr;
                    390:                    al->flags = ADDRLIST_IPV6;
1.1.1.3 ! misho     391:                    /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
        !           392:                       don't appear in forward queries, but will in reverse ones. */
        !           393:                    if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
        !           394:                      al->flags |= ADDRLIST_REVONLY;
1.1.1.2   misho     395:                 } 
                    396: #endif
                    397:              }
                    398:          }
                    399:     }
                    400:  
                    401:   /* check whether the interface IP has been added already 
                    402:      we call this routine multiple times. */
                    403:   for (iface = daemon->interfaces; iface; iface = iface->next) 
                    404:     if (sockaddr_isequal(&iface->addr, addr))
                    405:       {
1.1.1.3 ! misho     406:        iface->dad = !!(iface_flags & IFACE_TENTATIVE);
1.1.1.2   misho     407:        iface->found = 1; /* for garbage collection */
                    408:        return 1;
                    409:       }
                    410: 
                    411:  /* If we are restricting the set of interfaces to use, make
1.1       misho     412:      sure that loopback interfaces are in that set. */
                    413:   if (daemon->if_names && loopback)
                    414:     {
                    415:       struct iname *lo;
                    416:       for (lo = daemon->if_names; lo; lo = lo->next)
                    417:        if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
                    418:          break;
                    419:       
                    420:       if (!lo && (lo = whine_malloc(sizeof(struct iname)))) 
                    421:        {
                    422:          if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
                    423:            {
                    424:              strcpy(lo->name, ifr.ifr_name);
                    425:              lo->used = 1;
                    426:              lo->next = daemon->if_names;
                    427:              daemon->if_names = lo;
                    428:            }
                    429:          else
                    430:            free(lo);
                    431:        }
                    432:     }
                    433:   
                    434:   if (addr->sa.sa_family == AF_INET &&
1.1.1.2   misho     435:       !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
1.1       misho     436:     return 1;
                    437: 
                    438: #ifdef HAVE_IPV6
                    439:   if (addr->sa.sa_family == AF_INET6 &&
1.1.1.2   misho     440:       !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
1.1       misho     441:     return 1;
                    442: #endif
                    443:     
                    444: #ifdef HAVE_DHCP
                    445:   /* No DHCP where we're doing auth DNS. */
                    446:   if (auth_dns)
                    447:     {
                    448:       tftp_ok = 0;
                    449:       dhcp_ok = 0;
                    450:     }
                    451:   else
                    452:     for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
                    453:       if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
                    454:        {
                    455:          tftp_ok = 0;
                    456:          dhcp_ok = 0;
                    457:        }
                    458: #endif
                    459:  
1.1.1.2   misho     460:   
                    461: #ifdef HAVE_TFTP
                    462:   if (daemon->tftp_interfaces)
                    463:     {
                    464:       /* dedicated tftp interface list */
                    465:       tftp_ok = 0;
                    466:       for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
                    467:        if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
                    468:          tftp_ok = 1;
                    469:     }
                    470: #endif
                    471:   
1.1       misho     472:   /* add to list */
                    473:   if ((iface = whine_malloc(sizeof(struct irec))))
                    474:     {
                    475:       iface->addr = *addr;
                    476:       iface->netmask = netmask;
                    477:       iface->tftp_ok = tftp_ok;
                    478:       iface->dhcp_ok = dhcp_ok;
                    479:       iface->dns_auth = auth_dns;
                    480:       iface->mtu = mtu;
1.1.1.3 ! misho     481:       iface->dad = !!(iface_flags & IFACE_TENTATIVE);
1.1.1.2   misho     482:       iface->found = 1;
                    483:       iface->done = iface->multicast_done = iface->warned = 0;
1.1       misho     484:       iface->index = if_index;
                    485:       if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
                    486:        {
                    487:          strcpy(iface->name, ifr.ifr_name);
1.1.1.2   misho     488:          iface->next = daemon->interfaces;
                    489:          daemon->interfaces = iface;
1.1       misho     490:          return 1;
                    491:        }
                    492:       free(iface);
                    493: 
                    494:     }
                    495:   
                    496:   errno = ENOMEM; 
                    497:   return 0;
                    498: }
                    499: 
                    500: #ifdef HAVE_IPV6
                    501: static int iface_allowed_v6(struct in6_addr *local, int prefix, 
                    502:                            int scope, int if_index, int flags, 
                    503:                            int preferred, int valid, void *vparam)
                    504: {
                    505:   union mysockaddr addr;
                    506:   struct in_addr netmask; /* dummy */
                    507:   netmask.s_addr = 0;
                    508: 
                    509:   (void)scope; /* warning */
                    510:   (void)preferred;
                    511:   (void)valid;
                    512:   
                    513:   memset(&addr, 0, sizeof(addr));
                    514: #ifdef HAVE_SOCKADDR_SA_LEN
                    515:   addr.in6.sin6_len = sizeof(addr.in6);
                    516: #endif
                    517:   addr.in6.sin6_family = AF_INET6;
                    518:   addr.in6.sin6_addr = *local;
                    519:   addr.in6.sin6_port = htons(daemon->port);
1.1.1.2   misho     520:   /* FreeBSD insists this is zero for non-linklocal addresses */
                    521:   if (IN6_IS_ADDR_LINKLOCAL(local))
                    522:     addr.in6.sin6_scope_id = if_index;
                    523:   else
                    524:     addr.in6.sin6_scope_id = 0;
1.1       misho     525:   
1.1.1.3 ! misho     526:   return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
1.1       misho     527: }
                    528: #endif
                    529: 
1.1.1.2   misho     530: static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
1.1       misho     531:                            struct in_addr netmask, struct in_addr broadcast, void *vparam)
                    532: {
                    533:   union mysockaddr addr;
1.1.1.2   misho     534:   int prefix, bit;
1.1.1.3 ! misho     535:  
        !           536:   (void)broadcast; /* warning */
1.1       misho     537: 
                    538:   memset(&addr, 0, sizeof(addr));
                    539: #ifdef HAVE_SOCKADDR_SA_LEN
                    540:   addr.in.sin_len = sizeof(addr.in);
                    541: #endif
                    542:   addr.in.sin_family = AF_INET;
                    543:   addr.in.sin_addr = local;
                    544:   addr.in.sin_port = htons(daemon->port);
                    545: 
1.1.1.2   misho     546:   /* determine prefix length from netmask */
                    547:   for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
                    548: 
                    549:   return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
1.1       misho     550: }
                    551:    
1.1.1.2   misho     552: int enumerate_interfaces(int reset)
1.1       misho     553: {
1.1.1.2   misho     554:   static struct addrlist *spare = NULL;
1.1.1.3 ! misho     555:   static int done = 0;
1.1.1.2   misho     556:   struct iface_param param;
                    557:   int errsave, ret = 1;
                    558:   struct addrlist *addr, *tmp;
                    559:   struct interface_name *intname;
                    560:   struct irec *iface;
                    561: #ifdef HAVE_AUTH
                    562:   struct auth_zone *zone;
                    563: #endif
                    564: 
                    565:   /* Do this max once per select cycle  - also inhibits netlink socket use
                    566:    in TCP child processes. */
                    567: 
                    568:   if (reset)
                    569:     {
                    570:       done = 0;
                    571:       return 1;
                    572:     }
                    573: 
1.1.1.3 ! misho     574:   if (done)
1.1.1.2   misho     575:     return 1;
                    576: 
                    577:   done = 1;
                    578: 
                    579:   if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
                    580:     return 0;
                    581:  
                    582:   /* Mark interfaces for garbage collection */
                    583:   for (iface = daemon->interfaces; iface; iface = iface->next) 
                    584:     iface->found = 0;
                    585: 
                    586:   /* remove addresses stored against interface_names */
                    587:   for (intname = daemon->int_names; intname; intname = intname->next)
                    588:     {
                    589:       for (addr = intname->addr; addr; addr = tmp)
                    590:        {
                    591:          tmp = addr->next;
                    592:          addr->next = spare;
                    593:          spare = addr;
                    594:        }
                    595:       
                    596:       intname->addr = NULL;
                    597:     }
                    598: 
                    599:   /* Remove list of addresses of local interfaces */
                    600:   for (addr = daemon->interface_addrs; addr; addr = tmp)
                    601:     {
                    602:       tmp = addr->next;
                    603:       addr->next = spare;
                    604:       spare = addr;
                    605:     }
                    606:   daemon->interface_addrs = NULL;
                    607:   
                    608: #ifdef HAVE_AUTH
                    609:   /* remove addresses stored against auth_zone subnets, but not 
                    610:    ones configured as address literals */
                    611:   for (zone = daemon->auth_zones; zone; zone = zone->next)
                    612:     if (zone->interface_names)
                    613:       {
                    614:        struct addrlist **up;
                    615:        for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
                    616:          {
                    617:            tmp = addr->next;
                    618:            if (addr->flags & ADDRLIST_LITERAL)
                    619:              up = &addr->next;
                    620:            else
                    621:              {
                    622:                *up = addr->next;
                    623:                addr->next = spare;
                    624:                spare = addr;
                    625:              }
                    626:          }
                    627:       }
                    628: #endif
                    629: 
                    630:   param.spare = spare;
                    631:   
1.1       misho     632: #ifdef HAVE_IPV6
1.1.1.2   misho     633:   ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
1.1       misho     634: #endif
                    635: 
1.1.1.2   misho     636:   if (ret)
                    637:     ret = iface_enumerate(AF_INET, &param, iface_allowed_v4); 
                    638:  
                    639:   errsave = errno;
                    640:   close(param.fd);
                    641:   
                    642:   if (option_bool(OPT_CLEVERBIND))
                    643:     { 
                    644:       /* Garbage-collect listeners listening on addresses that no longer exist.
                    645:         Does nothing when not binding interfaces or for listeners on localhost, 
                    646:         since the ->iface field is NULL. Note that this needs the protections
                    647:         against re-entrancy, hence it's here.  It also means there's a possibility,
                    648:         in OPT_CLEVERBIND mode, that at listener will just disappear after
                    649:         a call to enumerate_interfaces, this is checked OK on all calls. */
                    650:       struct listener *l, *tmp, **up;
                    651:       
                    652:       for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
                    653:        {
                    654:          tmp = l->next;
                    655:          
                    656:          if (!l->iface || l->iface->found)
                    657:            up = &l->next;
                    658:          else
                    659:            {
                    660:              *up = l->next;
                    661:              
                    662:              /* In case it ever returns */
                    663:              l->iface->done = 0;
                    664:              
                    665:              if (l->fd != -1)
                    666:                close(l->fd);
                    667:              if (l->tcpfd != -1)
                    668:                close(l->tcpfd);
                    669:              if (l->tftpfd != -1)
                    670:                close(l->tftpfd);
                    671:              
                    672:              free(l);
                    673:            }
                    674:        }
                    675:     }
                    676:   
                    677:   errno = errsave;
                    678:   spare = param.spare;
1.1.1.3 ! misho     679:     
1.1.1.2   misho     680:   return ret;
1.1       misho     681: }
                    682: 
                    683: /* set NONBLOCK bit on fd: See Stevens 16.6 */
                    684: int fix_fd(int fd)
                    685: {
                    686:   int flags;
                    687: 
                    688:   if ((flags = fcntl(fd, F_GETFL)) == -1 ||
                    689:       fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
                    690:     return 0;
                    691:   
                    692:   return 1;
                    693: }
                    694: 
                    695: static int make_sock(union mysockaddr *addr, int type, int dienow)
                    696: {
                    697:   int family = addr->sa.sa_family;
                    698:   int fd, rc, opt = 1;
                    699:   
                    700:   if ((fd = socket(family, type, 0)) == -1)
                    701:     {
1.1.1.2   misho     702:       int port, errsav;
1.1       misho     703:       char *s;
                    704: 
                    705:       /* No error if the kernel just doesn't support this IP flavour */
                    706:       if (errno == EPROTONOSUPPORT ||
                    707:          errno == EAFNOSUPPORT ||
                    708:          errno == EINVAL)
                    709:        return -1;
                    710:       
                    711:     err:
1.1.1.2   misho     712:       errsav = errno;
1.1       misho     713:       port = prettyprint_addr(addr, daemon->addrbuff);
                    714:       if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
                    715:        sprintf(daemon->addrbuff, "port %d", port);
                    716:       s = _("failed to create listening socket for %s: %s");
                    717:       
                    718:       if (fd != -1)
                    719:        close (fd);
1.1.1.2   misho     720:        
                    721:       errno = errsav;
                    722: 
1.1       misho     723:       if (dienow)
                    724:        {
                    725:          /* failure to bind addresses given by --listen-address at this point
                    726:             is OK if we're doing bind-dynamic */
                    727:          if (!option_bool(OPT_CLEVERBIND))
                    728:            die(s, daemon->addrbuff, EC_BADNET);
                    729:        }
                    730:       else
                    731:        my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
                    732:       
                    733:       return -1;
                    734:     }  
                    735:   
                    736:   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
                    737:     goto err;
                    738:   
                    739: #ifdef HAVE_IPV6
                    740:   if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
                    741:     goto err;
                    742: #endif
                    743:   
                    744:   if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
                    745:     goto err;
                    746:   
                    747:   if (type == SOCK_STREAM)
                    748:     {
                    749:       if (listen(fd, 5) == -1)
                    750:        goto err;
                    751:     }
1.1.1.2   misho     752:   else if (family == AF_INET)
1.1       misho     753:     {
1.1.1.2   misho     754:       if (!option_bool(OPT_NOWILD))
1.1       misho     755:        {
                    756: #if defined(HAVE_LINUX_NETWORK) 
                    757:          if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
                    758:            goto err;
                    759: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
                    760:          if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
                    761:              setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
                    762:            goto err;
                    763: #endif
                    764:        }
1.1.1.2   misho     765:     }
1.1       misho     766: #ifdef HAVE_IPV6
1.1.1.2   misho     767:   else if (!set_ipv6pktinfo(fd))
                    768:     goto err;
1.1       misho     769: #endif
                    770:   
                    771:   return fd;
                    772: }
                    773: 
                    774: #ifdef HAVE_IPV6  
                    775: int set_ipv6pktinfo(int fd)
                    776: {
                    777:   int opt = 1;
                    778: 
                    779:   /* The API changed around Linux 2.6.14 but the old ABI is still supported:
                    780:      handle all combinations of headers and kernel.
                    781:      OpenWrt note that this fixes the problem addressed by your very broken patch. */
                    782:   daemon->v6pktinfo = IPV6_PKTINFO;
                    783:   
                    784: #ifdef IPV6_RECVPKTINFO
                    785:   if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
                    786:     return 1;
                    787: # ifdef IPV6_2292PKTINFO
                    788:   else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
                    789:     {
                    790:       daemon->v6pktinfo = IPV6_2292PKTINFO;
                    791:       return 1;
                    792:     }
                    793: # endif 
                    794: #else
                    795:   if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
                    796:     return 1;
                    797: #endif
                    798: 
                    799:   return 0;
                    800: }
                    801: #endif
                    802: 
                    803: 
                    804: /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
                    805: int tcp_interface(int fd, int af)
                    806: { 
                    807:   int if_index = 0;
                    808: 
                    809: #ifdef HAVE_LINUX_NETWORK
                    810:   int opt = 1;
                    811:   struct cmsghdr *cmptr;
                    812:   struct msghdr msg;
1.1.1.3 ! misho     813:   socklen_t len;
1.1       misho     814:   
1.1.1.3 ! misho     815:   /* use mshdr so that the CMSDG_* macros are available */
1.1       misho     816:   msg.msg_control = daemon->packet;
1.1.1.3 ! misho     817:   msg.msg_controllen = len = daemon->packet_buff_sz;
1.1       misho     818:   
                    819:   /* we overwrote the buffer... */
                    820:   daemon->srv_save = NULL;
                    821:   
                    822:   if (af == AF_INET)
                    823:     {
                    824:       if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
1.1.1.3 ! misho     825:          getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
        !           826:        {
        !           827:          msg.msg_controllen = len;
        !           828:          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
        !           829:            if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
        !           830:              {
        !           831:                union {
        !           832:                  unsigned char *c;
        !           833:                  struct in_pktinfo *p;
        !           834:                } p;
        !           835:                
        !           836:                p.c = CMSG_DATA(cmptr);
        !           837:                if_index = p.p->ipi_ifindex;
        !           838:              }
        !           839:        }
1.1       misho     840:     }
                    841: #ifdef HAVE_IPV6
                    842:   else
                    843:     {
                    844:       /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
                    845:         it was removed in RFC-3542 !!!! 
                    846: 
                    847:         Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
                    848:         uses the old ABI, and should work with pre- and post-3542 kernel headers */
                    849: 
                    850: #ifdef IPV6_2292PKTOPTIONS   
                    851: #  define PKTOPTIONS IPV6_2292PKTOPTIONS
                    852: #else
                    853: #  define PKTOPTIONS IPV6_PKTOPTIONS
                    854: #endif
                    855: 
                    856:       if (set_ipv6pktinfo(fd) &&
1.1.1.3 ! misho     857:          getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
1.1       misho     858:        {
1.1.1.3 ! misho     859:           msg.msg_controllen = len;
        !           860:          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1.1       misho     861:             if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
                    862:               {
                    863:                 union {
                    864:                   unsigned char *c;
                    865:                   struct in6_pktinfo *p;
                    866:                 } p;
                    867:                 p.c = CMSG_DATA(cmptr);
                    868:                
                    869:                if_index = p.p->ipi6_ifindex;
                    870:               }
                    871:        }
                    872:     }
                    873: #endif /* IPV6 */
                    874: #endif /* Linux */
                    875:  
                    876:   return if_index;
                    877: }
                    878:       
                    879: static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
                    880: {
                    881:   struct listener *l = NULL;
                    882:   int fd = -1, tcpfd = -1, tftpfd = -1;
                    883: 
1.1.1.2   misho     884:   (void)do_tftp;
                    885: 
1.1       misho     886:   if (daemon->port != 0)
                    887:     {
                    888:       fd = make_sock(addr, SOCK_DGRAM, dienow);
                    889:       tcpfd = make_sock(addr, SOCK_STREAM, dienow);
                    890:     }
                    891:   
                    892: #ifdef HAVE_TFTP
                    893:   if (do_tftp)
                    894:     {
                    895:       if (addr->sa.sa_family == AF_INET)
                    896:        {
                    897:          /* port must be restored to DNS port for TCP code */
                    898:          short save = addr->in.sin_port;
                    899:          addr->in.sin_port = htons(TFTP_PORT);
                    900:          tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
                    901:          addr->in.sin_port = save;
                    902:        }
                    903: #  ifdef HAVE_IPV6
                    904:       else
                    905:        {
                    906:          short save = addr->in6.sin6_port;
                    907:          addr->in6.sin6_port = htons(TFTP_PORT);
                    908:          tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
                    909:          addr->in6.sin6_port = save;
                    910:        }  
                    911: #  endif
                    912:     }
                    913: #endif
                    914: 
                    915:   if (fd != -1 || tcpfd != -1 || tftpfd != -1)
                    916:     {
                    917:       l = safe_malloc(sizeof(struct listener));
                    918:       l->next = NULL;
                    919:       l->family = addr->sa.sa_family;
                    920:       l->fd = fd;
                    921:       l->tcpfd = tcpfd;
1.1.1.2   misho     922:       l->tftpfd = tftpfd;      
                    923:       l->iface = NULL;
1.1       misho     924:     }
                    925: 
                    926:   return l;
                    927: }
                    928: 
                    929: void create_wildcard_listeners(void)
                    930: {
                    931:   union mysockaddr addr;
                    932:   struct listener *l, *l6;
                    933: 
                    934:   memset(&addr, 0, sizeof(addr));
                    935: #ifdef HAVE_SOCKADDR_SA_LEN
                    936:   addr.in.sin_len = sizeof(addr.in);
                    937: #endif
                    938:   addr.in.sin_family = AF_INET;
                    939:   addr.in.sin_addr.s_addr = INADDR_ANY;
                    940:   addr.in.sin_port = htons(daemon->port);
                    941: 
                    942:   l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
                    943: 
                    944: #ifdef HAVE_IPV6
                    945:   memset(&addr, 0, sizeof(addr));
                    946: #  ifdef HAVE_SOCKADDR_SA_LEN
                    947:   addr.in6.sin6_len = sizeof(addr.in6);
                    948: #  endif
                    949:   addr.in6.sin6_family = AF_INET6;
                    950:   addr.in6.sin6_addr = in6addr_any;
                    951:   addr.in6.sin6_port = htons(daemon->port);
                    952:  
                    953:   l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
                    954:   if (l) 
                    955:     l->next = l6;
                    956:   else 
                    957:     l = l6;
                    958: #endif
                    959: 
                    960:   daemon->listeners = l;
                    961: }
                    962: 
                    963: void create_bound_listeners(int dienow)
                    964: {
                    965:   struct listener *new;
                    966:   struct irec *iface;
                    967:   struct iname *if_tmp;
                    968: 
                    969:   for (iface = daemon->interfaces; iface; iface = iface->next)
1.1.1.2   misho     970:     if (!iface->done && !iface->dad && iface->found &&
1.1       misho     971:        (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
                    972:       {
                    973:        new->iface = iface;
                    974:        new->next = daemon->listeners;
                    975:        daemon->listeners = new;
                    976:        iface->done = 1;
                    977:       }
                    978: 
                    979:   /* Check for --listen-address options that haven't been used because there's
                    980:      no interface with a matching address. These may be valid: eg it's possible
                    981:      to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
                    982: 
                    983:      If the address isn't valid the bind() will fail and we'll die() 
                    984:      (except in bind-dynamic mode, when we'll complain but keep trying.)
                    985: 
                    986:      The resulting listeners have the ->iface field NULL, and this has to be
                    987:      handled by the DNS and TFTP code. It disables --localise-queries processing
                    988:      (no netmask) and some MTU login the tftp code. */
                    989: 
                    990:   for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
                    991:     if (!if_tmp->used && 
                    992:        (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
                    993:       {
                    994:        new->next = daemon->listeners;
                    995:        daemon->listeners = new;
                    996:       }
                    997: }
                    998: 
1.1.1.2   misho     999: /* In --bind-interfaces, the only access control is the addresses we're listening on. 
                   1000:    There's nothing to avoid a query to the address of an internal interface arriving via
                   1001:    an external interface where we don't want to accept queries, except that in the usual 
                   1002:    case the addresses of internal interfaces are RFC1918. When bind-interfaces in use, 
                   1003:    and we listen on an address that looks like it's probably globally routeable, shout.
                   1004: 
                   1005:    The fix is to use --bind-dynamic, which actually checks the arrival interface too.
                   1006:    Tough if your platform doesn't support this.
                   1007: 
                   1008:    Note that checking the arrival interface is supported in the standard IPv6 API and
                   1009:    always done, so we don't warn about any IPv6 addresses here.
                   1010: */
                   1011: 
                   1012: void warn_bound_listeners(void)
                   1013: {
                   1014:   struct irec *iface;  
                   1015:   int advice = 0;
                   1016: 
                   1017:   for (iface = daemon->interfaces; iface; iface = iface->next)
                   1018:     if (!iface->dns_auth)
                   1019:       {
                   1020:        if (iface->addr.sa.sa_family == AF_INET)
                   1021:          {
                   1022:            if (!private_net(iface->addr.in.sin_addr, 1))
                   1023:              {
                   1024:                inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
                   1025:                iface->warned = advice = 1;
                   1026:                my_syslog(LOG_WARNING, 
                   1027:                          _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
                   1028:                          daemon->addrbuff, iface->name);
                   1029:              }
                   1030:          }
                   1031:       }
                   1032:   
                   1033:   if (advice)
                   1034:     my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)")); 
                   1035: }
                   1036: 
                   1037: void warn_int_names(void)
                   1038: {
                   1039:   struct interface_name *intname;
                   1040:  
                   1041:   for (intname = daemon->int_names; intname; intname = intname->next)
                   1042:     if (!intname->addr)
                   1043:       my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
                   1044: }
                   1045:  
1.1       misho    1046: int is_dad_listeners(void)
                   1047: {
                   1048:   struct irec *iface;
                   1049:   
                   1050:   if (option_bool(OPT_NOWILD))
                   1051:     for (iface = daemon->interfaces; iface; iface = iface->next)
                   1052:       if (iface->dad && !iface->done)
                   1053:        return 1;
                   1054:   
                   1055:   return 0;
                   1056: }
                   1057: 
                   1058: #ifdef HAVE_DHCP6
                   1059: void join_multicast(int dienow)      
                   1060: {
                   1061:   struct irec *iface, *tmp;
                   1062: 
                   1063:   for (iface = daemon->interfaces; iface; iface = iface->next)
                   1064:     if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
                   1065:       {
                   1066:        /* There's an irec per address but we only want to join for multicast 
                   1067:           once per interface. Weed out duplicates. */
                   1068:        for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
                   1069:          if (tmp->multicast_done && tmp->index == iface->index)
                   1070:            break;
                   1071:        
                   1072:        iface->multicast_done = 1;
                   1073:        
                   1074:        if (!tmp)
                   1075:          {
                   1076:            struct ipv6_mreq mreq;
                   1077:            int err = 0;
                   1078: 
                   1079:            mreq.ipv6mr_interface = iface->index;
                   1080:            
                   1081:            inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
                   1082:            
1.1.1.2   misho    1083:            if ((daemon->doing_dhcp6 || daemon->relay6) &&
1.1       misho    1084:                setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1.1.1.3 ! misho    1085:              err = errno;
1.1       misho    1086:            
                   1087:            inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
                   1088:            
                   1089:            if (daemon->doing_dhcp6 && 
                   1090:                setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1.1.1.3 ! misho    1091:              err = errno;
1.1       misho    1092:            
                   1093:            inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
                   1094:            
                   1095:            if (daemon->doing_ra &&
                   1096:                setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1.1.1.3 ! misho    1097:              err = errno;
1.1       misho    1098:            
                   1099:            if (err)
                   1100:              {
                   1101:                char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
1.1.1.3 ! misho    1102:                errno = err;
        !          1103: 
        !          1104: #ifdef HAVE_LINUX_NETWORK
        !          1105:                if (errno == ENOMEM)
        !          1106:                  my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
        !          1107: #endif
        !          1108: 
1.1       misho    1109:                if (dienow)
                   1110:                  die(s, iface->name, EC_BADNET);
                   1111:                else
                   1112:                  my_syslog(LOG_ERR, s, iface->name, strerror(errno));
                   1113:              }
                   1114:          }
                   1115:       }
                   1116: }
                   1117: #endif
                   1118: 
                   1119: /* return a UDP socket bound to a random port, have to cope with straying into
                   1120:    occupied port nos and reserved ones. */
                   1121: int random_sock(int family)
                   1122: {
                   1123:   int fd;
                   1124: 
                   1125:   if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
                   1126:     {
                   1127:       union mysockaddr addr;
1.1.1.3 ! misho    1128:       unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
1.1       misho    1129:       int tries = ports_avail < 30 ? 3 * ports_avail : 100;
                   1130: 
                   1131:       memset(&addr, 0, sizeof(addr));
                   1132:       addr.sa.sa_family = family;
                   1133: 
                   1134:       /* don't loop forever if all ports in use. */
                   1135: 
                   1136:       if (fix_fd(fd))
                   1137:        while(tries--)
                   1138:          {
                   1139:            unsigned short port = rand16();
                   1140:            
1.1.1.3 ! misho    1141:             if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
        !          1142:               port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
1.1       misho    1143:            
                   1144:            if (family == AF_INET) 
                   1145:              {
                   1146:                addr.in.sin_addr.s_addr = INADDR_ANY;
                   1147:                addr.in.sin_port = port;
                   1148: #ifdef HAVE_SOCKADDR_SA_LEN
                   1149:                addr.in.sin_len = sizeof(struct sockaddr_in);
                   1150: #endif
                   1151:              }
                   1152: #ifdef HAVE_IPV6
                   1153:            else
                   1154:              {
                   1155:                addr.in6.sin6_addr = in6addr_any; 
                   1156:                addr.in6.sin6_port = port;
                   1157: #ifdef HAVE_SOCKADDR_SA_LEN
                   1158:                addr.in6.sin6_len = sizeof(struct sockaddr_in6);
                   1159: #endif
                   1160:              }
                   1161: #endif
                   1162:            
                   1163:            if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
                   1164:              return fd;
                   1165:            
                   1166:            if (errno != EADDRINUSE && errno != EACCES)
                   1167:              break;
                   1168:          }
                   1169: 
                   1170:       close(fd);
                   1171:     }
                   1172: 
                   1173:   return -1; 
                   1174: }
                   1175:   
                   1176: 
                   1177: int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
                   1178: {
                   1179:   union mysockaddr addr_copy = *addr;
                   1180: 
                   1181:   /* cannot set source _port_ for TCP connections. */
                   1182:   if (is_tcp)
                   1183:     {
                   1184:       if (addr_copy.sa.sa_family == AF_INET)
                   1185:        addr_copy.in.sin_port = 0;
                   1186: #ifdef HAVE_IPV6
                   1187:       else
                   1188:        addr_copy.in6.sin6_port = 0;
                   1189: #endif
                   1190:     }
                   1191:   
                   1192:   if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
                   1193:     return 0;
                   1194:     
                   1195: #if defined(SO_BINDTODEVICE)
                   1196:   if (intname[0] != 0 &&
                   1197:       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
                   1198:     return 0;
                   1199: #endif
                   1200: 
                   1201:   return 1;
                   1202: }
                   1203: 
                   1204: static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
                   1205: {
                   1206:   struct serverfd *sfd;
                   1207:   int errsave;
                   1208: 
                   1209:   /* when using random ports, servers which would otherwise use
                   1210:      the INADDR_ANY/port0 socket have sfd set to NULL */
                   1211:   if (!daemon->osport && intname[0] == 0)
                   1212:     {
                   1213:       errno = 0;
                   1214:       
                   1215:       if (addr->sa.sa_family == AF_INET &&
                   1216:          addr->in.sin_addr.s_addr == INADDR_ANY &&
                   1217:          addr->in.sin_port == htons(0)) 
                   1218:        return NULL;
                   1219: 
                   1220: #ifdef HAVE_IPV6
                   1221:       if (addr->sa.sa_family == AF_INET6 &&
                   1222:          memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
                   1223:          addr->in6.sin6_port == htons(0)) 
                   1224:        return NULL;
                   1225: #endif
                   1226:     }
                   1227:       
                   1228:   /* may have a suitable one already */
                   1229:   for (sfd = daemon->sfds; sfd; sfd = sfd->next )
                   1230:     if (sockaddr_isequal(&sfd->source_addr, addr) &&
                   1231:        strcmp(intname, sfd->interface) == 0)
                   1232:       return sfd;
                   1233:   
                   1234:   /* need to make a new one. */
                   1235:   errno = ENOMEM; /* in case malloc fails. */
                   1236:   if (!(sfd = whine_malloc(sizeof(struct serverfd))))
                   1237:     return NULL;
                   1238:   
                   1239:   if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
                   1240:     {
                   1241:       free(sfd);
                   1242:       return NULL;
                   1243:     }
                   1244:   
                   1245:   if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
                   1246:     { 
                   1247:       errsave = errno; /* save error from bind. */
                   1248:       close(sfd->fd);
                   1249:       free(sfd);
                   1250:       errno = errsave;
                   1251:       return NULL;
                   1252:     }
                   1253:     
                   1254:   strcpy(sfd->interface, intname); 
                   1255:   sfd->source_addr = *addr;
                   1256:   sfd->next = daemon->sfds;
                   1257:   daemon->sfds = sfd;
                   1258:   return sfd; 
                   1259: }
                   1260: 
                   1261: /* create upstream sockets during startup, before root is dropped which may be needed
                   1262:    this allows query_port to be a low port and interface binding */
                   1263: void pre_allocate_sfds(void)
                   1264: {
                   1265:   struct server *srv;
                   1266:   
                   1267:   if (daemon->query_port != 0)
                   1268:     {
                   1269:       union  mysockaddr addr;
                   1270:       memset(&addr, 0, sizeof(addr));
                   1271:       addr.in.sin_family = AF_INET;
                   1272:       addr.in.sin_addr.s_addr = INADDR_ANY;
                   1273:       addr.in.sin_port = htons(daemon->query_port);
                   1274: #ifdef HAVE_SOCKADDR_SA_LEN
                   1275:       addr.in.sin_len = sizeof(struct sockaddr_in);
                   1276: #endif
                   1277:       allocate_sfd(&addr, "");
                   1278: #ifdef HAVE_IPV6
                   1279:       memset(&addr, 0, sizeof(addr));
                   1280:       addr.in6.sin6_family = AF_INET6;
                   1281:       addr.in6.sin6_addr = in6addr_any;
                   1282:       addr.in6.sin6_port = htons(daemon->query_port);
                   1283: #ifdef HAVE_SOCKADDR_SA_LEN
                   1284:       addr.in6.sin6_len = sizeof(struct sockaddr_in6);
                   1285: #endif
                   1286:       allocate_sfd(&addr, "");
                   1287: #endif
                   1288:     }
                   1289:   
                   1290:   for (srv = daemon->servers; srv; srv = srv->next)
                   1291:     if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
                   1292:        !allocate_sfd(&srv->source_addr, srv->interface) &&
                   1293:        errno != 0 &&
                   1294:        option_bool(OPT_NOWILD))
                   1295:       {
                   1296:        prettyprint_addr(&srv->source_addr, daemon->namebuff);
                   1297:        if (srv->interface[0] != 0)
                   1298:          {
                   1299:            strcat(daemon->namebuff, " ");
                   1300:            strcat(daemon->namebuff, srv->interface);
                   1301:          }
                   1302:        die(_("failed to bind server socket for %s: %s"),
                   1303:            daemon->namebuff, EC_BADNET);
                   1304:       }  
                   1305: }
                   1306: 
1.1.1.2   misho    1307: void mark_servers(int flag)
                   1308: {
                   1309:   struct server *serv;
                   1310: 
                   1311:   /* mark everything with argument flag */
                   1312:   for (serv = daemon->servers; serv; serv = serv->next)
1.1.1.3 ! misho    1313:     {
        !          1314:       if (serv->flags & flag)
        !          1315:        serv->flags |= SERV_MARK;
        !          1316: #ifdef HAVE_LOOP
        !          1317:       /* Give looped servers another chance */
        !          1318:       serv->flags &= ~SERV_LOOP;
        !          1319: #endif
        !          1320:     }
1.1.1.2   misho    1321: }
                   1322: 
                   1323: void cleanup_servers(void)
                   1324: {
                   1325:   struct server *serv, *tmp, **up;
                   1326: 
                   1327:   /* unlink and free anything still marked. */
                   1328:   for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) 
                   1329:     {
                   1330:       tmp = serv->next;
                   1331:       if (serv->flags & SERV_MARK)
                   1332:        {
                   1333:          server_gone(serv);
                   1334:          *up = serv->next;
                   1335:          if (serv->domain)
                   1336:           free(serv->domain);
                   1337:         free(serv);
                   1338:        }
                   1339:       else 
                   1340:        up = &serv->next;
                   1341:     }
1.1.1.3 ! misho    1342: 
        !          1343: #ifdef HAVE_LOOP
        !          1344:   /* Now we have a new set of servers, test for loops. */
        !          1345:   loop_send_probes();
        !          1346: #endif
1.1.1.2   misho    1347: }
                   1348: 
                   1349: void add_update_server(int flags,
                   1350:                       union mysockaddr *addr,
                   1351:                       union mysockaddr *source_addr,
                   1352:                       const char *interface,
                   1353:                       const char *domain)
                   1354: {
                   1355:   struct server *serv, *next = NULL;
                   1356:   char *domain_str = NULL;
                   1357:   
                   1358:   /* See if there is a suitable candidate, and unmark */
                   1359:   for (serv = daemon->servers; serv; serv = serv->next)
                   1360:     if (serv->flags & SERV_MARK)
                   1361:       {
                   1362:        if (domain)
                   1363:          {
                   1364:            if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
                   1365:              continue;
                   1366:          }
                   1367:        else
                   1368:          {
                   1369:            if (serv->flags & SERV_HAS_DOMAIN)
                   1370:              continue;
                   1371:          }
                   1372:        
                   1373:         break;
                   1374:       }
                   1375: 
                   1376:   if (serv)
                   1377:     {
                   1378:       domain_str = serv->domain;
                   1379:       next = serv->next;
                   1380:     }
                   1381:   else if ((serv = whine_malloc(sizeof (struct server))))
                   1382:     {
                   1383:       /* Not found, create a new one. */
                   1384:       if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
                   1385:        {
                   1386:          free(serv);
                   1387:           serv = NULL;
                   1388:         }
                   1389:       else
                   1390:         {
                   1391:          struct server *s;
                   1392:          /* Add to the end of the chain, for order */
                   1393:          if (!daemon->servers)
                   1394:            daemon->servers = serv;
                   1395:          else
                   1396:            {
                   1397:              for (s = daemon->servers; s->next; s = s->next);
                   1398:              s->next = serv;
                   1399:            }
                   1400:          if (domain)
                   1401:            strcpy(domain_str, domain);
                   1402:        }
                   1403:     }
                   1404:   
                   1405:   if (serv)
                   1406:     {
                   1407:       memset(serv, 0, sizeof(struct server));
                   1408:       serv->flags = flags;
                   1409:       serv->domain = domain_str;
                   1410:       serv->next = next;
                   1411:       serv->queries = serv->failed_queries = 0;
1.1.1.3 ! misho    1412: #ifdef HAVE_LOOP
        !          1413:       serv->uid = rand32();
        !          1414: #endif      
        !          1415: 
1.1.1.2   misho    1416:       if (domain)
                   1417:        serv->flags |= SERV_HAS_DOMAIN;
                   1418:       
                   1419:       if (interface)
                   1420:        strcpy(serv->interface, interface);      
                   1421:       if (addr)
                   1422:        serv->addr = *addr;
                   1423:       if (source_addr)
                   1424:        serv->source_addr = *source_addr;
                   1425:     }
                   1426: }
1.1       misho    1427: 
                   1428: void check_servers(void)
                   1429: {
                   1430:   struct irec *iface;
1.1.1.2   misho    1431:   struct server *serv;
1.1.1.3 ! misho    1432:   int port = 0, count;
1.1       misho    1433: 
                   1434:   /* interface may be new since startup */
                   1435:   if (!option_bool(OPT_NOWILD))
1.1.1.2   misho    1436:     enumerate_interfaces(0);
1.1       misho    1437:   
1.1.1.3 ! misho    1438: #ifdef HAVE_DNSSEC
        !          1439:  /* Disable DNSSEC validation when using server=/domain/.... servers
        !          1440:     unless there's a configured trust anchor. */
1.1.1.2   misho    1441:   for (serv = daemon->servers; serv; serv = serv->next)
1.1.1.3 ! misho    1442:     serv->flags |= SERV_DO_DNSSEC;
        !          1443: #endif
        !          1444: 
        !          1445:   for (count = 0, serv = daemon->servers; serv; serv = serv->next)
1.1       misho    1446:     {
1.1.1.3 ! misho    1447:       if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
1.1       misho    1448:        {
1.1.1.3 ! misho    1449:          /* Init edns_pktsz for newly created server records. */
        !          1450:          if (serv->edns_pktsz == 0)
        !          1451:            serv->edns_pktsz = daemon->edns_pktsz;
        !          1452:          
        !          1453: #ifdef HAVE_DNSSEC
        !          1454:          if (option_bool(OPT_DNSSEC_VALID))
        !          1455:            { 
        !          1456:              if (serv->flags & SERV_HAS_DOMAIN)
        !          1457:                {
        !          1458:                  struct ds_config *ds;
        !          1459:                  char *domain = serv->domain;
        !          1460:                  
        !          1461:                  /* .example.com is valid */
        !          1462:                  while (*domain == '.')
        !          1463:                    domain++;
        !          1464:                  
        !          1465:                  for (ds = daemon->ds; ds; ds = ds->next)
        !          1466:                    if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
        !          1467:                      break;
        !          1468:                  
        !          1469:                  if (!ds)
        !          1470:                    serv->flags &= ~SERV_DO_DNSSEC;
        !          1471:                }
        !          1472:              else if (serv->flags & SERV_FOR_NODOTS) 
        !          1473:                serv->flags &= ~SERV_DO_DNSSEC;
        !          1474:            }
        !          1475: #endif
1.1       misho    1476: 
1.1.1.3 ! misho    1477:          port = prettyprint_addr(&serv->addr, daemon->namebuff);
        !          1478:          
1.1       misho    1479:          /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
1.1.1.2   misho    1480:          if (serv->addr.sa.sa_family == AF_INET &&
                   1481:              serv->addr.in.sin_addr.s_addr == 0)
1.1       misho    1482:            {
1.1.1.2   misho    1483:              serv->flags |= SERV_MARK;
1.1       misho    1484:              continue;
                   1485:            }
                   1486: 
                   1487:          for (iface = daemon->interfaces; iface; iface = iface->next)
1.1.1.2   misho    1488:            if (sockaddr_isequal(&serv->addr, &iface->addr))
1.1       misho    1489:              break;
                   1490:          if (iface)
                   1491:            {
                   1492:              my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
1.1.1.2   misho    1493:              serv->flags |= SERV_MARK;
1.1       misho    1494:              continue;
                   1495:            }
                   1496:          
                   1497:          /* Do we need a socket set? */
1.1.1.2   misho    1498:          if (!serv->sfd && 
                   1499:              !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
1.1       misho    1500:              errno != 0)
                   1501:            {
                   1502:              my_syslog(LOG_WARNING, 
                   1503:                        _("ignoring nameserver %s - cannot make/bind socket: %s"),
                   1504:                        daemon->namebuff, strerror(errno));
1.1.1.2   misho    1505:              serv->flags |= SERV_MARK;
1.1       misho    1506:              continue;
                   1507:            }
                   1508:        }
                   1509:       
1.1.1.3 ! misho    1510:       if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
1.1       misho    1511:        {
1.1.1.3 ! misho    1512:          if (++count > SERVERS_LOGGED)
        !          1513:            continue;
        !          1514:          
1.1.1.2   misho    1515:          if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
1.1       misho    1516:            {
1.1.1.3 ! misho    1517:              char *s1, *s2, *s3 = "";
        !          1518: #ifdef HAVE_DNSSEC
        !          1519:              if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
        !          1520:                s3 = _("(no DNSSEC)");
        !          1521: #endif
1.1.1.2   misho    1522:              if (!(serv->flags & SERV_HAS_DOMAIN))
1.1       misho    1523:                s1 = _("unqualified"), s2 = _("names");
1.1.1.2   misho    1524:              else if (strlen(serv->domain) == 0)
1.1       misho    1525:                s1 = _("default"), s2 = "";
                   1526:              else
1.1.1.2   misho    1527:                s1 = _("domain"), s2 = serv->domain;
1.1       misho    1528:              
1.1.1.2   misho    1529:              if (serv->flags & SERV_NO_ADDR)
1.1       misho    1530:                my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1.1.1.2   misho    1531:              else if (serv->flags & SERV_USE_RESOLV)
1.1       misho    1532:                my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
1.1.1.3 ! misho    1533:              else 
        !          1534:                my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
1.1       misho    1535:            }
1.1.1.3 ! misho    1536: #ifdef HAVE_LOOP
        !          1537:          else if (serv->flags & SERV_LOOP)
        !          1538:            my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port); 
        !          1539: #endif
1.1.1.2   misho    1540:          else if (serv->interface[0] != 0)
                   1541:            my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface); 
1.1       misho    1542:          else
                   1543:            my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 
                   1544:        }
                   1545:     }
1.1.1.3 ! misho    1546:   
        !          1547:   if (count - 1 > SERVERS_LOGGED)
        !          1548:     my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
1.1.1.2   misho    1549: 
                   1550:   cleanup_servers();
1.1       misho    1551: }
                   1552: 
                   1553: /* Return zero if no servers found, in that case we keep polling.
                   1554:    This is a protection against an update-time/write race on resolv.conf */
                   1555: int reload_servers(char *fname)
                   1556: {
                   1557:   FILE *f;
                   1558:   char *line;
                   1559:   int gotone = 0;
                   1560: 
                   1561:   /* buff happens to be MAXDNAME long... */
                   1562:   if (!(f = fopen(fname, "r")))
                   1563:     {
                   1564:       my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
                   1565:       return 0;
                   1566:     }
1.1.1.2   misho    1567:    
                   1568:   mark_servers(SERV_FROM_RESOLV);
                   1569:     
1.1       misho    1570:   while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
                   1571:     {
                   1572:       union mysockaddr addr, source_addr;
                   1573:       char *token = strtok(line, " \t\n\r");
                   1574:       
                   1575:       if (!token)
                   1576:        continue;
                   1577:       if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
                   1578:        continue;
                   1579:       if (!(token = strtok(NULL, " \t\n\r")))
                   1580:        continue;
                   1581:       
                   1582:       memset(&addr, 0, sizeof(addr));
                   1583:       memset(&source_addr, 0, sizeof(source_addr));
                   1584:       
                   1585:       if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
                   1586:        {
                   1587: #ifdef HAVE_SOCKADDR_SA_LEN
                   1588:          source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
                   1589: #endif
                   1590:          source_addr.in.sin_family = addr.in.sin_family = AF_INET;
                   1591:          addr.in.sin_port = htons(NAMESERVER_PORT);
                   1592:          source_addr.in.sin_addr.s_addr = INADDR_ANY;
                   1593:          source_addr.in.sin_port = htons(daemon->query_port);
                   1594:        }
                   1595: #ifdef HAVE_IPV6
                   1596:       else 
                   1597:        {       
                   1598:          int scope_index = 0;
                   1599:          char *scope_id = strchr(token, '%');
                   1600:          
                   1601:          if (scope_id)
                   1602:            {
                   1603:              *(scope_id++) = 0;
                   1604:              scope_index = if_nametoindex(scope_id);
                   1605:            }
                   1606:          
                   1607:          if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
                   1608:            {
                   1609: #ifdef HAVE_SOCKADDR_SA_LEN
                   1610:              source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
                   1611: #endif
                   1612:              source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
                   1613:              source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
                   1614:              addr.in6.sin6_port = htons(NAMESERVER_PORT);
                   1615:              addr.in6.sin6_scope_id = scope_index;
                   1616:              source_addr.in6.sin6_addr = in6addr_any;
                   1617:              source_addr.in6.sin6_port = htons(daemon->query_port);
                   1618:              source_addr.in6.sin6_scope_id = 0;
                   1619:            }
                   1620:          else
                   1621:            continue;
                   1622:        }
                   1623: #else /* IPV6 */
                   1624:       else
                   1625:        continue;
                   1626: #endif 
                   1627: 
1.1.1.2   misho    1628:       add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
1.1       misho    1629:       gotone = 1;
                   1630:     }
                   1631:   
                   1632:   fclose(f);
1.1.1.2   misho    1633:   cleanup_servers();
1.1       misho    1634: 
                   1635:   return gotone;
                   1636: }
                   1637: 
1.1.1.2   misho    1638: /* Called when addresses are added or deleted from an interface */
                   1639: void newaddress(time_t now)
                   1640: {
                   1641:   (void)now;
                   1642:   
                   1643:   if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
                   1644:       daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
                   1645:     enumerate_interfaces(0);
1.1       misho    1646:   
1.1.1.2   misho    1647:   if (option_bool(OPT_CLEVERBIND))
                   1648:     create_bound_listeners(0);
1.1       misho    1649:   
1.1.1.2   misho    1650: #ifdef HAVE_DHCP6
                   1651:   if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
                   1652:     join_multicast(0);
1.1       misho    1653:   
1.1.1.2   misho    1654:   if (daemon->doing_dhcp6 || daemon->doing_ra)
                   1655:     dhcp_construct_contexts(now);
1.1       misho    1656:   
1.1.1.2   misho    1657:   if (daemon->doing_dhcp6)
                   1658:     lease_find_interfaces(now);
                   1659: #endif
1.1       misho    1660: }
                   1661: 
1.1.1.2   misho    1662: 
                   1663: 
1.1       misho    1664: 
                   1665: 

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