1 /* $OpenBSD: bpf.c,v 1.62 2017/07/14 16:35:59 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 /* 69 * Returns a packet filter socket fd on the interface. 70 */ 71 int 72 get_bpf_sock(char *name) 73 { 74 struct ifreq ifr; 75 int sock; 76 77 if ((sock = open("/dev/bpf", O_RDWR | O_CLOEXEC)) == -1) 78 fatal("Can't open bpf"); 79 80 /* Set the BPF device to point at this interface. */ 81 strlcpy(ifr.ifr_name, name, IFNAMSIZ); 82 if (ioctl(sock, BIOCSETIF, &ifr) == -1) 83 fatal("Can't attach interface %s to /dev/bpf", name); 84 85 return sock; 86 } 87 88 int 89 get_udp_sock(int rdomain) 90 { 91 int sock, on = 1; 92 93 /* 94 * Use raw socket for unicast send. 95 */ 96 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) 97 fatal("socket(SOCK_RAW)"); 98 if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, 99 sizeof(on)) == -1) 100 fatal("setsockopt(IP_HDRINCL)"); 101 if (setsockopt(sock, IPPROTO_IP, SO_RTABLE, &rdomain, 102 sizeof(rdomain)) == -1) 103 fatal("setsockopt(SO_RTABLE)"); 104 105 return sock; 106 } 107 108 /* 109 * Packet filter program. 110 * 111 * XXX: Changes to the filter program may require changes to the 112 * constant offsets used in if_register_receive to patch the BPF program! 113 */ 114 struct bpf_insn dhcp_bpf_filter[] = { 115 /* Make sure this is an IP packet. */ 116 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), 117 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), 118 119 /* Make sure it's a UDP packet. */ 120 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), 121 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), 122 123 /* Make sure this isn't a fragment. */ 124 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), 125 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), 126 127 /* Get the IP header length. */ 128 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), 129 130 /* Make sure it's to the right port. */ 131 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), 132 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ 133 134 /* If we passed all the tests, ask for the whole packet. */ 135 BPF_STMT(BPF_RET+BPF_K, (unsigned int)-1), 136 137 /* Otherwise, drop it. */ 138 BPF_STMT(BPF_RET+BPF_K, 0), 139 }; 140 141 int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn); 142 143 /* 144 * Packet write filter program: 145 * 'ip and udp and src port bootps and dst port (bootps or bootpc)' 146 */ 147 struct bpf_insn dhcp_bpf_wfilter[] = { 148 BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14), 149 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12), 150 151 /* Make sure this is an IP packet. */ 152 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), 153 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10), 154 155 /* Make sure it's a UDP packet. */ 156 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), 157 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8), 158 159 /* Make sure this isn't a fragment. */ 160 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), 161 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */ 162 163 /* Get the IP header length. */ 164 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), 165 166 /* Make sure it's from the right port. */ 167 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14), 168 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3), 169 170 /* Make sure it is to the right ports. */ 171 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), 172 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), 173 174 /* If we passed all the tests, ask for the whole packet. */ 175 BPF_STMT(BPF_RET+BPF_K, (unsigned int)-1), 176 177 /* Otherwise, drop it. */ 178 BPF_STMT(BPF_RET+BPF_K, 0), 179 }; 180 181 int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn); 182 183 int 184 configure_bpf_sock(int bfdesc) 185 { 186 struct bpf_version v; 187 struct bpf_program p; 188 int flag = 1, sz; 189 190 /* Make sure the BPF version is in range. */ 191 if (ioctl(bfdesc, BIOCVERSION, &v) == -1) 192 fatal("Can't get BPF version"); 193 194 if (v.bv_major != BPF_MAJOR_VERSION || 195 v.bv_minor < BPF_MINOR_VERSION) 196 fatalx("Kernel BPF version out of range - recompile " 197 "dhclient!"); 198 199 /* 200 * Set immediate mode so that reads return as soon as a packet 201 * comes in, rather than waiting for the input buffer to fill 202 * with packets. 203 */ 204 if (ioctl(bfdesc, BIOCIMMEDIATE, &flag) == -1) 205 fatal("Can't set immediate mode on bpf device"); 206 207 if (ioctl(bfdesc, BIOCSFILDROP, &flag) == -1) 208 fatal("Can't set filter-drop mode on bpf device"); 209 210 /* Get the required BPF buffer length from the kernel. */ 211 if (ioctl(bfdesc, BIOCGBLEN, &sz) == -1) 212 fatal("Can't get bpf buffer length"); 213 214 /* Set up the bpf filter program structure. */ 215 p.bf_len = dhcp_bpf_filter_len; 216 p.bf_insns = dhcp_bpf_filter; 217 218 /* Patch the server port into the BPF program. 219 * 220 * XXX: changes to filter program may require changes to the 221 * insn number(s) used below! 222 */ 223 dhcp_bpf_filter[8].k = LOCAL_PORT; 224 225 if (ioctl(bfdesc, BIOCSETF, &p) == -1) 226 fatal("Can't install packet filter program"); 227 228 /* Set up the bpf write filter program structure. */ 229 p.bf_len = dhcp_bpf_wfilter_len; 230 p.bf_insns = dhcp_bpf_wfilter; 231 232 if (dhcp_bpf_wfilter[7].k == 0x1fff) 233 dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK); 234 235 if (ioctl(bfdesc, BIOCSETWF, &p) == -1) 236 fatal("Can't install write filter program"); 237 238 if (ioctl(bfdesc, BIOCLOCK, NULL) == -1) 239 fatal("Cannot lock bpf"); 240 241 return sz; 242 } 243 244 ssize_t 245 send_packet(struct interface_info *ifi, struct in_addr from, struct in_addr to) 246 { 247 struct iovec iov[4]; 248 struct sockaddr_in dest; 249 struct ether_header eh; 250 struct ip ip; 251 struct udphdr udp; 252 struct msghdr msg; 253 struct dhcp_packet *packet = &ifi->sent_packet; 254 ssize_t result; 255 int iovcnt = 0, len = ifi->sent_packet_length; 256 257 memset(&dest, 0, sizeof(dest)); 258 dest.sin_family = AF_INET; 259 dest.sin_port = htons(REMOTE_PORT); 260 dest.sin_addr.s_addr = to.s_addr; 261 262 if (to.s_addr == INADDR_BROADCAST) { 263 assemble_eh_header(ifi->hw_address, &eh); 264 iov[0].iov_base = &eh; 265 iov[0].iov_len = sizeof(eh); 266 iovcnt++; 267 } 268 269 ip.ip_v = 4; 270 ip.ip_hl = 5; 271 ip.ip_tos = IPTOS_LOWDELAY; 272 ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); 273 ip.ip_id = 0; 274 ip.ip_off = 0; 275 ip.ip_ttl = 128; 276 ip.ip_p = IPPROTO_UDP; 277 ip.ip_sum = 0; 278 ip.ip_src.s_addr = from.s_addr; 279 ip.ip_dst.s_addr = to.s_addr; 280 ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0)); 281 iov[iovcnt].iov_base = &ip; 282 iov[iovcnt].iov_len = sizeof(ip); 283 iovcnt++; 284 285 udp.uh_sport = htons(LOCAL_PORT); 286 udp.uh_dport = htons(REMOTE_PORT); 287 udp.uh_ulen = htons(sizeof(udp) + len); 288 udp.uh_sum = 0; 289 udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp), 290 checksum((unsigned char *)packet, len, 291 checksum((unsigned char *)&ip.ip_src, 292 2 * sizeof(ip.ip_src), 293 IPPROTO_UDP + (uint32_t)ntohs(udp.uh_ulen))))); 294 iov[iovcnt].iov_base = &udp; 295 iov[iovcnt].iov_len = sizeof(udp); 296 iovcnt++; 297 298 iov[iovcnt].iov_base = packet; 299 iov[iovcnt].iov_len = len; 300 iovcnt++; 301 302 if (to.s_addr == INADDR_BROADCAST) { 303 result = writev(ifi->bfdesc, iov, iovcnt); 304 } else { 305 memset(&msg, 0, sizeof(msg)); 306 msg.msg_name = (struct sockaddr *)&dest; 307 msg.msg_namelen = sizeof(dest); 308 msg.msg_iov = iov; 309 msg.msg_iovlen = iovcnt; 310 result = sendmsg(ifi->ufdesc, &msg, 0); 311 } 312 313 if (result == -1) 314 log_warn("send_packet"); 315 return result ; 316 } 317 318 ssize_t 319 receive_packet(struct interface_info *ifi, struct sockaddr_in *from, 320 struct ether_addr *hfrom) 321 { 322 struct bpf_hdr hdr; 323 struct dhcp_packet *packet = &ifi->recv_packet; 324 int length = 0, offset = 0; 325 326 /* 327 * All this complexity is because BPF doesn't guarantee that 328 * only one packet will be returned at a time. We're getting 329 * what we deserve, though - this is a terrible abuse of the BPF 330 * interface. Sigh. 331 */ 332 333 /* Process packets until we get one we can return or until we've 334 * done a read and gotten nothing we can return. 335 */ 336 do { 337 /* If the buffer is empty, fill it. */ 338 if (ifi->rbuf_offset >= ifi->rbuf_len) { 339 length = read(ifi->bfdesc, ifi->rbuf, ifi->rbuf_max); 340 if (length <= 0) 341 return length ; 342 ifi->rbuf_offset = 0; 343 ifi->rbuf_len = length; 344 } 345 346 /* 347 * If there isn't room for a whole bpf header, something 348 * went wrong, but we'll ignore it and hope it goes 349 * away. XXX 350 */ 351 if (ifi->rbuf_len - ifi->rbuf_offset < sizeof(hdr)) { 352 ifi->rbuf_offset = ifi->rbuf_len; 353 continue; 354 } 355 356 /* Copy out a bpf header. */ 357 memcpy(&hdr, &ifi->rbuf[ifi->rbuf_offset], sizeof(hdr)); 358 359 /* 360 * If the bpf header plus data doesn't fit in what's 361 * left of the buffer, stick head in sand yet again. 362 */ 363 if (ifi->rbuf_offset + hdr.bh_hdrlen + hdr.bh_caplen > 364 ifi->rbuf_len) { 365 ifi->rbuf_offset = ifi->rbuf_len; 366 continue; 367 } 368 369 /* 370 * If the captured data wasn't the whole packet, or if 371 * the packet won't fit in the input buffer, all we can 372 * do is drop it. 373 */ 374 if (hdr.bh_caplen != hdr.bh_datalen) { 375 ifi->rbuf_offset = BPF_WORDALIGN( 376 ifi->rbuf_offset + hdr.bh_hdrlen + 377 hdr.bh_caplen); 378 continue; 379 } 380 381 /* Skip over the BPF header. */ 382 ifi->rbuf_offset += hdr.bh_hdrlen; 383 384 /* Decode the physical header. */ 385 offset = decode_hw_header(ifi->rbuf + ifi->rbuf_offset, 386 hdr.bh_caplen, hfrom); 387 388 /* 389 * If a physical layer checksum failed (dunno of any 390 * physical layer that supports this, but WTH), skip 391 * this packet. 392 */ 393 if (offset < 0) { 394 ifi->rbuf_offset = BPF_WORDALIGN( 395 ifi->rbuf_offset + hdr.bh_caplen); 396 continue; 397 } 398 ifi->rbuf_offset += offset; 399 hdr.bh_caplen -= offset; 400 401 /* Decode the IP and UDP headers. */ 402 offset = decode_udp_ip_header(ifi->rbuf + ifi->rbuf_offset, 403 hdr.bh_caplen, from); 404 405 /* If the IP or UDP checksum was bad, skip the packet. */ 406 if (offset < 0) { 407 ifi->rbuf_offset = BPF_WORDALIGN( 408 ifi->rbuf_offset + hdr.bh_caplen); 409 continue; 410 } 411 ifi->rbuf_offset += offset; 412 hdr.bh_caplen -= offset; 413 414 /* 415 * If there's not enough room to stash the packet data, 416 * we have to skip it (this shouldn't happen in real 417 * life, though). 418 */ 419 if (hdr.bh_caplen > sizeof(*packet)) { 420 ifi->rbuf_offset = BPF_WORDALIGN( 421 ifi->rbuf_offset + hdr.bh_caplen); 422 continue; 423 } 424 425 /* Copy out the data in the packet. */ 426 memset(packet, DHO_END, sizeof(*packet)); 427 memcpy(packet, ifi->rbuf + ifi->rbuf_offset, hdr.bh_caplen); 428 ifi->rbuf_offset = BPF_WORDALIGN(ifi->rbuf_offset + 429 hdr.bh_caplen); 430 return hdr.bh_caplen ; 431 } while (length == 0); 432 return 0 ; 433 } 434