Annotation of embedaddon/dhcp/common/bpf.c, revision 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>