Annotation of embedaddon/dhcp/common/discover.c, revision 1.1.1.1

1.1       misho       1: /* discover.c
                      2: 
                      3:    Find and identify the network interfaces. */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2004-2009,2011 by Internet Systems Consortium, Inc. ("ISC")
                      7:  * Copyright (c) 1995-2003 by Internet Software Consortium
                      8:  *
                      9:  * Permission to use, copy, modify, and distribute this software for any
                     10:  * purpose with or without fee is hereby granted, provided that the above
                     11:  * copyright notice and this permission notice appear in all copies.
                     12:  *
                     13:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     14:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     15:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     16:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     17:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     18:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     19:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     20:  *
                     21:  *   Internet Systems Consortium, Inc.
                     22:  *   950 Charter Street
                     23:  *   Redwood City, CA 94063
                     24:  *   <info@isc.org>
                     25:  *   https://www.isc.org/
                     26:  *
                     27:  * This software has been written for Internet Systems Consortium
                     28:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
                     29:  * To learn more about Internet Systems Consortium, see
                     30:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
                     31:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
                     32:  * ``http://www.nominum.com''.
                     33:  */
                     34: 
                     35: #include "dhcpd.h"
                     36: 
                     37: #define BSD_COMP               /* needed on Solaris for SIOCGLIFNUM */
                     38: #include <sys/ioctl.h>
                     39: #include <errno.h>
                     40: 
                     41: #ifdef HAVE_NET_IF6_H
                     42: # include <net/if6.h>
                     43: #endif
                     44: 
                     45: struct interface_info *interfaces, *dummy_interfaces, *fallback_interface;
                     46: int interfaces_invalidated;
                     47: int quiet_interface_discovery;
                     48: u_int16_t local_port;
                     49: u_int16_t remote_port;
                     50: int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *);
                     51: int (*dhcp_interface_discovery_hook) (struct interface_info *);
                     52: isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *);
                     53: int (*dhcp_interface_shutdown_hook) (struct interface_info *);
                     54: 
                     55: struct in_addr limited_broadcast;
                     56: 
                     57: int local_family = AF_INET;
                     58: struct in_addr local_address;
                     59: 
                     60: #ifdef DHCPv6
                     61: struct in6_addr local_address6;
                     62: #endif /* DHCPv6 */
                     63: 
                     64: void (*bootp_packet_handler) (struct interface_info *,
                     65:                              struct dhcp_packet *, unsigned,
                     66:                              unsigned int,
                     67:                              struct iaddr, struct hardware *);
                     68: 
                     69: #ifdef DHCPv6
                     70: void (*dhcpv6_packet_handler)(struct interface_info *,
                     71:                              const char *, int,
                     72:                              int, const struct iaddr *,
                     73:                              isc_boolean_t);
                     74: #endif /* DHCPv6 */
                     75: 
                     76: 
                     77: omapi_object_type_t *dhcp_type_interface;
                     78: #if defined (TRACING)
                     79: trace_type_t *interface_trace;
                     80: trace_type_t *inpacket_trace;
                     81: trace_type_t *outpacket_trace;
                     82: #endif
                     83: struct interface_info **interface_vector;
                     84: int interface_count;
                     85: int interface_max;
                     86: 
                     87: OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface)
                     88: 
                     89: isc_result_t interface_setup ()
                     90: {
                     91:        isc_result_t status;
                     92:        status = omapi_object_type_register (&dhcp_type_interface,
                     93:                                             "interface",
                     94:                                             dhcp_interface_set_value,
                     95:                                             dhcp_interface_get_value,
                     96:                                             dhcp_interface_destroy,
                     97:                                             dhcp_interface_signal_handler,
                     98:                                             dhcp_interface_stuff_values,
                     99:                                             dhcp_interface_lookup, 
                    100:                                             dhcp_interface_create,
                    101:                                             dhcp_interface_remove,
                    102:                                             0, 0, 0,
                    103:                                             sizeof (struct interface_info),
                    104:                                             interface_initialize, RC_MISC);
                    105:        if (status != ISC_R_SUCCESS)
                    106:                log_fatal ("Can't register interface object type: %s",
                    107:                           isc_result_totext (status));
                    108: 
                    109:        return status;
                    110: }
                    111: 
                    112: #if defined (TRACING)
                    113: void interface_trace_setup ()
                    114: {
                    115:        interface_trace = trace_type_register ("interface", (void *)0,
                    116:                                               trace_interface_input,
                    117:                                               trace_interface_stop, MDL);
                    118:        inpacket_trace = trace_type_register ("inpacket", (void *)0,
                    119:                                               trace_inpacket_input,
                    120:                                               trace_inpacket_stop, MDL);
                    121:        outpacket_trace = trace_type_register ("outpacket", (void *)0,
                    122:                                               trace_outpacket_input,
                    123:                                               trace_outpacket_stop, MDL);
                    124: }
                    125: #endif
                    126: 
                    127: isc_result_t interface_initialize (omapi_object_t *ipo,
                    128:                                   const char *file, int line)
                    129: {
                    130:        struct interface_info *ip = (struct interface_info *)ipo;
                    131:        ip -> rfdesc = ip -> wfdesc = -1;
                    132:        return ISC_R_SUCCESS;
                    133: }
                    134: 
                    135: 
                    136: /* 
                    137:  * Scanning for Interfaces
                    138:  * -----------------------
                    139:  *
                    140:  * To find interfaces, we create an iterator that abstracts out most 
                    141:  * of the platform specifics. Use is fairly straightforward:
                    142:  *
                    143:  * - begin_iface_scan() starts the process.
                    144:  * - Use next_iface() until it returns 0.
                    145:  * - end_iface_scan() performs any necessary cleanup.
                    146:  *
                    147:  * We check for errors on each call to next_iface(), which returns a
                    148:  * description of the error as a string if any occurs.
                    149:  *
                    150:  * We currently have code for Solaris and Linux. Other systems need
                    151:  * to have code written.
                    152:  *
                    153:  * NOTE: the long-term goal is to use the interface code from BIND 9.
                    154:  */
                    155: 
                    156: #if defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && defined(SIOCGLIFFLAGS)
                    157: 
                    158: /* HP/UX doesn't define struct lifconf, instead they define struct
                    159:  * if_laddrconf.  Similarly, 'struct lifreq' and 'struct lifaddrreq'.
                    160:  */
                    161: #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
                    162: # define lifc_len iflc_len
                    163: # define lifc_buf iflc_buf
                    164: # define lifc_req iflc_req
                    165: # define LIFCONF if_laddrconf
                    166: #else
                    167: # define ISC_HAVE_LIFC_FAMILY 1
                    168: # define ISC_HAVE_LIFC_FLAGS 1
                    169: # define LIFCONF lifconf
                    170: #endif
                    171: 
                    172: #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
                    173: # define lifr_addr iflr_addr
                    174: # define lifr_name iflr_name
                    175: # define lifr_dstaddr iflr_dstaddr
                    176: # define lifr_flags iflr_flags
                    177: # define sockaddr_storage sockaddr_ext
                    178: # define ss_family sa_family
                    179: # define LIFREQ if_laddrreq
                    180: #else
                    181: # define LIFREQ lifreq
                    182: #endif
                    183: 
                    184: #ifndef IF_NAMESIZE
                    185: # if defined(LIFNAMSIZ)
                    186: #  define IF_NAMESIZE  LIFNAMSIZ
                    187: # elif defined(IFNAMSIZ)
                    188: #  define IF_NAMESIZE  IFNAMSIZ
                    189: # else
                    190: #  define IF_NAMESIZE  16
                    191: # endif
                    192: #endif
                    193: #elif !defined(__linux) && !defined(HAVE_IFADDRS_H)
                    194: # define SIOCGLIFCONF SIOCGIFCONF
                    195: # define SIOCGLIFFLAGS SIOCGIFFLAGS
                    196: # define LIFREQ ifreq
                    197: # define LIFCONF ifconf
                    198: # define lifr_name ifr_name
                    199: # define lifr_addr ifr_addr
                    200: # define lifr_flags ifr_flags
                    201: # define lifc_len ifc_len
                    202: # define lifc_buf ifc_buf
                    203: # define lifc_req ifc_req
                    204: #ifdef _AIX
                    205: # define ss_family __ss_family
                    206: #endif
                    207: #endif
                    208: 
                    209: #if defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
                    210: /* 
                    211:  * Solaris support
                    212:  * ---------------
                    213:  *
                    214:  * The SIOCGLIFCONF ioctl() are the extension that you need to use
                    215:  * on Solaris to get information about IPv6 addresses.
                    216:  *
                    217:  * Solaris' extended interface is documented in the if_tcp man page.
                    218:  */
                    219: 
                    220: /* 
                    221:  * Structure holding state about the scan.
                    222:  */
                    223: struct iface_conf_list {
                    224:        int sock;               /* file descriptor used to get information */
                    225:        int num;                /* total number of interfaces */
                    226:        struct LIFCONF conf;    /* structure used to get information */
                    227:        int next;               /* next interface to retrieve when iterating */
                    228: };
                    229: 
                    230: /* 
                    231:  * Structure used to return information about a specific interface.
                    232:  */
                    233: struct iface_info {
                    234:        char name[IF_NAMESIZE+1];       /* name of the interface, e.g. "bge0" */
                    235:        struct sockaddr_storage addr;   /* address information */
                    236:        isc_uint64_t flags;             /* interface flags, e.g. IFF_LOOPBACK */
                    237: };
                    238: 
                    239: /* 
                    240:  * Start a scan of interfaces.
                    241:  *
                    242:  * The iface_conf_list structure maintains state for this process.
                    243:  */
                    244: int 
                    245: begin_iface_scan(struct iface_conf_list *ifaces) {
                    246: #ifdef ISC_PLATFORM_HAVELIFNUM
                    247:        struct lifnum lifnum;
                    248: #else
                    249:        int lifnum;
                    250: #endif
                    251: 
                    252:        ifaces->sock = socket(local_family, SOCK_DGRAM, IPPROTO_UDP);
                    253:        if (ifaces->sock < 0) {
                    254:                log_error("Error creating socket to list interfaces; %m");
                    255:                return 0;
                    256:        }
                    257: 
                    258:        memset(&lifnum, 0, sizeof(lifnum));
                    259: #ifdef ISC_PLATFORM_HAVELIFNUM
                    260:        lifnum.lifn_family = AF_UNSPEC;
                    261: #endif
                    262: #ifdef SIOCGLIFNUM
                    263:        if (ioctl(ifaces->sock, SIOCGLIFNUM, &lifnum) < 0) {
                    264:                log_error("Error finding total number of interfaces; %m");
                    265:                close(ifaces->sock);
                    266:                ifaces->sock = -1;
                    267:                return 0;
                    268:        }
                    269: 
                    270: #ifdef ISC_PLATFORM_HAVELIFNUM
                    271:        ifaces->num = lifnum.lifn_count;
                    272: #else
                    273:        ifaces->num = lifnum;
                    274: #endif
                    275: #else
                    276:        ifaces->num = 64;
                    277: #endif /* SIOCGLIFNUM */
                    278: 
                    279:        memset(&ifaces->conf, 0, sizeof(ifaces->conf));
                    280: #ifdef ISC_HAVE_LIFC_FAMILY
                    281:        ifaces->conf.lifc_family = AF_UNSPEC;
                    282: #endif
                    283:        ifaces->conf.lifc_len = ifaces->num * sizeof(struct LIFREQ);
                    284:        ifaces->conf.lifc_buf = dmalloc(ifaces->conf.lifc_len, MDL);
                    285:        if (ifaces->conf.lifc_buf == NULL) {
                    286:                log_fatal("Out of memory getting interface list.");
                    287:        }
                    288: 
                    289:        if (ioctl(ifaces->sock, SIOCGLIFCONF, &ifaces->conf) < 0) {
                    290:                log_error("Error getting interfaces configuration list; %m");
                    291:                dfree(ifaces->conf.lifc_buf, MDL);
                    292:                close(ifaces->sock);
                    293:                ifaces->sock = -1;
                    294:                return 0;
                    295:        }
                    296: 
                    297:        ifaces->next = 0;
                    298: 
                    299:        return 1;
                    300: }
                    301: 
                    302: /*
                    303:  * Retrieve the next interface.
                    304:  *
                    305:  * Returns information in the info structure. 
                    306:  * Sets err to 1 if there is an error, otherwise 0.
                    307:  */
                    308: int
                    309: next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
                    310:        struct LIFREQ *p;
                    311:        struct LIFREQ tmp;
                    312:        isc_boolean_t foundif;
                    313: #if defined(sun) || defined(__linux)
                    314:        /* Pointer used to remove interface aliases. */
                    315:        char *s;
                    316: #endif
                    317: 
                    318:        do {
                    319:                foundif = ISC_FALSE;
                    320: 
                    321:                if (ifaces->next >= ifaces->num) {
                    322:                        *err = 0;
                    323:                        return 0;
                    324:                }
                    325: 
                    326:                p = ifaces->conf.lifc_req;
                    327:                p += ifaces->next;
                    328: 
                    329:                if (strlen(p->lifr_name) >= sizeof(info->name)) {
                    330:                        *err = 1;
                    331:                        log_error("Interface name '%s' too long", p->lifr_name);
                    332:                        return 0;
                    333:                }
                    334: 
                    335:                /* Reject if interface address family does not match */
                    336:                if (p->lifr_addr.ss_family != local_family) {
                    337:                        ifaces->next++;
                    338:                        continue;
                    339:                }
                    340: 
                    341:                strcpy(info->name, p->lifr_name);
                    342:                memset(&info->addr, 0, sizeof(info->addr));
                    343:                memcpy(&info->addr, &p->lifr_addr, sizeof(p->lifr_addr));
                    344: 
                    345: #if defined(sun) || defined(__linux)
                    346:                /* interface aliases look like "eth0:1" or "wlan1:3" */
                    347:                s = strchr(info->name, ':');
                    348:                if (s != NULL) {
                    349:                        *s = '\0';
                    350:                }
                    351: #endif /* defined(sun) || defined(__linux) */
                    352: 
                    353:                foundif = ISC_TRUE;
                    354:        } while ((foundif == ISC_FALSE) ||
                    355:                 (strncmp(info->name, "dummy", 5) == 0));
                    356:        
                    357:        memset(&tmp, 0, sizeof(tmp));
                    358:        strcpy(tmp.lifr_name, info->name);
                    359:        if (ioctl(ifaces->sock, SIOCGLIFFLAGS, &tmp) < 0) {
                    360:                log_error("Error getting interface flags for '%s'; %m", 
                    361:                          p->lifr_name);
                    362:                *err = 1;
                    363:                return 0;
                    364:        }
                    365:        info->flags = tmp.lifr_flags;
                    366: 
                    367:        ifaces->next++;
                    368:        *err = 0;
                    369:        return 1;
                    370: }
                    371: 
                    372: /*
                    373:  * End scan of interfaces.
                    374:  */
                    375: void
                    376: end_iface_scan(struct iface_conf_list *ifaces) {
                    377:        dfree(ifaces->conf.lifc_buf, MDL);
                    378:        close(ifaces->sock);
                    379:        ifaces->sock = -1;
                    380: }
                    381: 
                    382: #elif __linux /* !HAVE_SIOCGLIFCONF */
                    383: /* 
                    384:  * Linux support
                    385:  * -------------
                    386:  *
                    387:  * In Linux, we use the /proc pseudo-filesystem to get information
                    388:  * about interfaces, along with selected ioctl() calls.
                    389:  *
                    390:  * Linux low level access is documented in the netdevice man page.
                    391:  */
                    392: 
                    393: /* 
                    394:  * Structure holding state about the scan.
                    395:  */
                    396: struct iface_conf_list {
                    397:        int sock;       /* file descriptor used to get information */
                    398:        FILE *fp;       /* input from /proc/net/dev */
                    399: #ifdef DHCPv6
                    400:        FILE *fp6;      /* input from /proc/net/if_inet6 */
                    401: #endif
                    402: };
                    403: 
                    404: /* 
                    405:  * Structure used to return information about a specific interface.
                    406:  */
                    407: struct iface_info {
                    408:        char name[IFNAMSIZ];            /* name of the interface, e.g. "eth0" */
                    409:        struct sockaddr_storage addr;   /* address information */
                    410:        isc_uint64_t flags;             /* interface flags, e.g. IFF_LOOPBACK */
                    411: };
                    412: 
                    413: /* 
                    414:  * Start a scan of interfaces.
                    415:  *
                    416:  * The iface_conf_list structure maintains state for this process.
                    417:  */
                    418: int 
                    419: begin_iface_scan(struct iface_conf_list *ifaces) {
                    420:        char buf[256];
                    421:        int len;
                    422:        int i;
                    423: 
                    424:        ifaces->fp = fopen("/proc/net/dev", "r");
                    425:        if (ifaces->fp == NULL) {
                    426:                log_error("Error opening '/proc/net/dev' to list interfaces");
                    427:                return 0;
                    428:        }
                    429: 
                    430:        /*
                    431:         * The first 2 lines are header information, so read and ignore them.
                    432:         */
                    433:        for (i=0; i<2; i++) {
                    434:                if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
                    435:                        log_error("Error reading headers from '/proc/net/dev'");
                    436:                        fclose(ifaces->fp);
                    437:                        ifaces->fp = NULL;
                    438:                        return 0;
                    439:                }
                    440:                len = strlen(buf);
                    441:                if ((len <= 0) || (buf[len-1] != '\n')) { 
                    442:                        log_error("Bad header line in '/proc/net/dev'");
                    443:                        fclose(ifaces->fp);
                    444:                        ifaces->fp = NULL;
                    445:                        return 0;
                    446:                }
                    447:        }
                    448: 
                    449:        ifaces->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                    450:        if (ifaces->sock < 0) {
                    451:                log_error("Error creating socket to list interfaces; %m");
                    452:                fclose(ifaces->fp);
                    453:                ifaces->fp = NULL;
                    454:                return 0;
                    455:        }
                    456: 
                    457: #ifdef DHCPv6
                    458:        if (local_family == AF_INET6) {
                    459:                ifaces->fp6 = fopen("/proc/net/if_inet6", "r");
                    460:                if (ifaces->fp6 == NULL) {
                    461:                        log_error("Error opening '/proc/net/if_inet6' to "
                    462:                                  "list IPv6 interfaces; %m");
                    463:                        close(ifaces->sock);
                    464:                        ifaces->sock = -1;
                    465:                        fclose(ifaces->fp);
                    466:                        ifaces->fp = NULL;
                    467:                        return 0;
                    468:                }
                    469:        }
                    470: #endif
                    471: 
                    472:        return 1;
                    473: }
                    474: 
                    475: /*
                    476:  * Read our IPv4 interfaces from /proc/net/dev.
                    477:  *
                    478:  * The file looks something like this:
                    479:  *
                    480:  * Inter-|   Receive ...
                    481:  *  face |bytes    packets errs drop fifo frame ...
                    482:  *     lo: 1580562    4207    0    0    0     0 ...
                    483:  *   eth0:       0       0    0    0    0     0 ...
                    484:  *   eth1:1801552440   37895    0   14    0     ...
                    485:  *
                    486:  * We only care about the interface name, which is at the start of 
                    487:  * each line.
                    488:  *
                    489:  * We use an ioctl() to get the address and flags for each interface.
                    490:  */
                    491: static int
                    492: next_iface4(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
                    493:        char buf[256];
                    494:        int len;
                    495:        char *p;
                    496:        char *name;
                    497:        struct ifreq tmp;
                    498: 
                    499:        /*
                    500:         * Loop exits when we find an interface that has an address, or 
                    501:         * when we run out of interfaces.
                    502:         */
                    503:        for (;;) {
                    504:                do {
                    505:                        /*
                    506:                         *  Read the next line in the file.
                    507:                         */
                    508:                        if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
                    509:                                if (ferror(ifaces->fp)) {
                    510:                                        *err = 1;
                    511:                                        log_error("Error reading interface "
                    512:                                                "information");
                    513:                                } else {
                    514:                                        *err = 0;
                    515:                                }
                    516:                                return 0;
                    517:                        }
                    518: 
                    519:                        /*
                    520:                         * Make sure the line is a nice, 
                    521:                         * newline-terminated line.
                    522:                         */
                    523:                        len = strlen(buf);
                    524:                        if ((len <= 0) || (buf[len-1] != '\n')) { 
                    525:                                log_error("Bad line reading interface "
                    526:                                          "information");
                    527:                                *err = 1;
                    528:                                return 0;
                    529:                        }
                    530: 
                    531:                        /*
                    532:                         * Figure out our name.
                    533:                         */
                    534:                        p = strrchr(buf, ':');
                    535:                        if (p == NULL) {
                    536:                                log_error("Bad line reading interface "
                    537:                                          "information (no colon)");
                    538:                                *err = 1;
                    539:                                return 0;
                    540:                        }
                    541:                        *p = '\0';
                    542:                        name = buf;
                    543:                        while (isspace(*name)) {
                    544:                                name++;
                    545:                        }
                    546: 
                    547:                        /* 
                    548:                         * Copy our name into our interface structure.
                    549:                         */
                    550:                        len = p - name;
                    551:                        if (len >= sizeof(info->name)) {
                    552:                                *err = 1;
                    553:                                log_error("Interface name '%s' too long", name);
                    554:                                return 0;
                    555:                        }
                    556:                        strcpy(info->name, name);
                    557: 
                    558: #ifdef ALIAS_NAMED_PERMUTED
                    559:                        /* interface aliases look like "eth0:1" or "wlan1:3" */
                    560:                        s = strchr(info->name, ':');
                    561:                        if (s != NULL) {
                    562:                                *s = '\0';
                    563:                        }
                    564: #endif
                    565: 
                    566: #ifdef SKIP_DUMMY_INTERFACES
                    567:                } while (strncmp(info->name, "dummy", 5) == 0);
                    568: #else
                    569:                } while (0);
                    570: #endif
                    571: 
                    572:                memset(&tmp, 0, sizeof(tmp));
                    573:                strcpy(tmp.ifr_name, name);
                    574:                if (ioctl(ifaces->sock, SIOCGIFADDR, &tmp) < 0) {
                    575:                        if (errno == EADDRNOTAVAIL) {
                    576:                                continue;
                    577:                        }
                    578:                        log_error("Error getting interface address "
                    579:                                  "for '%s'; %m", name);
                    580:                        *err = 1;
                    581:                        return 0;
                    582:                }
                    583:                memcpy(&info->addr, &tmp.ifr_addr, sizeof(tmp.ifr_addr));
                    584: 
                    585:                memset(&tmp, 0, sizeof(tmp));
                    586:                strcpy(tmp.ifr_name, name);
                    587:                if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
                    588:                        log_error("Error getting interface flags for '%s'; %m", 
                    589:                                name);
                    590:                        *err = 1;
                    591:                        return 0;
                    592:                }
                    593:                info->flags = tmp.ifr_flags;
                    594: 
                    595:                *err = 0;
                    596:                return 1;
                    597:        }
                    598: }
                    599: 
                    600: #ifdef DHCPv6
                    601: /*
                    602:  * Read our IPv6 interfaces from /proc/net/if_inet6.
                    603:  *
                    604:  * The file looks something like this:
                    605:  *
                    606:  * fe80000000000000025056fffec00008 05 40 20 80   vmnet8
                    607:  * 00000000000000000000000000000001 01 80 10 80       lo
                    608:  * fe80000000000000025056fffec00001 06 40 20 80   vmnet1
                    609:  * 200108881936000202166ffffe497d9b 03 40 00 00     eth1
                    610:  * fe8000000000000002166ffffe497d9b 03 40 20 80     eth1
                    611:  *
                    612:  * We get IPv6 address from the start, the interface name from the end, 
                    613:  * and ioctl() to get flags.
                    614:  */
                    615: static int
                    616: next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
                    617:        char buf[256];
                    618:        int len;
                    619:        char *p;
                    620:        char *name;
                    621:        int i;
                    622:        struct sockaddr_in6 addr;
                    623:        struct ifreq tmp;
                    624: 
                    625:        do {
                    626:                /*
                    627:                 *  Read the next line in the file.
                    628:                 */
                    629:                if (fgets(buf, sizeof(buf), ifaces->fp6) == NULL) {
                    630:                        if (ferror(ifaces->fp6)) {
                    631:                                *err = 1;
                    632:                                log_error("Error reading IPv6 "
                    633:                                          "interface information");
                    634:                        } else {
                    635:                                *err = 0;
                    636:                        }
                    637:                        return 0;
                    638:                }
                    639: 
                    640:                /*
                    641:                 * Make sure the line is a nice, newline-terminated line.
                    642:                 */
                    643:                len = strlen(buf);
                    644:                if ((len <= 0) || (buf[len-1] != '\n')) { 
                    645:                        log_error("Bad line reading IPv6 "
                    646:                                  "interface information");
                    647:                        *err = 1;
                    648:                        return 0;
                    649:                }
                    650: 
                    651:                /*
                    652:                 * Figure out our name.
                    653:                 */
                    654:                buf[--len] = '\0';
                    655:                p = strrchr(buf, ' ');
                    656:                if (p == NULL) {
                    657:                        log_error("Bad line reading IPv6 interface "
                    658:                                  "information (no space)");
                    659:                        *err = 1;
                    660:                        return 0;
                    661:                }
                    662:                name = p+1;
                    663: 
                    664:                /* 
                    665:                 * Copy our name into our interface structure.
                    666:                 */
                    667:                len = strlen(name);
                    668:                if (len >= sizeof(info->name)) {
                    669:                        *err = 1;
                    670:                        log_error("IPv6 interface name '%s' too long", name);
                    671:                        return 0;
                    672:                }
                    673:                strcpy(info->name, name);
                    674: 
                    675: #ifdef SKIP_DUMMY_INTERFACES
                    676:        } while (strncmp(info->name, "dummy", 5) == 0);
                    677: #else
                    678:        } while (0);
                    679: #endif
                    680: 
                    681:        /*
                    682:         * Double-check we start with the IPv6 address.
                    683:         */
                    684:        for (i=0; i<32; i++) {
                    685:                if (!isxdigit(buf[i]) || isupper(buf[i])) {
                    686:                        *err = 1;
                    687:                        log_error("Bad line reading IPv6 interface address "
                    688:                                  "for '%s'", name);
                    689:                        return 0;
                    690:                }
                    691:        }
                    692: 
                    693:        /* 
                    694:         * Load our socket structure.
                    695:         */
                    696:        memset(&addr, 0, sizeof(addr));
                    697:        addr.sin6_family = AF_INET6;
                    698:        for (i=0; i<16; i++) {
                    699:                unsigned char byte;
                    700:                 static const char hex[] = "0123456789abcdef";
                    701:                 byte = ((index(hex, buf[i * 2]) - hex) << 4) |
                    702:                        (index(hex, buf[i * 2 + 1]) - hex);
                    703:                addr.sin6_addr.s6_addr[i] = byte;
                    704:        }
                    705:        memcpy(&info->addr, &addr, sizeof(addr));
                    706: 
                    707:        /*
                    708:         * Get our flags.
                    709:         */
                    710:        memset(&tmp, 0, sizeof(tmp));
                    711:        strcpy(tmp.ifr_name, name);
                    712:        if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
                    713:                log_error("Error getting interface flags for '%s'; %m", name);
                    714:                *err = 1;
                    715:                return 0;
                    716:        }
                    717:        info->flags = tmp.ifr_flags;
                    718: 
                    719:        *err = 0;
                    720:        return 1;
                    721: }
                    722: #endif /* DHCPv6 */
                    723: 
                    724: /*
                    725:  * Retrieve the next interface.
                    726:  *
                    727:  * Returns information in the info structure. 
                    728:  * Sets err to 1 if there is an error, otherwise 0.
                    729:  */
                    730: int
                    731: next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
                    732:        if (next_iface4(info, err, ifaces)) {
                    733:                return 1;
                    734:        }
                    735: #ifdef DHCPv6
                    736:        if (!(*err)) {
                    737:                if (local_family == AF_INET6)
                    738:                        return next_iface6(info, err, ifaces);
                    739:        }
                    740: #endif
                    741:        return 0;
                    742: }
                    743: 
                    744: /*
                    745:  * End scan of interfaces.
                    746:  */
                    747: void
                    748: end_iface_scan(struct iface_conf_list *ifaces) {
                    749:        fclose(ifaces->fp);
                    750:        ifaces->fp = NULL;
                    751:        close(ifaces->sock);
                    752:        ifaces->sock = -1;
                    753: #ifdef DHCPv6
                    754:        if (local_family == AF_INET6) {
                    755:                fclose(ifaces->fp6);
                    756:                ifaces->fp6 = NULL;
                    757:        }
                    758: #endif
                    759: }
                    760: #else
                    761: 
                    762: /* 
                    763:  * BSD support
                    764:  * -----------
                    765:  *
                    766:  * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs() 
                    767:  * function.
                    768:  *
                    769:  * The getifaddrs() man page describes the use.
                    770:  */
                    771: 
                    772: #include <ifaddrs.h>
                    773: 
                    774: /* 
                    775:  * Structure holding state about the scan.
                    776:  */
                    777: struct iface_conf_list {
                    778:        struct ifaddrs *head;   /* beginning of the list */
                    779:        struct ifaddrs *next;   /* current position in the list */
                    780: };
                    781: 
                    782: /* 
                    783:  * Structure used to return information about a specific interface.
                    784:  */
                    785: struct iface_info {
                    786:        char name[IFNAMSIZ];            /* name of the interface, e.g. "bge0" */
                    787:        struct sockaddr_storage addr;   /* address information */
                    788:        isc_uint64_t flags;             /* interface flags, e.g. IFF_LOOPBACK */
                    789: };
                    790: 
                    791: /* 
                    792:  * Start a scan of interfaces.
                    793:  *
                    794:  * The iface_conf_list structure maintains state for this process.
                    795:  */
                    796: int 
                    797: begin_iface_scan(struct iface_conf_list *ifaces) {
                    798:        if (getifaddrs(&ifaces->head) != 0) {
                    799:                log_error("Error getting interfaces; %m");
                    800:                return 0;
                    801:        }
                    802:        ifaces->next = ifaces->head;
                    803:        return 1;
                    804: }
                    805: 
                    806: /*
                    807:  * Retrieve the next interface.
                    808:  *
                    809:  * Returns information in the info structure. 
                    810:  * Sets err to 1 if there is an error, otherwise 0.
                    811:  */
                    812: int
                    813: next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
                    814:        if (ifaces->next == NULL) {
                    815:                *err = 0;
                    816:                return 0;
                    817:        }
                    818:        if (strlen(ifaces->next->ifa_name) >= sizeof(info->name)) {
                    819:                log_error("Interface name '%s' too long", 
                    820:                          ifaces->next->ifa_name);
                    821:                *err = 1;
                    822:                return 0;
                    823:        }
                    824:        strcpy(info->name, ifaces->next->ifa_name);
                    825:        memcpy(&info->addr, ifaces->next->ifa_addr, 
                    826:               ifaces->next->ifa_addr->sa_len);
                    827:        info->flags = ifaces->next->ifa_flags;
                    828:        ifaces->next = ifaces->next->ifa_next;
                    829:        *err = 0;
                    830:        return 1;
                    831: }
                    832: 
                    833: /*
                    834:  * End scan of interfaces.
                    835:  */
                    836: void
                    837: end_iface_scan(struct iface_conf_list *ifaces) {
                    838:        freeifaddrs(ifaces->head);
                    839:        ifaces->head = NULL;
                    840:        ifaces->next = NULL;
                    841: }
                    842: #endif 
                    843: 
                    844: /* XXX: perhaps create drealloc() rather than do it manually */
                    845: void
                    846: add_ipv4_addr_to_interface(struct interface_info *iface, 
                    847:                           const struct in_addr *addr) {
                    848:        /*
                    849:         * We don't expect a lot of addresses per IPv4 interface, so
                    850:         * we use 4, as our "chunk size" for collecting addresses.
                    851:         */
                    852:        if (iface->addresses == NULL) {
                    853:                iface->addresses = dmalloc(4 * sizeof(struct in_addr), MDL);
                    854:                if (iface->addresses == NULL) {
                    855:                        log_fatal("Out of memory saving IPv4 address "
                    856:                                  "on interface.");
                    857:                }
                    858:                iface->address_count = 0;
                    859:                iface->address_max = 4;
                    860:        } else if (iface->address_count >= iface->address_max) {
                    861:                struct in_addr *tmp;
                    862:                int new_max;
                    863: 
                    864:                new_max = iface->address_max + 4;
                    865:                tmp = dmalloc(new_max * sizeof(struct in_addr), MDL);
                    866:                if (tmp == NULL) {
                    867:                        log_fatal("Out of memory saving IPv4 address "
                    868:                                  "on interface.");
                    869:                }
                    870:                memcpy(tmp, 
                    871:                       iface->addresses, 
                    872:                       iface->address_max * sizeof(struct in_addr));
                    873:                dfree(iface->addresses, MDL);
                    874:                iface->addresses = tmp;
                    875:                iface->address_max = new_max;
                    876:        }
                    877:        iface->addresses[iface->address_count++] = *addr;
                    878: }
                    879: 
                    880: #ifdef DHCPv6
                    881: /* XXX: perhaps create drealloc() rather than do it manually */
                    882: void
                    883: add_ipv6_addr_to_interface(struct interface_info *iface, 
                    884:                           const struct in6_addr *addr) {
                    885:        /*
                    886:         * Each IPv6 interface will have at least two IPv6 addresses,
                    887:         * and likely quite a few more. So we use 8, as our "chunk size" for
                    888:         * collecting addresses.
                    889:         */
                    890:        if (iface->v6addresses == NULL) {
                    891:                iface->v6addresses = dmalloc(8 * sizeof(struct in6_addr), MDL);
                    892:                if (iface->v6addresses == NULL) {
                    893:                        log_fatal("Out of memory saving IPv6 address "
                    894:                                  "on interface.");
                    895:                }
                    896:                iface->v6address_count = 0;
                    897:                iface->v6address_max = 8;
                    898:        } else if (iface->v6address_count >= iface->v6address_max) {
                    899:                struct in6_addr *tmp;
                    900:                int new_max;
                    901: 
                    902:                new_max = iface->v6address_max + 8;
                    903:                tmp = dmalloc(new_max * sizeof(struct in6_addr), MDL);
                    904:                if (tmp == NULL) {
                    905:                        log_fatal("Out of memory saving IPv6 address "
                    906:                                  "on interface.");
                    907:                }
                    908:                memcpy(tmp, 
                    909:                       iface->v6addresses, 
                    910:                       iface->v6address_max * sizeof(struct in6_addr));
                    911:                dfree(iface->v6addresses, MDL);
                    912:                iface->v6addresses = tmp;
                    913:                iface->v6address_max = new_max;
                    914:        }
                    915:        iface->v6addresses[iface->v6address_count++] = *addr;
                    916: }
                    917: #endif /* DHCPv6 */
                    918: 
                    919: /* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
                    920:    For each interface that's of type INET and not the loopback interface,
                    921:    register that interface with the network I/O software, figure out what
                    922:    subnet it's on, and add it to the list of interfaces. */
                    923: 
                    924: void 
                    925: discover_interfaces(int state) {
                    926:        struct iface_conf_list ifaces;
                    927:        struct iface_info info;
                    928:        int err;
                    929: 
                    930:        struct interface_info *tmp;
                    931:        struct interface_info *last, *next;
                    932: 
                    933: #ifdef DHCPv6
                    934:         char abuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
                    935: #endif /* DHCPv6 */
                    936: 
                    937: 
                    938:        struct subnet *subnet;
                    939:        int ir;
                    940:        isc_result_t status;
                    941:        int wifcount = 0;
                    942: 
                    943:        static int setup_fallback = 0;
                    944: 
                    945:        if (!begin_iface_scan(&ifaces)) {
                    946:                log_fatal("Can't get list of interfaces.");
                    947:        }
                    948: 
                    949:        /* If we already have a list of interfaces, and we're running as
                    950:           a DHCP server, the interfaces were requested. */
                    951:        if (interfaces && (state == DISCOVER_SERVER ||
                    952:                           state == DISCOVER_RELAY ||
                    953:                           state == DISCOVER_REQUESTED))
                    954:                ir = 0;
                    955:        else if (state == DISCOVER_UNCONFIGURED)
                    956:                ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC;
                    957:        else
                    958:                ir = INTERFACE_REQUESTED;
                    959: 
                    960:        /* Cycle through the list of interfaces looking for IP addresses. */
                    961:        while (next_iface(&info, &err, &ifaces)) {
                    962: 
                    963:                /* See if we've seen an interface that matches this one. */
                    964:                for (tmp = interfaces; tmp; tmp = tmp->next) {
                    965:                        if (!strcmp(tmp->name, info.name))
                    966:                                break;
                    967:                }
                    968: 
                    969:                /* Skip non broadcast interfaces (plus loopback and
                    970:                   point-to-point in case an OS incorrectly marks them
                    971:                   as broadcast). Also skip down interfaces unless we're
                    972:                   trying to get a list of configurable interfaces. */
                    973:                if ((((local_family == AF_INET &&
                    974:                    !(info.flags & IFF_BROADCAST)) ||
                    975: #ifdef DHCPv6
                    976:                    (local_family == AF_INET6 &&
                    977:                    !(info.flags & IFF_MULTICAST)) ||
                    978: #endif
                    979:                      info.flags & IFF_LOOPBACK ||
                    980:                      info.flags & IFF_POINTOPOINT) && !tmp) ||
                    981:                    (!(info.flags & IFF_UP) &&
                    982:                     state != DISCOVER_UNCONFIGURED))
                    983:                        continue;
                    984:                
                    985:                /* If there isn't already an interface by this name,
                    986:                   allocate one. */
                    987:                if (tmp == NULL) {
                    988:                        status = interface_allocate(&tmp, MDL);
                    989:                        if (status != ISC_R_SUCCESS) {
                    990:                                log_fatal("Error allocating interface %s: %s",
                    991:                                          info.name, isc_result_totext(status));
                    992:                        }
                    993:                        strcpy(tmp->name, info.name);
                    994:                        interface_snorf(tmp, ir);
                    995:                        interface_dereference(&tmp, MDL);
                    996:                        tmp = interfaces; /* XXX */
                    997:                }
                    998: 
                    999:                if (dhcp_interface_discovery_hook) {
                   1000:                        (*dhcp_interface_discovery_hook)(tmp);
                   1001:                }
                   1002: 
                   1003:                if ((info.addr.ss_family == AF_INET) && 
                   1004:                    (local_family == AF_INET)) {
                   1005:                        struct sockaddr_in *a = (struct sockaddr_in*)&info.addr;
                   1006:                        struct iaddr addr;
                   1007: 
                   1008:                        /* We don't want the loopback interface. */
                   1009:                        if (a->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
                   1010:                            ((tmp->flags & INTERFACE_AUTOMATIC) &&
                   1011:                             state == DISCOVER_SERVER))
                   1012:                                continue;
                   1013: 
                   1014:                        /* If the only address we have is 0.0.0.0, we
                   1015:                           shouldn't consider the interface configured. */
                   1016:                        if (a->sin_addr.s_addr != htonl(INADDR_ANY))
                   1017:                                tmp->configured = 1;
                   1018: 
                   1019:                        add_ipv4_addr_to_interface(tmp, &a->sin_addr);
                   1020: 
                   1021:                        /* invoke the setup hook */
                   1022:                        addr.len = 4;
                   1023:                        memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len);
                   1024:                        if (dhcp_interface_setup_hook) {
                   1025:                                (*dhcp_interface_setup_hook)(tmp, &addr);
                   1026:                        }
                   1027:                }
                   1028: #ifdef DHCPv6
                   1029:                else if ((info.addr.ss_family == AF_INET6) && 
                   1030:                         (local_family == AF_INET6)) {
                   1031:                        struct sockaddr_in6 *a = 
                   1032:                                        (struct sockaddr_in6*)&info.addr;
                   1033:                        struct iaddr addr;
                   1034: 
                   1035:                        /* We don't want the loopback interface. */
                   1036:                        if (IN6_IS_ADDR_LOOPBACK(&a->sin6_addr) && 
                   1037:                            ((tmp->flags & INTERFACE_AUTOMATIC) &&
                   1038:                             state == DISCOVER_SERVER))
                   1039:                            continue;
                   1040: 
                   1041:                        /* If the only address we have is 0.0.0.0, we
                   1042:                           shouldn't consider the interface configured. */
                   1043:                        if (IN6_IS_ADDR_UNSPECIFIED(&a->sin6_addr))
                   1044:                                tmp->configured = 1;
                   1045: 
                   1046:                        add_ipv6_addr_to_interface(tmp, &a->sin6_addr);
                   1047: 
                   1048:                        /* invoke the setup hook */
                   1049:                        addr.len = 16;
                   1050:                        memcpy(addr.iabuf, &a->sin6_addr, addr.len);
                   1051:                        if (dhcp_interface_setup_hook) {
                   1052:                                (*dhcp_interface_setup_hook)(tmp, &addr);
                   1053:                        }
                   1054:                }
                   1055: #endif /* DHCPv6 */
                   1056:        }
                   1057: 
                   1058:        if (err) {
                   1059:                log_fatal("Error getting interface information.");
                   1060:        }
                   1061: 
                   1062:        end_iface_scan(&ifaces);
                   1063: 
                   1064: 
                   1065:        /* Mock-up an 'ifp' structure which is no longer used in the
                   1066:         * new interface-sensing code, but is used in higher layers
                   1067:         * (for example to sense fallback interfaces).
                   1068:         */
                   1069:        for (tmp = interfaces ; tmp != NULL ; tmp = tmp->next) {
                   1070:                if (tmp->ifp == NULL) {
                   1071:                        struct ifreq *tif;
                   1072: 
                   1073:                        tif = (struct ifreq *)dmalloc(sizeof(struct ifreq),
                   1074:                                                      MDL);
                   1075:                        if (tif == NULL)
                   1076:                                log_fatal("no space for ifp mockup.");
                   1077:                        strcpy(tif->ifr_name, tmp->name);
                   1078:                        tmp->ifp = tif;
                   1079:                }
                   1080:        }
                   1081: 
                   1082: 
                   1083:        /* If we're just trying to get a list of interfaces that we might
                   1084:           be able to configure, we can quit now. */
                   1085:        if (state == DISCOVER_UNCONFIGURED) {
                   1086:                return;
                   1087:        }
                   1088: 
                   1089:        /* Weed out the interfaces that did not have IP addresses. */
                   1090:        tmp = last = next = NULL;
                   1091:        if (interfaces)
                   1092:                interface_reference (&tmp, interfaces, MDL);
                   1093:        while (tmp) {
                   1094:                if (next)
                   1095:                        interface_dereference (&next, MDL);
                   1096:                if (tmp -> next)
                   1097:                        interface_reference (&next, tmp -> next, MDL);
                   1098:                /* skip interfaces that are running already */
                   1099:                if (tmp -> flags & INTERFACE_RUNNING) {
                   1100:                        interface_dereference(&tmp, MDL);
                   1101:                        if(next)
                   1102:                                interface_reference(&tmp, next, MDL);
                   1103:                        continue;
                   1104:                }
                   1105:                if ((tmp -> flags & INTERFACE_AUTOMATIC) &&
                   1106:                    state == DISCOVER_REQUESTED)
                   1107:                        tmp -> flags &= ~(INTERFACE_AUTOMATIC |
                   1108:                                          INTERFACE_REQUESTED);
                   1109: 
                   1110: #ifdef DHCPv6
                   1111:                if (!(tmp->flags & INTERFACE_REQUESTED)) {
                   1112: #else
                   1113:                if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
                   1114: #endif /* DHCPv6 */
                   1115:                        if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
                   1116:                                log_fatal ("%s: not found", tmp -> name);
                   1117:                        if (!last) {
                   1118:                                if (interfaces)
                   1119:                                        interface_dereference (&interfaces,
                   1120:                                                               MDL);
                   1121:                                if (next)
                   1122:                                interface_reference (&interfaces, next, MDL);
                   1123:                        } else {
                   1124:                                interface_dereference (&last -> next, MDL);
                   1125:                                if (next)
                   1126:                                        interface_reference (&last -> next,
                   1127:                                                             next, MDL);
                   1128:                        }
                   1129:                        if (tmp -> next)
                   1130:                                interface_dereference (&tmp -> next, MDL);
                   1131: 
                   1132:                        /* Remember the interface in case we need to know
                   1133:                           about it later. */
                   1134:                        if (dummy_interfaces) {
                   1135:                                interface_reference (&tmp -> next,
                   1136:                                                     dummy_interfaces, MDL);
                   1137:                                interface_dereference (&dummy_interfaces, MDL);
                   1138:                        }
                   1139:                        interface_reference (&dummy_interfaces, tmp, MDL);
                   1140:                        interface_dereference (&tmp, MDL);
                   1141:                        if (next)
                   1142:                                interface_reference (&tmp, next, MDL);
                   1143:                        continue;
                   1144:                }
                   1145:                last = tmp;
                   1146: 
                   1147:                /* We must have a subnet declaration for each interface. */
                   1148:                if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
                   1149:                        log_error("%s", "");
                   1150:                        if (local_family == AF_INET) {
                   1151:                                log_error("No subnet declaration for %s (%s).",
                   1152:                                          tmp->name, 
                   1153:                                          (tmp->addresses == NULL) ?
                   1154:                                           "no IPv4 addresses" :
                   1155:                                           inet_ntoa(tmp->addresses[0]));
                   1156: #ifdef DHCPv6
                   1157:                        } else {
                   1158:                                if (tmp->v6addresses != NULL) {
                   1159:                                        inet_ntop(AF_INET6, 
                   1160:                                                  &tmp->v6addresses[0],
                   1161:                                                  abuf,
                   1162:                                                  sizeof(abuf));
                   1163:                                } else {
                   1164:                                        strcpy(abuf, "no IPv6 addresses");
                   1165:                                }
                   1166:                                log_error("No subnet6 declaration for %s (%s).",
                   1167:                                          tmp->name,
                   1168:                                          abuf);
                   1169: #endif /* DHCPv6 */
                   1170:                        }
                   1171:                        if (supports_multiple_interfaces(tmp)) {
                   1172:                                log_error ("** Ignoring requests on %s.  %s",
                   1173:                                           tmp -> name, "If this is not what");
                   1174:                                log_error ("   you want, please write %s",
                   1175: #ifdef DHCPv6
                   1176:                                           (local_family != AF_INET) ?
                   1177:                                           "a subnet6 declaration" :
                   1178: #endif
                   1179:                                           "a subnet declaration");
                   1180:                                log_error ("   in your dhcpd.conf file %s",
                   1181:                                           "for the network segment");
                   1182:                                log_error ("   to %s %s %s",
                   1183:                                           "which interface",
                   1184:                                           tmp -> name, "is attached. **");
                   1185:                                log_error ("%s", "");
                   1186:                                goto next;
                   1187:                        } else {
                   1188:                                log_error ("You must write a %s",
                   1189: #ifdef DHCPv6
                   1190:                                           (local_family != AF_INET) ?
                   1191:                                           "subnet6 declaration for this" :
                   1192: #endif
                   1193:                                           "subnet declaration for this");
                   1194:                                log_error ("subnet.   You cannot prevent %s",
                   1195:                                           "the DHCP server");
                   1196:                                log_error ("from listening on this subnet %s",
                   1197:                                           "because your");
                   1198:                                log_fatal ("operating system does not %s.",
                   1199:                                           "support this capability");
                   1200:                        }
                   1201:                }
                   1202: 
                   1203:                /* Find subnets that don't have valid interface
                   1204:                   addresses... */
                   1205:                for (subnet = (tmp -> shared_network
                   1206:                               ? tmp -> shared_network -> subnets
                   1207:                               : (struct subnet *)0);
                   1208:                     subnet; subnet = subnet -> next_sibling) {
                   1209:                        /* Set the interface address for this subnet
                   1210:                           to the first address we found. */
                   1211:                        if (subnet->interface_address.len == 0) {
                   1212:                                if (tmp->address_count > 0) {
                   1213:                                        subnet->interface_address.len = 4;
                   1214:                                        memcpy(subnet->interface_address.iabuf,
                   1215:                                               &tmp->addresses[0].s_addr, 4);
                   1216:                                } else if (tmp->v6address_count > 0) {
                   1217:                                        subnet->interface_address.len = 16;
                   1218:                                        memcpy(subnet->interface_address.iabuf,
                   1219:                                               &tmp->v6addresses[0].s6_addr, 
                   1220:                                               16);
                   1221:                                } else {
                   1222:                                        /* XXX: should be one */
                   1223:                                        log_error("%s missing an interface "
                   1224:                                                  "address", tmp->name);
                   1225:                                        continue;
                   1226:                                }
                   1227:                        }
                   1228:                }
                   1229: 
                   1230:                /* Flag the index as not having been set, so that the
                   1231:                   interface registerer can set it or not as it chooses. */
                   1232:                tmp -> index = -1;
                   1233: 
                   1234:                /* Register the interface... */
                   1235:                if (local_family == AF_INET) {
                   1236:                        if_register_receive(tmp);
                   1237:                        if_register_send(tmp);
                   1238: #ifdef DHCPv6
                   1239:                } else {
                   1240:                        if ((state == DISCOVER_SERVER) ||
                   1241:                            (state == DISCOVER_RELAY)) {
                   1242:                                if_register6(tmp, 1);
                   1243:                        } else {
                   1244:                                if_register6(tmp, 0);
                   1245:                        }
                   1246: #endif /* DHCPv6 */
                   1247:                }
                   1248: 
                   1249:                interface_stash (tmp);
                   1250:                wifcount++;
                   1251: #if defined (F_SETFD)
                   1252:                if (fcntl (tmp -> rfdesc, F_SETFD, 1) < 0)
                   1253:                        log_error ("Can't set close-on-exec on %s: %m",
                   1254:                                   tmp -> name);
                   1255:                if (tmp -> rfdesc != tmp -> wfdesc) {
                   1256:                        if (fcntl (tmp -> wfdesc, F_SETFD, 1) < 0)
                   1257:                                log_error ("Can't set close-on-exec on %s: %m",
                   1258:                                           tmp -> name);
                   1259:                }
                   1260: #endif
                   1261:              next:
                   1262:                interface_dereference (&tmp, MDL);
                   1263:                if (next)
                   1264:                        interface_reference (&tmp, next, MDL);
                   1265:        }
                   1266: 
                   1267:        /* Now register all the remaining interfaces as protocols. */
                   1268:        for (tmp = interfaces; tmp; tmp = tmp -> next) {
                   1269:                /* not if it's been registered before */
                   1270:                if (tmp -> flags & INTERFACE_RUNNING)
                   1271:                        continue;
                   1272:                if (tmp -> rfdesc == -1)
                   1273:                        continue;
                   1274: #ifdef DHCPv6 
                   1275:                if (local_family == AF_INET6) {
                   1276:                        status = omapi_register_io_object((omapi_object_t *)tmp,
                   1277:                                                          if_readsocket, 
                   1278:                                                          0, got_one_v6, 0, 0);
                   1279:                } else {
                   1280: #else
                   1281:                {
                   1282: #endif /* DHCPv6 */
                   1283:                        status = omapi_register_io_object((omapi_object_t *)tmp,
                   1284:                                                          if_readsocket, 
                   1285:                                                          0, got_one, 0, 0);
                   1286:                }
                   1287:                if (status != ISC_R_SUCCESS)
                   1288:                        log_fatal ("Can't register I/O handle for %s: %s",
                   1289:                                   tmp -> name, isc_result_totext (status));
                   1290: 
                   1291: #if defined(DHCPv6)
                   1292:                /* Only register the first interface for V6, since they all
                   1293:                 * use the same socket.  XXX: This has some messy side
                   1294:                 * effects if we start dynamically adding and removing
                   1295:                 * interfaces, but we're well beyond that point in terms of
                   1296:                 * mess.
                   1297:                 */
                   1298:                if (local_family == AF_INET6)
                   1299:                        break;
                   1300: #endif
                   1301:        }
                   1302: 
                   1303:        if (state == DISCOVER_SERVER && wifcount == 0) {
                   1304:                log_info ("%s", "");
                   1305:                log_fatal ("Not configured to listen on any interfaces!");
                   1306:        }
                   1307: 
                   1308:        if ((local_family == AF_INET) && !setup_fallback) {
                   1309:                setup_fallback = 1;
                   1310:                maybe_setup_fallback();
                   1311:        }
                   1312: 
                   1313: #if defined (F_SETFD)
                   1314:        if (fallback_interface) {
                   1315:            if (fcntl (fallback_interface -> rfdesc, F_SETFD, 1) < 0)
                   1316:                log_error ("Can't set close-on-exec on fallback: %m");
                   1317:            if (fallback_interface -> rfdesc != fallback_interface -> wfdesc) {
                   1318:                if (fcntl (fallback_interface -> wfdesc, F_SETFD, 1) < 0)
                   1319:                    log_error ("Can't set close-on-exec on fallback: %m");
                   1320:            }
                   1321:        }
                   1322: #endif /* F_SETFD */
                   1323: }
                   1324: 
                   1325: int if_readsocket (h)
                   1326:        omapi_object_t *h;
                   1327: {
                   1328:        struct interface_info *ip;
                   1329: 
                   1330:        if (h -> type != dhcp_type_interface)
                   1331:                return -1;
                   1332:        ip = (struct interface_info *)h;
                   1333:        return ip -> rfdesc;
                   1334: }
                   1335: 
                   1336: int setup_fallback (struct interface_info **fp, const char *file, int line)
                   1337: {
                   1338:        isc_result_t status;
                   1339: 
                   1340:        status = interface_allocate (&fallback_interface, file, line);
                   1341:        if (status != ISC_R_SUCCESS)
                   1342:                log_fatal ("Error allocating fallback interface: %s",
                   1343:                           isc_result_totext (status));
                   1344:        strcpy (fallback_interface -> name, "fallback");
                   1345:        if (dhcp_interface_setup_hook)
                   1346:                (*dhcp_interface_setup_hook) (fallback_interface,
                   1347:                                              (struct iaddr *)0);
                   1348:        status = interface_reference (fp, fallback_interface, file, line);
                   1349: 
                   1350:        fallback_interface -> index = -1;
                   1351:        interface_stash (fallback_interface);
                   1352:        return status == ISC_R_SUCCESS;
                   1353: }
                   1354: 
                   1355: void reinitialize_interfaces ()
                   1356: {
                   1357:        struct interface_info *ip;
                   1358: 
                   1359:        for (ip = interfaces; ip; ip = ip -> next) {
                   1360:                if_reinitialize_receive (ip);
                   1361:                if_reinitialize_send (ip);
                   1362:        }
                   1363: 
                   1364:        if (fallback_interface)
                   1365:                if_reinitialize_send (fallback_interface);
                   1366: 
                   1367:        interfaces_invalidated = 1;
                   1368: }
                   1369: 
                   1370: isc_result_t got_one (h)
                   1371:        omapi_object_t *h;
                   1372: {
                   1373:        struct sockaddr_in from;
                   1374:        struct hardware hfrom;
                   1375:        struct iaddr ifrom;
                   1376:        int result;
                   1377:        union {
                   1378:                unsigned char packbuf [4095]; /* Packet input buffer.
                   1379:                                                 Must be as large as largest
                   1380:                                                 possible MTU. */
                   1381:                struct dhcp_packet packet;
                   1382:        } u;
                   1383:        struct interface_info *ip;
                   1384: 
                   1385:        if (h -> type != dhcp_type_interface)
                   1386:                return ISC_R_INVALIDARG;
                   1387:        ip = (struct interface_info *)h;
                   1388: 
                   1389:       again:
                   1390:        if ((result =
                   1391:             receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) {
                   1392:                log_error ("receive_packet failed on %s: %m", ip -> name);
                   1393:                return ISC_R_UNEXPECTED;
                   1394:        }
                   1395:        if (result == 0)
                   1396:                return ISC_R_UNEXPECTED;
                   1397: 
                   1398:        /*
                   1399:         * If we didn't at least get the fixed portion of the BOOTP
                   1400:         * packet, drop the packet.
                   1401:         * Previously we allowed packets with no sname or filename
                   1402:         * as we were aware of at least one client that did.  But
                   1403:         * a bug caused short packets to not work and nobody has
                   1404:         * complained, it seems rational to tighten up that
                   1405:         * restriction.
                   1406:         */
                   1407:        if (result < DHCP_FIXED_NON_UDP)
                   1408:                return ISC_R_UNEXPECTED;
                   1409: 
                   1410: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
                   1411:        {
                   1412:                /* We retrieve the ifindex from the unused hfrom variable */
                   1413:                unsigned int ifindex;
                   1414: 
                   1415:                memcpy(&ifindex, hfrom.hbuf, sizeof (ifindex));
                   1416: 
                   1417:                /*
                   1418:                 * Seek forward from the first interface to find the matching
                   1419:                 * source interface by interface index.
                   1420:                 */
                   1421:                ip = interfaces;
                   1422:                while ((ip != NULL) && (if_nametoindex(ip->name) != ifindex))
                   1423:                        ip = ip->next;
                   1424:                if (ip == NULL)
                   1425:                        return ISC_R_NOTFOUND;
                   1426:        }
                   1427: #endif
                   1428: 
                   1429:        if (bootp_packet_handler) {
                   1430:                ifrom.len = 4;
                   1431:                memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
                   1432: 
                   1433:                (*bootp_packet_handler) (ip, &u.packet, (unsigned)result,
                   1434:                                         from.sin_port, ifrom, &hfrom);
                   1435:        }
                   1436: 
                   1437:        /* If there is buffered data, read again.    This is for, e.g.,
                   1438:           bpf, which may return two packets at once. */
                   1439:        if (ip -> rbuf_offset != ip -> rbuf_len)
                   1440:                goto again;
                   1441:        return ISC_R_SUCCESS;
                   1442: }
                   1443: 
                   1444: #ifdef DHCPv6
                   1445: isc_result_t
                   1446: got_one_v6(omapi_object_t *h) {
                   1447:        struct sockaddr_in6 from;
                   1448:        struct in6_addr to;
                   1449:        struct iaddr ifrom;
                   1450:        int result;
                   1451:        char buf[65536];        /* maximum size for a UDP packet is 65536 */
                   1452:        struct interface_info *ip;
                   1453:        int is_unicast;
                   1454:        unsigned int if_idx = 0;
                   1455: 
                   1456:        if (h->type != dhcp_type_interface) {
                   1457:                return ISC_R_INVALIDARG;
                   1458:        }
                   1459:        ip = (struct interface_info *)h;
                   1460: 
                   1461:        result = receive_packet6(ip, (unsigned char *)buf, sizeof(buf),
                   1462:                                 &from, &to, &if_idx);
                   1463:        if (result < 0) {
                   1464:                log_error("receive_packet6() failed on %s: %m", ip->name);
                   1465:                return ISC_R_UNEXPECTED;
                   1466:        }
                   1467: 
                   1468:        /* 0 is 'any' interface. */
                   1469:        if (if_idx == 0)
                   1470:                return ISC_R_NOTFOUND;
                   1471: 
                   1472:        if (dhcpv6_packet_handler != NULL) {
                   1473:                /*
                   1474:                 * If a packet is not multicast, we assume it is unicast.
                   1475:                 */
                   1476:                if (IN6_IS_ADDR_MULTICAST(&to)) { 
                   1477:                        is_unicast = ISC_FALSE;
                   1478:                } else {
                   1479:                        is_unicast = ISC_TRUE;
                   1480:                }
                   1481: 
                   1482:                ifrom.len = 16;
                   1483:                memcpy(ifrom.iabuf, &from.sin6_addr, ifrom.len);
                   1484: 
                   1485:                /* Seek forward to find the matching source interface. */
                   1486:                ip = interfaces;
                   1487:                while ((ip != NULL) && (if_nametoindex(ip->name) != if_idx))
                   1488:                        ip = ip->next;
                   1489: 
                   1490:                if (ip == NULL)
                   1491:                        return ISC_R_NOTFOUND;
                   1492: 
                   1493:                (*dhcpv6_packet_handler)(ip, buf, 
                   1494:                                         result, from.sin6_port, 
                   1495:                                         &ifrom, is_unicast);
                   1496:        }
                   1497: 
                   1498:        return ISC_R_SUCCESS;
                   1499: }
                   1500: #endif /* DHCPv6 */
                   1501: 
                   1502: isc_result_t dhcp_interface_set_value  (omapi_object_t *h,
                   1503:                                        omapi_object_t *id,
                   1504:                                        omapi_data_string_t *name,
                   1505:                                        omapi_typed_data_t *value)
                   1506: {
                   1507:        struct interface_info *interface;
                   1508:        isc_result_t status;
                   1509: 
                   1510:        if (h -> type != dhcp_type_interface)
                   1511:                return ISC_R_INVALIDARG;
                   1512:        interface = (struct interface_info *)h;
                   1513: 
                   1514:        if (!omapi_ds_strcmp (name, "name")) {
                   1515:                if ((value -> type == omapi_datatype_data ||
                   1516:                     value -> type == omapi_datatype_string) &&
                   1517:                    value -> u.buffer.len < sizeof interface -> name) {
                   1518:                        memcpy (interface -> name,
                   1519:                                value -> u.buffer.value,
                   1520:                                value -> u.buffer.len);
                   1521:                        interface -> name [value -> u.buffer.len] = 0;
                   1522:                } else
                   1523:                        return ISC_R_INVALIDARG;
                   1524:                return ISC_R_SUCCESS;
                   1525:        }
                   1526: 
                   1527:        /* Try to find some inner object that can take the value. */
                   1528:        if (h -> inner && h -> inner -> type -> set_value) {
                   1529:                status = ((*(h -> inner -> type -> set_value))
                   1530:                          (h -> inner, id, name, value));
                   1531:                if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
                   1532:                        return status;
                   1533:        }
                   1534:                          
                   1535:        return ISC_R_NOTFOUND;
                   1536: }
                   1537: 
                   1538: 
                   1539: isc_result_t dhcp_interface_get_value (omapi_object_t *h,
                   1540:                                       omapi_object_t *id,
                   1541:                                       omapi_data_string_t *name,
                   1542:                                       omapi_value_t **value)
                   1543: {
                   1544:        return ISC_R_NOTIMPLEMENTED;
                   1545: }
                   1546: 
                   1547: isc_result_t dhcp_interface_destroy (omapi_object_t *h,
                   1548:                                         const char *file, int line)
                   1549: {
                   1550:        struct interface_info *interface;
                   1551: 
                   1552:        if (h -> type != dhcp_type_interface)
                   1553:                return ISC_R_INVALIDARG;
                   1554:        interface = (struct interface_info *)h;
                   1555: 
                   1556:        if (interface -> ifp) {
                   1557:                dfree (interface -> ifp, file, line);
                   1558:                interface -> ifp = 0;
                   1559:        }
                   1560:        if (interface -> next)
                   1561:                interface_dereference (&interface -> next, file, line);
                   1562:        if (interface -> rbuf) {
                   1563:                dfree (interface -> rbuf, file, line);
                   1564:                interface -> rbuf = (unsigned char *)0;
                   1565:        }
                   1566:        if (interface -> client)
                   1567:                interface -> client = (struct client_state *)0;
                   1568: 
                   1569:        if (interface -> shared_network)
                   1570:                omapi_object_dereference ((omapi_object_t **)
                   1571:                                          &interface -> shared_network, MDL);
                   1572: 
                   1573:        return ISC_R_SUCCESS;
                   1574: }
                   1575: 
                   1576: isc_result_t dhcp_interface_signal_handler (omapi_object_t *h,
                   1577:                                            const char *name, va_list ap)
                   1578: {
                   1579:        struct interface_info *ip, *interface;
                   1580:        isc_result_t status;
                   1581: 
                   1582:        if (h -> type != dhcp_type_interface)
                   1583:                return ISC_R_INVALIDARG;
                   1584:        interface = (struct interface_info *)h;
                   1585: 
                   1586:        /* If it's an update signal, see if the interface is dead right
                   1587:           now, or isn't known at all, and if that's the case, revive it. */
                   1588:        if (!strcmp (name, "update")) {
                   1589:                for (ip = dummy_interfaces; ip; ip = ip -> next)
                   1590:                        if (ip == interface)
                   1591:                                break;
                   1592:                if (ip && dhcp_interface_startup_hook)
                   1593:                        return (*dhcp_interface_startup_hook) (ip);
                   1594: 
                   1595:                for (ip = interfaces; ip; ip = ip -> next)
                   1596:                        if (ip == interface)
                   1597:                                break;
                   1598:                if (!ip && dhcp_interface_startup_hook)
                   1599:                        return (*dhcp_interface_startup_hook) (ip);
                   1600:        }
                   1601: 
                   1602:        /* Try to find some inner object that can take the value. */
                   1603:        if (h -> inner && h -> inner -> type -> signal_handler) {
                   1604:                status = ((*(h -> inner -> type -> signal_handler))
                   1605:                          (h -> inner, name, ap));
                   1606:                if (status == ISC_R_SUCCESS)
                   1607:                        return status;
                   1608:        }
                   1609:        return ISC_R_NOTFOUND;
                   1610: }
                   1611: 
                   1612: isc_result_t dhcp_interface_stuff_values (omapi_object_t *c,
                   1613:                                          omapi_object_t *id,
                   1614:                                          omapi_object_t *h)
                   1615: {
                   1616:        struct interface_info *interface;
                   1617:        isc_result_t status;
                   1618: 
                   1619:        if (h -> type != dhcp_type_interface)
                   1620:                return ISC_R_INVALIDARG;
                   1621:        interface = (struct interface_info *)h;
                   1622: 
                   1623:        /* Write out all the values. */
                   1624: 
                   1625:        status = omapi_connection_put_name (c, "state");
                   1626:        if (status != ISC_R_SUCCESS)
                   1627:                return status;
                   1628:        if ((interface->flags & INTERFACE_REQUESTED) != 0)
                   1629:            status = omapi_connection_put_string (c, "up");
                   1630:        else
                   1631:            status = omapi_connection_put_string (c, "down");
                   1632:        if (status != ISC_R_SUCCESS)
                   1633:                return status;
                   1634: 
                   1635:        /* Write out the inner object, if any. */
                   1636:        if (h -> inner && h -> inner -> type -> stuff_values) {
                   1637:                status = ((*(h -> inner -> type -> stuff_values))
                   1638:                          (c, id, h -> inner));
                   1639:                if (status == ISC_R_SUCCESS)
                   1640:                        return status;
                   1641:        }
                   1642: 
                   1643:        return ISC_R_SUCCESS;
                   1644: }
                   1645: 
                   1646: isc_result_t dhcp_interface_lookup (omapi_object_t **ip,
                   1647:                                    omapi_object_t *id,
                   1648:                                    omapi_object_t *ref)
                   1649: {
                   1650:        omapi_value_t *tv = (omapi_value_t *)0;
                   1651:        isc_result_t status;
                   1652:        struct interface_info *interface;
                   1653: 
                   1654:        if (!ref)
                   1655:                return ISC_R_NOKEYS;
                   1656: 
                   1657:        /* First see if we were sent a handle. */
                   1658:        status = omapi_get_value_str (ref, id, "handle", &tv);
                   1659:        if (status == ISC_R_SUCCESS) {
                   1660:                status = omapi_handle_td_lookup (ip, tv -> value);
                   1661: 
                   1662:                omapi_value_dereference (&tv, MDL);
                   1663:                if (status != ISC_R_SUCCESS)
                   1664:                        return status;
                   1665: 
                   1666:                /* Don't return the object if the type is wrong. */
                   1667:                if ((*ip) -> type != dhcp_type_interface) {
                   1668:                        omapi_object_dereference (ip, MDL);
                   1669:                        return ISC_R_INVALIDARG;
                   1670:                }
                   1671:        }
                   1672: 
                   1673:        /* Now look for an interface name. */
                   1674:        status = omapi_get_value_str (ref, id, "name", &tv);
                   1675:        if (status == ISC_R_SUCCESS) {
                   1676:                char *s;
                   1677:                unsigned len;
                   1678:                for (interface = interfaces; interface;
                   1679:                     interface = interface -> next) {
                   1680:                    s = memchr (interface -> name, 0, IFNAMSIZ);
                   1681:                    if (s)
                   1682:                            len = s - &interface -> name [0];
                   1683:                    else
                   1684:                            len = IFNAMSIZ;
                   1685:                    if ((tv -> value -> u.buffer.len == len &&
                   1686:                         !memcmp (interface -> name,
                   1687:                                  (char *)tv -> value -> u.buffer.value,
                   1688:                                  len)))
                   1689:                            break;
                   1690:                }
                   1691:                if (!interface) {
                   1692:                    for (interface = dummy_interfaces;
                   1693:                         interface; interface = interface -> next) {
                   1694:                            s = memchr (interface -> name, 0, IFNAMSIZ);
                   1695:                            if (s)
                   1696:                                    len = s - &interface -> name [0];
                   1697:                            else
                   1698:                                    len = IFNAMSIZ;
                   1699:                            if ((tv -> value -> u.buffer.len == len &&
                   1700:                                 !memcmp (interface -> name,
                   1701:                                          (char *)
                   1702:                                          tv -> value -> u.buffer.value,
                   1703:                                          len)))
                   1704:                                    break;
                   1705:                    }
                   1706:                }
                   1707: 
                   1708:                omapi_value_dereference (&tv, MDL);
                   1709:                if (*ip && *ip != (omapi_object_t *)interface) {
                   1710:                        omapi_object_dereference (ip, MDL);
                   1711:                        return ISC_R_KEYCONFLICT;
                   1712:                } else if (!interface) {
                   1713:                        if (*ip)
                   1714:                                omapi_object_dereference (ip, MDL);
                   1715:                        return ISC_R_NOTFOUND;
                   1716:                } else if (!*ip)
                   1717:                        omapi_object_reference (ip,
                   1718:                                                (omapi_object_t *)interface,
                   1719:                                                MDL);
                   1720:        }
                   1721: 
                   1722:        /* If we get to here without finding an interface, no valid key was
                   1723:           specified. */
                   1724:        if (!*ip)
                   1725:                return ISC_R_NOKEYS;
                   1726:        return ISC_R_SUCCESS;
                   1727: }
                   1728: 
                   1729: /* actually just go discover the interface */
                   1730: isc_result_t dhcp_interface_create (omapi_object_t **lp,
                   1731:                                    omapi_object_t *id)
                   1732: {
                   1733:        struct interface_info *hp;
                   1734:        isc_result_t status;
                   1735:        
                   1736:        hp = (struct interface_info *)0;
                   1737:        status = interface_allocate (&hp, MDL);
                   1738:        if (status != ISC_R_SUCCESS)
                   1739:                return status;
                   1740:        hp -> flags = INTERFACE_REQUESTED;
                   1741:        status = interface_reference ((struct interface_info **)lp, hp, MDL);
                   1742:        interface_dereference (&hp, MDL);
                   1743:        return status;
                   1744: }
                   1745: 
                   1746: isc_result_t dhcp_interface_remove (omapi_object_t *lp,
                   1747:                                    omapi_object_t *id)
                   1748: {
                   1749:        struct interface_info *interface, *ip, *last;
                   1750: 
                   1751:        interface = (struct interface_info *)lp;
                   1752: 
                   1753:        /* remove from interfaces */
                   1754:        last = 0;
                   1755:        for (ip = interfaces; ip; ip = ip -> next) {
                   1756:                if (ip == interface) {
                   1757:                        if (last) {
                   1758:                                interface_dereference (&last -> next, MDL);
                   1759:                                if (ip -> next)
                   1760:                                        interface_reference (&last -> next,
                   1761:                                                             ip -> next, MDL);
                   1762:                        } else {
                   1763:                                interface_dereference (&interfaces, MDL);
                   1764:                                if (ip -> next)
                   1765:                                        interface_reference (&interfaces,
                   1766:                                                             ip -> next, MDL);
                   1767:                        }
                   1768:                        if (ip -> next)
                   1769:                                interface_dereference (&ip -> next, MDL);
                   1770:                        break;
                   1771:                }
                   1772:                last = ip;
                   1773:        }
                   1774:        if (!ip)
                   1775:                return ISC_R_NOTFOUND;
                   1776: 
                   1777:        /* add the interface to the dummy_interface list */
                   1778:        if (dummy_interfaces) {
                   1779:                interface_reference (&interface -> next,
                   1780:                                     dummy_interfaces, MDL);
                   1781:                interface_dereference (&dummy_interfaces, MDL);
                   1782:        }
                   1783:        interface_reference (&dummy_interfaces, interface, MDL);
                   1784: 
                   1785:        /* do a DHCPRELEASE */
                   1786:        if (dhcp_interface_shutdown_hook)
                   1787:                (*dhcp_interface_shutdown_hook) (interface);
                   1788: 
                   1789:        /* remove the io object */
                   1790:        omapi_unregister_io_object ((omapi_object_t *)interface);
                   1791: 
                   1792:        if (local_family == AF_INET) {
                   1793:                if_deregister_send(interface);
                   1794:                if_deregister_receive(interface);
                   1795: #ifdef DHCPv6
                   1796:        } else {
                   1797:                if_deregister6(interface);
                   1798: #endif /* DHCPv6 */
                   1799:        }
                   1800: 
                   1801:        return ISC_R_SUCCESS;
                   1802: }
                   1803: 
                   1804: void interface_stash (struct interface_info *tptr)
                   1805: {
                   1806:        struct interface_info **vec;
                   1807:        int delta;
                   1808: 
                   1809:        /* If the registerer didn't assign an index, assign one now. */
                   1810:        if (tptr -> index == -1) {
                   1811:                tptr -> index = interface_count++;
                   1812:                while (tptr -> index < interface_max &&
                   1813:                       interface_vector [tptr -> index])
                   1814:                        tptr -> index = interface_count++;
                   1815:        }
                   1816: 
                   1817:        if (interface_max <= tptr -> index) {
                   1818:                delta = tptr -> index - interface_max + 10;
                   1819:                vec = dmalloc ((interface_max + delta) *
                   1820:                               sizeof (struct interface_info *), MDL);
                   1821:                if (!vec)
                   1822:                        return;
                   1823:                memset (&vec [interface_max], 0,
                   1824:                        (sizeof (struct interface_info *)) * delta);
                   1825:                interface_max += delta;
                   1826:                if (interface_vector) {
                   1827:                    memcpy (vec, interface_vector,
                   1828:                            (interface_count *
                   1829:                             sizeof (struct interface_info *)));
                   1830:                    dfree (interface_vector, MDL);
                   1831:                }
                   1832:                interface_vector = vec;
                   1833:        }
                   1834:        interface_reference (&interface_vector [tptr -> index], tptr, MDL);
                   1835:        if (tptr -> index >= interface_count)
                   1836:                interface_count = tptr -> index + 1;
                   1837: #if defined (TRACING)
                   1838:        trace_interface_register (interface_trace, tptr);
                   1839: #endif
                   1840: }
                   1841: 
                   1842: void interface_snorf (struct interface_info *tmp, int ir)
                   1843: {
                   1844:        tmp -> circuit_id = (u_int8_t *)tmp -> name;
                   1845:        tmp -> circuit_id_len = strlen (tmp -> name);
                   1846:        tmp -> remote_id = 0;
                   1847:        tmp -> remote_id_len = 0;
                   1848:        tmp -> flags = ir;
                   1849:        if (interfaces) {
                   1850:                interface_reference (&tmp -> next,
                   1851:                                     interfaces, MDL);
                   1852:                interface_dereference (&interfaces, MDL);
                   1853:        }
                   1854:        interface_reference (&interfaces, tmp, MDL);
                   1855: }

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