1169689Skan/* $NetBSD: bpf.c,v 1.5 2022/04/03 01:10:58 christos Exp $ */ 2169689Skan 3169689Skan/* bpf.c 4169689Skan 5169689Skan BPF socket interface code, originally contributed by Archie Cobbs. */ 6169689Skan 7169689Skan/* 8169689Skan * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC") 9169689Skan * Copyright (c) 1996-2003 by Internet Software Consortium 10169689Skan * 11169689Skan * This Source Code Form is subject to the terms of the Mozilla Public 12169689Skan * License, v. 2.0. If a copy of the MPL was not distributed with this 13169689Skan * file, You can obtain one at http://mozilla.org/MPL/2.0/. 14169689Skan * 15169689Skan * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 16169689Skan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17169689Skan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 18169689Skan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19169689Skan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20169689Skan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21169689Skan * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22169689Skan * 23169689Skan * Internet Systems Consortium, Inc. 24169689Skan * PO Box 360 25169689Skan * Newmarket, NH 03857 USA 26169689Skan * <info@isc.org> 27169689Skan * https://www.isc.org/ 28169689Skan * 29169689Skan * This software was contributed to Internet Systems Consortium 30169689Skan * by Archie Cobbs. 31169689Skan * 32169689Skan * Patches for FDDI support on Digital Unix were written by Bill 33169689Skan * Stapleton, and maintained for a while by Mike Meredith before he 34169689Skan * managed to get me to integrate them. 35169689Skan */ 36169689Skan 37169689Skan#include <sys/cdefs.h> 38169689Skan__RCSID("$NetBSD: bpf.c,v 1.5 2022/04/03 01:10:58 christos Exp $"); 39169689Skan 40169689Skan#include "dhcpd.h" 41169689Skan#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \ 42169689Skan || defined (USE_LPF_RECEIVE) 43169689Skan# if defined (USE_LPF_RECEIVE) 44169689Skan# include <asm/types.h> 45169689Skan# include <linux/filter.h> 46169689Skan# define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */ 47169689Skan# else 48169689Skan# include <sys/ioctl.h> 49169689Skan# include <sys/uio.h> 50169689Skan# include <net/bpf.h> 51169689Skan# if defined (NEED_OSF_PFILT_HACKS) 52169689Skan# include <net/pfilt.h> 53169689Skan# endif 54169689Skan# endif 55169689Skan 56169689Skan#include <sys/param.h> 57169689Skan#include <netinet/in_systm.h> 58169689Skan#include "includes/netinet/ip.h" 59169689Skan#include "includes/netinet/udp.h" 60169689Skan#include "includes/netinet/if_ether.h" 61169689Skan#endif 62169689Skan 63169689Skan#if defined(USE_BPF_SEND) || defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR) 64169689Skan#include <net/if_types.h> 65169689Skan#include <ifaddrs.h> 66169689Skan#endif 67169689Skan 68169689Skan#include <errno.h> 69169689Skan 70169689Skan/* Reinitializes the specified interface after an address change. This 71169689Skan is not required for packet-filter APIs. */ 72169689Skan 73169689Skan#ifdef USE_BPF_SEND 74169689Skanvoid if_reinitialize_send (info) 75169689Skan struct interface_info *info; 76169689Skan{ 77169689Skan} 78169689Skan#endif 79169689Skan 80169689Skan#ifdef USE_BPF_RECEIVE 81169689Skanvoid if_reinitialize_receive (info) 82169689Skan struct interface_info *info; 83169689Skan{ 84169689Skan} 85169689Skan#endif 86169689Skan 87169689Skan/* Called by get_interface_list for each interface that's discovered. 88169689Skan Opens a packet filter for each interface and adds it to the select 89169689Skan mask. */ 90169689Skan 91169689Skan#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) 92169689Skanint if_register_bpf (info) 93169689Skan struct interface_info *info; 94169689Skan{ 95169689Skan int sock; 96169689Skan char filename[50]; 97169689Skan int b; 98169689Skan 99169689Skan /* Open a BPF device */ 100169689Skan for (b = 0; 1; b++) { 101169689Skan /* %Audit% 31 bytes max. %2004.06.17,Safe% */ 102169689Skan sprintf(filename, BPF_FORMAT, b); 103169689Skan sock = open (filename, O_RDWR, 0); 104169689Skan if (sock < 0) { 105169689Skan if (errno == EBUSY) { 106169689Skan continue; 107169689Skan } else { 108169689Skan if (!b) 109169689Skan log_fatal ("No bpf devices.%s%s%s", 110169689Skan " Please read the README", 111169689Skan " section for your operating", 112169689Skan " system."); 113169689Skan log_fatal ("Can't find free bpf: %m"); 114169689Skan } 115169689Skan } else { 116169689Skan break; 117169689Skan } 118169689Skan } 119169689Skan 120169689Skan /* Set the BPF device to point at this interface. */ 121169689Skan if (ioctl (sock, BIOCSETIF, info -> ifp) < 0) 122169689Skan log_fatal ("Can't attach interface %s to bpf device %s: %m", 123169689Skan info -> name, filename); 124169689Skan 125169689Skan get_hw_addr(info->name, &info->hw_address); 126169689Skan 127169689Skan return sock; 128169689Skan} 129169689Skan#endif /* USE_BPF_SEND || USE_BPF_RECEIVE */ 130169689Skan 131169689Skan#ifdef USE_BPF_SEND 132169689Skanvoid if_register_send (info) 133169689Skan struct interface_info *info; 134169689Skan{ 135169689Skan /* If we're using the bpf API for sending and receiving, 136169689Skan we don't need to register this interface twice. */ 137169689Skan#ifndef USE_BPF_RECEIVE 138169689Skan info -> wfdesc = if_register_bpf (info, interface); 139169689Skan#else 140169689Skan info -> wfdesc = info -> rfdesc; 141169689Skan#endif 142169689Skan if (!quiet_interface_discovery) 143169689Skan log_info ("Sending on BPF/%s/%s%s%s", 144169689Skan info -> name, 145169689Skan print_hw_addr (info -> hw_address.hbuf [0], 146169689Skan info -> hw_address.hlen - 1, 147169689Skan &info -> hw_address.hbuf [1]), 148169689Skan (info -> shared_network ? "/" : ""), 149169689Skan (info -> shared_network ? 150169689Skan info -> shared_network -> name : "")); 151169689Skan} 152169689Skan 153169689Skanvoid if_deregister_send (info) 154169689Skan struct interface_info *info; 155169689Skan{ 156169689Skan /* If we're using the bpf API for sending and receiving, 157169689Skan we don't need to register this interface twice. */ 158169689Skan#ifndef USE_BPF_RECEIVE 159169689Skan close (info -> wfdesc); 160169689Skan#endif 161169689Skan info -> wfdesc = -1; 162169689Skan 163169689Skan if (!quiet_interface_discovery) 164169689Skan log_info ("Disabling output on BPF/%s/%s%s%s", 165169689Skan info -> name, 166169689Skan print_hw_addr (info -> hw_address.hbuf [0], 167169689Skan info -> hw_address.hlen - 1, 168169689Skan &info -> hw_address.hbuf [1]), 169169689Skan (info -> shared_network ? "/" : ""), 170169689Skan (info -> shared_network ? 171169689Skan info -> shared_network -> name : "")); 172169689Skan} 173169689Skan#endif /* USE_BPF_SEND */ 174169689Skan 175169689Skan#if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE) 176169689Skan/* Packet filter program... 177169689Skan XXX Changes to the filter program may require changes to the constant 178169689Skan offsets used in if_register_send to patch the BPF program! XXX */ 179169689Skan 180169689Skanstruct bpf_insn dhcp_bpf_filter [] = { 181169689Skan /* Make sure this is an IP packet... */ 182169689Skan BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12), 183169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), 184169689Skan 185169689Skan /* Make sure it's a UDP packet... */ 186169689Skan BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23), 187169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), 188169689Skan 189169689Skan /* Make sure this isn't a fragment... */ 190169689Skan BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), 191169689Skan BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), 192169689Skan 193169689Skan /* Get the IP header length... */ 194169689Skan BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), 195169689Skan 196169689Skan /* Make sure it's to the right port... */ 197169689Skan BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), 198169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ 199169689Skan 200169689Skan /* If we passed all the tests, ask for the whole packet. */ 201169689Skan BPF_STMT (BPF_RET + BPF_K, (u_int)-1), 202169689Skan 203169689Skan /* Otherwise, drop it. */ 204169689Skan BPF_STMT (BPF_RET + BPF_K, 0), 205169689Skan}; 206169689Skan 207169689Skan#if defined(RELAY_PORT) 208169689Skan/* 209169689Skan * For relay port extension 210169689Skan */ 211169689Skanstruct bpf_insn dhcp_bpf_relay_filter [] = { 212169689Skan /* Make sure this is an IP packet... */ 213169689Skan BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12), 214169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10), 215169689Skan 216169689Skan /* Make sure it's a UDP packet... */ 217169689Skan BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23), 218169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8), 219169689Skan 220169689Skan /* Make sure this isn't a fragment... */ 221169689Skan BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), 222169689Skan BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), 223169689Skan 224169689Skan /* Get the IP header length... */ 225169689Skan BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), 226169689Skan 227169689Skan /* Make sure it's to the right port... */ 228169689Skan BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), 229169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 2, 0), /* patch */ 230169689Skan 231169689Skan /* relay can have an alternative port... */ 232169689Skan BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), 233169689Skan BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ 234169689Skan 235169689Skan /* If we passed all the tests, ask for the whole packet. */ 236169689Skan BPF_STMT (BPF_RET + BPF_K, (u_int)-1), 237169689Skan 238169689Skan /* Otherwise, drop it. */ 239169689Skan BPF_STMT (BPF_RET + BPF_K, 0), 240169689Skan}; 241169689Skan 242169689Skanint dhcp_bpf_relay_filter_len = 243169689Skan sizeof dhcp_bpf_relay_filter / sizeof (struct bpf_insn); 244169689Skan#endif 245169689Skan 246169689Skan#if defined (DEC_FDDI) 247169689Skanstruct bpf_insn *bpf_fddi_filter = NULL; 248169689Skan#endif 249169689Skan 250169689Skanint dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn); 251169689Skan#if defined (HAVE_TR_SUPPORT) 252169689Skanstruct bpf_insn dhcp_bpf_tr_filter [] = { 253169689Skan /* accept all token ring packets due to variable length header */ 254169689Skan /* if we want to get clever, insert the program here */ 255169689Skan 256169689Skan /* If we passed all the tests, ask for the whole packet. */ 257169689Skan BPF_STMT(BPF_RET+BPF_K, (u_int)-1), 258169689Skan 259169689Skan /* Otherwise, drop it. */ 260169689Skan BPF_STMT(BPF_RET+BPF_K, 0), 261169689Skan}; 262169689Skan 263169689Skanint dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter / 264169689Skan sizeof (struct bpf_insn)); 265169689Skan#endif /* HAVE_TR_SUPPORT */ 266169689Skan#endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */ 267169689Skan 268169689Skan#if defined (USE_BPF_RECEIVE) 269169689Skanvoid if_register_receive (info) 270169689Skan struct interface_info *info; 271169689Skan{ 272169689Skan int flag = 1; 273169689Skan struct bpf_version v; 274169689Skan struct bpf_program p; 275169689Skan#ifdef NEED_OSF_PFILT_HACKS 276169689Skan u_int32_t bits; 277169689Skan#endif 278169689Skan#ifdef DEC_FDDI 279169689Skan int link_layer; 280169689Skan#endif /* DEC_FDDI */ 281169689Skan 282169689Skan /* Open a BPF device and hang it on this interface... */ 283169689Skan info -> rfdesc = if_register_bpf (info); 284169689Skan 285169689Skan /* Make sure the BPF version is in range... */ 286169689Skan if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0) 287169689Skan log_fatal ("Can't get BPF version: %m"); 288169689Skan 289169689Skan if (v.bv_major != BPF_MAJOR_VERSION || 290169689Skan v.bv_minor < BPF_MINOR_VERSION) 291169689Skan log_fatal ("BPF version mismatch - recompile DHCP!"); 292169689Skan 293169689Skan /* Set immediate mode so that reads return as soon as a packet 294169689Skan comes in, rather than waiting for the input buffer to fill with 295169689Skan packets. */ 296169689Skan if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0) 297169689Skan log_fatal ("Can't set immediate mode on bpf device: %m"); 298169689Skan 299169689Skan#ifdef NEED_OSF_PFILT_HACKS 300169689Skan /* Allow the copyall flag to be set... */ 301169689Skan if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0) 302169689Skan log_fatal ("Can't set ALLOWCOPYALL: %m"); 303169689Skan 304169689Skan /* Clear all the packet filter mode bits first... */ 305169689Skan bits = 0; 306169689Skan if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) 307169689Skan log_fatal ("Can't clear pfilt bits: %m"); 308169689Skan 309169689Skan /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */ 310169689Skan bits = ENBATCH | ENCOPYALL | ENBPFHDR; 311169689Skan if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) 312169689Skan log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m"); 313169689Skan#endif 314169689Skan /* Get the required BPF buffer length from the kernel. */ 315169689Skan if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0) 316169689Skan log_fatal ("Can't get bpf buffer length: %m"); 317169689Skan info -> rbuf = dmalloc (info -> rbuf_max, MDL); 318169689Skan if (!info -> rbuf) 319169689Skan log_fatal ("Can't allocate %ld bytes for bpf input buffer.", 320169689Skan (long)(info -> rbuf_max)); 321169689Skan info -> rbuf_offset = 0; 322169689Skan info -> rbuf_len = 0; 323169689Skan 324169689Skan /* Set up the bpf filter program structure. */ 325169689Skan p.bf_len = dhcp_bpf_filter_len; 326169689Skan 327169689Skan#ifdef DEC_FDDI 328169689Skan /* See if this is an FDDI interface, flag it for later. */ 329169689Skan if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 && 330169689Skan link_layer == DLT_FDDI) { 331169689Skan if (!bpf_fddi_filter) { 332169689Skan bpf_fddi_filter = dmalloc (sizeof dhcp_bpf_filter, 333169689Skan MDL); 334169689Skan if (!bpf_fddi_filter) 335169689Skan log_fatal ("No memory for FDDI filter."); 336169689Skan memcpy (bpf_fddi_filter, 337169689Skan dhcp_bpf_filter, sizeof dhcp_bpf_filter); 338169689Skan /* Patch the BPF program to account for the difference 339169689Skan in length between ethernet headers (14), FDDI and 340169689Skan 802.2 headers (16 +8=24, +10). 341169689Skan XXX changes to filter program may require changes to 342169689Skan XXX the insn number(s) used below! */ 343169689Skan bpf_fddi_filter[0].k += 10; 344169689Skan bpf_fddi_filter[2].k += 10; 345169689Skan bpf_fddi_filter[4].k += 10; 346169689Skan bpf_fddi_filter[6].k += 10; 347169689Skan bpf_fddi_filter[7].k += 10; 348169689Skan } 349169689Skan p.bf_insns = bpf_fddi_filter; 350169689Skan } else 351169689Skan#endif /* DEC_FDDI */ 352169689Skan p.bf_insns = dhcp_bpf_filter; 353169689Skan 354169689Skan /* Patch the server port into the BPF program... 355169689Skan XXX changes to filter program may require changes 356169689Skan to the insn number(s) used below! XXX */ 357169689Skan#if defined(RELAY_PORT) 358169689Skan if (relay_port) { 359169689Skan /* 360169689Skan * If user defined relay UDP port, we need to filter 361169689Skan * also on the user UDP port. 362169689Skan */ 363169689Skan p.bf_len = dhcp_bpf_relay_filter_len; 364169689Skan p.bf_insns = dhcp_bpf_relay_filter; 365169689Skan 366169689Skan dhcp_bpf_relay_filter [10].k = ntohs (relay_port); 367169689Skan } 368169689Skan#endif 369169689Skan p.bf_insns [8].k = ntohs (*libdhcp_callbacks.local_port); 370169689Skan 371169689Skan if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0) 372169689Skan log_fatal ("Can't install packet filter program: %m"); 373169689Skan if (!quiet_interface_discovery) 374169689Skan log_info ("Listening on BPF/%s/%s%s%s", 375169689Skan info -> name, 376169689Skan print_hw_addr (info -> hw_address.hbuf [0], 377169689Skan info -> hw_address.hlen - 1, 378169689Skan &info -> hw_address.hbuf [1]), 379169689Skan (info -> shared_network ? "/" : ""), 380169689Skan (info -> shared_network ? 381169689Skan info -> shared_network -> name : "")); 382169689Skan} 383169689Skan 384169689Skanvoid if_deregister_receive (info) 385169689Skan struct interface_info *info; 386169689Skan{ 387169689Skan close (info -> rfdesc); 388169689Skan info -> rfdesc = -1; 389169689Skan 390169689Skan if (!quiet_interface_discovery) 391169689Skan log_info ("Disabling input on BPF/%s/%s%s%s", 392169689Skan info -> name, 393169689Skan print_hw_addr (info -> hw_address.hbuf [0], 394169689Skan info -> hw_address.hlen - 1, 395169689Skan &info -> hw_address.hbuf [1]), 396169689Skan (info -> shared_network ? "/" : ""), 397169689Skan (info -> shared_network ? 398169689Skan info -> shared_network -> name : "")); 399169689Skan} 400169689Skan#endif /* USE_BPF_RECEIVE */ 401169689Skan 402169689Skan#ifdef USE_BPF_SEND 403169689Skanssize_t send_packet (interface, packet, raw, len, from, to, hto) 404169689Skan struct interface_info *interface; 405169689Skan struct packet *packet; 406169689Skan struct dhcp_packet *raw; 407169689Skan size_t len; 408169689Skan struct in_addr from; 409169689Skan struct sockaddr_in *to; 410169689Skan struct hardware *hto; 411169689Skan{ 412169689Skan unsigned hbufp = 0, ibufp = 0; 413169689Skan double hw [4]; 414169689Skan double ip [32]; 415169689Skan struct iovec iov [3]; 416169689Skan int result; 417169689Skan 418169689Skan if (!strcmp (interface -> name, "fallback")) 419169689Skan return send_fallback (interface, packet, raw, 420169689Skan len, from, to, hto); 421169689Skan 422169689Skan if (hto == NULL && interface->anycast_mac_addr.hlen) 423169689Skan hto = &interface->anycast_mac_addr; 424169689Skan 425169689Skan /* Assemble the headers... */ 426169689Skan assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto); 427169689Skan assemble_udp_ip_header (interface, 428169689Skan (unsigned char *)ip, &ibufp, from.s_addr, 429169689Skan to -> sin_addr.s_addr, to -> sin_port, 430169689Skan (unsigned char *)raw, len); 431169689Skan 432169689Skan /* Fire it off */ 433169689Skan iov [0].iov_base = ((char *)hw); 434169689Skan iov [0].iov_len = hbufp; 435169689Skan iov [1].iov_base = ((char *)ip); 436169689Skan iov [1].iov_len = ibufp; 437169689Skan iov [2].iov_base = (char *)raw; 438169689Skan iov [2].iov_len = len; 439169689Skan 440169689Skan result = writev(interface -> wfdesc, iov, 3); 441169689Skan if (result < 0) 442169689Skan log_error ("send_packet: %m"); 443169689Skan return result; 444169689Skan} 445169689Skan#endif /* USE_BPF_SEND */ 446169689Skan 447169689Skan#ifdef USE_BPF_RECEIVE 448169689Skanssize_t receive_packet (interface, buf, len, from, hfrom) 449169689Skan struct interface_info *interface; 450169689Skan unsigned char *buf; 451169689Skan size_t len; 452169689Skan struct sockaddr_in *from; 453169689Skan struct hardware *hfrom; 454169689Skan{ 455169689Skan int length = 0; 456169689Skan int offset = 0; 457169689Skan struct bpf_hdr hdr; 458169689Skan unsigned paylen; 459169689Skan 460169689Skan /* All this complexity is because BPF doesn't guarantee 461169689Skan that only one packet will be returned at a time. We're 462169689Skan getting what we deserve, though - this is a terrible abuse 463169689Skan of the BPF interface. Sigh. */ 464169689Skan 465169689Skan /* Process packets until we get one we can return or until we've 466169689Skan done a read and gotten nothing we can return... */ 467169689Skan 468169689Skan /* If the buffer is empty, fill it. */ 469169689Skan if (interface->rbuf_offset >= interface->rbuf_len) { 470169689Skan length = read(interface->rfdesc, interface->rbuf, 471169689Skan (size_t)interface->rbuf_max); 472169689Skan if (length <= 0) { 473169689Skan#ifdef __FreeBSD__ 474169689Skan if (errno == ENXIO) { 475169689Skan#else 476169689Skan if (errno == EIO) { 477169689Skan#endif 478169689Skan dhcp_interface_remove 479169689Skan ((omapi_object_t *)interface, NULL); 480169689Skan } 481169689Skan return (length); 482169689Skan } 483169689Skan interface->rbuf_offset = 0; 484169689Skan interface->rbuf_len = BPF_WORDALIGN(length); 485169689Skan } 486169689Skan 487169689Skan do { 488169689Skan /* If there isn't room for a whole bpf header, something went 489169689Skan wrong, but we'll ignore it and hope it goes away... XXX */ 490169689Skan if (interface->rbuf_len - 491169689Skan interface->rbuf_offset < sizeof hdr) { 492169689Skan interface->rbuf_offset = interface->rbuf_len; 493169689Skan continue; 494169689Skan } 495169689Skan 496169689Skan /* Copy out a bpf header... */ 497169689Skan memcpy(&hdr, &interface->rbuf[interface->rbuf_offset], 498169689Skan sizeof hdr); 499169689Skan 500169689Skan /* If the bpf header plus data doesn't fit in what's left 501169689Skan of the buffer, stick head in sand yet again... */ 502169689Skan if (interface->rbuf_offset + 503169689Skan hdr.bh_hdrlen + hdr.bh_caplen > interface->rbuf_len) { 504169689Skan interface->rbuf_offset = interface->rbuf_len; 505169689Skan continue; 506169689Skan } 507169689Skan 508169689Skan /* If the captured data wasn't the whole packet, or if 509169689Skan the packet won't fit in the input buffer, all we 510169689Skan can do is drop it. */ 511169689Skan if (hdr.bh_caplen != hdr.bh_datalen) { 512169689Skan interface->rbuf_offset = 513169689Skan BPF_WORDALIGN(interface->rbuf_offset + 514169689Skan hdr.bh_hdrlen + hdr.bh_caplen); 515169689Skan continue; 516169689Skan } 517169689Skan 518169689Skan /* Skip over the BPF header... */ 519169689Skan interface->rbuf_offset += hdr.bh_hdrlen; 520169689Skan 521169689Skan /* Decode the physical header... */ 522169689Skan offset = decode_hw_header(interface, interface->rbuf, 523169689Skan interface->rbuf_offset, hfrom); 524169689Skan 525169689Skan /* If a physical layer checksum failed (dunno of any 526169689Skan physical layer that supports this, but WTH), skip this 527169689Skan packet. */ 528169689Skan if (offset < 0) { 529169689Skan interface->rbuf_offset = 530169689Skan BPF_WORDALIGN(interface->rbuf_offset + 531169689Skan hdr.bh_caplen); 532169689Skan continue; 533169689Skan } 534169689Skan interface->rbuf_offset += offset; 535169689Skan hdr.bh_caplen -= offset; 536169689Skan 537169689Skan /* Decode the IP and UDP headers... */ 538169689Skan offset = decode_udp_ip_header(interface, interface->rbuf, 539169689Skan interface->rbuf_offset, 540169689Skan from, hdr.bh_caplen, &paylen, 1); 541169689Skan 542169689Skan /* If the IP or UDP checksum was bad, skip the packet... */ 543169689Skan if (offset < 0) { 544169689Skan interface->rbuf_offset = 545169689Skan BPF_WORDALIGN(interface->rbuf_offset + 546169689Skan hdr.bh_caplen); 547169689Skan continue; 548169689Skan } 549169689Skan interface->rbuf_offset = interface->rbuf_offset + offset; 550169689Skan hdr.bh_caplen -= offset; 551169689Skan 552169689Skan /* If there's not enough room to stash the packet data, 553169689Skan we have to skip it (this shouldn't happen in real 554169689Skan life, though). */ 555169689Skan if (hdr.bh_caplen > len) { 556169689Skan interface->rbuf_offset = 557169689Skan BPF_WORDALIGN(interface->rbuf_offset + 558169689Skan hdr.bh_caplen); 559169689Skan continue; 560169689Skan } 561169689Skan 562169689Skan /* Copy out the data in the packet... */ 563169689Skan memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen); 564169689Skan interface->rbuf_offset = 565169689Skan BPF_WORDALIGN(interface->rbuf_offset + hdr.bh_caplen); 566169689Skan return paylen; 567169689Skan } while (interface->rbuf_offset < interface->rbuf_len); 568169689Skan 569169689Skan return (0); 570169689Skan} 571169689Skan 572169689Skanint can_unicast_without_arp (ip) 573169689Skan struct interface_info *ip; 574169689Skan{ 575169689Skan return 1; 576169689Skan} 577169689Skan 578169689Skanint can_receive_unicast_unconfigured (ip) 579169689Skan struct interface_info *ip; 580169689Skan{ 581169689Skan return 1; 582169689Skan} 583169689Skan 584169689Skanint supports_multiple_interfaces (ip) 585169689Skan struct interface_info *ip; 586169689Skan{ 587169689Skan return 1; 588169689Skan} 589169689Skan 590169689Skanvoid maybe_setup_fallback () 591169689Skan{ 592169689Skan isc_result_t status; 593169689Skan struct interface_info *fbi = (struct interface_info *)0; 594169689Skan if (setup_fallback (&fbi, MDL)) { 595169689Skan if_register_fallback (fbi); 596169689Skan status = omapi_register_io_object ((omapi_object_t *)fbi, 597169689Skan if_readsocket, 0, 598169689Skan fallback_discard, 0, 0); 599169689Skan if (status != ISC_R_SUCCESS) 600169689Skan log_fatal ("Can't register I/O handle for %s: %s", 601169689Skan fbi -> name, isc_result_totext (status)); 602169689Skan interface_dereference (&fbi, MDL); 603169689Skan } 604169689Skan} 605169689Skan 606169689Skan#endif 607169689Skan 608169689Skan#if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR) 609169689Skanstatic int 610169689Skanlladdr_active(int s, const char *name, const struct ifaddrs *ifa) 611169689Skan{ 612169689Skan if (ifa->ifa_addr->sa_family != AF_LINK) 613169689Skan return 0; 614169689Skan if (strcmp(ifa->ifa_name, name) != 0) 615169689Skan return 0; 616169689Skan 617169689Skan#ifdef SIOCGLIFADDR 618169689Skan{ 619169689Skan struct if_laddrreq iflr; 620169689Skan const struct sockaddr_dl *sdl; 621169689Skan 622169689Skan sdl = satocsdl(ifa->ifa_addr); 623169689Skan memset(&iflr, 0, sizeof(iflr)); 624169689Skan 625169689Skan strlcpy(iflr.iflr_name, ifa->ifa_name, sizeof(iflr.iflr_name)); 626169689Skan memcpy(&iflr.addr, ifa->ifa_addr, MIN(ifa->ifa_addr->sa_len, 627169689Skan sizeof(iflr.addr))); 628169689Skan iflr.flags = IFLR_PREFIX; 629169689Skan iflr.prefixlen = sdl->sdl_alen * NBBY; 630169689Skan 631169689Skan if (ioctl(s, SIOCGLIFADDR, &iflr) == -1) { 632169689Skan log_fatal("ioctl(SIOCGLIFADDR): %m"); 633169689Skan } 634169689Skan 635169689Skan if ((iflr.flags & IFLR_ACTIVE) == 0) 636169689Skan return 0; 637169689Skan} 638169689Skan#endif 639169689Skan return 1; 640169689Skan} 641169689Skan 642169689Skanvoid 643169689Skanget_hw_addr(const char *name, struct hardware *hw) { 644169689Skan struct ifaddrs *ifa; 645169689Skan struct ifaddrs *p; 646169689Skan struct sockaddr_dl *sa; 647169689Skan int s; 648169689Skan 649169689Skan if ((s = socket(AF_LINK, SOCK_DGRAM, 0)) == -1) { 650169689Skan log_fatal("socket AF_LINK: %m"); 651169689Skan } 652169689Skan 653169689Skan if (getifaddrs(&ifa) != 0) { 654169689Skan log_fatal("Error getting interface information; %m"); 655169689Skan } 656169689Skan 657169689Skan /* 658169689Skan * Loop through our interfaces finding a match. 659169689Skan */ 660169689Skan sa = NULL; 661169689Skan for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) { 662169689Skan if (lladdr_active(s, name, p)) { 663169689Skan sa = (struct sockaddr_dl *)p->ifa_addr; 664169689Skan break; 665169689Skan } 666169689Skan } 667169689Skan if (sa == NULL) { 668169689Skan log_fatal("No interface called '%s'", name); 669169689Skan } 670169689Skan close(s); 671169689Skan 672169689Skan /* 673169689Skan * Pull out the appropriate information. 674169689Skan */ 675169689Skan switch (sa->sdl_type) { 676169689Skan case IFT_ETHER: 677169689Skan#ifdef IFT_CARP 678169689Skan case IFT_CARP: 679169689Skan#endif 680169689Skan#if defined (IFT_L2VLAN) 681169689Skan case IFT_L2VLAN: 682169689Skan#endif 683169689Skan hw->hlen = sa->sdl_alen + 1; 684169689Skan hw->hbuf[0] = HTYPE_ETHER; 685169689Skan memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen); 686169689Skan break; 687169689Skan case IFT_ISO88023: 688169689Skan case IFT_ISO88024: /* "token ring" */ 689169689Skan case IFT_ISO88025: 690169689Skan case IFT_ISO88026: 691169689Skan hw->hlen = sa->sdl_alen + 1; 692169689Skan hw->hbuf[0] = HTYPE_IEEE802; 693169689Skan memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen); 694169689Skan break; 695169689Skan#ifdef IFT_FDDI 696169689Skan case IFT_FDDI: 697169689Skan hw->hlen = sa->sdl_alen + 1; 698169689Skan hw->hbuf[0] = HTYPE_FDDI; 699169689Skan memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen); 700169689Skan break; 701169689Skan#endif /* IFT_FDDI */ 702169689Skan default: 703169689Skan log_fatal("Unsupported device type %d for \"%s\"", 704169689Skan sa->sdl_type, name); 705169689Skan } 706169689Skan 707169689Skan freeifaddrs(ifa); 708169689Skan} 709169689Skan#endif 710169689Skan