common/bpf.c

Go to the documentation of this file.
00001 /* bpf.c
00002 
00003    BPF socket interface code, originally contributed by Archie Cobbs. */
00004 
00005 /*
00006  * Copyright (c) 2009,2012-2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
00008  * Copyright (c) 1996-2003 by Internet Software Consortium
00009  *
00010  * Permission to use, copy, modify, and distribute this software for any
00011  * purpose with or without fee is hereby granted, provided that the above
00012  * copyright notice and this permission notice appear in all copies.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00015  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00016  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00017  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00018  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00019  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00020  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  *   Internet Systems Consortium, Inc.
00023  *   950 Charter Street
00024  *   Redwood City, CA 94063
00025  *   <info@isc.org>
00026  *   https://www.isc.org/
00027  *
00028  * This software was contributed to Internet Systems Consortium
00029  * by Archie Cobbs.
00030  *
00031  * Patches for FDDI support on Digital Unix were written by Bill
00032  * Stapleton, and maintained for a while by Mike Meredith before he
00033  * managed to get me to integrate them.
00034  */
00035 
00036 #include "dhcpd.h"
00037 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \
00038                                 || defined (USE_LPF_RECEIVE)
00039 # if defined (USE_LPF_RECEIVE)
00040 #  include <asm/types.h>
00041 #  include <linux/filter.h>
00042 #  define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */
00043 # else
00044 #  include <sys/ioctl.h>
00045 #  include <sys/uio.h>
00046 #  include <net/bpf.h>
00047 #  if defined (NEED_OSF_PFILT_HACKS)
00048 #   include <net/pfilt.h>
00049 #  endif
00050 # endif
00051 
00052 #include <netinet/in_systm.h>
00053 #include "includes/netinet/ip.h"
00054 #include "includes/netinet/udp.h"
00055 #include "includes/netinet/if_ether.h"
00056 #endif
00057 
00058 #if defined(USE_BPF_SEND) || defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
00059 #include <net/if_types.h>
00060 #include <ifaddrs.h>
00061 #endif
00062 
00063 #include <errno.h>
00064 
00065 /* Reinitializes the specified interface after an address change.   This
00066    is not required for packet-filter APIs. */
00067 
00068 #ifdef USE_BPF_SEND
00069 void if_reinitialize_send (info)
00070         struct interface_info *info;
00071 {
00072 }
00073 #endif
00074 
00075 #ifdef USE_BPF_RECEIVE
00076 void if_reinitialize_receive (info)
00077         struct interface_info *info;
00078 {
00079 }
00080 #endif
00081 
00082 /* Called by get_interface_list for each interface that's discovered.
00083    Opens a packet filter for each interface and adds it to the select
00084    mask. */
00085 
00086 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
00087 int if_register_bpf (info)
00088         struct interface_info *info;
00089 {
00090         int sock;
00091         char filename[50];
00092         int b;
00093 
00094         /* Open a BPF device */
00095         for (b = 0; 1; b++) {
00096                 /* %Audit% 31 bytes max. %2004.06.17,Safe% */
00097                 sprintf(filename, BPF_FORMAT, b);
00098                 sock = open (filename, O_RDWR | O_CLOEXEC, 0);
00099                 if (sock < 0) {
00100                         if (errno == EBUSY) {
00101                                 continue;
00102                         } else {
00103                                 if (!b)
00104                                         log_fatal ("No bpf devices.%s%s%s",
00105                                                "   Please read the README",
00106                                                " section for your operating",
00107                                                " system.");
00108                                 log_fatal ("Can't find free bpf: %m");
00109                         }
00110                 } else {
00111                         break;
00112                 }
00113         }
00114 
00115         /* Set the BPF device to point at this interface. */
00116         if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
00117                 log_fatal ("Can't attach interface %s to bpf device %s: %m",
00118                        info -> name, filename);
00119 
00120         get_hw_addr(info->name, &info->hw_address);
00121 
00122         return sock;
00123 }
00124 #endif /* USE_BPF_SEND || USE_BPF_RECEIVE */
00125 
00126 #ifdef USE_BPF_SEND
00127 void if_register_send (info)
00128         struct interface_info *info;
00129 {
00130         /* If we're using the bpf API for sending and receiving,
00131            we don't need to register this interface twice. */
00132 #ifndef USE_BPF_RECEIVE
00133         info -> wfdesc = if_register_bpf (info, interface);
00134 #else
00135         info -> wfdesc = info -> rfdesc;
00136 #endif
00137         if (!quiet_interface_discovery)
00138                 log_info ("Sending on   BPF/%s/%s%s%s",
00139                       info -> name,
00140                       print_hw_addr (info -> hw_address.hbuf [0],
00141                                      info -> hw_address.hlen - 1,
00142                                      &info -> hw_address.hbuf [1]),
00143                       (info -> shared_network ? "/" : ""),
00144                       (info -> shared_network ?
00145                        info -> shared_network -> name : ""));
00146 }
00147 
00148 void if_deregister_send (info)
00149         struct interface_info *info;
00150 {
00151         /* If we're using the bpf API for sending and receiving,
00152            we don't need to register this interface twice. */
00153 #ifndef USE_BPF_RECEIVE
00154         close (info -> wfdesc);
00155 #endif
00156         info -> wfdesc = -1;
00157 
00158         if (!quiet_interface_discovery)
00159                 log_info ("Disabling output on BPF/%s/%s%s%s",
00160                       info -> name,
00161                       print_hw_addr (info -> hw_address.hbuf [0],
00162                                      info -> hw_address.hlen - 1,
00163                                      &info -> hw_address.hbuf [1]),
00164                       (info -> shared_network ? "/" : ""),
00165                       (info -> shared_network ?
00166                        info -> shared_network -> name : ""));
00167 }
00168 #endif /* USE_BPF_SEND */
00169 
00170 #if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)
00171 /* Packet filter program...
00172    XXX Changes to the filter program may require changes to the constant
00173    offsets used in if_register_send to patch the BPF program! XXX */
00174 
00175 struct bpf_insn dhcp_bpf_filter [] = {
00176         /* Make sure this is an IP packet... */
00177         BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
00178         BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
00179 
00180         /* Make sure it's a UDP packet... */
00181         BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
00182         BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
00183 
00184         /* Make sure this isn't a fragment... */
00185         BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
00186         BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
00187 
00188         /* Get the IP header length... */
00189         BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
00190 
00191         /* Make sure it's to the right port... */
00192         BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
00193         BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),             /* patch */
00194 
00195         /* If we passed all the tests, ask for the whole packet. */
00196         BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
00197 
00198         /* Otherwise, drop it. */
00199         BPF_STMT(BPF_RET+BPF_K, 0),
00200 };
00201 
00202 /* Packet filter program for DHCP over Infiniband.
00203  *
00204  * XXX
00205  * Changes to the filter program may require changes to the constant offsets
00206  * used in lpf_gen_filter_setup to patch the port in the BPF program!
00207  * XXX
00208  */
00209 struct bpf_insn dhcp_ib_bpf_filter [] = {
00210         /* Packet filter for Infiniband */
00211         /* Make sure it's a UDP packet... */
00212         BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
00213         BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
00214 
00215         /* Make sure this isn't a fragment... */
00216         BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
00217         BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
00218 
00219         /* Get the IP header length... */
00220         BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
00221 
00222         /* Make sure it's to the right port... */
00223         BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
00224         BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
00225 
00226         /* If we passed all the tests, ask for the whole packet. */
00227         BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
00228 
00229         /* Otherwise, drop it. */
00230         BPF_STMT(BPF_RET + BPF_K, 0),
00231 };
00232 
00233 #if defined (DEC_FDDI)
00234 struct bpf_insn *bpf_fddi_filter;
00235 #endif
00236 
00237 int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
00238 int dhcp_ib_bpf_filter_len = sizeof dhcp_ib_bpf_filter / sizeof (struct bpf_insn);
00239 
00240 #if defined (HAVE_TR_SUPPORT)
00241 struct bpf_insn dhcp_bpf_tr_filter [] = {
00242         /* accept all token ring packets due to variable length header */
00243         /* if we want to get clever, insert the program here */
00244 
00245         /* If we passed all the tests, ask for the whole packet. */
00246         BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
00247 
00248         /* Otherwise, drop it. */
00249         BPF_STMT(BPF_RET+BPF_K, 0),
00250 };
00251 
00252 int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
00253                               sizeof (struct bpf_insn));
00254 #endif /* HAVE_TR_SUPPORT */
00255 #endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */
00256 
00257 #if defined (USE_BPF_RECEIVE)
00258 void if_register_receive (info)
00259         struct interface_info *info;
00260 {
00261         int flag = 1;
00262         struct bpf_version v;
00263         struct bpf_program p;
00264 #ifdef NEED_OSF_PFILT_HACKS
00265         u_int32_t bits;
00266 #endif
00267 #ifdef DEC_FDDI
00268         int link_layer;
00269 #endif /* DEC_FDDI */
00270 
00271         /* Open a BPF device and hang it on this interface... */
00272         info -> rfdesc = if_register_bpf (info);
00273 
00274         /* Make sure the BPF version is in range... */
00275         if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
00276                 log_fatal ("Can't get BPF version: %m");
00277 
00278         if (v.bv_major != BPF_MAJOR_VERSION ||
00279             v.bv_minor < BPF_MINOR_VERSION)
00280                 log_fatal ("BPF version mismatch - recompile DHCP!");
00281 
00282         /* Set immediate mode so that reads return as soon as a packet
00283            comes in, rather than waiting for the input buffer to fill with
00284            packets. */
00285         if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
00286                 log_fatal ("Can't set immediate mode on bpf device: %m");
00287 
00288 #ifdef NEED_OSF_PFILT_HACKS
00289         /* Allow the copyall flag to be set... */
00290         if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
00291                 log_fatal ("Can't set ALLOWCOPYALL: %m");
00292 
00293         /* Clear all the packet filter mode bits first... */
00294         bits = 0;
00295         if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
00296                 log_fatal ("Can't clear pfilt bits: %m");
00297 
00298         /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */
00299         bits = ENBATCH | ENCOPYALL | ENBPFHDR;
00300         if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
00301                 log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
00302 #endif
00303         /* Get the required BPF buffer length from the kernel. */
00304         if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
00305                 log_fatal ("Can't get bpf buffer length: %m");
00306         info -> rbuf = dmalloc (info -> rbuf_max, MDL);
00307         if (!info -> rbuf)
00308                 log_fatal ("Can't allocate %ld bytes for bpf input buffer.",
00309                            (long)(info -> rbuf_max));
00310         info -> rbuf_offset = 0;
00311         info -> rbuf_len = 0;
00312 
00313         /* Set up the bpf filter program structure. */
00314         p.bf_len = dhcp_bpf_filter_len;
00315 
00316 #ifdef DEC_FDDI
00317         /* See if this is an FDDI interface, flag it for later. */
00318         if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
00319             link_layer == DLT_FDDI) {
00320                 if (!bpf_fddi_filter) {
00321                         bpf_fddi_filter = dmalloc (sizeof bpf_fddi_filter,
00322                                                     MDL);
00323                         if (!bpf_fddi_filter)
00324                                 log_fatal ("No memory for FDDI filter.");
00325                         memcpy (bpf_fddi_filter,
00326                                 dhcp_bpf_filter, sizeof dhcp_bpf_filter);
00327                         /* Patch the BPF program to account for the difference
00328                            in length between ethernet headers (14), FDDI and
00329                            802.2 headers (16 +8=24, +10).
00330                            XXX changes to filter program may require changes to
00331                            XXX the insn number(s) used below! */
00332                         bpf_fddi_filter[0].k += 10;
00333                         bpf_fddi_filter[2].k += 10;
00334                         bpf_fddi_filter[4].k += 10;
00335                         bpf_fddi_filter[6].k += 10;
00336                         bpf_fddi_filter[7].k += 10;
00337                 }
00338                 p.bf_insns = bpf_fddi_filter;
00339         } else
00340 #endif /* DEC_FDDI */
00341         p.bf_insns = dhcp_bpf_filter;
00342 
00343         /* Patch the server port into the BPF  program...
00344            XXX changes to filter program may require changes
00345            to the insn number(s) used below! XXX */
00346         dhcp_bpf_filter [8].k = ntohs (local_port);
00347 
00348         if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
00349                 log_fatal ("Can't install packet filter program: %m");
00350         if (!quiet_interface_discovery)
00351                 log_info ("Listening on BPF/%s/%s%s%s",
00352                       info -> name,
00353                       print_hw_addr (info -> hw_address.hbuf [0],
00354                                      info -> hw_address.hlen - 1,
00355                                      &info -> hw_address.hbuf [1]),
00356                       (info -> shared_network ? "/" : ""),
00357                       (info -> shared_network ?
00358                        info -> shared_network -> name : ""));
00359 }
00360 
00361 void if_deregister_receive (info)
00362         struct interface_info *info;
00363 {
00364         close (info -> rfdesc);
00365         info -> rfdesc = -1;
00366 
00367         if (!quiet_interface_discovery)
00368                 log_info ("Disabling input on BPF/%s/%s%s%s",
00369                       info -> name,
00370                       print_hw_addr (info -> hw_address.hbuf [0],
00371                                      info -> hw_address.hlen - 1,
00372                                      &info -> hw_address.hbuf [1]),
00373                       (info -> shared_network ? "/" : ""),
00374                       (info -> shared_network ?
00375                        info -> shared_network -> name : ""));
00376 }
00377 #endif /* USE_BPF_RECEIVE */
00378 
00379 #ifdef USE_BPF_SEND
00380 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
00381         struct interface_info *interface;
00382         struct packet *packet;
00383         struct dhcp_packet *raw;
00384         size_t len;
00385         struct in_addr from;
00386         struct sockaddr_in *to;
00387         struct hardware *hto;
00388 {
00389         unsigned hbufp = 0, ibufp = 0;
00390         double hw [4];
00391         double ip [32];
00392         struct iovec iov [3];
00393         int result;
00394 
00395         if (!strcmp (interface -> name, "fallback"))
00396                 return send_fallback (interface, packet, raw,
00397                                       len, from, to, hto);
00398 
00399         if (hto == NULL && interface->anycast_mac_addr.hlen)
00400                 hto = &interface->anycast_mac_addr;
00401 
00402         /* Assemble the headers... */
00403         assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
00404         assemble_udp_ip_header (interface,
00405                                 (unsigned char *)ip, &ibufp, from.s_addr,
00406                                 to -> sin_addr.s_addr, to -> sin_port,
00407                                 (unsigned char *)raw, len);
00408 
00409         /* Fire it off */
00410         iov [0].iov_base = ((char *)hw);
00411         iov [0].iov_len = hbufp;
00412         iov [1].iov_base = ((char *)ip);
00413         iov [1].iov_len = ibufp;
00414         iov [2].iov_base = (char *)raw;
00415         iov [2].iov_len = len;
00416 
00417         result = writev(interface -> wfdesc, iov, 3);
00418         if (result < 0)
00419                 log_error ("send_packet: %m");
00420         return result;
00421 }
00422 #endif /* USE_BPF_SEND */
00423 
00424 #ifdef USE_BPF_RECEIVE
00425 ssize_t receive_packet (interface, buf, len, from, hfrom)
00426         struct interface_info *interface;
00427         unsigned char *buf;
00428         size_t len;
00429         struct sockaddr_in *from;
00430         struct hardware *hfrom;
00431 {
00432         int length = 0;
00433         int offset = 0;
00434         struct bpf_hdr hdr;
00435         unsigned paylen;
00436 
00437         /* All this complexity is because BPF doesn't guarantee
00438            that only one packet will be returned at a time.   We're
00439            getting what we deserve, though - this is a terrible abuse
00440            of the BPF interface.   Sigh. */
00441 
00442         /* Process packets until we get one we can return or until we've
00443            done a read and gotten nothing we can return... */
00444 
00445         /* If the buffer is empty, fill it. */
00446         if (interface->rbuf_offset >= interface->rbuf_len) {
00447                 length = read(interface->rfdesc, interface->rbuf,
00448                               (size_t)interface->rbuf_max);
00449                 if (length <= 0) {
00450 #ifdef __FreeBSD__
00451                         if (errno == ENXIO) {
00452 #else
00453                         if (errno == EIO) {
00454 #endif
00455                                 dhcp_interface_remove
00456                                         ((omapi_object_t *)interface, NULL);
00457                         }
00458                         return (length);
00459                 }
00460                 interface->rbuf_offset = 0;
00461                 interface->rbuf_len = BPF_WORDALIGN(length);
00462         }
00463 
00464         do {
00465                 /* If there isn't room for a whole bpf header, something went
00466                    wrong, but we'll ignore it and hope it goes away... XXX */
00467                 if (interface->rbuf_len -
00468                     interface->rbuf_offset < sizeof hdr) {
00469                         interface->rbuf_offset = interface->rbuf_len;
00470                         continue;
00471                 }
00472 
00473                 /* Copy out a bpf header... */
00474                 memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
00475                        sizeof hdr);
00476 
00477                 /* If the bpf header plus data doesn't fit in what's left
00478                    of the buffer, stick head in sand yet again... */
00479                 if (interface->rbuf_offset +
00480                     hdr.bh_hdrlen + hdr.bh_caplen > interface->rbuf_len) {
00481                         interface->rbuf_offset = interface->rbuf_len;
00482                         continue;
00483                 }
00484 
00485                 /* If the captured data wasn't the whole packet, or if
00486                    the packet won't fit in the input buffer, all we
00487                    can do is drop it. */
00488                 if (hdr.bh_caplen != hdr.bh_datalen) {
00489                         interface->rbuf_offset =
00490                                 BPF_WORDALIGN(interface->rbuf_offset +
00491                                               hdr.bh_hdrlen + hdr.bh_caplen);
00492                         continue;
00493                 }
00494 
00495                 /* Skip over the BPF header... */
00496                 interface->rbuf_offset += hdr.bh_hdrlen;
00497 
00498                 /* Decode the physical header... */
00499                 offset = decode_hw_header(interface, interface->rbuf,
00500                                           interface->rbuf_offset, hfrom);
00501 
00502                 /* If a physical layer checksum failed (dunno of any
00503                    physical layer that supports this, but WTH), skip this
00504                    packet. */
00505                 if (offset < 0) {
00506                         interface->rbuf_offset = 
00507                                 BPF_WORDALIGN(interface->rbuf_offset +
00508                                               hdr.bh_caplen);
00509                         continue;
00510                 }
00511                 interface->rbuf_offset += offset;
00512                 hdr.bh_caplen -= offset;
00513 
00514                 /* Decode the IP and UDP headers... */
00515                 offset = decode_udp_ip_header(interface, interface->rbuf,
00516                                                interface->rbuf_offset,
00517                                                from, hdr.bh_caplen, &paylen, 0);
00518 
00519                 /* If the IP or UDP checksum was bad, skip the packet... */
00520                 if (offset < 0) {
00521                         interface->rbuf_offset = 
00522                                 BPF_WORDALIGN(interface->rbuf_offset +
00523                                               hdr.bh_caplen);
00524                         continue;
00525                 }
00526                 interface->rbuf_offset = interface->rbuf_offset + offset;
00527                 hdr.bh_caplen -= offset;
00528 
00529                 /* If there's not enough room to stash the packet data,
00530                    we have to skip it (this shouldn't happen in real
00531                    life, though). */
00532                 if (hdr.bh_caplen > len) {
00533                         interface->rbuf_offset =
00534                                 BPF_WORDALIGN(interface->rbuf_offset +
00535                                                hdr.bh_caplen);
00536                         continue;
00537                 }
00538 
00539                 /* Copy out the data in the packet... */
00540                 memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen);
00541                 interface->rbuf_offset =
00542                         BPF_WORDALIGN(interface->rbuf_offset + hdr.bh_caplen);
00543                 return paylen;
00544         } while (interface->rbuf_offset < interface->rbuf_len);
00545 
00546         return (0);
00547 }
00548 
00549 int can_unicast_without_arp (ip)
00550         struct interface_info *ip;
00551 {
00552         return 1;
00553 }
00554 
00555 int can_receive_unicast_unconfigured (ip)
00556         struct interface_info *ip;
00557 {
00558         return 1;
00559 }
00560 
00561 int supports_multiple_interfaces (ip)
00562         struct interface_info *ip;
00563 {
00564         return 1;
00565 }
00566 
00567 void maybe_setup_fallback ()
00568 {
00569         isc_result_t status;
00570         struct interface_info *fbi = (struct interface_info *)0;
00571         if (setup_fallback (&fbi, MDL)) {
00572                 if_register_fallback (fbi);
00573                 status = omapi_register_io_object ((omapi_object_t *)fbi,
00574                                                    if_readsocket, 0,
00575                                                    fallback_discard, 0, 0);
00576                 if (status != ISC_R_SUCCESS)
00577                         log_fatal ("Can't register I/O handle for %s: %s",
00578                                    fbi -> name, isc_result_totext (status));
00579                 interface_dereference (&fbi, MDL);
00580         }
00581 }
00582 #endif
00583 
00584 #if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
00585 void
00586 get_hw_addr(const char *name, struct hardware *hw) {
00587         struct ifaddrs *ifa;
00588         struct ifaddrs *p;
00589         struct sockaddr_dl *sa;
00590 
00591         if (getifaddrs(&ifa) != 0) {
00592                 log_fatal("Error getting interface information; %m");
00593         }
00594 
00595         /*
00596          * Loop through our interfaces finding a match.
00597          */
00598         sa = NULL;
00599         for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
00600                 if ((p->ifa_addr->sa_family == AF_LINK) && 
00601                     !strcmp(p->ifa_name, name)) {
00602                         sa = (struct sockaddr_dl *)p->ifa_addr;
00603                 }
00604         }
00605         if (sa == NULL) {
00606                 log_fatal("No interface called '%s'", name);
00607         }
00608 
00609         /*
00610          * Pull out the appropriate information.
00611          */
00612         switch (sa->sdl_type) {
00613                 case IFT_ETHER:
00614                         hw->hlen = sa->sdl_alen + 1;
00615                         hw->hbuf[0] = HTYPE_ETHER;
00616                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
00617                         break;
00618                 case IFT_ISO88023:
00619                 case IFT_ISO88024: /* "token ring" */
00620                 case IFT_ISO88025:
00621                 case IFT_ISO88026:
00622                         hw->hlen = sa->sdl_alen + 1;
00623                         hw->hbuf[0] = HTYPE_IEEE802;
00624                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
00625                         break;
00626 #ifdef IFT_FDDI
00627                 case IFT_FDDI:
00628                         hw->hlen = sa->sdl_alen + 1;
00629                         hw->hbuf[0] = HTYPE_FDDI;
00630                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
00631                         break;
00632 #endif /* IFT_FDDI */
00633 #if defined(IFT_PPP)
00634                 case IFT_PPP:
00635                         if (local_family != AF_INET6)
00636                              log_fatal("Unsupported device type %d for \"%s\"",
00637                                         sa->sdl_type, name);
00638                         hw->hlen = 0;
00639                         hw->hbuf[0] = HTYPE_RESERVED;
00640                         /* 0xdeadbeef should never occur on the wire,
00641                          *  and is a signature that something went wrong.
00642                          */
00643                         hw->hbuf[1] = 0xde;
00644                         hw->hbuf[2] = 0xad;
00645                         hw->hbuf[3] = 0xbe;
00646                         hw->hbuf[4] = 0xef;
00647                         break;
00648 #endif
00649                 default:
00650                         log_fatal("Unsupported device type %d for \"%s\"",
00651                                   sa->sdl_type, name);
00652         }
00653 
00654         freeifaddrs(ifa);
00655 }
00656 #endif

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1