* SUCH DAMAGE.
*/
-/* Credit where credit is due :)
- * The below BPF filter is taken from ISC DHCP */
-static struct bpf_insn dhcp_bpf_filter [] = {
+#ifndef BPF_ETHCOOK
+# define BPF_ETHCOOK 0
+#endif
+#ifndef BPF_WHOLEPACKET
+# define BPF_WHOLEPACKET ~0U
+#endif
+
+static const struct bpf_insn const dhcp_bpf_filter [] = {
+#ifndef BPF_SKIPTYPE
/* Make sure this is an IP packet... */
- BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
- BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
+#endif
/* Make sure it's a UDP packet... */
- BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
- BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
+ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23 + BPF_ETHCOOK),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
/* Make sure this isn't a fragment... */
- BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 20),
- BPF_JUMP (BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 + BPF_ETHCOOK),
+ BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
/* Get the IP header length... */
- BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
+ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14 + BPF_ETHCOOK),
/* Make sure it's to the right port... */
- BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
- BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, DHCP_CLIENT_PORT, 0, 1),
+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16 + BPF_ETHCOOK),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_CLIENT_PORT, 0, 1),
/* If we passed all the tests, ask for the whole packet. */
- BPF_STMT (BPF_RET + BPF_K, ~0U),
+ BPF_STMT(BPF_RET + BPF_K, BPF_WHOLEPACKET),
/* Otherwise, drop it. */
- BPF_STMT (BPF_RET + BPF_K, 0),
+ BPF_STMT(BPF_RET + BPF_K, 0),
};
static const size_t dhcp_bpf_filter_len =
sizeof(dhcp_bpf_filter) / sizeof(dhcp_bpf_filter[0]);
-
-/* This, however, is mine */
-static struct bpf_insn arp_bpf_filter [] = {
+static const struct bpf_insn const arp_bpf_filter [] = {
+#ifndef BPF_SKIPTYPE
/* Make sure this is an ARP packet... */
- BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
- BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_ARP, 0, 3),
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_ARP, 0, 3),
+#endif
/* Make sure this is an ARP REPLY... */
- BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 20),
- BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 0, 1),
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 + BPF_ETHCOOK),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 0, 1),
/* If we passed all the tests, ask for the whole packet. */
- BPF_STMT (BPF_RET + BPF_K, ~0U),
+ BPF_STMT(BPF_RET + BPF_K, BPF_WHOLEPACKET),
/* Otherwise, drop it. */
- BPF_STMT (BPF_RET + BPF_K, 0),
+ BPF_STMT(BPF_RET + BPF_K, 0),
};
static const size_t arp_bpf_filter_len =
sizeof(arp_bpf_filter) / sizeof(arp_bpf_filter[0]);
# include <linux/filter.h>
# include <netpacket/packet.h>
# define bpf_insn sock_filter
+# define BPF_SKIPTYPE
+# define BPF_ETHCOOK -ETH_HLEN
+# define BPF_WHOLEPACKET 65535 /* work around buggy LPF filters */
#endif
#include <errno.h>
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
};
-void
-setup_packet_filters(void)
-{
-#ifdef __linux__
- /* We need to massage the filters for Linux cooked packets */
- dhcp_bpf_filter[1].jf = 0; /* skip the IP packet type check */
- dhcp_bpf_filter[2].k -= ETH_HLEN;
- dhcp_bpf_filter[4].k -= ETH_HLEN;
- dhcp_bpf_filter[6].k -= ETH_HLEN;
- dhcp_bpf_filter[7].k -= ETH_HLEN;
-
- arp_bpf_filter[1].jf = 0; /* skip the IP packet type check */
- arp_bpf_filter[2].k -= ETH_HLEN;
-
- /* Some buggy Linux kernels do not work with ~0U.
- * 65536 should be enough for anyone ;) */
- dhcp_bpf_filter[9].k = 65536;
- arp_bpf_filter[5].k = 65536;
-#endif
-}
-
int
open_socket(struct interface *iface, int protocol)
{
errno = ENOENT;
goto eexit;
}
-
/* Install the DHCP filter */
memset(&pf, 0, sizeof(pf));
if (protocol == ETHERTYPE_ARP) {
- pf.filter = arp_bpf_filter;
+ pf.filter = UNCONST(arp_bpf_filter);
pf.len = arp_bpf_filter_len;
} else {
- pf.filter = dhcp_bpf_filter;
+ pf.filter = UNCONST(dhcp_bpf_filter);
pf.len = dhcp_bpf_filter_len;
}
if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) != 0)