1 /* $NetBSD: lpf.c,v 1.4 2022/04/03 01:10:58 christos Exp $ */ 2 3 /* lpf.c 4 5 Linux packet filter code, contributed by Brian Murrel at Interlinx 6 Support Services in Vancouver, B.C. */ 7 8 /* 9 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC") 10 * Copyright (c) 1996-2003 by Internet Software Consortium 11 * 12 * This Source Code Form is subject to the terms of the Mozilla Public 13 * License, v. 2.0. If a copy of the MPL was not distributed with this 14 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 22 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23 * 24 * Internet Systems Consortium, Inc. 25 * PO Box 360 26 * Newmarket, NH 03857 USA 27 * <info@isc.org> 28 * https://www.isc.org/ 29 */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: lpf.c,v 1.4 2022/04/03 01:10:58 christos Exp $"); 33 34 #include "dhcpd.h" 35 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) 36 #include <sys/uio.h> 37 #include <errno.h> 38 39 #include <asm/types.h> 40 #include <linux/filter.h> 41 #include <linux/if_ether.h> 42 #include <linux/if_packet.h> 43 #include <netinet/in_systm.h> 44 #include "includes/netinet/ip.h" 45 #include "includes/netinet/udp.h" 46 #include "includes/netinet/if_ether.h" 47 #endif 48 49 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR) 50 #include <sys/ioctl.h> 51 #include <sys/socket.h> 52 #include <net/if.h> 53 #endif 54 55 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) 56 /* Reinitializes the specified interface after an address change. This 57 is not required for packet-filter APIs. */ 58 59 #ifdef USE_LPF_SEND 60 void if_reinitialize_send (info) 61 struct interface_info *info; 62 { 63 } 64 #endif 65 66 #ifdef USE_LPF_RECEIVE 67 void if_reinitialize_receive (info) 68 struct interface_info *info; 69 { 70 } 71 #endif 72 73 /* Called by get_interface_list for each interface that's discovered. 74 Opens a packet filter for each interface and adds it to the select 75 mask. */ 76 77 int if_register_lpf (info) 78 struct interface_info *info; 79 { 80 int sock; 81 union { 82 struct sockaddr_ll ll; 83 struct sockaddr common; 84 } sa; 85 struct ifreq ifr; 86 87 /* Make an LPF socket. */ 88 if ((sock = socket(PF_PACKET, SOCK_RAW, 89 htons((short)ETH_P_ALL))) < 0) { 90 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || 91 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || 92 errno == EAFNOSUPPORT || errno == EINVAL) { 93 log_error ("socket: %m - make sure"); 94 log_error ("CONFIG_PACKET (Packet socket) %s", 95 "and CONFIG_FILTER"); 96 log_error ("(Socket Filtering) are enabled %s", 97 "in your kernel"); 98 log_fatal ("configuration!"); 99 } 100 log_fatal ("Open a socket for LPF: %m"); 101 } 102 103 memset (&ifr, 0, sizeof ifr); 104 strncpy (ifr.ifr_name, (const char *)info -> ifp, sizeof ifr.ifr_name); 105 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 106 if (ioctl (sock, SIOCGIFINDEX, &ifr)) 107 log_fatal ("Failed to get interface index: %m"); 108 109 /* Bind to the interface name */ 110 memset (&sa, 0, sizeof sa); 111 sa.ll.sll_family = AF_PACKET; 112 sa.ll.sll_ifindex = ifr.ifr_ifindex; 113 if (bind (sock, &sa.common, sizeof sa)) { 114 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || 115 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || 116 errno == EAFNOSUPPORT || errno == EINVAL) { 117 log_error ("socket: %m - make sure"); 118 log_error ("CONFIG_PACKET (Packet socket) %s", 119 "and CONFIG_FILTER"); 120 log_error ("(Socket Filtering) are enabled %s", 121 "in your kernel"); 122 log_fatal ("configuration!"); 123 } 124 log_fatal ("Bind socket to interface: %m"); 125 126 } 127 128 get_hw_addr(info->name, &info->hw_address); 129 130 return sock; 131 } 132 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */ 133 134 #ifdef USE_LPF_SEND 135 void if_register_send (info) 136 struct interface_info *info; 137 { 138 /* If we're using the lpf API for sending and receiving, 139 we don't need to register this interface twice. */ 140 #ifndef USE_LPF_RECEIVE 141 info -> wfdesc = if_register_lpf (info); 142 #else 143 info -> wfdesc = info -> rfdesc; 144 #endif 145 if (!quiet_interface_discovery) 146 log_info ("Sending on LPF/%s/%s%s%s", 147 info -> name, 148 print_hw_addr (info -> hw_address.hbuf [0], 149 info -> hw_address.hlen - 1, 150 &info -> hw_address.hbuf [1]), 151 (info -> shared_network ? "/" : ""), 152 (info -> shared_network ? 153 info -> shared_network -> name : "")); 154 } 155 156 void if_deregister_send (info) 157 struct interface_info *info; 158 { 159 /* don't need to close twice if we are using lpf for sending and 160 receiving */ 161 #ifndef USE_LPF_RECEIVE 162 /* for LPF this is simple, packet filters are removed when sockets 163 are closed */ 164 close (info -> wfdesc); 165 #endif 166 info -> wfdesc = -1; 167 if (!quiet_interface_discovery) 168 log_info ("Disabling output on LPF/%s/%s%s%s", 169 info -> name, 170 print_hw_addr (info -> hw_address.hbuf [0], 171 info -> hw_address.hlen - 1, 172 &info -> hw_address.hbuf [1]), 173 (info -> shared_network ? "/" : ""), 174 (info -> shared_network ? 175 info -> shared_network -> name : "")); 176 } 177 #endif /* USE_LPF_SEND */ 178 179 #ifdef USE_LPF_RECEIVE 180 /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling 181 in bpf includes... */ 182 extern struct sock_filter dhcp_bpf_filter []; 183 extern int dhcp_bpf_filter_len; 184 185 #if defined(RELAY_PORT) 186 extern struct sock_filter dhcp_bpf_relay_filter []; 187 extern int dhcp_bpf_relay_filter_len; 188 #endif 189 190 #if defined (HAVE_TR_SUPPORT) 191 extern struct sock_filter dhcp_bpf_tr_filter []; 192 extern int dhcp_bpf_tr_filter_len; 193 static void lpf_tr_filter_setup (struct interface_info *); 194 #endif 195 196 static void lpf_gen_filter_setup (struct interface_info *); 197 198 void if_register_receive (info) 199 struct interface_info *info; 200 { 201 /* Open a LPF device and hang it on this interface... */ 202 info -> rfdesc = if_register_lpf (info); 203 204 #ifdef PACKET_AUXDATA 205 { 206 int val = 1; 207 208 if (setsockopt(info->rfdesc, SOL_PACKET, PACKET_AUXDATA, 209 &val, sizeof(val)) < 0) { 210 if (errno != ENOPROTOOPT) { 211 log_fatal ("Failed to set auxiliary packet data: %m"); 212 } 213 } 214 } 215 #endif 216 217 218 #if defined (HAVE_TR_SUPPORT) 219 if (info -> hw_address.hbuf [0] == HTYPE_IEEE802) 220 lpf_tr_filter_setup (info); 221 else 222 #endif 223 lpf_gen_filter_setup (info); 224 225 if (!quiet_interface_discovery) 226 log_info ("Listening on LPF/%s/%s%s%s", 227 info -> name, 228 print_hw_addr (info -> hw_address.hbuf [0], 229 info -> hw_address.hlen - 1, 230 &info -> hw_address.hbuf [1]), 231 (info -> shared_network ? "/" : ""), 232 (info -> shared_network ? 233 info -> shared_network -> name : "")); 234 } 235 236 void if_deregister_receive (info) 237 struct interface_info *info; 238 { 239 /* for LPF this is simple, packet filters are removed when sockets 240 are closed */ 241 close (info -> rfdesc); 242 info -> rfdesc = -1; 243 if (!quiet_interface_discovery) 244 log_info ("Disabling input on LPF/%s/%s%s%s", 245 info -> name, 246 print_hw_addr (info -> hw_address.hbuf [0], 247 info -> hw_address.hlen - 1, 248 &info -> hw_address.hbuf [1]), 249 (info -> shared_network ? "/" : ""), 250 (info -> shared_network ? 251 info -> shared_network -> name : "")); 252 } 253 254 static void lpf_gen_filter_setup (info) 255 struct interface_info *info; 256 { 257 struct sock_fprog p; 258 259 memset(&p, 0, sizeof(p)); 260 261 /* Set up the bpf filter program structure. This is defined in 262 bpf.c */ 263 p.len = dhcp_bpf_filter_len; 264 p.filter = dhcp_bpf_filter; 265 266 /* Patch the server port into the LPF program... 267 XXX changes to filter program may require changes 268 to the insn number(s) used below! XXX */ 269 #if defined(RELAY_PORT) 270 if (relay_port) { 271 /* 272 * If user defined relay UDP port, we need to filter 273 * also on the user UDP port. 274 */ 275 p.len = dhcp_bpf_relay_filter_len; 276 p.filter = dhcp_bpf_relay_filter; 277 278 dhcp_bpf_relay_filter [10].k = ntohs (relay_port); 279 } 280 #endif 281 dhcp_bpf_filter [8].k = ntohs (*libdhcp_callbacks.local_port); 282 283 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, 284 sizeof p) < 0) { 285 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || 286 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || 287 errno == EAFNOSUPPORT) { 288 log_error ("socket: %m - make sure"); 289 log_error ("CONFIG_PACKET (Packet socket) %s", 290 "and CONFIG_FILTER"); 291 log_error ("(Socket Filtering) are enabled %s", 292 "in your kernel"); 293 log_fatal ("configuration!"); 294 } 295 log_fatal ("Can't install packet filter program: %m"); 296 } 297 } 298 299 #if defined (HAVE_TR_SUPPORT) 300 static void lpf_tr_filter_setup (info) 301 struct interface_info *info; 302 { 303 struct sock_fprog p; 304 305 memset(&p, 0, sizeof(p)); 306 307 /* Set up the bpf filter program structure. This is defined in 308 bpf.c */ 309 p.len = dhcp_bpf_tr_filter_len; 310 p.filter = dhcp_bpf_tr_filter; 311 312 /* Patch the server port into the LPF program... 313 XXX changes to filter program may require changes 314 XXX to the insn number(s) used below! 315 XXX Token ring filter is null - when/if we have a filter 316 XXX that's not, we'll need this code. 317 XXX dhcp_bpf_filter [?].k = ntohs (*libdhcp_callbacks.local_port); */ 318 319 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, 320 sizeof p) < 0) { 321 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || 322 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || 323 errno == EAFNOSUPPORT) { 324 log_error ("socket: %m - make sure"); 325 log_error ("CONFIG_PACKET (Packet socket) %s", 326 "and CONFIG_FILTER"); 327 log_error ("(Socket Filtering) are enabled %s", 328 "in your kernel"); 329 log_fatal ("configuration!"); 330 } 331 log_fatal ("Can't install packet filter program: %m"); 332 } 333 } 334 #endif /* HAVE_TR_SUPPORT */ 335 #endif /* USE_LPF_RECEIVE */ 336 337 #ifdef USE_LPF_SEND 338 ssize_t send_packet (interface, packet, raw, len, from, to, hto) 339 struct interface_info *interface; 340 struct packet *packet; 341 struct dhcp_packet *raw; 342 size_t len; 343 struct in_addr from; 344 struct sockaddr_in *to; 345 struct hardware *hto; 346 { 347 unsigned hbufp = 0, ibufp = 0; 348 double hh [16]; 349 double ih [1536 / sizeof (double)]; 350 unsigned char *buf = (unsigned char *)ih; 351 int result; 352 int fudge; 353 354 if (!strcmp (interface -> name, "fallback")) 355 return send_fallback (interface, packet, raw, 356 len, from, to, hto); 357 358 if (hto == NULL && interface->anycast_mac_addr.hlen) 359 hto = &interface->anycast_mac_addr; 360 361 /* Assemble the headers... */ 362 assemble_hw_header (interface, (unsigned char *)hh, &hbufp, hto); 363 fudge = hbufp % 4; /* IP header must be word-aligned. */ 364 memcpy (buf + fudge, (unsigned char *)hh, hbufp); 365 ibufp = hbufp + fudge; 366 assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr, 367 to -> sin_addr.s_addr, to -> sin_port, 368 (unsigned char *)raw, len); 369 memcpy (buf + ibufp, raw, len); 370 result = write(interface->wfdesc, buf + fudge, ibufp + len - fudge); 371 if (result < 0) 372 log_error ("send_packet: %m"); 373 return result; 374 } 375 #endif /* USE_LPF_SEND */ 376 377 #ifdef USE_LPF_RECEIVE 378 ssize_t receive_packet (interface, buf, len, from, hfrom) 379 struct interface_info *interface; 380 unsigned char *buf; 381 size_t len; 382 struct sockaddr_in *from; 383 struct hardware *hfrom; 384 { 385 int length = 0; 386 int offset = 0; 387 int csum_ready = 1; 388 unsigned char ibuf [1536]; 389 unsigned bufix = 0; 390 unsigned paylen; 391 struct iovec iov = { 392 .iov_base = ibuf, 393 .iov_len = sizeof ibuf, 394 }; 395 #ifdef PACKET_AUXDATA 396 /* 397 * We only need cmsgbuf if we are getting the aux data and we 398 * only get the auxdata if it is actually defined 399 */ 400 unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; 401 struct msghdr msg = { 402 .msg_iov = &iov, 403 .msg_iovlen = 1, 404 .msg_control = cmsgbuf, 405 .msg_controllen = sizeof(cmsgbuf), 406 }; 407 #else 408 struct msghdr msg = { 409 .msg_iov = &iov, 410 .msg_iovlen = 1, 411 .msg_control = NULL, 412 .msg_controllen = 0, 413 }; 414 #endif /* PACKET_AUXDATA */ 415 416 length = recvmsg (interface->rfdesc, &msg, 0); 417 if (length <= 0) 418 return length; 419 420 #ifdef PACKET_AUXDATA 421 { 422 /* Use auxiliary packet data to: 423 * 424 * a. Weed out extraneous VLAN-tagged packets - If the NIC driver is 425 * handling VLAN encapsulation (i.e. stripping/adding VLAN tags), 426 * then an inbound VLAN packet will be seen twice: Once by 427 * the parent interface (e.g. eth0) with a VLAN tag != 0; and once 428 * by the vlan interface (e.g. eth0.n) with a VLAN tag of 0 (i.e none). 429 * We want to discard the packet sent to the parent and thus respond 430 * only over the vlan interface. (Drivers for Intel PRO/1000 series 431 * NICs perform VLAN encapsulation, while drivers for PCnet series 432 * do not, for example. The linux kernel makes stripped vlan info 433 * visible to user space via CMSG/auxdata, this appears to not be 434 * true for BSD OSs.). NOTE: this is only supported on linux flavors 435 * which define the tpacket_auxdata.tp_vlan_tci. 436 * 437 * b. Determine if checksum is valid for use. It may not be if 438 * checksum offloading is enabled on the interface. */ 439 struct cmsghdr *cmsg; 440 441 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 442 if (cmsg->cmsg_level == SOL_PACKET && 443 cmsg->cmsg_type == PACKET_AUXDATA) { 444 struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); 445 #ifdef VLAN_TCI_PRESENT 446 /* Discard packets with stripped vlan id */ 447 /* VLAN ID is only bottom 12-bits of TCI */ 448 if (aux->tp_vlan_tci & 0x0fff) 449 return 0; 450 #endif 451 452 csum_ready = ((aux->tp_status & TP_STATUS_CSUMNOTREADY) 453 ? 0 : 1); 454 } 455 } 456 457 } 458 #endif /* PACKET_AUXDATA */ 459 460 bufix = 0; 461 /* Decode the physical header... */ 462 offset = decode_hw_header (interface, ibuf, bufix, hfrom); 463 464 /* If a physical layer checksum failed (dunno of any 465 physical layer that supports this, but WTH), skip this 466 packet. */ 467 if (offset < 0) { 468 return 0; 469 } 470 471 bufix += offset; 472 length -= offset; 473 474 /* Decode the IP and UDP headers... */ 475 offset = decode_udp_ip_header (interface, ibuf, bufix, from, 476 (unsigned)length, &paylen, csum_ready); 477 478 /* If the IP or UDP checksum was bad, skip the packet... */ 479 if (offset < 0) 480 return 0; 481 482 bufix += offset; 483 length -= offset; 484 485 if (length < paylen) 486 log_fatal("Internal inconsistency at %s:%d.", MDL); 487 488 /* Copy out the data in the packet... */ 489 memcpy(buf, &ibuf[bufix], paylen); 490 return paylen; 491 } 492 493 int can_unicast_without_arp (ip) 494 struct interface_info *ip; 495 { 496 return 1; 497 } 498 499 int can_receive_unicast_unconfigured (ip) 500 struct interface_info *ip; 501 { 502 return 1; 503 } 504 505 int supports_multiple_interfaces (ip) 506 struct interface_info *ip; 507 { 508 return 1; 509 } 510 511 void maybe_setup_fallback () 512 { 513 isc_result_t status; 514 struct interface_info *fbi = (struct interface_info *)0; 515 if (setup_fallback (&fbi, MDL)) { 516 if_register_fallback (fbi); 517 status = omapi_register_io_object ((omapi_object_t *)fbi, 518 if_readsocket, 0, 519 fallback_discard, 0, 0); 520 if (status != ISC_R_SUCCESS) 521 log_fatal ("Can't register I/O handle for \"%s\": %s", 522 fbi -> name, isc_result_totext (status)); 523 interface_dereference (&fbi, MDL); 524 } 525 } 526 #endif 527 528 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR) 529 void 530 get_hw_addr(const char *name, struct hardware *hw) { 531 int sock; 532 struct ifreq tmp; 533 struct sockaddr *sa; 534 535 if (strlen(name) >= sizeof(tmp.ifr_name)) { 536 log_fatal("Device name too long: \"%s\"", name); 537 } 538 539 sock = socket(AF_INET, SOCK_DGRAM, 0); 540 if (sock < 0) { 541 log_fatal("Can't create socket for \"%s\": %m", name); 542 } 543 544 memset(&tmp, 0, sizeof(tmp)); 545 strcpy(tmp.ifr_name, name); 546 if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) { 547 log_fatal("Error getting hardware address for \"%s\": %m", 548 name); 549 } 550 551 sa = &tmp.ifr_hwaddr; 552 switch (sa->sa_family) { 553 case ARPHRD_ETHER: 554 hw->hlen = 7; 555 hw->hbuf[0] = HTYPE_ETHER; 556 memcpy(&hw->hbuf[1], sa->sa_data, 6); 557 break; 558 case ARPHRD_IEEE802: 559 #ifdef ARPHRD_IEEE802_TR 560 case ARPHRD_IEEE802_TR: 561 #endif /* ARPHRD_IEEE802_TR */ 562 hw->hlen = 7; 563 hw->hbuf[0] = HTYPE_IEEE802; 564 memcpy(&hw->hbuf[1], sa->sa_data, 6); 565 break; 566 case ARPHRD_FDDI: 567 hw->hlen = 7; 568 hw->hbuf[0] = HTYPE_FDDI; 569 memcpy(&hw->hbuf[1], sa->sa_data, 6); 570 break; 571 default: 572 log_fatal("Unsupported device type %ld for \"%s\"", 573 (long int)sa->sa_family, name); 574 } 575 576 close(sock); 577 } 578 #endif 579