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

1.1       misho       1: /* bpf.c
                      2: 
                      3:    BPF socket interface code, originally contributed by Archie Cobbs. */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
                      7:  * Copyright (c) 1996-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 was contributed to Internet Systems Consortium
                     28:  * by Archie Cobbs.
                     29:  *
                     30:  * Patches for FDDI support on Digital Unix were written by Bill
                     31:  * Stapleton, and maintained for a while by Mike Meredith before he
                     32:  * managed to get me to integrate them.
                     33:  */
                     34: 
                     35: #include "dhcpd.h"
                     36: #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)        \
                     37:                                || defined (USE_LPF_RECEIVE)
                     38: # if defined (USE_LPF_RECEIVE)
                     39: #  include <asm/types.h>
                     40: #  include <linux/filter.h>
                     41: #  define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */
                     42: # else
                     43: #  include <sys/ioctl.h>
                     44: #  include <sys/uio.h>
                     45: #  include <net/bpf.h>
                     46: #  include <net/if_types.h>
                     47: #  if defined (NEED_OSF_PFILT_HACKS)
                     48: #   include <net/pfilt.h>
                     49: #  endif
                     50: # endif
                     51: 
                     52: #include <netinet/in_systm.h>
                     53: #include "includes/netinet/ip.h"
                     54: #include "includes/netinet/udp.h"
                     55: #include "includes/netinet/if_ether.h"
                     56: #endif
                     57: 
                     58: #ifdef USE_BPF_RECEIVE
                     59: #include <ifaddrs.h>
                     60: #endif
                     61: 
                     62: #include <errno.h>
                     63: 
                     64: /* Reinitializes the specified interface after an address change.   This
                     65:    is not required for packet-filter APIs. */
                     66: 
                     67: #ifdef USE_BPF_SEND
                     68: void if_reinitialize_send (info)
                     69:        struct interface_info *info;
                     70: {
                     71: }
                     72: #endif
                     73: 
                     74: #ifdef USE_BPF_RECEIVE
                     75: void if_reinitialize_receive (info)
                     76:        struct interface_info *info;
                     77: {
                     78: }
                     79: #endif
                     80: 
                     81: /* Called by get_interface_list for each interface that's discovered.
                     82:    Opens a packet filter for each interface and adds it to the select
                     83:    mask. */
                     84: 
                     85: #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
                     86: int if_register_bpf (info)
                     87:        struct interface_info *info;
                     88: {
                     89:        int sock;
                     90:        char filename[50];
                     91:        int b;
                     92: 
                     93:        /* Open a BPF device */
                     94:        for (b = 0; 1; b++) {
                     95:                /* %Audit% 31 bytes max. %2004.06.17,Safe% */
                     96:                sprintf(filename, BPF_FORMAT, b);
                     97:                sock = open (filename, O_RDWR, 0);
                     98:                if (sock < 0) {
                     99:                        if (errno == EBUSY) {
                    100:                                continue;
                    101:                        } else {
                    102:                                if (!b)
                    103:                                        log_fatal ("No bpf devices.%s%s%s",
                    104:                                               "   Please read the README",
                    105:                                               " section for your operating",
                    106:                                               " system.");
                    107:                                log_fatal ("Can't find free bpf: %m");
                    108:                        }
                    109:                } else {
                    110:                        break;
                    111:                }
                    112:        }
                    113: 
                    114:        /* Set the BPF device to point at this interface. */
                    115:        if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
                    116:                log_fatal ("Can't attach interface %s to bpf device %s: %m",
                    117:                       info -> name, filename);
                    118: 
                    119:        get_hw_addr(info->name, &info->hw_address);
                    120: 
                    121:        return sock;
                    122: }
                    123: #endif /* USE_BPF_SEND || USE_BPF_RECEIVE */
                    124: 
                    125: #ifdef USE_BPF_SEND
                    126: void if_register_send (info)
                    127:        struct interface_info *info;
                    128: {
                    129:        /* If we're using the bpf API for sending and receiving,
                    130:           we don't need to register this interface twice. */
                    131: #ifndef USE_BPF_RECEIVE
                    132:        info -> wfdesc = if_register_bpf (info, interface);
                    133: #else
                    134:        info -> wfdesc = info -> rfdesc;
                    135: #endif
                    136:        if (!quiet_interface_discovery)
                    137:                log_info ("Sending on   BPF/%s/%s%s%s",
                    138:                      info -> name,
                    139:                      print_hw_addr (info -> hw_address.hbuf [0],
                    140:                                     info -> hw_address.hlen - 1,
                    141:                                     &info -> hw_address.hbuf [1]),
                    142:                      (info -> shared_network ? "/" : ""),
                    143:                      (info -> shared_network ?
                    144:                       info -> shared_network -> name : ""));
                    145: }
                    146: 
                    147: void if_deregister_send (info)
                    148:        struct interface_info *info;
                    149: {
                    150:        /* If we're using the bpf API for sending and receiving,
                    151:           we don't need to register this interface twice. */
                    152: #ifndef USE_BPF_RECEIVE
                    153:        close (info -> wfdesc);
                    154: #endif
                    155:        info -> wfdesc = -1;
                    156: 
                    157:        if (!quiet_interface_discovery)
                    158:                log_info ("Disabling output on BPF/%s/%s%s%s",
                    159:                      info -> name,
                    160:                      print_hw_addr (info -> hw_address.hbuf [0],
                    161:                                     info -> hw_address.hlen - 1,
                    162:                                     &info -> hw_address.hbuf [1]),
                    163:                      (info -> shared_network ? "/" : ""),
                    164:                      (info -> shared_network ?
                    165:                       info -> shared_network -> name : ""));
                    166: }
                    167: #endif /* USE_BPF_SEND */
                    168: 
                    169: #if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)
                    170: /* Packet filter program...
                    171:    XXX Changes to the filter program may require changes to the constant
                    172:    offsets used in if_register_send to patch the BPF program! XXX */
                    173: 
                    174: struct bpf_insn dhcp_bpf_filter [] = {
                    175:        /* Make sure this is an IP packet... */
                    176:        BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
                    177:        BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
                    178: 
                    179:        /* Make sure it's a UDP packet... */
                    180:        BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
                    181:        BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
                    182: 
                    183:        /* Make sure this isn't a fragment... */
                    184:        BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
                    185:        BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
                    186: 
                    187:        /* Get the IP header length... */
                    188:        BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
                    189: 
                    190:        /* Make sure it's to the right port... */
                    191:        BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
                    192:        BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),             /* patch */
                    193: 
                    194:        /* If we passed all the tests, ask for the whole packet. */
                    195:        BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
                    196: 
                    197:        /* Otherwise, drop it. */
                    198:        BPF_STMT(BPF_RET+BPF_K, 0),
                    199: };
                    200: 
                    201: #if defined (DEC_FDDI)
                    202: struct bpf_insn *bpf_fddi_filter;
                    203: #endif
                    204: 
                    205: int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
                    206: #if defined (HAVE_TR_SUPPORT)
                    207: struct bpf_insn dhcp_bpf_tr_filter [] = {
                    208:         /* accept all token ring packets due to variable length header */
                    209:         /* if we want to get clever, insert the program here */
                    210: 
                    211:        /* If we passed all the tests, ask for the whole packet. */
                    212:        BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
                    213: 
                    214:        /* Otherwise, drop it. */
                    215:        BPF_STMT(BPF_RET+BPF_K, 0),
                    216: };
                    217: 
                    218: int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
                    219:                              sizeof (struct bpf_insn));
                    220: #endif /* HAVE_TR_SUPPORT */
                    221: #endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */
                    222: 
                    223: #if defined (USE_BPF_RECEIVE)
                    224: void if_register_receive (info)
                    225:        struct interface_info *info;
                    226: {
                    227:        int flag = 1;
                    228:        struct bpf_version v;
                    229:        struct bpf_program p;
                    230: #ifdef NEED_OSF_PFILT_HACKS
                    231:        u_int32_t bits;
                    232: #endif
                    233: #ifdef DEC_FDDI
                    234:        int link_layer;
                    235: #endif /* DEC_FDDI */
                    236: 
                    237:        /* Open a BPF device and hang it on this interface... */
                    238:        info -> rfdesc = if_register_bpf (info);
                    239: 
                    240:        /* Make sure the BPF version is in range... */
                    241:        if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
                    242:                log_fatal ("Can't get BPF version: %m");
                    243: 
                    244:        if (v.bv_major != BPF_MAJOR_VERSION ||
                    245:            v.bv_minor < BPF_MINOR_VERSION)
                    246:                log_fatal ("BPF version mismatch - recompile DHCP!");
                    247: 
                    248:        /* Set immediate mode so that reads return as soon as a packet
                    249:           comes in, rather than waiting for the input buffer to fill with
                    250:           packets. */
                    251:        if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
                    252:                log_fatal ("Can't set immediate mode on bpf device: %m");
                    253: 
                    254: #ifdef NEED_OSF_PFILT_HACKS
                    255:        /* Allow the copyall flag to be set... */
                    256:        if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
                    257:                log_fatal ("Can't set ALLOWCOPYALL: %m");
                    258: 
                    259:        /* Clear all the packet filter mode bits first... */
                    260:        bits = 0;
                    261:        if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
                    262:                log_fatal ("Can't clear pfilt bits: %m");
                    263: 
                    264:        /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */
                    265:        bits = ENBATCH | ENCOPYALL | ENBPFHDR;
                    266:        if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
                    267:                log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
                    268: #endif
                    269:        /* Get the required BPF buffer length from the kernel. */
                    270:        if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
                    271:                log_fatal ("Can't get bpf buffer length: %m");
                    272:        info -> rbuf = dmalloc (info -> rbuf_max, MDL);
                    273:        if (!info -> rbuf)
                    274:                log_fatal ("Can't allocate %ld bytes for bpf input buffer.",
                    275:                           (long)(info -> rbuf_max));
                    276:        info -> rbuf_offset = 0;
                    277:        info -> rbuf_len = 0;
                    278: 
                    279:        /* Set up the bpf filter program structure. */
                    280:        p.bf_len = dhcp_bpf_filter_len;
                    281: 
                    282: #ifdef DEC_FDDI
                    283:        /* See if this is an FDDI interface, flag it for later. */
                    284:        if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
                    285:            link_layer == DLT_FDDI) {
                    286:                if (!bpf_fddi_filter) {
                    287:                        bpf_fddi_filter = dmalloc (sizeof bpf_fddi_filter,
                    288:                                                    MDL);
                    289:                        if (!bpf_fddi_filter)
                    290:                                log_fatal ("No memory for FDDI filter.");
                    291:                        memcpy (bpf_fddi_filter,
                    292:                                dhcp_bpf_filter, sizeof dhcp_bpf_filter);
                    293:                        /* Patch the BPF program to account for the difference
                    294:                           in length between ethernet headers (14), FDDI and
                    295:                           802.2 headers (16 +8=24, +10).
                    296:                           XXX changes to filter program may require changes to
                    297:                           XXX the insn number(s) used below! */
                    298:                        bpf_fddi_filter[0].k += 10;
                    299:                        bpf_fddi_filter[2].k += 10;
                    300:                        bpf_fddi_filter[4].k += 10;
                    301:                        bpf_fddi_filter[6].k += 10;
                    302:                        bpf_fddi_filter[7].k += 10;
                    303:                }
                    304:                p.bf_insns = bpf_fddi_filter;
                    305:        } else
                    306: #endif /* DEC_FDDI */
                    307:        p.bf_insns = dhcp_bpf_filter;
                    308: 
                    309:         /* Patch the server port into the BPF  program...
                    310:           XXX changes to filter program may require changes
                    311:           to the insn number(s) used below! XXX */
                    312:        dhcp_bpf_filter [8].k = ntohs (local_port);
                    313: 
                    314:        if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
                    315:                log_fatal ("Can't install packet filter program: %m");
                    316:        if (!quiet_interface_discovery)
                    317:                log_info ("Listening on BPF/%s/%s%s%s",
                    318:                      info -> name,
                    319:                      print_hw_addr (info -> hw_address.hbuf [0],
                    320:                                     info -> hw_address.hlen - 1,
                    321:                                     &info -> hw_address.hbuf [1]),
                    322:                      (info -> shared_network ? "/" : ""),
                    323:                      (info -> shared_network ?
                    324:                       info -> shared_network -> name : ""));
                    325: }
                    326: 
                    327: void if_deregister_receive (info)
                    328:        struct interface_info *info;
                    329: {
                    330:        close (info -> rfdesc);
                    331:        info -> rfdesc = -1;
                    332: 
                    333:        if (!quiet_interface_discovery)
                    334:                log_info ("Disabling input on BPF/%s/%s%s%s",
                    335:                      info -> name,
                    336:                      print_hw_addr (info -> hw_address.hbuf [0],
                    337:                                     info -> hw_address.hlen - 1,
                    338:                                     &info -> hw_address.hbuf [1]),
                    339:                      (info -> shared_network ? "/" : ""),
                    340:                      (info -> shared_network ?
                    341:                       info -> shared_network -> name : ""));
                    342: }
                    343: #endif /* USE_BPF_RECEIVE */
                    344: 
                    345: #ifdef USE_BPF_SEND
                    346: ssize_t send_packet (interface, packet, raw, len, from, to, hto)
                    347:        struct interface_info *interface;
                    348:        struct packet *packet;
                    349:        struct dhcp_packet *raw;
                    350:        size_t len;
                    351:        struct in_addr from;
                    352:        struct sockaddr_in *to;
                    353:        struct hardware *hto;
                    354: {
                    355:        unsigned hbufp = 0, ibufp = 0;
                    356:        double hw [4];
                    357:        double ip [32];
                    358:        struct iovec iov [3];
                    359:        int result;
                    360: 
                    361:        if (!strcmp (interface -> name, "fallback"))
                    362:                return send_fallback (interface, packet, raw,
                    363:                                      len, from, to, hto);
                    364: 
                    365:        /* Assemble the headers... */
                    366:        assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
                    367:        assemble_udp_ip_header (interface,
                    368:                                (unsigned char *)ip, &ibufp, from.s_addr,
                    369:                                to -> sin_addr.s_addr, to -> sin_port,
                    370:                                (unsigned char *)raw, len);
                    371: 
                    372:        /* Fire it off */
                    373:        iov [0].iov_base = ((char *)hw);
                    374:        iov [0].iov_len = hbufp;
                    375:        iov [1].iov_base = ((char *)ip);
                    376:        iov [1].iov_len = ibufp;
                    377:        iov [2].iov_base = (char *)raw;
                    378:        iov [2].iov_len = len;
                    379: 
                    380:        result = writev(interface -> wfdesc, iov, 3);
                    381:        if (result < 0)
                    382:                log_error ("send_packet: %m");
                    383:        return result;
                    384: }
                    385: #endif /* USE_BPF_SEND */
                    386: 
                    387: #ifdef USE_BPF_RECEIVE
                    388: ssize_t receive_packet (interface, buf, len, from, hfrom)
                    389:        struct interface_info *interface;
                    390:        unsigned char *buf;
                    391:        size_t len;
                    392:        struct sockaddr_in *from;
                    393:        struct hardware *hfrom;
                    394: {
                    395:        int length = 0;
                    396:        int offset = 0;
                    397:        struct bpf_hdr hdr;
                    398:        unsigned paylen;
                    399: 
                    400:        /* All this complexity is because BPF doesn't guarantee
                    401:           that only one packet will be returned at a time.   We're
                    402:           getting what we deserve, though - this is a terrible abuse
                    403:           of the BPF interface.   Sigh. */
                    404: 
                    405:        /* Process packets until we get one we can return or until we've
                    406:           done a read and gotten nothing we can return... */
                    407: 
                    408:        do {
                    409:                /* If the buffer is empty, fill it. */
                    410:                if (interface -> rbuf_offset == interface -> rbuf_len) {
                    411:                        length = read (interface -> rfdesc,
                    412:                                       interface -> rbuf,
                    413:                                       (size_t)interface -> rbuf_max);
                    414:                        if (length <= 0) {
                    415: #ifdef __FreeBSD__
                    416:                                if (errno == ENXIO) {
                    417: #else
                    418:                                if (errno == EIO) {
                    419: #endif
                    420:                                        dhcp_interface_remove
                    421:                                                ((omapi_object_t *)interface,
                    422:                                                 (omapi_object_t *)0);
                    423:                                }
                    424:                                return length;
                    425:                        }
                    426:                        interface -> rbuf_offset = 0;
                    427:                        interface -> rbuf_len = BPF_WORDALIGN (length);
                    428:                }
                    429: 
                    430:                /* If there isn't room for a whole bpf header, something went
                    431:                   wrong, but we'll ignore it and hope it goes away... XXX */
                    432:                if (interface -> rbuf_len -
                    433:                    interface -> rbuf_offset < sizeof hdr) {
                    434:                        interface -> rbuf_offset = interface -> rbuf_len;
                    435:                        continue;
                    436:                }
                    437: 
                    438:                /* Copy out a bpf header... */
                    439:                memcpy (&hdr, &interface -> rbuf [interface -> rbuf_offset],
                    440:                        sizeof hdr);
                    441: 
                    442:                /* If the bpf header plus data doesn't fit in what's left
                    443:                   of the buffer, stick head in sand yet again... */
                    444:                if (interface -> rbuf_offset +
                    445:                    hdr.bh_hdrlen + hdr.bh_caplen > interface -> rbuf_len) {
                    446:                        interface -> rbuf_offset = interface -> rbuf_len;
                    447:                        continue;
                    448:                }
                    449: 
                    450:                /* If the captured data wasn't the whole packet, or if
                    451:                   the packet won't fit in the input buffer, all we
                    452:                   can do is drop it. */
                    453:                if (hdr.bh_caplen != hdr.bh_datalen) {
                    454:                        interface -> rbuf_offset =
                    455:                                BPF_WORDALIGN (interface -> rbuf_offset +
                    456:                                               hdr.bh_hdrlen + hdr.bh_caplen);
                    457:                        continue;
                    458:                }
                    459: 
                    460:                /* Skip over the BPF header... */
                    461:                interface -> rbuf_offset += hdr.bh_hdrlen;
                    462: 
                    463:                /* Decode the physical header... */
                    464:                offset = decode_hw_header (interface,
                    465:                                           interface -> rbuf,
                    466:                                           interface -> rbuf_offset,
                    467:                                           hfrom);
                    468: 
                    469:                /* If a physical layer checksum failed (dunno of any
                    470:                   physical layer that supports this, but WTH), skip this
                    471:                   packet. */
                    472:                if (offset < 0) {
                    473:                        interface -> rbuf_offset = 
                    474:                                BPF_WORDALIGN (interface -> rbuf_offset +
                    475:                                               hdr.bh_caplen);
                    476:                        continue;
                    477:                }
                    478:                interface -> rbuf_offset += offset;
                    479:                hdr.bh_caplen -= offset;
                    480: 
                    481:                /* Decode the IP and UDP headers... */
                    482:                offset = decode_udp_ip_header (interface,
                    483:                                               interface -> rbuf,
                    484:                                               interface -> rbuf_offset,
                    485:                                               from, hdr.bh_caplen, &paylen);
                    486: 
                    487:                /* If the IP or UDP checksum was bad, skip the packet... */
                    488:                if (offset < 0) {
                    489:                        interface -> rbuf_offset = 
                    490:                                BPF_WORDALIGN (interface -> rbuf_offset +
                    491:                                               hdr.bh_caplen);
                    492:                        continue;
                    493:                }
                    494:                interface -> rbuf_offset = interface -> rbuf_offset + offset;
                    495:                hdr.bh_caplen -= offset;
                    496: 
                    497:                /* If there's not enough room to stash the packet data,
                    498:                   we have to skip it (this shouldn't happen in real
                    499:                   life, though). */
                    500:                if (hdr.bh_caplen > len) {
                    501:                        interface -> rbuf_offset =
                    502:                                BPF_WORDALIGN (interface -> rbuf_offset +
                    503:                                               hdr.bh_caplen);
                    504:                        continue;
                    505:                }
                    506: 
                    507:                /* Copy out the data in the packet... */
                    508:                memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen);
                    509:                interface -> rbuf_offset =
                    510:                        BPF_WORDALIGN (interface -> rbuf_offset +
                    511:                                       hdr.bh_caplen);
                    512:                return paylen;
                    513:        } while (!length);
                    514:        return 0;
                    515: }
                    516: 
                    517: int can_unicast_without_arp (ip)
                    518:        struct interface_info *ip;
                    519: {
                    520:        return 1;
                    521: }
                    522: 
                    523: int can_receive_unicast_unconfigured (ip)
                    524:        struct interface_info *ip;
                    525: {
                    526:        return 1;
                    527: }
                    528: 
                    529: int supports_multiple_interfaces (ip)
                    530:        struct interface_info *ip;
                    531: {
                    532:        return 1;
                    533: }
                    534: 
                    535: void maybe_setup_fallback ()
                    536: {
                    537:        isc_result_t status;
                    538:        struct interface_info *fbi = (struct interface_info *)0;
                    539:        if (setup_fallback (&fbi, MDL)) {
                    540:                if_register_fallback (fbi);
                    541:                status = omapi_register_io_object ((omapi_object_t *)fbi,
                    542:                                                   if_readsocket, 0,
                    543:                                                   fallback_discard, 0, 0);
                    544:                if (status != ISC_R_SUCCESS)
                    545:                        log_fatal ("Can't register I/O handle for %s: %s",
                    546:                                   fbi -> name, isc_result_totext (status));
                    547:                interface_dereference (&fbi, MDL);
                    548:        }
                    549: }
                    550: 
                    551: void
                    552: get_hw_addr(const char *name, struct hardware *hw) {
                    553:        struct ifaddrs *ifa;
                    554:        struct ifaddrs *p;
                    555:        struct sockaddr_dl *sa;
                    556: 
                    557:        if (getifaddrs(&ifa) != 0) {
                    558:                log_fatal("Error getting interface information; %m");
                    559:        }
                    560: 
                    561:        /*
                    562:         * Loop through our interfaces finding a match.
                    563:         */
                    564:        sa = NULL;
                    565:        for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
                    566:                if ((p->ifa_addr->sa_family == AF_LINK) && 
                    567:                    !strcmp(p->ifa_name, name)) {
                    568:                        sa = (struct sockaddr_dl *)p->ifa_addr;
                    569:                }
                    570:        }
                    571:        if (sa == NULL) {
                    572:                log_fatal("No interface called '%s'", name);
                    573:        }
                    574: 
                    575:        /*
                    576:         * Pull out the appropriate information.
                    577:         */
                    578:         switch (sa->sdl_type) {
                    579:                 case IFT_ETHER:
                    580:                         hw->hlen = sa->sdl_alen + 1;
                    581:                         hw->hbuf[0] = HTYPE_ETHER;
                    582:                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
                    583:                         break;
                    584:                case IFT_ISO88023:
                    585:                case IFT_ISO88024: /* "token ring" */
                    586:                case IFT_ISO88025:
                    587:                case IFT_ISO88026:
                    588:                         hw->hlen = sa->sdl_alen + 1;
                    589:                         hw->hbuf[0] = HTYPE_IEEE802;
                    590:                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
                    591:                         break;
                    592: #ifdef IFT_FDDI
                    593:                 case IFT_FDDI:
                    594:                         hw->hlen = sa->sdl_alen + 1;
                    595:                         hw->hbuf[0] = HTYPE_FDDI;
                    596:                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
                    597:                         break;
                    598: #endif /* IFT_FDDI */
                    599:                 default:
                    600:                         log_fatal("Unsupported device type %d for \"%s\"",
                    601:                                   sa->sdl_type, name);
                    602:         }
                    603: 
                    604:        freeifaddrs(ifa);
                    605: }
                    606: #endif

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