1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd: BPF arp and bootp filtering
4 * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
32 #include <arpa/inet.h>
35 #include <netinet/in.h>
36 #include <netinet/if_ether.h>
39 /* Special BPF snowflake. */
40 #include <linux/filter.h>
41 #define bpf_insn sock_filter
60 #define ARP_ADDRS_MAX 3
62 /* BPF helper macros */
64 #define BPF_WHOLEPACKET 0x7fffffff /* work around buggy LPF filters */
66 #define BPF_WHOLEPACKET ~0U
69 /* Macros to update the BPF structure */
70 #define BPF_SET_STMT(insn, c, v) { \
74 (insn)->k = (uint32_t)(v); \
77 #define BPF_SET_JUMP(insn, c, v, t, f) { \
81 (insn)->k = (uint32_t)(v); \
85 bpf_frame_header_len(const struct interface
*ifp
)
88 switch (ifp
->family
) {
90 return sizeof(struct ether_header
);
96 static const uint8_t etherbcastaddr
[] =
97 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
100 bpf_frame_bcast(const struct interface
*ifp
, const char *frame
)
103 switch (ifp
->family
) {
105 return memcmp(frame
+
106 offsetof(struct ether_header
, ether_dhost
),
107 etherbcastaddr
, sizeof(etherbcastaddr
));
114 /* Linux is a special snowflake for opening, attaching and reading BPF.
115 * See if-linux.c for the Linux specific BPF functions. */
117 const char *bpf_name
= "Berkley Packet Filter";
120 bpf_open(struct interface
*ifp
, int (*filter
)(struct interface
*, int))
122 struct ipv4_state
*state
;
127 struct bpf_version pv
;
136 fd
= open(_PATH_BPF
, O_RDWR
| O_NONBLOCK
146 snprintf(device
, sizeof(device
), "/dev/bpf%d", n
++);
147 fd
= open(device
, O_RDWR
| O_NONBLOCK
152 } while (fd
== -1 && errno
== EBUSY
);
159 if ((fd_opts
= fcntl(fd
, F_GETFD
)) == -1 ||
160 fcntl(fd
, F_SETFD
, fd_opts
| FD_CLOEXEC
) == -1) {
166 memset(&pv
, 0, sizeof(pv
));
167 if (ioctl(fd
, BIOCVERSION
, &pv
) == -1)
169 if (pv
.bv_major
!= BPF_MAJOR_VERSION
||
170 pv
.bv_minor
< BPF_MINOR_VERSION
) {
171 logerrx("BPF version mismatch - recompile");
175 if (filter(ifp
, fd
) != 0)
178 memset(&ifr
, 0, sizeof(ifr
));
179 strlcpy(ifr
.ifr_name
, ifp
->name
, sizeof(ifr
.ifr_name
));
180 if (ioctl(fd
, BIOCSETIF
, &ifr
) == -1)
183 /* Get the required BPF buffer length from the kernel. */
184 if (ioctl(fd
, BIOCGBLEN
, &ibuf_len
) == -1)
186 buf_len
= (size_t)ibuf_len
;
187 state
= ipv4_getstate(ifp
);
190 if (state
->buffer_size
!= buf_len
) {
193 if ((nb
= realloc(state
->buffer
, buf_len
)) == NULL
)
196 state
->buffer_size
= buf_len
;
201 if (ioctl(fd
, BIOCIMMEDIATE
, &flags
) == -1)
212 /* BPF requires that we read the entire buffer.
213 * So we pass the buffer in the API so we can loop on >1 packet. */
215 bpf_read(struct interface
*ifp
, int fd
, void *data
, size_t len
,
218 ssize_t fl
= (ssize_t
)bpf_frame_header_len(ifp
);
220 struct ipv4_state
*state
= IPV4_STATE(ifp
);
222 struct bpf_hdr packet
;
227 if (state
->buffer_len
== 0) {
228 bytes
= read(fd
, state
->buffer
, state
->buffer_size
);
230 /* After 2^31 bytes, the kernel offset overflows.
231 * To work around this bug, lseek 0. */
232 if (bytes
== -1 && errno
== EINVAL
) {
233 lseek(fd
, 0, SEEK_SET
);
237 if (bytes
== -1 || bytes
== 0)
239 state
->buffer_len
= (size_t)bytes
;
240 state
->buffer_pos
= 0;
243 memcpy(&packet
, state
->buffer
+ state
->buffer_pos
,
245 if (state
->buffer_pos
+ packet
.bh_caplen
+ packet
.bh_hdrlen
>
247 goto next
; /* Packet beyond buffer, drop. */
248 payload
= state
->buffer
+ state
->buffer_pos
+ packet
.bh_hdrlen
;
249 if (bpf_frame_bcast(ifp
, payload
) == 0)
252 *flags
&= ~BPF_BCAST
;
254 bytes
= (ssize_t
)packet
.bh_caplen
- fl
;
255 if ((size_t)bytes
> len
)
256 bytes
= (ssize_t
)len
;
257 memcpy(data
, payload
, (size_t)bytes
);
259 state
->buffer_pos
+= BPF_WORDALIGN(packet
.bh_hdrlen
+
261 if (state
->buffer_pos
>= state
->buffer_len
) {
262 state
->buffer_len
= state
->buffer_pos
= 0;
273 bpf_attach(int fd
, void *filter
, unsigned int filter_len
)
275 struct bpf_program pf
;
277 /* Install the filter. */
278 memset(&pf
, 0, sizeof(pf
));
279 pf
.bf_insns
= filter
;
280 pf
.bf_len
= filter_len
;
281 return ioctl(fd
, BIOCSETF
, &pf
);
286 /* SunOS is special too - sending via BPF goes nowhere. */
288 bpf_send(const struct interface
*ifp
, int fd
, uint16_t protocol
,
289 const void *data
, size_t len
)
292 struct ether_header eh
;
294 switch(ifp
->family
) {
296 memset(&eh
.ether_dhost
, 0xff, sizeof(eh
.ether_dhost
));
297 memcpy(&eh
.ether_shost
, ifp
->hwaddr
, sizeof(eh
.ether_shost
));
298 eh
.ether_type
= htons(protocol
);
299 iov
[0].iov_base
= &eh
;
300 iov
[0].iov_len
= sizeof(eh
);
303 iov
[0].iov_base
= NULL
;
307 iov
[1].iov_base
= UNCONST(data
);
308 iov
[1].iov_len
= len
;
309 return writev(fd
, iov
, 2);
314 bpf_close(struct interface
*ifp
, int fd
)
316 struct ipv4_state
*state
= IPV4_STATE(ifp
);
318 /* Rewind the buffer on closing. */
319 state
->buffer_len
= state
->buffer_pos
= 0;
323 /* Normally this is needed by bootp.
324 * Once that uses this again, the ARP guard here can be removed. */
326 #define BPF_CMP_HWADDR_LEN ((((HWADDR_LEN / 4) + 2) * 2) + 1)
328 bpf_cmp_hwaddr(struct bpf_insn
*bpf
, size_t bpf_len
, size_t off
,
329 bool equal
, uint8_t *hwaddr
, size_t hwaddr_len
)
332 size_t maclen
, nlft
, njmps
;
337 /* Calc the number of jumps */
338 if ((hwaddr_len
/ 4) >= 128) {
342 njmps
= (hwaddr_len
/ 4) * 2; /* 2 instructions per check */
343 /* We jump after the 1st check. */
346 nlft
= hwaddr_len
% 4;
348 njmps
+= (nlft
/ 2) * 2;
355 /* Skip to positive finish. */
366 for (; hwaddr_len
> 0;
367 hwaddr
+= maclen
, hwaddr_len
-= maclen
, off
+= maclen
)
375 if (hwaddr_len
>= 4) {
376 maclen
= sizeof(mac32
);
377 memcpy(&mac32
, hwaddr
, maclen
);
378 BPF_SET_STMT(bp
, BPF_LD
+ BPF_W
+ BPF_IND
, off
);
380 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
381 htonl(mac32
), jt
, jf
);
382 } else if (hwaddr_len
>= 2) {
383 maclen
= sizeof(mac16
);
384 memcpy(&mac16
, hwaddr
, maclen
);
385 BPF_SET_STMT(bp
, BPF_LD
+ BPF_H
+ BPF_IND
, off
);
387 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
388 htons(mac16
), jt
, jf
);
390 maclen
= sizeof(*hwaddr
);
391 BPF_SET_STMT(bp
, BPF_LD
+ BPF_B
+ BPF_IND
, off
);
393 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
397 jt
= (uint8_t)(jt
- 2);
399 jf
= (uint8_t)(jf
- 2);
403 /* Last step is always return failure.
404 * Next step is a positive finish. */
405 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, 0);
408 return (unsigned int)(bp
- bpf
);
414 static const struct bpf_insn bpf_arp_ether
[] = {
415 /* Ensure packet is at least correct size. */
416 BPF_STMT(BPF_LD
+ BPF_W
+ BPF_LEN
, 0),
417 BPF_JUMP(BPF_JMP
+ BPF_JGE
+ BPF_K
, sizeof(struct ether_arp
), 1, 0),
418 BPF_STMT(BPF_RET
+ BPF_K
, 0),
420 /* Check this is an ARP packet. */
421 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_ABS
,
422 offsetof(struct ether_header
, ether_type
)),
423 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ETHERTYPE_ARP
, 1, 0),
424 BPF_STMT(BPF_RET
+ BPF_K
, 0),
426 /* Load frame header length into X */
427 BPF_STMT(BPF_LDX
+ BPF_W
+ BPF_IMM
, sizeof(struct ether_header
)),
429 /* Make sure the hardware family matches. */
430 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_IND
, offsetof(struct arphdr
, ar_hrd
)),
431 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ARPHRD_ETHER
, 1, 0),
432 BPF_STMT(BPF_RET
+ BPF_K
, 0),
434 /* Make sure the hardware length matches. */
435 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_IND
, offsetof(struct arphdr
, ar_hln
)),
436 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
,
437 sizeof(((struct ether_arp
*)0)->arp_sha
), 1, 0),
438 BPF_STMT(BPF_RET
+ BPF_K
, 0),
440 #define BPF_ARP_ETHER_LEN __arraycount(bpf_arp_ether)
442 static const struct bpf_insn bpf_arp_filter
[] = {
443 /* Make sure this is for IP. */
444 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_IND
, offsetof(struct arphdr
, ar_pro
)),
445 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ETHERTYPE_IP
, 1, 0),
446 BPF_STMT(BPF_RET
+ BPF_K
, 0),
447 /* Make sure this is an ARP REQUEST. */
448 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_IND
, offsetof(struct arphdr
, ar_op
)),
449 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ARPOP_REQUEST
, 2, 0),
451 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ARPOP_REPLY
, 1, 0),
452 BPF_STMT(BPF_RET
+ BPF_K
, 0),
453 /* Make sure the protocol length matches. */
454 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_IND
, offsetof(struct arphdr
, ar_pln
)),
455 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, sizeof(in_addr_t
), 1, 0),
456 BPF_STMT(BPF_RET
+ BPF_K
, 0),
458 #define BPF_ARP_FILTER_LEN __arraycount(bpf_arp_filter)
460 #define BPF_ARP_ADDRS_LEN 1 + (ARP_ADDRS_MAX * 2) + 3 + \
461 (ARP_ADDRS_MAX * 2) + 1
463 #define BPF_ARP_LEN BPF_ARP_ETHER_LEN + BPF_ARP_FILTER_LEN + \
464 BPF_CMP_HWADDR_LEN + BPF_ARP_ADDRS_LEN
467 bpf_arp(struct interface
*ifp
, int fd
)
469 struct bpf_insn bpf
[BPF_ARP_LEN
];
471 struct iarp_state
*state
;
478 /* Check frame header. */
479 switch(ifp
->family
) {
481 memcpy(bp
, bpf_arp_ether
, sizeof(bpf_arp_ether
));
482 bp
+= BPF_ARP_ETHER_LEN
;
483 arp_len
= sizeof(struct ether_header
)+sizeof(struct ether_arp
);
490 /* Copy in the main filter. */
491 memcpy(bp
, bpf_arp_filter
, sizeof(bpf_arp_filter
));
492 bp
+= BPF_ARP_FILTER_LEN
;
494 /* Ensure it's not from us. */
495 bp
+= bpf_cmp_hwaddr(bp
, BPF_CMP_HWADDR_LEN
, sizeof(struct arphdr
),
496 false, ifp
->hwaddr
, ifp
->hwlen
);
498 state
= ARP_STATE(ifp
);
499 if (TAILQ_FIRST(&state
->arp_states
)) {
500 struct arp_state
*astate
;
503 /* Match sender protocol address */
504 BPF_SET_STMT(bp
, BPF_LD
+ BPF_W
+ BPF_IND
,
505 sizeof(struct arphdr
) + ifp
->hwlen
);
508 TAILQ_FOREACH(astate
, &state
->arp_states
, next
) {
509 if (++naddrs
> ARP_ADDRS_MAX
) {
514 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
515 htonl(astate
->addr
.s_addr
), 0, 1);
517 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, arp_len
);
521 /* If we didn't match sender, then we're only interested in
522 * ARP probes to us, so check the null host sender. */
523 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
, INADDR_ANY
, 1, 0);
525 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, 0);
528 /* Match target protocol address */
529 BPF_SET_STMT(bp
, BPF_LD
+ BPF_W
+ BPF_IND
,
530 (sizeof(struct arphdr
)
531 + (size_t)(ifp
->hwlen
* 2) + sizeof(in_addr_t
)));
534 TAILQ_FOREACH(astate
, &state
->arp_states
, next
) {
535 if (++naddrs
> ARP_ADDRS_MAX
) {
536 /* Already logged error above. */
539 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
540 htonl(astate
->addr
.s_addr
), 0, 1);
542 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, arp_len
);
546 /* Return nothing, no protocol address match. */
547 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, 0);
551 return bpf_attach(fd
, bpf
, (unsigned int)(bp
- bpf
));
555 #define BPF_M_FHLEN 0
556 #define BPF_M_IPHLEN 1
557 #define BPF_M_IPLEN 2
559 #define BPF_M_UDPLEN 4
562 static const struct bpf_insn bpf_bootp_none
[] = {
563 /* Set the frame header length to zero. */
564 BPF_STMT(BPF_LD
+ BPF_IMM
, 0),
565 BPF_STMT(BPF_ST
, BPF_M_FHLEN
),
567 #define BPF_BOOTP_NONE_LEN __arraycount(bpf_bootp_none)
570 static const struct bpf_insn bpf_bootp_ether
[] = {
571 /* Make sure this is an IP packet. */
572 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_ABS
,
573 offsetof(struct ether_header
, ether_type
)),
574 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ETHERTYPE_IP
, 1, 0),
575 BPF_STMT(BPF_RET
+ BPF_K
, 0),
577 /* Load frame header length into X. */
578 BPF_STMT(BPF_LDX
+ BPF_W
+ BPF_IMM
, sizeof(struct ether_header
)),
579 /* Copy frame header length to memory */
580 BPF_STMT(BPF_STX
, BPF_M_FHLEN
),
582 #define BPF_BOOTP_ETHER_LEN __arraycount(bpf_bootp_ether)
584 static const struct bpf_insn bpf_bootp_filter
[] = {
585 /* Make sure it's an IPv4 packet. */
586 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_IND
, 0),
587 BPF_STMT(BPF_ALU
+ BPF_AND
+ BPF_K
, 0xf0),
588 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, 0x40, 1, 0),
589 BPF_STMT(BPF_RET
+ BPF_K
, 0),
591 /* Ensure IP header length is big enough and
592 * store the IP header length in memory. */
593 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_IND
, 0),
594 BPF_STMT(BPF_ALU
+ BPF_AND
+ BPF_K
, 0x0f),
595 BPF_STMT(BPF_ALU
+ BPF_MUL
+ BPF_K
, 4),
596 BPF_JUMP(BPF_JMP
+ BPF_JGE
+ BPF_K
, sizeof(struct ip
), 1, 0),
597 BPF_STMT(BPF_RET
+ BPF_K
, 0),
598 BPF_STMT(BPF_ST
, BPF_M_IPHLEN
),
600 /* Make sure it's a UDP packet. */
601 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_IND
, offsetof(struct ip
, ip_p
)),
602 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, IPPROTO_UDP
, 1, 0),
603 BPF_STMT(BPF_RET
+ BPF_K
, 0),
605 /* Make sure this isn't a fragment. */
606 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_IND
, offsetof(struct ip
, ip_off
)),
607 BPF_JUMP(BPF_JMP
+ BPF_JSET
+ BPF_K
, 0x1fff, 0, 1),
608 BPF_STMT(BPF_RET
+ BPF_K
, 0),
610 /* Store IP length. */
611 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_IND
, offsetof(struct ip
, ip_len
)),
612 BPF_STMT(BPF_ST
, BPF_M_IPLEN
),
614 /* Advance to the UDP header. */
615 BPF_STMT(BPF_LD
+ BPF_MEM
, BPF_M_IPHLEN
),
616 BPF_STMT(BPF_ALU
+ BPF_ADD
+ BPF_X
, 0),
617 BPF_STMT(BPF_MISC
+ BPF_TAX
, 0),
619 /* Store UDP location */
620 BPF_STMT(BPF_STX
, BPF_M_UDP
),
622 /* Make sure it's from and to the right port. */
623 BPF_STMT(BPF_LD
+ BPF_W
+ BPF_IND
, 0),
624 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, (BOOTPS
<< 16) + BOOTPC
, 1, 0),
625 BPF_STMT(BPF_RET
+ BPF_K
, 0),
627 /* Store UDP length. */
628 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_IND
, offsetof(struct udphdr
, uh_ulen
)),
629 BPF_STMT(BPF_ST
, BPF_M_UDPLEN
),
631 /* Ensure that UDP length + IP header length == IP length */
632 /* Copy IP header length to X. */
633 BPF_STMT(BPF_LDX
+ BPF_MEM
, BPF_M_IPHLEN
),
634 /* Add UDP length (A) to IP header length (X). */
635 BPF_STMT(BPF_ALU
+ BPF_ADD
+ BPF_X
, 0),
636 /* Store result in X. */
637 BPF_STMT(BPF_MISC
+ BPF_TAX
, 0),
638 /* Copy IP length to A. */
639 BPF_STMT(BPF_LD
+ BPF_MEM
, BPF_M_IPLEN
),
641 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_X
, 0, 1, 0),
642 BPF_STMT(BPF_RET
+ BPF_K
, 0),
644 /* Advance to the BOOTP packet. */
645 BPF_STMT(BPF_LD
+ BPF_MEM
, BPF_M_UDP
),
646 BPF_STMT(BPF_ALU
+ BPF_ADD
+ BPF_K
, sizeof(struct udphdr
)),
647 BPF_STMT(BPF_MISC
+ BPF_TAX
, 0),
649 /* Make sure it's BOOTREPLY. */
650 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_IND
, offsetof(struct bootp
, op
)),
651 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, BOOTREPLY
, 1, 0),
652 BPF_STMT(BPF_RET
+ BPF_K
, 0),
655 #define BPF_BOOTP_FILTER_LEN __arraycount(bpf_bootp_filter)
656 #define BPF_BOOTP_CHADDR_LEN ((BOOTP_CHADDR_LEN / 4) * 3)
657 #define BPF_BOOTP_XID_LEN 4 /* BOUND check is 4 instructions */
659 #define BPF_BOOTP_LEN BPF_BOOTP_ETHER_LEN + BPF_BOOTP_FILTER_LEN \
660 + BPF_BOOTP_XID_LEN + BPF_BOOTP_CHADDR_LEN + 4
663 bpf_bootp(struct interface
*ifp
, int fd
)
666 const struct dhcp_state
*state
= D_CSTATE(ifp
);
668 struct bpf_insn bpf
[BPF_BOOTP_LEN
];
675 /* Check frame header. */
676 switch(ifp
->family
) {
679 memcpy(bp
, bpf_bootp_none
, sizeof(bpf_bootp_none
));
680 bp
+= BPF_BOOTP_NONE_LEN
;
684 memcpy(bp
, bpf_bootp_ether
, sizeof(bpf_bootp_ether
));
685 bp
+= BPF_BOOTP_ETHER_LEN
;
692 /* Copy in the main filter. */
693 memcpy(bp
, bpf_bootp_filter
, sizeof(bpf_bootp_filter
));
694 bp
+= BPF_BOOTP_FILTER_LEN
;
696 /* These checks won't work when same IP exists on other interfaces. */
698 if (ifp
->hwlen
<= sizeof(((struct bootp
*)0)->chaddr
))
699 bp
+= bpf_cmp_hwaddr(bp
, BPF_BOOTP_CHADDR_LEN
,
700 offsetof(struct bootp
, chaddr
),
701 true, ifp
->hwaddr
, ifp
->hwlen
);
703 /* Make sure the BOOTP packet is for us. */
704 if (state
->state
== DHS_BOUND
) {
705 /* If bound, we only expect FORCERENEW messages
706 * and they need to be unicast to us.
707 * Move back to the IP header in M0 and check dst. */
708 BPF_SET_STMT(bp
, BPF_LDX
+ BPF_W
+ BPF_MEM
, 0);
710 BPF_SET_STMT(bp
, BPF_LD
+ BPF_W
+ BPF_IND
,
711 offsetof(struct ip
, ip_dst
));
713 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
714 htonl(state
->lease
.addr
.s_addr
), 1, 0);
716 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, 0);
719 /* As we're not bound, we need to check xid to ensure
720 * it's a reply to our transaction. */
721 BPF_SET_STMT(bp
, BPF_LD
+ BPF_W
+ BPF_IND
,
722 offsetof(struct bootp
, xid
));
724 BPF_SET_JUMP(bp
, BPF_JMP
+ BPF_JEQ
+ BPF_K
,
727 BPF_SET_STMT(bp
, BPF_RET
+ BPF_K
, 0);
732 /* All passed, return the packet - frame length + ip length */
733 BPF_SET_STMT(bp
, BPF_LD
+ BPF_MEM
, BPF_M_FHLEN
);
735 BPF_SET_STMT(bp
, BPF_LDX
+ BPF_MEM
, BPF_M_IPLEN
);
737 BPF_SET_STMT(bp
, BPF_ALU
+ BPF_ADD
+ BPF_X
, 0);
739 BPF_SET_STMT(bp
, BPF_RET
+ BPF_A
, 0);
742 return bpf_attach(fd
, bpf
, (unsigned int)(bp
- bpf
));