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

1.1       misho       1: /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
                      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: { 
                    102:   if (index == 0 || !if_indextoname(index, name))
                    103:     return 0;
                    104: 
                    105:   return 1;
                    106: }
                    107: 
                    108: #endif
                    109: 
                    110: int iface_check(int family, struct all_addr *addr, char *name, int *auth)
                    111: {
                    112:   struct iname *tmp;
                    113:   int ret = 1;
                    114: 
                    115:   /* Note: have to check all and not bail out early, so that we set the
                    116:      "used" flags. */
                    117:   
                    118:   if (auth)
                    119:     *auth = 0;
                    120:   
                    121:   if (daemon->if_names || daemon->if_addrs)
                    122:     {
                    123:       ret = 0;
                    124: 
                    125:       for (tmp = daemon->if_names; tmp; tmp = tmp->next)
                    126:        if (tmp->name && wildcard_match(tmp->name, name))
                    127:          ret = tmp->used = 1;
                    128:                
                    129:       if (addr)
                    130:        for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
                    131:          if (tmp->addr.sa.sa_family == family)
                    132:            {
                    133:              if (family == AF_INET &&
                    134:                  tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
                    135:                ret = tmp->used = 1;
                    136: #ifdef HAVE_IPV6
                    137:              else if (family == AF_INET6 &&
                    138:                       IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 
                    139:                                          &addr->addr.addr6))
                    140:                ret = tmp->used = 1;
                    141: #endif
                    142:            }          
                    143:     }
                    144:   
                    145:   for (tmp = daemon->if_except; tmp; tmp = tmp->next)
                    146:     if (tmp->name && wildcard_match(tmp->name, name))
                    147:       ret = 0;
                    148:     
                    149: 
                    150:   for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
                    151:     if (tmp->name)
                    152:       {
                    153:        if (strcmp(tmp->name, name) == 0)
                    154:          break;
                    155:       }
                    156:     else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
                    157:             tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
                    158:       break;
                    159: #ifdef HAVE_IPV6
                    160:     else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
                    161:             IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
                    162:       break;
                    163: #endif      
                    164: 
                    165:   if (tmp && auth) 
                    166:     {
                    167:       *auth = 1;
                    168:       ret = 1;
                    169:     }
                    170: 
                    171:   return ret; 
                    172: }
                    173: 
                    174: 
                    175: /* Fix for problem that the kernel sometimes reports the loopback inerface as the
                    176:    arrival interface when a packet originates locally, even when sent to address of 
                    177:    an interface other than the loopback. Accept packet if it arrived via a loopback 
                    178:    interface, even when we're not accepting packets that way, as long as the destination
                    179:    address is one we're believing. Interface list must be up-to-date before calling. */
                    180: int loopback_exception(int fd, int family, struct all_addr *addr, char *name)    
                    181: {
                    182:   struct ifreq ifr;
                    183:   struct irec *iface;
                    184: 
                    185:   strncpy(ifr.ifr_name, name, IF_NAMESIZE);
                    186:   if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
                    187:       ifr.ifr_flags & IFF_LOOPBACK)
                    188:     {
                    189:       for (iface = daemon->interfaces; iface; iface = iface->next)
                    190:        if (iface->addr.sa.sa_family == family)
                    191:          {
                    192:            if (family == AF_INET)
                    193:              {
                    194:                if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
                    195:                  return 1;
                    196:              }
                    197: #ifdef HAVE_IPV6
                    198:            else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
                    199:              return 1;
                    200: #endif
                    201:            
                    202:          }
                    203:     }
                    204:   return 0;
                    205: }
                    206: 
                    207: static int iface_allowed(struct irec **irecp, int if_index, 
                    208:                         union mysockaddr *addr, struct in_addr netmask, int dad) 
                    209: {
                    210:   struct irec *iface;
                    211:   int fd, mtu = 0, loopback;
                    212:   struct ifreq ifr;
                    213:   int tftp_ok = !!option_bool(OPT_TFTP);
                    214:   int dhcp_ok = 1;
                    215:   int auth_dns = 0;
                    216: #ifdef HAVE_DHCP
                    217:   struct iname *tmp;
                    218: #endif
                    219: 
                    220:   /* check whether the interface IP has been added already 
                    221:      we call this routine multiple times. */
                    222:   for (iface = *irecp; iface; iface = iface->next) 
                    223:     if (sockaddr_isequal(&iface->addr, addr))
                    224:       {
                    225:        iface->dad = dad;
                    226:        return 1;
                    227:       }
                    228: 
                    229:   if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
                    230:       !indextoname(fd, if_index, ifr.ifr_name) ||
                    231:       ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
                    232:     {
                    233:       if (fd != -1)
                    234:        {
                    235:          int errsave = errno;
                    236:          close(fd);
                    237:          errno = errsave;
                    238:        }
                    239:       return 0;
                    240:     }
                    241:    
                    242:   loopback = ifr.ifr_flags & IFF_LOOPBACK;
                    243:   
                    244:   if (loopback)
                    245:      dhcp_ok = 0;
                    246: 
                    247:   if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
                    248:     mtu = ifr.ifr_mtu;
                    249:   
                    250:   close(fd);
                    251:   
                    252:   /* If we are restricting the set of interfaces to use, make
                    253:      sure that loopback interfaces are in that set. */
                    254:   if (daemon->if_names && loopback)
                    255:     {
                    256:       struct iname *lo;
                    257:       for (lo = daemon->if_names; lo; lo = lo->next)
                    258:        if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
                    259:          break;
                    260:       
                    261:       if (!lo && (lo = whine_malloc(sizeof(struct iname)))) 
                    262:        {
                    263:          if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
                    264:            {
                    265:              strcpy(lo->name, ifr.ifr_name);
                    266:              lo->used = 1;
                    267:              lo->next = daemon->if_names;
                    268:              daemon->if_names = lo;
                    269:            }
                    270:          else
                    271:            free(lo);
                    272:        }
                    273:     }
                    274:   
                    275:   if (addr->sa.sa_family == AF_INET &&
                    276:       !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
                    277:     return 1;
                    278: 
                    279: #ifdef HAVE_IPV6
                    280:   if (addr->sa.sa_family == AF_INET6 &&
                    281:       !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
                    282:     return 1;
                    283: #endif
                    284:     
                    285: #ifdef HAVE_DHCP
                    286:   /* No DHCP where we're doing auth DNS. */
                    287:   if (auth_dns)
                    288:     {
                    289:       tftp_ok = 0;
                    290:       dhcp_ok = 0;
                    291:     }
                    292:   else
                    293:     for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
                    294:       if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
                    295:        {
                    296:          tftp_ok = 0;
                    297:          dhcp_ok = 0;
                    298:        }
                    299: #endif
                    300:  
                    301:   /* add to list */
                    302:   if ((iface = whine_malloc(sizeof(struct irec))))
                    303:     {
                    304:       iface->addr = *addr;
                    305:       iface->netmask = netmask;
                    306:       iface->tftp_ok = tftp_ok;
                    307:       iface->dhcp_ok = dhcp_ok;
                    308:       iface->dns_auth = auth_dns;
                    309:       iface->mtu = mtu;
                    310:       iface->dad = dad;
                    311:       iface->done = iface->multicast_done = 0;
                    312:       iface->index = if_index;
                    313:       if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
                    314:        {
                    315:          strcpy(iface->name, ifr.ifr_name);
                    316:          iface->next = *irecp;
                    317:          *irecp = iface;
                    318:          return 1;
                    319:        }
                    320:       free(iface);
                    321: 
                    322:     }
                    323:   
                    324:   errno = ENOMEM; 
                    325:   return 0;
                    326: }
                    327: 
                    328: #ifdef HAVE_IPV6
                    329: static int iface_allowed_v6(struct in6_addr *local, int prefix, 
                    330:                            int scope, int if_index, int flags, 
                    331:                            int preferred, int valid, void *vparam)
                    332: {
                    333:   union mysockaddr addr;
                    334:   struct in_addr netmask; /* dummy */
                    335:   netmask.s_addr = 0;
                    336: 
                    337:   (void)prefix; /* warning */
                    338:   (void)scope; /* warning */
                    339:   (void)preferred;
                    340:   (void)valid;
                    341:   
                    342:   memset(&addr, 0, sizeof(addr));
                    343: #ifdef HAVE_SOCKADDR_SA_LEN
                    344:   addr.in6.sin6_len = sizeof(addr.in6);
                    345: #endif
                    346:   addr.in6.sin6_family = AF_INET6;
                    347:   addr.in6.sin6_addr = *local;
                    348:   addr.in6.sin6_port = htons(daemon->port);
                    349:   addr.in6.sin6_scope_id = if_index;
                    350:   
                    351:   return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, !!(flags & IFACE_TENTATIVE));
                    352: }
                    353: #endif
                    354: 
                    355: static int iface_allowed_v4(struct in_addr local, int if_index, 
                    356:                            struct in_addr netmask, struct in_addr broadcast, void *vparam)
                    357: {
                    358:   union mysockaddr addr;
                    359: 
                    360:   memset(&addr, 0, sizeof(addr));
                    361: #ifdef HAVE_SOCKADDR_SA_LEN
                    362:   addr.in.sin_len = sizeof(addr.in);
                    363: #endif
                    364:   addr.in.sin_family = AF_INET;
                    365:   addr.in.sin_addr = broadcast; /* warning */
                    366:   addr.in.sin_addr = local;
                    367:   addr.in.sin_port = htons(daemon->port);
                    368: 
                    369:   return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, 0);
                    370: }
                    371:    
                    372: int enumerate_interfaces(void)
                    373: {
                    374: #ifdef HAVE_IPV6
                    375:   if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6))
                    376:     return 0; 
                    377: #endif
                    378: 
                    379:   return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4); 
                    380: }
                    381: 
                    382: /* set NONBLOCK bit on fd: See Stevens 16.6 */
                    383: int fix_fd(int fd)
                    384: {
                    385:   int flags;
                    386: 
                    387:   if ((flags = fcntl(fd, F_GETFL)) == -1 ||
                    388:       fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
                    389:     return 0;
                    390:   
                    391:   return 1;
                    392: }
                    393: 
                    394: static int make_sock(union mysockaddr *addr, int type, int dienow)
                    395: {
                    396:   int family = addr->sa.sa_family;
                    397:   int fd, rc, opt = 1;
                    398:   
                    399:   if ((fd = socket(family, type, 0)) == -1)
                    400:     {
                    401:       int port;
                    402:       char *s;
                    403: 
                    404:       /* No error if the kernel just doesn't support this IP flavour */
                    405:       if (errno == EPROTONOSUPPORT ||
                    406:          errno == EAFNOSUPPORT ||
                    407:          errno == EINVAL)
                    408:        return -1;
                    409:       
                    410:     err:
                    411:       port = prettyprint_addr(addr, daemon->addrbuff);
                    412:       if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
                    413:        sprintf(daemon->addrbuff, "port %d", port);
                    414:       s = _("failed to create listening socket for %s: %s");
                    415:       
                    416:       if (fd != -1)
                    417:        close (fd);
                    418:       
                    419:       if (dienow)
                    420:        {
                    421:          /* failure to bind addresses given by --listen-address at this point
                    422:             is OK if we're doing bind-dynamic */
                    423:          if (!option_bool(OPT_CLEVERBIND))
                    424:            die(s, daemon->addrbuff, EC_BADNET);
                    425:        }
                    426:       else
                    427:        my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
                    428:       
                    429:       return -1;
                    430:     }  
                    431:   
                    432:   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
                    433:     goto err;
                    434:   
                    435: #ifdef HAVE_IPV6
                    436:   if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
                    437:     goto err;
                    438: #endif
                    439:   
                    440:   if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
                    441:     goto err;
                    442:   
                    443:   if (type == SOCK_STREAM)
                    444:     {
                    445:       if (listen(fd, 5) == -1)
                    446:        goto err;
                    447:     }
                    448:   else if (!option_bool(OPT_NOWILD))
                    449:     {
                    450:       if (family == AF_INET)
                    451:        {
                    452: #if defined(HAVE_LINUX_NETWORK) 
                    453:          if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
                    454:            goto err;
                    455: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
                    456:          if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
                    457:              setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
                    458:            goto err;
                    459: #endif
                    460:        }
                    461: #ifdef HAVE_IPV6
                    462:       else if (!set_ipv6pktinfo(fd))
                    463:        goto err;
                    464: #endif
                    465:     }
                    466:   
                    467:   return fd;
                    468: }
                    469: 
                    470: #ifdef HAVE_IPV6  
                    471: int set_ipv6pktinfo(int fd)
                    472: {
                    473:   int opt = 1;
                    474: 
                    475:   /* The API changed around Linux 2.6.14 but the old ABI is still supported:
                    476:      handle all combinations of headers and kernel.
                    477:      OpenWrt note that this fixes the problem addressed by your very broken patch. */
                    478:   daemon->v6pktinfo = IPV6_PKTINFO;
                    479:   
                    480: #ifdef IPV6_RECVPKTINFO
                    481:   if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
                    482:     return 1;
                    483: # ifdef IPV6_2292PKTINFO
                    484:   else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
                    485:     {
                    486:       daemon->v6pktinfo = IPV6_2292PKTINFO;
                    487:       return 1;
                    488:     }
                    489: # endif 
                    490: #else
                    491:   if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
                    492:     return 1;
                    493: #endif
                    494: 
                    495:   return 0;
                    496: }
                    497: #endif
                    498: 
                    499: 
                    500: /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
                    501: int tcp_interface(int fd, int af)
                    502: { 
                    503:   int if_index = 0;
                    504: 
                    505: #ifdef HAVE_LINUX_NETWORK
                    506:   int opt = 1;
                    507:   struct cmsghdr *cmptr;
                    508:   struct msghdr msg;
                    509:   
                    510:   /* use mshdr do that the CMSDG_* macros are available */
                    511:   msg.msg_control = daemon->packet;
                    512:   msg.msg_controllen = daemon->packet_buff_sz;
                    513:   
                    514:   /* we overwrote the buffer... */
                    515:   daemon->srv_save = NULL;
                    516:   
                    517:   if (af == AF_INET)
                    518:     {
                    519:       if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
                    520:          getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
                    521:        for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
                    522:          if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
                    523:             {
                    524:               union {
                    525:                 unsigned char *c;
                    526:                 struct in_pktinfo *p;
                    527:               } p;
                    528:              
                    529:              p.c = CMSG_DATA(cmptr);
                    530:              if_index = p.p->ipi_ifindex;
                    531:            }
                    532:     }
                    533: #ifdef HAVE_IPV6
                    534:   else
                    535:     {
                    536:       /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
                    537:         it was removed in RFC-3542 !!!! 
                    538: 
                    539:         Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
                    540:         uses the old ABI, and should work with pre- and post-3542 kernel headers */
                    541: 
                    542: #ifdef IPV6_2292PKTOPTIONS   
                    543: #  define PKTOPTIONS IPV6_2292PKTOPTIONS
                    544: #else
                    545: #  define PKTOPTIONS IPV6_PKTOPTIONS
                    546: #endif
                    547: 
                    548:       if (set_ipv6pktinfo(fd) &&
                    549:          getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
                    550:        {
                    551:           for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
                    552:             if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
                    553:               {
                    554:                 union {
                    555:                   unsigned char *c;
                    556:                   struct in6_pktinfo *p;
                    557:                 } p;
                    558:                 p.c = CMSG_DATA(cmptr);
                    559:                
                    560:                if_index = p.p->ipi6_ifindex;
                    561:               }
                    562:        }
                    563:     }
                    564: #endif /* IPV6 */
                    565: #endif /* Linux */
                    566:  
                    567:   return if_index;
                    568: }
                    569:       
                    570: static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
                    571: {
                    572:   struct listener *l = NULL;
                    573:   int fd = -1, tcpfd = -1, tftpfd = -1;
                    574: 
                    575:   if (daemon->port != 0)
                    576:     {
                    577:       fd = make_sock(addr, SOCK_DGRAM, dienow);
                    578:       tcpfd = make_sock(addr, SOCK_STREAM, dienow);
                    579:     }
                    580:   
                    581: #ifdef HAVE_TFTP
                    582:   if (do_tftp)
                    583:     {
                    584:       if (addr->sa.sa_family == AF_INET)
                    585:        {
                    586:          /* port must be restored to DNS port for TCP code */
                    587:          short save = addr->in.sin_port;
                    588:          addr->in.sin_port = htons(TFTP_PORT);
                    589:          tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
                    590:          addr->in.sin_port = save;
                    591:        }
                    592: #  ifdef HAVE_IPV6
                    593:       else
                    594:        {
                    595:          short save = addr->in6.sin6_port;
                    596:          addr->in6.sin6_port = htons(TFTP_PORT);
                    597:          tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
                    598:          addr->in6.sin6_port = save;
                    599:        }  
                    600: #  endif
                    601:     }
                    602: #endif
                    603: 
                    604:   if (fd != -1 || tcpfd != -1 || tftpfd != -1)
                    605:     {
                    606:       l = safe_malloc(sizeof(struct listener));
                    607:       l->next = NULL;
                    608:       l->family = addr->sa.sa_family;
                    609:       l->fd = fd;
                    610:       l->tcpfd = tcpfd;
                    611:       l->tftpfd = tftpfd;
                    612:     }
                    613: 
                    614:   return l;
                    615: }
                    616: 
                    617: void create_wildcard_listeners(void)
                    618: {
                    619:   union mysockaddr addr;
                    620:   struct listener *l, *l6;
                    621: 
                    622:   memset(&addr, 0, sizeof(addr));
                    623: #ifdef HAVE_SOCKADDR_SA_LEN
                    624:   addr.in.sin_len = sizeof(addr.in);
                    625: #endif
                    626:   addr.in.sin_family = AF_INET;
                    627:   addr.in.sin_addr.s_addr = INADDR_ANY;
                    628:   addr.in.sin_port = htons(daemon->port);
                    629: 
                    630:   l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
                    631: 
                    632: #ifdef HAVE_IPV6
                    633:   memset(&addr, 0, sizeof(addr));
                    634: #  ifdef HAVE_SOCKADDR_SA_LEN
                    635:   addr.in6.sin6_len = sizeof(addr.in6);
                    636: #  endif
                    637:   addr.in6.sin6_family = AF_INET6;
                    638:   addr.in6.sin6_addr = in6addr_any;
                    639:   addr.in6.sin6_port = htons(daemon->port);
                    640:  
                    641:   l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
                    642:   if (l) 
                    643:     l->next = l6;
                    644:   else 
                    645:     l = l6;
                    646: #endif
                    647: 
                    648:   daemon->listeners = l;
                    649: }
                    650: 
                    651: void create_bound_listeners(int dienow)
                    652: {
                    653:   struct listener *new;
                    654:   struct irec *iface;
                    655:   struct iname *if_tmp;
                    656: 
                    657:   for (iface = daemon->interfaces; iface; iface = iface->next)
                    658:     if (!iface->done && !iface->dad && 
                    659:        (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
                    660:       {
                    661:        new->iface = iface;
                    662:        new->next = daemon->listeners;
                    663:        daemon->listeners = new;
                    664:        iface->done = 1;
                    665:       }
                    666: 
                    667:   /* Check for --listen-address options that haven't been used because there's
                    668:      no interface with a matching address. These may be valid: eg it's possible
                    669:      to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
                    670: 
                    671:      If the address isn't valid the bind() will fail and we'll die() 
                    672:      (except in bind-dynamic mode, when we'll complain but keep trying.)
                    673: 
                    674:      The resulting listeners have the ->iface field NULL, and this has to be
                    675:      handled by the DNS and TFTP code. It disables --localise-queries processing
                    676:      (no netmask) and some MTU login the tftp code. */
                    677: 
                    678:   for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
                    679:     if (!if_tmp->used && 
                    680:        (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
                    681:       {
                    682:        new->iface = NULL;
                    683:        new->next = daemon->listeners;
                    684:        daemon->listeners = new;
                    685:       }
                    686: }
                    687: 
                    688: int is_dad_listeners(void)
                    689: {
                    690:   struct irec *iface;
                    691:   
                    692:   if (option_bool(OPT_NOWILD))
                    693:     for (iface = daemon->interfaces; iface; iface = iface->next)
                    694:       if (iface->dad && !iface->done)
                    695:        return 1;
                    696:   
                    697:   return 0;
                    698: }
                    699: 
                    700: #ifdef HAVE_DHCP6
                    701: void join_multicast(int dienow)      
                    702: {
                    703:   struct irec *iface, *tmp;
                    704: 
                    705:   for (iface = daemon->interfaces; iface; iface = iface->next)
                    706:     if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
                    707:       {
                    708:        /* There's an irec per address but we only want to join for multicast 
                    709:           once per interface. Weed out duplicates. */
                    710:        for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
                    711:          if (tmp->multicast_done && tmp->index == iface->index)
                    712:            break;
                    713:        
                    714:        iface->multicast_done = 1;
                    715:        
                    716:        if (!tmp)
                    717:          {
                    718:            struct ipv6_mreq mreq;
                    719:            int err = 0;
                    720: 
                    721:            mreq.ipv6mr_interface = iface->index;
                    722:            
                    723:            inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
                    724:            
                    725:            if (daemon->doing_dhcp6 &&
                    726:                setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
                    727:              err = 1;
                    728:            
                    729:            inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
                    730:            
                    731:            if (daemon->doing_dhcp6 && 
                    732:                setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
                    733:              err = 1;
                    734:            
                    735:            inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
                    736:            
                    737:            if (daemon->doing_ra &&
                    738:                setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
                    739:              err = 1;
                    740:            
                    741:            if (err)
                    742:              {
                    743:                char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
                    744:                if (dienow)
                    745:                  die(s, iface->name, EC_BADNET);
                    746:                else
                    747:                  my_syslog(LOG_ERR, s, iface->name, strerror(errno));
                    748:              }
                    749:          }
                    750:       }
                    751: }
                    752: #endif
                    753: 
                    754: /* return a UDP socket bound to a random port, have to cope with straying into
                    755:    occupied port nos and reserved ones. */
                    756: int random_sock(int family)
                    757: {
                    758:   int fd;
                    759: 
                    760:   if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
                    761:     {
                    762:       union mysockaddr addr;
                    763:       unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
                    764:       int tries = ports_avail < 30 ? 3 * ports_avail : 100;
                    765: 
                    766:       memset(&addr, 0, sizeof(addr));
                    767:       addr.sa.sa_family = family;
                    768: 
                    769:       /* don't loop forever if all ports in use. */
                    770: 
                    771:       if (fix_fd(fd))
                    772:        while(tries--)
                    773:          {
                    774:            unsigned short port = rand16();
                    775:            
                    776:            if (daemon->min_port != 0)
                    777:              port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
                    778:            
                    779:            if (family == AF_INET) 
                    780:              {
                    781:                addr.in.sin_addr.s_addr = INADDR_ANY;
                    782:                addr.in.sin_port = port;
                    783: #ifdef HAVE_SOCKADDR_SA_LEN
                    784:                addr.in.sin_len = sizeof(struct sockaddr_in);
                    785: #endif
                    786:              }
                    787: #ifdef HAVE_IPV6
                    788:            else
                    789:              {
                    790:                addr.in6.sin6_addr = in6addr_any; 
                    791:                addr.in6.sin6_port = port;
                    792: #ifdef HAVE_SOCKADDR_SA_LEN
                    793:                addr.in6.sin6_len = sizeof(struct sockaddr_in6);
                    794: #endif
                    795:              }
                    796: #endif
                    797:            
                    798:            if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
                    799:              return fd;
                    800:            
                    801:            if (errno != EADDRINUSE && errno != EACCES)
                    802:              break;
                    803:          }
                    804: 
                    805:       close(fd);
                    806:     }
                    807: 
                    808:   return -1; 
                    809: }
                    810:   
                    811: 
                    812: int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
                    813: {
                    814:   union mysockaddr addr_copy = *addr;
                    815: 
                    816:   /* cannot set source _port_ for TCP connections. */
                    817:   if (is_tcp)
                    818:     {
                    819:       if (addr_copy.sa.sa_family == AF_INET)
                    820:        addr_copy.in.sin_port = 0;
                    821: #ifdef HAVE_IPV6
                    822:       else
                    823:        addr_copy.in6.sin6_port = 0;
                    824: #endif
                    825:     }
                    826:   
                    827:   if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
                    828:     return 0;
                    829:     
                    830: #if defined(SO_BINDTODEVICE)
                    831:   if (intname[0] != 0 &&
                    832:       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
                    833:     return 0;
                    834: #endif
                    835: 
                    836:   return 1;
                    837: }
                    838: 
                    839: static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
                    840: {
                    841:   struct serverfd *sfd;
                    842:   int errsave;
                    843: 
                    844:   /* when using random ports, servers which would otherwise use
                    845:      the INADDR_ANY/port0 socket have sfd set to NULL */
                    846:   if (!daemon->osport && intname[0] == 0)
                    847:     {
                    848:       errno = 0;
                    849:       
                    850:       if (addr->sa.sa_family == AF_INET &&
                    851:          addr->in.sin_addr.s_addr == INADDR_ANY &&
                    852:          addr->in.sin_port == htons(0)) 
                    853:        return NULL;
                    854: 
                    855: #ifdef HAVE_IPV6
                    856:       if (addr->sa.sa_family == AF_INET6 &&
                    857:          memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
                    858:          addr->in6.sin6_port == htons(0)) 
                    859:        return NULL;
                    860: #endif
                    861:     }
                    862:       
                    863:   /* may have a suitable one already */
                    864:   for (sfd = daemon->sfds; sfd; sfd = sfd->next )
                    865:     if (sockaddr_isequal(&sfd->source_addr, addr) &&
                    866:        strcmp(intname, sfd->interface) == 0)
                    867:       return sfd;
                    868:   
                    869:   /* need to make a new one. */
                    870:   errno = ENOMEM; /* in case malloc fails. */
                    871:   if (!(sfd = whine_malloc(sizeof(struct serverfd))))
                    872:     return NULL;
                    873:   
                    874:   if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
                    875:     {
                    876:       free(sfd);
                    877:       return NULL;
                    878:     }
                    879:   
                    880:   if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
                    881:     { 
                    882:       errsave = errno; /* save error from bind. */
                    883:       close(sfd->fd);
                    884:       free(sfd);
                    885:       errno = errsave;
                    886:       return NULL;
                    887:     }
                    888:     
                    889:   strcpy(sfd->interface, intname); 
                    890:   sfd->source_addr = *addr;
                    891:   sfd->next = daemon->sfds;
                    892:   daemon->sfds = sfd;
                    893:   return sfd; 
                    894: }
                    895: 
                    896: /* create upstream sockets during startup, before root is dropped which may be needed
                    897:    this allows query_port to be a low port and interface binding */
                    898: void pre_allocate_sfds(void)
                    899: {
                    900:   struct server *srv;
                    901:   
                    902:   if (daemon->query_port != 0)
                    903:     {
                    904:       union  mysockaddr addr;
                    905:       memset(&addr, 0, sizeof(addr));
                    906:       addr.in.sin_family = AF_INET;
                    907:       addr.in.sin_addr.s_addr = INADDR_ANY;
                    908:       addr.in.sin_port = htons(daemon->query_port);
                    909: #ifdef HAVE_SOCKADDR_SA_LEN
                    910:       addr.in.sin_len = sizeof(struct sockaddr_in);
                    911: #endif
                    912:       allocate_sfd(&addr, "");
                    913: #ifdef HAVE_IPV6
                    914:       memset(&addr, 0, sizeof(addr));
                    915:       addr.in6.sin6_family = AF_INET6;
                    916:       addr.in6.sin6_addr = in6addr_any;
                    917:       addr.in6.sin6_port = htons(daemon->query_port);
                    918: #ifdef HAVE_SOCKADDR_SA_LEN
                    919:       addr.in6.sin6_len = sizeof(struct sockaddr_in6);
                    920: #endif
                    921:       allocate_sfd(&addr, "");
                    922: #endif
                    923:     }
                    924:   
                    925:   for (srv = daemon->servers; srv; srv = srv->next)
                    926:     if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
                    927:        !allocate_sfd(&srv->source_addr, srv->interface) &&
                    928:        errno != 0 &&
                    929:        option_bool(OPT_NOWILD))
                    930:       {
                    931:        prettyprint_addr(&srv->source_addr, daemon->namebuff);
                    932:        if (srv->interface[0] != 0)
                    933:          {
                    934:            strcat(daemon->namebuff, " ");
                    935:            strcat(daemon->namebuff, srv->interface);
                    936:          }
                    937:        die(_("failed to bind server socket for %s: %s"),
                    938:            daemon->namebuff, EC_BADNET);
                    939:       }  
                    940: }
                    941: 
                    942: 
                    943: void check_servers(void)
                    944: {
                    945:   struct irec *iface;
                    946:   struct server *new, *tmp, *ret = NULL;
                    947:   int port = 0;
                    948: 
                    949:   /* interface may be new since startup */
                    950:   if (!option_bool(OPT_NOWILD))
                    951:     enumerate_interfaces();
                    952:   
                    953:   for (new = daemon->servers; new; new = tmp)
                    954:     {
                    955:       tmp = new->next;
                    956:       
                    957:       if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
                    958:        {
                    959:          port = prettyprint_addr(&new->addr, daemon->namebuff);
                    960: 
                    961:          /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
                    962:          if (new->addr.sa.sa_family == AF_INET &&
                    963:              new->addr.in.sin_addr.s_addr == 0)
                    964:            {
                    965:              free(new);
                    966:              continue;
                    967:            }
                    968: 
                    969:          for (iface = daemon->interfaces; iface; iface = iface->next)
                    970:            if (sockaddr_isequal(&new->addr, &iface->addr))
                    971:              break;
                    972:          if (iface)
                    973:            {
                    974:              my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
                    975:              free(new);
                    976:              continue;
                    977:            }
                    978:          
                    979:          /* Do we need a socket set? */
                    980:          if (!new->sfd && 
                    981:              !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
                    982:              errno != 0)
                    983:            {
                    984:              my_syslog(LOG_WARNING, 
                    985:                        _("ignoring nameserver %s - cannot make/bind socket: %s"),
                    986:                        daemon->namebuff, strerror(errno));
                    987:              free(new);
                    988:              continue;
                    989:            }
                    990:        }
                    991:       
                    992:       /* reverse order - gets it right. */
                    993:       new->next = ret;
                    994:       ret = new;
                    995:       
                    996:       if (!(new->flags & SERV_NO_REBIND))
                    997:        {
                    998:          if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
                    999:            {
                   1000:              char *s1, *s2;
                   1001:              if (!(new->flags & SERV_HAS_DOMAIN))
                   1002:                s1 = _("unqualified"), s2 = _("names");
                   1003:              else if (strlen(new->domain) == 0)
                   1004:                s1 = _("default"), s2 = "";
                   1005:              else
                   1006:                s1 = _("domain"), s2 = new->domain;
                   1007:              
                   1008:              if (new->flags & SERV_NO_ADDR)
                   1009:                my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
                   1010:              else if (new->flags & SERV_USE_RESOLV)
                   1011:                my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
                   1012:              else if (!(new->flags & SERV_LITERAL_ADDRESS))
                   1013:                my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
                   1014:            }
                   1015:          else if (new->interface[0] != 0)
                   1016:            my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface); 
                   1017:          else
                   1018:            my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 
                   1019:        }
                   1020:     }
                   1021:   
                   1022:   daemon->servers = ret;
                   1023: }
                   1024: 
                   1025: /* Return zero if no servers found, in that case we keep polling.
                   1026:    This is a protection against an update-time/write race on resolv.conf */
                   1027: int reload_servers(char *fname)
                   1028: {
                   1029:   FILE *f;
                   1030:   char *line;
                   1031:   struct server *old_servers = NULL;
                   1032:   struct server *new_servers = NULL;
                   1033:   struct server *serv;
                   1034:   int gotone = 0;
                   1035: 
                   1036:   /* buff happens to be MAXDNAME long... */
                   1037:   if (!(f = fopen(fname, "r")))
                   1038:     {
                   1039:       my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
                   1040:       return 0;
                   1041:     }
                   1042:   
                   1043:   /* move old servers to free list - we can reuse the memory 
                   1044:      and not risk malloc if there are the same or fewer new servers. 
                   1045:      Servers which were specced on the command line go to the new list. */
                   1046:   for (serv = daemon->servers; serv;)
                   1047:     {
                   1048:       struct server *tmp = serv->next;
                   1049:       if (serv->flags & SERV_FROM_RESOLV)
                   1050:        {
                   1051:          serv->next = old_servers;
                   1052:          old_servers = serv; 
                   1053:          /* forward table rules reference servers, so have to blow them away */
                   1054:          server_gone(serv);
                   1055:        }
                   1056:       else
                   1057:        {
                   1058:          serv->next = new_servers;
                   1059:          new_servers = serv;
                   1060:        }
                   1061:       serv = tmp;
                   1062:     }
                   1063:   
                   1064:   while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
                   1065:     {
                   1066:       union mysockaddr addr, source_addr;
                   1067:       char *token = strtok(line, " \t\n\r");
                   1068:       
                   1069:       if (!token)
                   1070:        continue;
                   1071:       if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
                   1072:        continue;
                   1073:       if (!(token = strtok(NULL, " \t\n\r")))
                   1074:        continue;
                   1075:       
                   1076:       memset(&addr, 0, sizeof(addr));
                   1077:       memset(&source_addr, 0, sizeof(source_addr));
                   1078:       
                   1079:       if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
                   1080:        {
                   1081: #ifdef HAVE_SOCKADDR_SA_LEN
                   1082:          source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
                   1083: #endif
                   1084:          source_addr.in.sin_family = addr.in.sin_family = AF_INET;
                   1085:          addr.in.sin_port = htons(NAMESERVER_PORT);
                   1086:          source_addr.in.sin_addr.s_addr = INADDR_ANY;
                   1087:          source_addr.in.sin_port = htons(daemon->query_port);
                   1088:        }
                   1089: #ifdef HAVE_IPV6
                   1090:       else 
                   1091:        {       
                   1092:          int scope_index = 0;
                   1093:          char *scope_id = strchr(token, '%');
                   1094:          
                   1095:          if (scope_id)
                   1096:            {
                   1097:              *(scope_id++) = 0;
                   1098:              scope_index = if_nametoindex(scope_id);
                   1099:            }
                   1100:          
                   1101:          if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
                   1102:            {
                   1103: #ifdef HAVE_SOCKADDR_SA_LEN
                   1104:              source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
                   1105: #endif
                   1106:              source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
                   1107:              source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
                   1108:              addr.in6.sin6_port = htons(NAMESERVER_PORT);
                   1109:              addr.in6.sin6_scope_id = scope_index;
                   1110:              source_addr.in6.sin6_addr = in6addr_any;
                   1111:              source_addr.in6.sin6_port = htons(daemon->query_port);
                   1112:              source_addr.in6.sin6_scope_id = 0;
                   1113:            }
                   1114:          else
                   1115:            continue;
                   1116:        }
                   1117: #else /* IPV6 */
                   1118:       else
                   1119:        continue;
                   1120: #endif 
                   1121: 
                   1122:       if (old_servers)
                   1123:        {
                   1124:          serv = old_servers;
                   1125:          old_servers = old_servers->next;
                   1126:        }
                   1127:       else if (!(serv = whine_malloc(sizeof (struct server))))
                   1128:        continue;
                   1129:       
                   1130:       /* this list is reverse ordered: 
                   1131:         it gets reversed again in check_servers */
                   1132:       serv->next = new_servers;
                   1133:       new_servers = serv;
                   1134:       serv->addr = addr;
                   1135:       serv->source_addr = source_addr;
                   1136:       serv->domain = NULL;
                   1137:       serv->interface[0] = 0;
                   1138:       serv->sfd = NULL;
                   1139:       serv->flags = SERV_FROM_RESOLV;
                   1140:       serv->queries = serv->failed_queries = 0;
                   1141:       gotone = 1;
                   1142:     }
                   1143:   
                   1144:   /* Free any memory not used. */
                   1145:   while (old_servers)
                   1146:     {
                   1147:       struct server *tmp = old_servers->next;
                   1148:       free(old_servers);
                   1149:       old_servers = tmp;
                   1150:     }
                   1151: 
                   1152:   daemon->servers = new_servers;
                   1153:   fclose(f);
                   1154: 
                   1155:   return gotone;
                   1156: }
                   1157: 
                   1158: 
                   1159: /* Use an IPv4 listener socket for ioctling */
                   1160: struct in_addr get_ifaddr(char *intr)
                   1161: {
                   1162:   struct listener *l;
                   1163:   struct ifreq ifr;
                   1164:   struct sockaddr_in ret;
                   1165:   
                   1166:   ret.sin_addr.s_addr = -1;
                   1167: 
                   1168:   for (l = daemon->listeners; 
                   1169:        l && (l->family != AF_INET || l->fd == -1);
                   1170:        l = l->next);
                   1171:   
                   1172:   strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
                   1173:   ifr.ifr_addr.sa_family = AF_INET;
                   1174:   
                   1175:   if (l &&  ioctl(l->fd, SIOCGIFADDR, &ifr) != -1)
                   1176:     memcpy(&ret, &ifr.ifr_addr, sizeof(ret)); 
                   1177:   
                   1178:   return ret.sin_addr;
                   1179: }
                   1180: 
                   1181: 
                   1182: 

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