1 /* $OpenBSD: bpf.c,v 1.71 2018/12/08 23:06:41 krw Exp $ */ 2 3 /* BPF socket interface code, originally contributed by Archie Cobbs. */ 4 5 /* 6 * Copyright (c) 1995, 1996, 1998, 1999 7 * The Internet Software Consortium. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of The Internet Software Consortium nor the names 19 * of its contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND 23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * This software has been written for the Internet Software Consortium 37 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie 38 * Enterprises. To learn more about the Internet Software Consortium, 39 * see ``http://www.vix.com/isc''. To learn more about Vixie 40 * Enterprises, see ``http://www.vix.com''. 41 */ 42 43 #include <sys/ioctl.h> 44 #include <sys/queue.h> 45 #include <sys/socket.h> 46 #include <sys/types.h> 47 48 #include <net/bpf.h> 49 #include <net/if.h> 50 51 #include <netinet/in.h> 52 #include <netinet/ip.h> 53 #include <netinet/udp.h> 54 #include <netinet/if_ether.h> 55 56 #include <errno.h> 57 #include <fcntl.h> 58 #include <signal.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <unistd.h> 63 64 #include "dhcp.h" 65 #include "dhcpd.h" 66 #include "log.h" 67 68 int 69 get_bpf_sock(char *name) 70 { 71 struct ifreq ifr; 72 int sock; 73 74 if ((sock = open("/dev/bpf", O_RDWR | O_CLOEXEC)) == -1) 75 fatal("open(/dev/bpf)"); 76 77 /* Set the BPF device to point at this interface. */ 78 strlcpy(ifr.ifr_name, name, IFNAMSIZ); 79 if (ioctl(sock, BIOCSETIF, &ifr) == -1) 80 fatal("BIOCSETIF"); 81 82 return sock; 83 } 84 85 int 86 get_udp_sock(int rdomain) 87 { 88 int sock, on = 1; 89 90 /* 91 * Use raw socket for unicast send. 92 */ 93 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) 94 fatal("socket(AF_INET, SOCK_RAW)"); 95 if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, 96 sizeof(on)) == -1) 97 fatal("setsockopt(IP_HDRINCL)"); 98 if (setsockopt(sock, IPPROTO_IP, SO_RTABLE, &rdomain, 99 sizeof(rdomain)) == -1) 100 fatal("setsockopt(SO_RTABLE)"); 101 102 return sock; 103 } 104 105 /* 106 * Packet filter program. 107 * 108 * N.B.: Changes to the filter program may require changes to the 109 * constant offsets used in if_register_receive to patch the BPF program! 110 */ 111 struct bpf_insn dhcp_bpf_filter[] = { 112 /* Make sure this is an IP packet. */ 113 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), 114 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), 115 116 /* Make sure it's a UDP packet. */ 117 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), 118 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), 119 120 /* Make sure this isn't a fragment. */ 121 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), 122 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), 123 124 /* Get the IP header length. */ 125 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), 126 127 /* Make sure it's to the right port. */ 128 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), 129 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ 130 131 /* If we passed all the tests, ask for the whole packet. */ 132 BPF_STMT(BPF_RET+BPF_K, (unsigned int)-1), 133 134 /* Otherwise, drop it. */ 135 BPF_STMT(BPF_RET+BPF_K, 0), 136 }; 137 138 int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn); 139 140 /* 141 * Packet write filter program: 142 * 'ip and udp and src port bootps and dst port (bootps or bootpc)' 143 */ 144 struct bpf_insn dhcp_bpf_wfilter[] = { 145 BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14), 146 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12), 147 148 /* Make sure this is an IP packet. */ 149 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), 150 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10), 151 152 /* Make sure it's a UDP packet. */ 153 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), 154 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8), 155 156 /* Make sure this isn't a fragment. */ 157 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), 158 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */ 159 160 /* Get the IP header length. */ 161 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), 162 163 /* Make sure it's from the right port. */ 164 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14), 165 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3), 166 167 /* Make sure it is to the right ports. */ 168 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), 169 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), 170 171 /* If we passed all the tests, ask for the whole packet. */ 172 BPF_STMT(BPF_RET+BPF_K, (unsigned int)-1), 173 174 /* Otherwise, drop it. */ 175 BPF_STMT(BPF_RET+BPF_K, 0), 176 }; 177 178 int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn); 179 180 int 181 configure_bpf_sock(int bfdesc) 182 { 183 struct bpf_version v; 184 struct bpf_program p; 185 int flag = 1, sz; 186 187 /* Make sure the BPF version is in range. */ 188 if (ioctl(bfdesc, BIOCVERSION, &v) == -1) 189 fatal("BIOCVERSION"); 190 191 if (v.bv_major != BPF_MAJOR_VERSION || 192 v.bv_minor < BPF_MINOR_VERSION) 193 fatalx("kernel BPF version out of range - recompile " 194 "dhclient"); 195 196 /* 197 * Set immediate mode so that reads return as soon as a packet 198 * comes in, rather than waiting for the input buffer to fill 199 * with packets. 200 */ 201 if (ioctl(bfdesc, BIOCIMMEDIATE, &flag) == -1) 202 fatal("BIOCIMMEDIATE"); 203 204 if (ioctl(bfdesc, BIOCSFILDROP, &flag) == -1) 205 fatal("BIOCSFILDROP"); 206 207 /* Get the required BPF buffer length from the kernel. */ 208 if (ioctl(bfdesc, BIOCGBLEN, &sz) == -1) 209 fatal("BIOCGBLEN"); 210 211 /* Set up the bpf filter program structure. */ 212 p.bf_len = dhcp_bpf_filter_len; 213 p.bf_insns = dhcp_bpf_filter; 214 215 /* Patch the server port into the BPF program. 216 * 217 * N.B.: changes to filter program may require changes to the 218 * insn number(s) used below! 219 */ 220 dhcp_bpf_filter[8].k = LOCAL_PORT; 221 222 if (ioctl(bfdesc, BIOCSETF, &p) == -1) 223 fatal("BIOCSETF"); 224 225 /* Set up the bpf write filter program structure. */ 226 p.bf_len = dhcp_bpf_wfilter_len; 227 p.bf_insns = dhcp_bpf_wfilter; 228 229 if (dhcp_bpf_wfilter[7].k == 0x1fff) 230 dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK); 231 232 if (ioctl(bfdesc, BIOCSETWF, &p) == -1) 233 fatal("BIOCSETWF"); 234 235 if (ioctl(bfdesc, BIOCLOCK, NULL) == -1) 236 fatal("BIOCLOCK"); 237 238 return sz; 239 } 240 241 ssize_t 242 send_packet(struct interface_info *ifi, struct in_addr from, struct in_addr to, 243 const char *desc) 244 { 245 struct iovec iov[4]; 246 struct sockaddr_in dest; 247 struct ether_header eh; 248 struct ip ip; 249 struct udphdr udp; 250 struct msghdr msg; 251 struct dhcp_packet *packet = &ifi->sent_packet; 252 ssize_t result, total; 253 unsigned int iovcnt = 0, i; 254 int len = ifi->sent_packet_length; 255 256 memset(&dest, 0, sizeof(dest)); 257 dest.sin_family = AF_INET; 258 dest.sin_port = htons(REMOTE_PORT); 259 dest.sin_addr.s_addr = to.s_addr; 260 261 if (to.s_addr == INADDR_BROADCAST) { 262 assemble_eh_header(ifi->hw_address, &eh); 263 iov[0].iov_base = &eh; 264 iov[0].iov_len = sizeof(eh); 265 iovcnt++; 266 } 267 268 ip.ip_v = 4; 269 ip.ip_hl = 5; 270 ip.ip_tos = IPTOS_LOWDELAY; 271 ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); 272 ip.ip_id = 0; 273 ip.ip_off = 0; 274 ip.ip_ttl = 128; 275 ip.ip_p = IPPROTO_UDP; 276 ip.ip_sum = 0; 277 ip.ip_src.s_addr = from.s_addr; 278 ip.ip_dst.s_addr = to.s_addr; 279 ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0)); 280 iov[iovcnt].iov_base = &ip; 281 iov[iovcnt].iov_len = sizeof(ip); 282 iovcnt++; 283 284 udp.uh_sport = htons(LOCAL_PORT); 285 udp.uh_dport = htons(REMOTE_PORT); 286 udp.uh_ulen = htons(sizeof(udp) + len); 287 udp.uh_sum = 0; 288 udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp), 289 checksum((unsigned char *)packet, len, 290 checksum((unsigned char *)&ip.ip_src, 291 2 * sizeof(ip.ip_src), 292 IPPROTO_UDP + (uint32_t)ntohs(udp.uh_ulen))))); 293 iov[iovcnt].iov_base = &udp; 294 iov[iovcnt].iov_len = sizeof(udp); 295 iovcnt++; 296 297 iov[iovcnt].iov_base = packet; 298 iov[iovcnt].iov_len = len; 299 iovcnt++; 300 301 total = 0; 302 for (i = 0; i < iovcnt; i++) 303 total += iov[i].iov_len; 304 305 if (to.s_addr == INADDR_BROADCAST) { 306 result = writev(ifi->bfdesc, iov, iovcnt); 307 if (result == -1) 308 log_warn("%s: writev(%s)", log_procname, desc); 309 else if (result < total) { 310 log_warnx("%s, writev(%s): %zd of %zd bytes", 311 log_procname, desc, result, total); 312 result = -1; 313 } 314 } else { 315 memset(&msg, 0, sizeof(msg)); 316 msg.msg_name = (struct sockaddr *)&dest; 317 msg.msg_namelen = sizeof(dest); 318 msg.msg_iov = iov; 319 msg.msg_iovlen = iovcnt; 320 result = sendmsg(ifi->ufdesc, &msg, 0); 321 if (result == -1) 322 log_warn("%s: sendmsg(%s)", log_procname, desc); 323 else if (result < total) { 324 result = -1; 325 log_warnx("%s, sendmsg(%s): %zd of %zd bytes", 326 log_procname, desc, result, total); 327 } 328 } 329 330 return result; 331 } 332 333 ssize_t 334 receive_packet(struct interface_info *ifi, struct sockaddr_in *from, 335 struct ether_addr *hfrom) 336 { 337 struct bpf_hdr hdr; 338 struct dhcp_packet *packet = &ifi->recv_packet; 339 ssize_t length = 0; 340 int offset = 0; 341 342 /* 343 * All this complexity is because BPF doesn't guarantee that 344 * only one packet will be returned at a time. We're getting 345 * what we deserve, though - this is a terrible abuse of the BPF 346 * interface. Sigh. 347 */ 348 349 /* Process packets until we get one we can return or until we've 350 * done a read and gotten nothing we can return. 351 */ 352 do { 353 /* If the buffer is empty, fill it. */ 354 if (ifi->rbuf_offset >= ifi->rbuf_len) { 355 length = read(ifi->bfdesc, ifi->rbuf, ifi->rbuf_max); 356 if (length == -1) { 357 log_warn("%s: read(bfdesc)", log_procname); 358 return length; 359 } else if (length == 0) 360 return length; 361 ifi->rbuf_offset = 0; 362 ifi->rbuf_len = length; 363 } 364 365 /* 366 * If there isn't room for a whole bpf header, something 367 * went wrong, but we'll ignore it and hope it goes 368 * away. XXX 369 */ 370 if (ifi->rbuf_len - ifi->rbuf_offset < sizeof(hdr)) { 371 ifi->rbuf_offset = ifi->rbuf_len; 372 continue; 373 } 374 375 /* Copy out a bpf header. */ 376 memcpy(&hdr, &ifi->rbuf[ifi->rbuf_offset], sizeof(hdr)); 377 378 /* 379 * If the bpf header plus data doesn't fit in what's 380 * left of the buffer, stick head in sand yet again. 381 */ 382 if (ifi->rbuf_offset + hdr.bh_hdrlen + hdr.bh_caplen > 383 ifi->rbuf_len) { 384 ifi->rbuf_offset = ifi->rbuf_len; 385 continue; 386 } 387 388 /* 389 * If the captured data wasn't the whole packet, or if 390 * the packet won't fit in the input buffer, all we can 391 * do is drop it. 392 */ 393 if (hdr.bh_caplen != hdr.bh_datalen) { 394 ifi->rbuf_offset = BPF_WORDALIGN( 395 ifi->rbuf_offset + hdr.bh_hdrlen + 396 hdr.bh_caplen); 397 continue; 398 } 399 400 /* Skip over the BPF header. */ 401 ifi->rbuf_offset += hdr.bh_hdrlen; 402 403 /* Decode the physical header. */ 404 offset = decode_hw_header(ifi->rbuf + ifi->rbuf_offset, 405 hdr.bh_caplen, hfrom); 406 407 /* 408 * If a physical layer checksum failed (dunno of any 409 * physical layer that supports this, but WTH), skip 410 * this packet. 411 */ 412 if (offset < 0) { 413 ifi->rbuf_offset = BPF_WORDALIGN( 414 ifi->rbuf_offset + hdr.bh_caplen); 415 continue; 416 } 417 ifi->rbuf_offset += offset; 418 hdr.bh_caplen -= offset; 419 420 /* Decode the IP and UDP headers. */ 421 offset = decode_udp_ip_header(ifi->rbuf + ifi->rbuf_offset, 422 hdr.bh_caplen, from); 423 424 /* If the IP or UDP checksum was bad, skip the packet. */ 425 if (offset < 0) { 426 ifi->rbuf_offset = BPF_WORDALIGN( 427 ifi->rbuf_offset + hdr.bh_caplen); 428 continue; 429 } 430 ifi->rbuf_offset += offset; 431 hdr.bh_caplen -= offset; 432 433 /* 434 * If there's not enough room to stash the packet data, 435 * we have to skip it (this shouldn't happen in real 436 * life, though). 437 */ 438 if (hdr.bh_caplen > sizeof(*packet)) { 439 ifi->rbuf_offset = BPF_WORDALIGN( 440 ifi->rbuf_offset + hdr.bh_caplen); 441 continue; 442 } 443 444 /* Copy out the data in the packet. */ 445 memset(packet, DHO_END, sizeof(*packet)); 446 memcpy(packet, ifi->rbuf + ifi->rbuf_offset, hdr.bh_caplen); 447 ifi->rbuf_offset = BPF_WORDALIGN(ifi->rbuf_offset + 448 hdr.bh_caplen); 449 return hdr.bh_caplen; 450 } while (length == 0); 451 return 0 ; 452 } 453