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

1.1       misho       1: /* socket.c
                      2: 
                      3:    BSD socket interface code... */
                      4: 
                      5: /*
1.1.1.1 ! misho       6:  * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
1.1       misho       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: /* SO_BINDTODEVICE support added by Elliot Poger (poger@leland.stanford.edu).
                     36:  * This sockopt allows a socket to be bound to a particular interface,
                     37:  * thus enabling the use of DHCPD on a multihomed host.
                     38:  * If SO_BINDTODEVICE is defined in your system header files, the use of
                     39:  * this sockopt will be automatically enabled. 
                     40:  * I have implemented it under Linux; other systems should be doable also.
                     41:  */
                     42: 
                     43: #include "dhcpd.h"
                     44: #include <errno.h>
                     45: #include <sys/ioctl.h>
                     46: #include <sys/uio.h>
                     47: #include <sys/uio.h>
                     48: #include <signal.h>
                     49: 
                     50: #if defined(sun) && defined(USE_V4_PKTINFO)
                     51: #include <sys/sysmacros.h>
                     52: #include <net/if.h>
                     53: #include <sys/sockio.h>
                     54: #include <net/if_dl.h>
1.1.1.1 ! misho      55: #include <sys/dlpi.h>
1.1       misho      56: #endif
                     57: 
                     58: #ifdef USE_SOCKET_FALLBACK
                     59: # if !defined (USE_SOCKET_SEND)
                     60: #  define if_register_send if_register_fallback
                     61: #  define send_packet send_fallback
                     62: #  define if_reinitialize_send if_reinitialize_fallback
                     63: # endif
                     64: #endif
                     65: 
                     66: #if defined(DHCPv6)
                     67: /*
                     68:  * XXX: this is gross.  we need to go back and overhaul the API for socket
                     69:  * handling.
                     70:  */
                     71: static unsigned int global_v6_socket_references = 0;
                     72: static int global_v6_socket = -1;
                     73: 
                     74: static void if_register_multicast(struct interface_info *info);
                     75: #endif
                     76: 
                     77: /*
                     78:  * We can use a single socket for AF_INET (similar to AF_INET6) on all
                     79:  * interfaces configured for DHCP if the system has support for IP_PKTINFO
                     80:  * and IP_RECVPKTINFO (for example Solaris 11).
                     81:  */
                     82: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
                     83: static unsigned int global_v4_socket_references = 0;
                     84: static int global_v4_socket = -1;
                     85: #endif
                     86: 
                     87: /*
                     88:  * If we can't bind() to a specific interface, then we can only have
                     89:  * a single socket. This variable insures that we don't try to listen
                     90:  * on two sockets.
                     91:  */
                     92: #if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK)
                     93: static int once = 0;
                     94: #endif /* !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK) */
                     95: 
                     96: /* Reinitializes the specified interface after an address change.   This
                     97:    is not required for packet-filter APIs. */
                     98: 
                     99: #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
                    100: void if_reinitialize_send (info)
                    101:        struct interface_info *info;
                    102: {
                    103: #if 0
                    104: #ifndef USE_SOCKET_RECEIVE
                    105:        once = 0;
                    106:        close (info -> wfdesc);
                    107: #endif
                    108:        if_register_send (info);
                    109: #endif
                    110: }
                    111: #endif
                    112: 
                    113: #ifdef USE_SOCKET_RECEIVE
                    114: void if_reinitialize_receive (info)
                    115:        struct interface_info *info;
                    116: {
                    117: #if 0
                    118:        once = 0;
                    119:        close (info -> rfdesc);
                    120:        if_register_receive (info);
                    121: #endif
                    122: }
                    123: #endif
                    124: 
                    125: #if defined (USE_SOCKET_SEND) || \
                    126:        defined (USE_SOCKET_RECEIVE) || \
                    127:                defined (USE_SOCKET_FALLBACK)
                    128: /* Generic interface registration routine... */
                    129: int
                    130: if_register_socket(struct interface_info *info, int family,
                    131:                   int *do_multicast)
                    132: {
                    133:        struct sockaddr_storage name;
                    134:        int name_len;
                    135:        int sock;
                    136:        int flag;
                    137:        int domain;
                    138: 
                    139:        /* INSIST((family == AF_INET) || (family == AF_INET6)); */
                    140: 
                    141: #if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK)
                    142:        /* Make sure only one interface is registered. */
                    143:        if (once) {
                    144:                log_fatal ("The standard socket API can only support %s",
                    145:                       "hosts with a single network interface.");
                    146:        }
                    147:        once = 1;
                    148: #endif
                    149: 
                    150:        /* 
                    151:         * Set up the address we're going to bind to, depending on the
                    152:         * address family. 
                    153:         */ 
                    154:        memset(&name, 0, sizeof(name));
                    155: #ifdef DHCPv6
                    156:        if (family == AF_INET6) {
                    157:                struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&name; 
                    158:                addr->sin6_family = AF_INET6;
                    159:                addr->sin6_port = local_port;
                    160:                /* XXX: What will happen to multicasts if this is nonzero? */
                    161:                memcpy(&addr->sin6_addr,
                    162:                       &local_address6, 
                    163:                       sizeof(addr->sin6_addr));
                    164: #ifdef HAVE_SA_LEN
                    165:                addr->sin6_len = sizeof(*addr);
                    166: #endif
                    167:                name_len = sizeof(*addr);
                    168:                domain = PF_INET6;
                    169:                if ((info->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM) {
                    170:                        *do_multicast = 0;
                    171:                }
                    172:        } else { 
                    173: #else 
                    174:        {
                    175: #endif /* DHCPv6 */
                    176:                struct sockaddr_in *addr = (struct sockaddr_in *)&name; 
                    177:                addr->sin_family = AF_INET;
                    178:                addr->sin_port = local_port;
                    179:                memcpy(&addr->sin_addr,
                    180:                       &local_address,
                    181:                       sizeof(addr->sin_addr));
                    182: #ifdef HAVE_SA_LEN
                    183:                addr->sin_len = sizeof(*addr);
                    184: #endif
                    185:                name_len = sizeof(*addr);
                    186:                domain = PF_INET;
                    187:        }
                    188: 
                    189:        /* Make a socket... */
                    190:        sock = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
                    191:        if (sock < 0) {
                    192:                log_fatal("Can't create dhcp socket: %m");
                    193:        }
                    194: 
                    195:        /* Set the REUSEADDR option so that we don't fail to start if
                    196:           we're being restarted. */
                    197:        flag = 1;
                    198:        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
                    199:                        (char *)&flag, sizeof(flag)) < 0) {
                    200:                log_fatal("Can't set SO_REUSEADDR option on dhcp socket: %m");
                    201:        }
                    202: 
                    203:        /* Set the BROADCAST option so that we can broadcast DHCP responses.
                    204:           We shouldn't do this for fallback devices, and we can detect that
                    205:           a device is a fallback because it has no ifp structure. */
                    206:        if (info->ifp &&
                    207:            (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
                    208:                         (char *)&flag, sizeof(flag)) < 0)) {
                    209:                log_fatal("Can't set SO_BROADCAST option on dhcp socket: %m");
                    210:        }
                    211: 
                    212: #if defined(DHCPv6) && defined(SO_REUSEPORT)
                    213:        /*
                    214:         * We only set SO_REUSEPORT on AF_INET6 sockets, so that multiple
                    215:         * daemons can bind to their own sockets and get data for their
                    216:         * respective interfaces.  This does not (and should not) affect
                    217:         * DHCPv4 sockets; we can't yet support BSD sockets well, much
                    218:         * less multiple sockets.
                    219:         */
                    220:        if (local_family == AF_INET6) {
                    221:                flag = 1;
                    222:                if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
                    223:                               (char *)&flag, sizeof(flag)) < 0) {
                    224:                        log_fatal("Can't set SO_REUSEPORT option on dhcp "
                    225:                                  "socket: %m");
                    226:                }
                    227:        }
                    228: #endif
                    229: 
                    230:        /* Bind the socket to this interface's IP address. */
                    231:        if (bind(sock, (struct sockaddr *)&name, name_len) < 0) {
                    232:                log_error("Can't bind to dhcp address: %m");
                    233:                log_error("Please make sure there is no other dhcp server");
                    234:                log_error("running and that there's no entry for dhcp or");
                    235:                log_error("bootp in /etc/inetd.conf.   Also make sure you");
                    236:                log_error("are not running HP JetAdmin software, which");
                    237:                log_fatal("includes a bootp server.");
                    238:        }
                    239: 
                    240: #if defined(SO_BINDTODEVICE)
                    241:        /* Bind this socket to this interface. */
                    242:        if ((local_family != AF_INET6) && (info->ifp != NULL) &&
                    243:            setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
                    244:                        (char *)(info -> ifp), sizeof(*(info -> ifp))) < 0) {
                    245:                log_fatal("setsockopt: SO_BINDTODEVICE: %m");
                    246:        }
                    247: #endif
                    248: 
                    249:        /* IP_BROADCAST_IF instructs the kernel which interface to send
                    250:         * IP packets whose destination address is 255.255.255.255.  These
                    251:         * will be treated as subnet broadcasts on the interface identified
                    252:         * by ip address (info -> primary_address).  This is only known to
                    253:         * be defined in SCO system headers, and may not be defined in all
                    254:         * releases.
                    255:         */
                    256: #if defined(SCO) && defined(IP_BROADCAST_IF)
                    257:         if (info->address_count &&
                    258:            setsockopt(sock, IPPROTO_IP, IP_BROADCAST_IF, &info->addresses[0],
                    259:                       sizeof(info->addresses[0])) < 0)
                    260:                log_fatal("Can't set IP_BROADCAST_IF on dhcp socket: %m");
                    261: #endif
                    262: 
                    263: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO)  && defined(USE_V4_PKTINFO)
                    264:        /*
                    265:         * If we turn on IP_RECVPKTINFO we will be able to receive
                    266:         * the interface index information of the received packet.
                    267:         */
                    268:        if (family == AF_INET) {
                    269:                int on = 1;
                    270:                if (setsockopt(sock, IPPROTO_IP, IP_RECVPKTINFO, 
                    271:                               &on, sizeof(on)) != 0) {
                    272:                        log_fatal("setsockopt: IPV_RECVPKTINFO: %m");
                    273:                }
                    274:        }
                    275: #endif
                    276: 
                    277: #ifdef DHCPv6
                    278:        /*
                    279:         * If we turn on IPV6_PKTINFO, we will be able to receive 
                    280:         * additional information, such as the destination IP address.
                    281:         * We need this to spot unicast packets.
                    282:         */
                    283:        if (family == AF_INET6) {
                    284:                int on = 1;
                    285: #ifdef IPV6_RECVPKTINFO
                    286:                /* RFC3542 */
                    287:                if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, 
                    288:                               &on, sizeof(on)) != 0) {
                    289:                        log_fatal("setsockopt: IPV6_RECVPKTINFO: %m");
                    290:                }
                    291: #else
                    292:                /* RFC2292 */
                    293:                if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, 
                    294:                               &on, sizeof(on)) != 0) {
                    295:                        log_fatal("setsockopt: IPV6_PKTINFO: %m");
                    296:                }
                    297: #endif
                    298:        }
                    299: 
                    300:        if ((family == AF_INET6) &&
                    301:            ((info->flags & INTERFACE_UPSTREAM) != 0)) {
                    302:                int hop_limit = 32;
                    303:                if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
                    304:                               &hop_limit, sizeof(int)) < 0) {
                    305:                        log_fatal("setsockopt: IPV6_MULTICAST_HOPS: %m");
                    306:                }
                    307:        }
                    308: #endif /* DHCPv6 */
                    309: 
                    310:        return sock;
                    311: }
                    312: #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE || USE_SOCKET_FALLBACK */
                    313: 
                    314: #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
                    315: void if_register_send (info)
                    316:        struct interface_info *info;
                    317: {
                    318: #ifndef USE_SOCKET_RECEIVE
                    319:        info->wfdesc = if_register_socket(info, AF_INET, 0);
                    320:        /* If this is a normal IPv4 address, get the hardware address. */
                    321:        if (strcmp(info->name, "fallback") != 0)
                    322:                get_hw_addr(info->name, &info->hw_address);
                    323: #if defined (USE_SOCKET_FALLBACK)
                    324:        /* Fallback only registers for send, but may need to receive as
                    325:           well. */
                    326:        info->rfdesc = info->wfdesc;
                    327: #endif
                    328: #else
                    329:        info->wfdesc = info->rfdesc;
                    330: #endif
                    331:        if (!quiet_interface_discovery)
                    332:                log_info ("Sending on   Socket/%s%s%s",
                    333:                      info->name,
                    334:                      (info->shared_network ? "/" : ""),
                    335:                      (info->shared_network ?
                    336:                       info->shared_network->name : ""));
                    337: }
                    338: 
                    339: #if defined (USE_SOCKET_SEND)
                    340: void if_deregister_send (info)
                    341:        struct interface_info *info;
                    342: {
                    343: #ifndef USE_SOCKET_RECEIVE
                    344:        close (info -> wfdesc);
                    345: #endif
                    346:        info -> wfdesc = -1;
                    347: 
                    348:        if (!quiet_interface_discovery)
                    349:                log_info ("Disabling output on Socket/%s%s%s",
                    350:                      info -> name,
                    351:                      (info -> shared_network ? "/" : ""),
                    352:                      (info -> shared_network ?
                    353:                       info -> shared_network -> name : ""));
                    354: }
                    355: #endif /* USE_SOCKET_SEND */
                    356: #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */
                    357: 
                    358: #ifdef USE_SOCKET_RECEIVE
                    359: void if_register_receive (info)
                    360:        struct interface_info *info;
                    361: {
                    362: 
                    363: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
                    364:        if (global_v4_socket_references == 0) {
                    365:                global_v4_socket = if_register_socket(info, AF_INET, 0);
                    366:                if (global_v4_socket < 0) {
                    367:                        /*
                    368:                         * if_register_socket() fatally logs if it fails to
                    369:                         * create a socket, this is just a sanity check.
                    370:                         */
                    371:                        log_fatal("Failed to create AF_INET socket %s:%d",
                    372:                                  MDL);
                    373:                }
                    374:        }
                    375:                
                    376:        info->rfdesc = global_v4_socket;
                    377:        global_v4_socket_references++;
                    378: #else
                    379:        /* If we're using the socket API for sending and receiving,
                    380:           we don't need to register this interface twice. */
                    381:        info->rfdesc = if_register_socket(info, AF_INET, 0);
                    382: #endif /* IP_PKTINFO... */
                    383:        /* If this is a normal IPv4 address, get the hardware address. */
                    384:        if (strcmp(info->name, "fallback") != 0)
                    385:                get_hw_addr(info->name, &info->hw_address);
                    386: 
                    387:        if (!quiet_interface_discovery)
                    388:                log_info ("Listening on Socket/%s%s%s",
                    389:                      info->name,
                    390:                      (info->shared_network ? "/" : ""),
                    391:                      (info->shared_network ?
                    392:                       info->shared_network->name : ""));
                    393: }
                    394: 
                    395: void if_deregister_receive (info)
                    396:        struct interface_info *info;
                    397: {
                    398: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
                    399:        /* Dereference the global v4 socket. */
                    400:        if ((info->rfdesc == global_v4_socket) &&
                    401:            (info->wfdesc == global_v4_socket) &&
                    402:            (global_v4_socket_references > 0)) {
                    403:                global_v4_socket_references--;
                    404:                info->rfdesc = -1;
                    405:        } else {
                    406:                log_fatal("Impossible condition at %s:%d", MDL);
                    407:        }
                    408: 
                    409:        if (global_v4_socket_references == 0) {
                    410:                close(global_v4_socket);
                    411:                global_v4_socket = -1;
                    412:        }
                    413: #else
                    414:        close(info->rfdesc);
                    415:        info->rfdesc = -1;
                    416: #endif /* IP_PKTINFO... */
                    417:        if (!quiet_interface_discovery)
                    418:                log_info ("Disabling input on Socket/%s%s%s",
                    419:                      info -> name,
                    420:                      (info -> shared_network ? "/" : ""),
                    421:                      (info -> shared_network ?
                    422:                       info -> shared_network -> name : ""));
                    423: }
                    424: #endif /* USE_SOCKET_RECEIVE */
                    425: 
                    426: 
                    427: #ifdef DHCPv6 
                    428: /*
                    429:  * This function joins the interface to DHCPv6 multicast groups so we will
                    430:  * receive multicast messages.
                    431:  */
                    432: static void
                    433: if_register_multicast(struct interface_info *info) {
                    434:        int sock = info->rfdesc;
                    435:        struct ipv6_mreq mreq;
                    436: 
                    437:        if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
                    438:                      &mreq.ipv6mr_multiaddr) <= 0) {
                    439:                log_fatal("inet_pton: unable to convert '%s'", 
                    440:                          All_DHCP_Relay_Agents_and_Servers);
                    441:        }
                    442:        mreq.ipv6mr_interface = if_nametoindex(info->name);
                    443:        if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 
                    444:                       &mreq, sizeof(mreq)) < 0) {
                    445:                log_fatal("setsockopt: IPV6_JOIN_GROUP: %m");
                    446:        }
                    447: 
                    448:        /*
                    449:         * The relay agent code sets the streams so you know which way
                    450:         * is up and down.  But a relay agent shouldn't join to the
                    451:         * Server address, or else you get fun loops.  So up or down
                    452:         * doesn't matter, we're just using that config to sense this is
                    453:         * a relay agent.
                    454:         */
                    455:        if ((info->flags & INTERFACE_STREAMS) == 0) {
                    456:                if (inet_pton(AF_INET6, All_DHCP_Servers,
                    457:                              &mreq.ipv6mr_multiaddr) <= 0) {
                    458:                        log_fatal("inet_pton: unable to convert '%s'", 
                    459:                                  All_DHCP_Servers);
                    460:                }
                    461:                mreq.ipv6mr_interface = if_nametoindex(info->name);
                    462:                if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 
                    463:                               &mreq, sizeof(mreq)) < 0) {
                    464:                        log_fatal("setsockopt: IPV6_JOIN_GROUP: %m");
                    465:                }
                    466:        }
                    467: }
                    468: 
                    469: void
                    470: if_register6(struct interface_info *info, int do_multicast) {
                    471:        /* Bounce do_multicast to a stack variable because we may change it. */
                    472:        int req_multi = do_multicast;
                    473: 
                    474:        if (global_v6_socket_references == 0) {
                    475:                global_v6_socket = if_register_socket(info, AF_INET6,
                    476:                                                      &req_multi);
                    477:                if (global_v6_socket < 0) {
                    478:                        /*
                    479:                         * if_register_socket() fatally logs if it fails to
                    480:                         * create a socket, this is just a sanity check.
                    481:                         */
                    482:                        log_fatal("Impossible condition at %s:%d", MDL);
                    483:                } else {
                    484:                        log_info("Bound to *:%d", ntohs(local_port));
                    485:                }
                    486:        }
                    487:                
                    488:        info->rfdesc = global_v6_socket;
                    489:        info->wfdesc = global_v6_socket;
                    490:        global_v6_socket_references++;
                    491: 
                    492:        if (req_multi)
                    493:                if_register_multicast(info);
                    494: 
                    495:        get_hw_addr(info->name, &info->hw_address);
                    496: 
                    497:        if (!quiet_interface_discovery) {
                    498:                if (info->shared_network != NULL) {
                    499:                        log_info("Listening on Socket/%d/%s/%s",
                    500:                                 global_v6_socket, info->name, 
                    501:                                 info->shared_network->name);
                    502:                        log_info("Sending on   Socket/%d/%s/%s",
                    503:                                 global_v6_socket, info->name,
                    504:                                 info->shared_network->name);
                    505:                } else {
                    506:                        log_info("Listening on Socket/%s", info->name);
                    507:                        log_info("Sending on   Socket/%s", info->name);
                    508:                }
                    509:        }
                    510: }
                    511: 
                    512: void 
                    513: if_deregister6(struct interface_info *info) {
                    514:        /* Dereference the global v6 socket. */
                    515:        if ((info->rfdesc == global_v6_socket) &&
                    516:            (info->wfdesc == global_v6_socket) &&
                    517:            (global_v6_socket_references > 0)) {
                    518:                global_v6_socket_references--;
                    519:                info->rfdesc = -1;
                    520:                info->wfdesc = -1;
                    521:        } else {
                    522:                log_fatal("Impossible condition at %s:%d", MDL);
                    523:        }
                    524: 
                    525:        if (!quiet_interface_discovery) {
                    526:                if (info->shared_network != NULL) {
                    527:                        log_info("Disabling input on  Socket/%s/%s", info->name,
                    528:                                 info->shared_network->name);
                    529:                        log_info("Disabling output on Socket/%s/%s", info->name,
                    530:                                 info->shared_network->name);
                    531:                } else {
                    532:                        log_info("Disabling input on  Socket/%s", info->name);
                    533:                        log_info("Disabling output on Socket/%s", info->name);
                    534:                }
                    535:        }
                    536: 
                    537:        if (global_v6_socket_references == 0) {
                    538:                close(global_v6_socket);
                    539:                global_v6_socket = -1;
                    540: 
                    541:                log_info("Unbound from *:%d", ntohs(local_port));
                    542:        }
                    543: }
                    544: #endif /* DHCPv6 */
                    545: 
                    546: #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
                    547: ssize_t send_packet (interface, packet, raw, len, from, to, hto)
                    548:        struct interface_info *interface;
                    549:        struct packet *packet;
                    550:        struct dhcp_packet *raw;
                    551:        size_t len;
                    552:        struct in_addr from;
                    553:        struct sockaddr_in *to;
                    554:        struct hardware *hto;
                    555: {
                    556:        int result;
                    557: #ifdef IGNORE_HOSTUNREACH
                    558:        int retry = 0;
                    559:        do {
                    560: #endif
                    561: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
                    562:                struct in_pktinfo pktinfo;
                    563: 
                    564:                if (interface->ifp != NULL) {
                    565:                        memset(&pktinfo, 0, sizeof (pktinfo));
                    566:                        pktinfo.ipi_ifindex = interface->ifp->ifr_index;
                    567:                        if (setsockopt(interface->wfdesc, IPPROTO_IP,
                    568:                                       IP_PKTINFO, (char *)&pktinfo,
                    569:                                       sizeof(pktinfo)) < 0) 
                    570:                                log_fatal("setsockopt: IP_PKTINFO: %m");
                    571:                }
                    572: #endif
                    573:                result = sendto (interface -> wfdesc, (char *)raw, len, 0,
                    574:                                 (struct sockaddr *)to, sizeof *to);
                    575: #ifdef IGNORE_HOSTUNREACH
                    576:        } while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) &&
                    577:                 result < 0 &&
                    578:                 (errno == EHOSTUNREACH ||
                    579:                  errno == ECONNREFUSED) &&
                    580:                 retry++ < 10);
                    581: #endif
                    582:        if (result < 0) {
                    583:                log_error ("send_packet: %m");
                    584:                if (errno == ENETUNREACH)
                    585:                        log_error ("send_packet: please consult README file%s",
                    586:                                   " regarding broadcast address.");
                    587:        }
                    588:        return result;
                    589: }
                    590: 
                    591: #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */
                    592: 
                    593: #ifdef DHCPv6
                    594: /*
                    595:  * Solaris 9 is missing the CMSG_LEN and CMSG_SPACE macros, so we will 
                    596:  * synthesize them (based on the BIND 9 technique).
                    597:  */
                    598: 
                    599: #ifndef CMSG_LEN
                    600: static size_t CMSG_LEN(size_t len) {
                    601:        size_t hdrlen;
                    602:        /*
                    603:         * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
                    604:         * is correct.
                    605:         */
                    606:        hdrlen = (size_t)CMSG_DATA(((struct cmsghdr *)NULL));
                    607:        return hdrlen + len;
                    608: }
                    609: #endif /* !CMSG_LEN */
                    610: 
                    611: #ifndef CMSG_SPACE
                    612: static size_t CMSG_SPACE(size_t len) {
                    613:        struct msghdr msg;
                    614:        struct cmsghdr *cmsgp;
                    615: 
                    616:        /*
                    617:         * XXX: The buffer length is an ad-hoc value, but should be enough
                    618:         * in a practical sense.
                    619:         */
                    620:        union {
                    621:                struct cmsghdr cmsg_sizer;
                    622:                u_int8_t pktinfo_sizer[sizeof(struct cmsghdr) + 1024];
                    623:        } dummybuf;
                    624: 
                    625:        memset(&msg, 0, sizeof(msg));
                    626:        msg.msg_control = &dummybuf;
                    627:        msg.msg_controllen = sizeof(dummybuf);
                    628: 
                    629:        cmsgp = (struct cmsghdr *)&dummybuf;
                    630:        cmsgp->cmsg_len = CMSG_LEN(len);
                    631: 
                    632:        cmsgp = CMSG_NXTHDR(&msg, cmsgp);
                    633:        if (cmsgp != NULL) {
                    634:                return (char *)cmsgp - (char *)msg.msg_control;
                    635:        } else {
                    636:                return 0;
                    637:        }
                    638: }
                    639: #endif /* !CMSG_SPACE */
                    640: 
                    641: #endif /* DHCPv6 */
                    642: 
                    643: #if defined(DHCPv6) || \
                    644:        (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
                    645:         defined(USE_V4_PKTINFO))
                    646: /*
                    647:  * For both send_packet6() and receive_packet6() we need to allocate
                    648:  * space for the cmsg header information.  We do this once and reuse
                    649:  * the buffer.  We also need the control buf for send_packet() and
                    650:  * receive_packet() when we use a single socket and IP_PKTINFO to
                    651:  * send the packet out the correct interface.
                    652:  */
                    653: static void   *control_buf = NULL;
                    654: static size_t  control_buf_len = 0;
                    655: 
                    656: static void
                    657: allocate_cmsg_cbuf(void) {
                    658:        control_buf_len = CMSG_SPACE(sizeof(struct in6_pktinfo));
                    659:        control_buf = dmalloc(control_buf_len, MDL);
                    660:        return;
                    661: }
                    662: #endif /* DHCPv6, IP_PKTINFO ... */
                    663: 
                    664: #ifdef DHCPv6
                    665: /* 
                    666:  * For both send_packet6() and receive_packet6() we need to use the 
                    667:  * sendmsg()/recvmsg() functions rather than the simpler send()/recv()
                    668:  * functions.
                    669:  *
                    670:  * In the case of send_packet6(), we need to do this in order to insure
                    671:  * that the reply packet leaves on the same interface that it arrived 
                    672:  * on. 
                    673:  *
                    674:  * In the case of receive_packet6(), we need to do this in order to 
                    675:  * get the IP address the packet was sent to. This is used to identify
                    676:  * whether a packet is multicast or unicast.
                    677:  *
                    678:  * Helpful man pages: recvmsg, readv (talks about the iovec stuff), cmsg.
                    679:  *
                    680:  * Also see the sections in RFC 3542 about IPV6_PKTINFO.
                    681:  */
                    682: 
                    683: /* Send an IPv6 packet */
                    684: ssize_t send_packet6(struct interface_info *interface,
                    685:                     const unsigned char *raw, size_t len,
                    686:                     struct sockaddr_in6 *to) {
                    687:        struct msghdr m;
                    688:        struct iovec v;
                    689:        int result;
                    690:        struct in6_pktinfo *pktinfo;
                    691:        struct cmsghdr *cmsg;
                    692: 
                    693:        /*
                    694:         * If necessary allocate space for the control message header.
                    695:         * The space is common between send and receive.
                    696:         */
                    697: 
                    698:        if (control_buf == NULL) {
                    699:                allocate_cmsg_cbuf();
                    700:                if (control_buf == NULL) {
                    701:                        log_error("send_packet6: unable to allocate cmsg header");
                    702:                        return(ENOMEM);
                    703:                }
                    704:        }
                    705:        memset(control_buf, 0, control_buf_len);
                    706: 
                    707:        /*
                    708:         * Initialize our message header structure.
                    709:         */
                    710:        memset(&m, 0, sizeof(m));
                    711: 
                    712:        /*
                    713:         * Set the target address we're sending to.
                    714:         */
                    715:        m.msg_name = to;
                    716:        m.msg_namelen = sizeof(*to);
                    717: 
                    718:        /*
                    719:         * Set the data buffer we're sending. (Using this wacky 
                    720:         * "scatter-gather" stuff... we only have a single chunk 
                    721:         * of data to send, so we declare a single vector entry.)
                    722:         */
                    723:        v.iov_base = (char *)raw;
                    724:        v.iov_len = len;
                    725:        m.msg_iov = &v;
                    726:        m.msg_iovlen = 1;
                    727: 
                    728:        /*
                    729:         * Setting the interface is a bit more involved.
                    730:         * 
                    731:         * We have to create a "control message", and set that to 
                    732:         * define the IPv6 packet information. We could set the
                    733:         * source address if we wanted, but we can safely let the
                    734:         * kernel decide what that should be. 
                    735:         */
                    736:        m.msg_control = control_buf;
                    737:        m.msg_controllen = control_buf_len;
                    738:        cmsg = CMSG_FIRSTHDR(&m);
                    739:        cmsg->cmsg_level = IPPROTO_IPV6;
                    740:        cmsg->cmsg_type = IPV6_PKTINFO;
                    741:        cmsg->cmsg_len = CMSG_LEN(sizeof(*pktinfo));
                    742:        pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
                    743:        memset(pktinfo, 0, sizeof(*pktinfo));
                    744:        pktinfo->ipi6_ifindex = if_nametoindex(interface->name);
                    745:        m.msg_controllen = cmsg->cmsg_len;
                    746: 
                    747:        result = sendmsg(interface->wfdesc, &m, 0);
                    748:        if (result < 0) {
                    749:                log_error("send_packet6: %m");
                    750:        }
                    751:        return result;
                    752: }
                    753: #endif /* DHCPv6 */
                    754: 
                    755: #ifdef USE_SOCKET_RECEIVE
                    756: ssize_t receive_packet (interface, buf, len, from, hfrom)
                    757:        struct interface_info *interface;
                    758:        unsigned char *buf;
                    759:        size_t len;
                    760:        struct sockaddr_in *from;
                    761:        struct hardware *hfrom;
                    762: {
1.1.1.1 ! misho     763: #if !(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO))
1.1       misho     764:        SOCKLEN_T flen = sizeof *from;
                    765: #endif
                    766:        int result;
                    767: 
                    768:        /*
                    769:         * The normal Berkeley socket interface doesn't give us any way
                    770:         * to know what hardware interface we received the message on,
                    771:         * but we should at least make sure the structure is emptied.
                    772:         */
                    773:        memset(hfrom, 0, sizeof(*hfrom));
                    774: 
                    775: #ifdef IGNORE_HOSTUNREACH
                    776:        int retry = 0;
                    777:        do {
                    778: #endif
                    779: 
                    780: #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
                    781:        struct msghdr m;
                    782:        struct iovec v;
                    783:        struct cmsghdr *cmsg;
                    784:        struct in_pktinfo *pktinfo;
                    785:        unsigned int ifindex;
                    786: 
                    787:        /*
                    788:         * If necessary allocate space for the control message header.
                    789:         * The space is common between send and receive.
                    790:         */
                    791:        if (control_buf == NULL) {
                    792:                allocate_cmsg_cbuf();
                    793:                if (control_buf == NULL) {
                    794:                        log_error("receive_packet: unable to allocate cmsg "
                    795:                                  "header");
                    796:                        return(ENOMEM);
                    797:                }
                    798:        }
                    799:        memset(control_buf, 0, control_buf_len);
                    800: 
                    801:        /*
                    802:         * Initialize our message header structure.
                    803:         */
                    804:        memset(&m, 0, sizeof(m));
                    805: 
                    806:        /*
                    807:         * Point so we can get the from address.
                    808:         */
                    809:        m.msg_name = from;
                    810:        m.msg_namelen = sizeof(*from);
                    811: 
                    812:        /*
                    813:         * Set the data buffer we're receiving. (Using this wacky 
                    814:         * "scatter-gather" stuff... but we that doesn't really make
                    815:         * sense for us, so we use a single vector entry.)
                    816:         */
                    817:        v.iov_base = buf;
                    818:        v.iov_len = len;
                    819:        m.msg_iov = &v;
                    820:        m.msg_iovlen = 1;
                    821: 
                    822:        /*
                    823:         * Getting the interface is a bit more involved.
                    824:         *
                    825:         * We set up some space for a "control message". We have 
                    826:         * previously asked the kernel to give us packet 
                    827:         * information (when we initialized the interface), so we
1.1.1.1 ! misho     828:         * should get the interface index from that.
1.1       misho     829:         */
                    830:        m.msg_control = control_buf;
                    831:        m.msg_controllen = control_buf_len;
                    832: 
                    833:        result = recvmsg(interface->rfdesc, &m, 0);
                    834: 
                    835:        if (result >= 0) {
                    836:                /*
                    837:                 * If we did read successfully, then we need to loop
                    838:                 * through the control messages we received and 
1.1.1.1 ! misho     839:                 * find the one with our inteface index.
1.1       misho     840:                 */
                    841:                cmsg = CMSG_FIRSTHDR(&m);
                    842:                while (cmsg != NULL) {
                    843:                        if ((cmsg->cmsg_level == IPPROTO_IP) && 
                    844:                            (cmsg->cmsg_type == IP_PKTINFO)) {
                    845:                                pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
                    846:                                ifindex = pktinfo->ipi_ifindex;
                    847:                                /*
                    848:                                 * We pass the ifindex back to the caller 
                    849:                                 * using the unused hfrom parameter avoiding
                    850:                                 * interface changes between sockets and 
                    851:                                 * the discover code.
                    852:                                 */
                    853:                                memcpy(hfrom->hbuf, &ifindex, sizeof(ifindex));
1.1.1.1 ! misho     854:                                return (result);
1.1       misho     855:                        }
                    856:                        cmsg = CMSG_NXTHDR(&m, cmsg);
                    857:                }
1.1.1.1 ! misho     858: 
        !           859:                /*
        !           860:                 * We didn't find the necessary control message
        !           861:                 * flag it as an error
        !           862:                 */
        !           863:                result = -1;
        !           864:                errno = EIO;
1.1       misho     865:        }
                    866: #else
1.1.1.1 ! misho     867:                result = recvfrom(interface -> rfdesc, (char *)buf, len, 0,
        !           868:                                  (struct sockaddr *)from, &flen);
1.1       misho     869: #endif /* IP_PKTINFO ... */
                    870: #ifdef IGNORE_HOSTUNREACH
                    871:        } while (result < 0 &&
                    872:                 (errno == EHOSTUNREACH ||
                    873:                  errno == ECONNREFUSED) &&
                    874:                 retry++ < 10);
                    875: #endif
1.1.1.1 ! misho     876:        return (result);
1.1       misho     877: }
                    878: 
                    879: #endif /* USE_SOCKET_RECEIVE */
                    880: 
                    881: #ifdef DHCPv6
                    882: ssize_t 
                    883: receive_packet6(struct interface_info *interface, 
                    884:                unsigned char *buf, size_t len, 
                    885:                struct sockaddr_in6 *from, struct in6_addr *to_addr,
                    886:                unsigned int *if_idx)
                    887: {
                    888:        struct msghdr m;
                    889:        struct iovec v;
                    890:        int result;
                    891:        struct cmsghdr *cmsg;
                    892:        struct in6_pktinfo *pktinfo;
                    893: 
                    894:        /*
                    895:         * If necessary allocate space for the control message header.
                    896:         * The space is common between send and receive.
                    897:         */
                    898:        if (control_buf == NULL) {
                    899:                allocate_cmsg_cbuf();
                    900:                if (control_buf == NULL) {
                    901:                        log_error("receive_packet6: unable to allocate cmsg "
                    902:                                  "header");
                    903:                        return(ENOMEM);
                    904:                }
                    905:        }
                    906:        memset(control_buf, 0, control_buf_len);
                    907: 
                    908:        /*
                    909:         * Initialize our message header structure.
                    910:         */
                    911:        memset(&m, 0, sizeof(m));
                    912: 
                    913:        /*
                    914:         * Point so we can get the from address.
                    915:         */
                    916:        m.msg_name = from;
                    917:        m.msg_namelen = sizeof(*from);
                    918: 
                    919:        /*
                    920:         * Set the data buffer we're receiving. (Using this wacky 
                    921:         * "scatter-gather" stuff... but we that doesn't really make
                    922:         * sense for us, so we use a single vector entry.)
                    923:         */
                    924:        v.iov_base = buf;
                    925:        v.iov_len = len;
                    926:        m.msg_iov = &v;
                    927:        m.msg_iovlen = 1;
                    928: 
                    929:        /*
                    930:         * Getting the interface is a bit more involved.
                    931:         *
                    932:         * We set up some space for a "control message". We have 
                    933:         * previously asked the kernel to give us packet 
                    934:         * information (when we initialized the interface), so we
                    935:         * should get the destination address from that.
                    936:         */
                    937:        m.msg_control = control_buf;
                    938:        m.msg_controllen = control_buf_len;
                    939: 
                    940:        result = recvmsg(interface->rfdesc, &m, 0);
                    941: 
                    942:        if (result >= 0) {
                    943:                /*
                    944:                 * If we did read successfully, then we need to loop
                    945:                 * through the control messages we received and 
                    946:                 * find the one with our destination address.
                    947:                 */
                    948:                cmsg = CMSG_FIRSTHDR(&m);
                    949:                while (cmsg != NULL) {
                    950:                        if ((cmsg->cmsg_level == IPPROTO_IPV6) && 
                    951:                            (cmsg->cmsg_type == IPV6_PKTINFO)) {
                    952:                                pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
                    953:                                *to_addr = pktinfo->ipi6_addr;
                    954:                                *if_idx = pktinfo->ipi6_ifindex;
1.1.1.1 ! misho     955: 
        !           956:                                return (result);
1.1       misho     957:                        }
                    958:                        cmsg = CMSG_NXTHDR(&m, cmsg);
                    959:                }
1.1.1.1 ! misho     960: 
        !           961:                /*
        !           962:                 * We didn't find the necessary control message
        !           963:                 * flag is as an error
        !           964:                 */
        !           965:                result = -1;
        !           966:                errno = EIO;
1.1       misho     967:        }
                    968: 
1.1.1.1 ! misho     969:        return (result);
1.1       misho     970: }
                    971: #endif /* DHCPv6 */
                    972: 
                    973: #if defined (USE_SOCKET_FALLBACK)
                    974: /* This just reads in a packet and silently discards it. */
                    975: 
                    976: isc_result_t fallback_discard (object)
                    977:        omapi_object_t *object;
                    978: {
                    979:        char buf [1540];
                    980:        struct sockaddr_in from;
                    981:        SOCKLEN_T flen = sizeof from;
                    982:        int status;
                    983:        struct interface_info *interface;
                    984: 
                    985:        if (object -> type != dhcp_type_interface)
                    986:                return ISC_R_INVALIDARG;
                    987:        interface = (struct interface_info *)object;
                    988: 
                    989:        status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0,
                    990:                           (struct sockaddr *)&from, &flen);
                    991: #if defined (DEBUG)
                    992:        /* Only report fallback discard errors if we're debugging. */
                    993:        if (status < 0) {
                    994:                log_error ("fallback_discard: %m");
                    995:                return ISC_R_UNEXPECTED;
                    996:        }
1.1.1.1 ! misho     997: #else
        !           998:         /* ignore the fact that status value is never used */
        !           999:         IGNORE_UNUSED(status);
1.1       misho    1000: #endif
                   1001:        return ISC_R_SUCCESS;
                   1002: }
                   1003: #endif /* USE_SOCKET_FALLBACK */
                   1004: 
                   1005: #if defined (USE_SOCKET_SEND)
                   1006: int can_unicast_without_arp (ip)
                   1007:        struct interface_info *ip;
                   1008: {
                   1009:        return 0;
                   1010: }
                   1011: 
                   1012: int can_receive_unicast_unconfigured (ip)
                   1013:        struct interface_info *ip;
                   1014: {
                   1015: #if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED)
                   1016:        return 1;
                   1017: #else
                   1018:        return 0;
                   1019: #endif
                   1020: }
                   1021: 
                   1022: int supports_multiple_interfaces (ip)
                   1023:        struct interface_info *ip;
                   1024: {
                   1025: #if defined(SO_BINDTODEVICE) || \
                   1026:        (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
                   1027:         defined(USE_V4_PKTINFO))
                   1028:        return(1);
                   1029: #else
                   1030:        return(0);
                   1031: #endif
                   1032: }
                   1033: 
                   1034: /* If we have SO_BINDTODEVICE, set up a fallback interface; otherwise,
                   1035:    do not. */
                   1036: 
                   1037: void maybe_setup_fallback ()
                   1038: {
                   1039: #if defined (USE_SOCKET_FALLBACK)
                   1040:        isc_result_t status;
                   1041:        struct interface_info *fbi = (struct interface_info *)0;
                   1042:        if (setup_fallback (&fbi, MDL)) {
                   1043:                fbi -> wfdesc = if_register_socket (fbi, AF_INET, 0);
                   1044:                fbi -> rfdesc = fbi -> wfdesc;
                   1045:                log_info ("Sending on   Socket/%s%s%s",
                   1046:                      fbi -> name,
                   1047:                      (fbi -> shared_network ? "/" : ""),
                   1048:                      (fbi -> shared_network ?
                   1049:                       fbi -> shared_network -> name : ""));
                   1050:        
                   1051:                status = omapi_register_io_object ((omapi_object_t *)fbi,
                   1052:                                                   if_readsocket, 0,
                   1053:                                                   fallback_discard, 0, 0);
                   1054:                if (status != ISC_R_SUCCESS)
                   1055:                        log_fatal ("Can't register I/O handle for %s: %s",
                   1056:                                   fbi -> name, isc_result_totext (status));
                   1057:                interface_dereference (&fbi, MDL);
                   1058:        }
                   1059: #endif
                   1060: }
                   1061: 
                   1062: 
                   1063: #if defined(sun) && defined(USE_V4_PKTINFO)
                   1064: /* This code assumes the existence of SIOCGLIFHWADDR */
                   1065: void
                   1066: get_hw_addr(const char *name, struct hardware *hw) {
                   1067:        struct sockaddr_dl *dladdrp;
1.1.1.1 ! misho    1068:        int sock, i;
1.1       misho    1069:        struct lifreq lifr;
                   1070: 
                   1071:        memset(&lifr, 0, sizeof (lifr));
                   1072:        (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
                   1073:        /*
                   1074:         * Check if the interface is a virtual or IPMP interface - in those
                   1075:         * cases it has no hw address, so generate a random one.
                   1076:         */
                   1077:        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
                   1078:            ioctl(sock, SIOCGLIFFLAGS, &lifr) < 0) {
                   1079:                if (sock != -1)
                   1080:                        (void) close(sock);
                   1081: 
                   1082: #ifdef DHCPv6
                   1083:                /*
                   1084:                 * If approrpriate try this with an IPv6 socket
                   1085:                 */
                   1086:                if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0 &&
                   1087:                    ioctl(sock, SIOCGLIFFLAGS, &lifr) >= 0) {
                   1088:                        goto flag_check;
                   1089:                }
                   1090:                if (sock != -1)
                   1091:                        (void) close(sock);
                   1092: #endif
                   1093:                log_fatal("Couldn't get interface flags for %s: %m", name);
                   1094: 
                   1095:        }
                   1096: 
                   1097:  flag_check:
                   1098:        if (lifr.lifr_flags & (IFF_VIRTUAL|IFF_IPMP)) {
                   1099:                hw->hlen = sizeof (hw->hbuf);
                   1100:                srandom((long)gethrtime());
                   1101: 
1.1.1.1 ! misho    1102:                hw->hbuf[0] = HTYPE_IPMP;
        !          1103:                for (i = 1; i < hw->hlen; ++i) {
1.1       misho    1104:                        hw->hbuf[i] = random() % 256;
                   1105:                }
                   1106: 
                   1107:                if (sock != -1)
                   1108:                        (void) close(sock);
                   1109:                return;
                   1110:        }
                   1111: 
                   1112:        if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
                   1113:                log_fatal("Couldn't get interface hardware address for %s: %m",
                   1114:                          name);
                   1115:        dladdrp = (struct sockaddr_dl *)&lifr.lifr_addr;
1.1.1.1 ! misho    1116:        hw->hlen = dladdrp->sdl_alen+1;
        !          1117:        switch (dladdrp->sdl_type) {
        !          1118:                case DL_CSMACD: /* IEEE 802.3 */
        !          1119:                case DL_ETHER:
        !          1120:                        hw->hbuf[0] = HTYPE_ETHER;
        !          1121:                        break;
        !          1122:                case DL_TPR:
        !          1123:                        hw->hbuf[0] = HTYPE_IEEE802;
        !          1124:                        break;
        !          1125:                case DL_FDDI:
        !          1126:                        hw->hbuf[0] = HTYPE_FDDI;
        !          1127:                        break;
        !          1128:                case DL_IB:
        !          1129:                        hw->hbuf[0] = HTYPE_INFINIBAND;
        !          1130:                        break;
        !          1131:                default:
        !          1132:                        log_fatal("%s: unsupported DLPI MAC type %lu", name,
        !          1133:                                  (unsigned long)dladdrp->sdl_type);
        !          1134:        }
        !          1135: 
        !          1136:        memcpy(hw->hbuf+1, LLADDR(dladdrp), hw->hlen-1);
1.1       misho    1137: 
                   1138:        if (sock != -1)
                   1139:                (void) close(sock);
                   1140: }
                   1141: #endif /* defined(sun) */
                   1142: 
                   1143: #endif /* USE_SOCKET_SEND */
                   1144: 
                   1145: /*
                   1146:  * Code to set a handler for signals.  This
                   1147:  * exists to allow us to ignore SIGPIPE signals
                   1148:  * but could be used for other purposes in the
                   1149:  * future.
                   1150:  */
                   1151: 
                   1152: isc_result_t
                   1153: dhcp_handle_signal(int sig, void (*handler)(int)) {
                   1154:        struct sigaction sa;
                   1155: 
                   1156:        memset(&sa, 0, sizeof(sa));
                   1157:        sa.sa_handler = handler;
                   1158: 
                   1159:        if (sigfillset(&sa.sa_mask) != 0 ||
                   1160:            sigaction(sig, &sa, NULL) < 0) {
                   1161:                log_error("Unable to set up signal handler for %d, %m", sig);
                   1162:                return (ISC_R_UNEXPECTED);
                   1163:        }
                   1164: 
                   1165:        return (ISC_R_SUCCESS);
                   1166: }

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