From 30a950ed5a15b6236a6c479284fbe26ee3605026 Mon Sep 17 00:00:00 2001 From: krw Date: Tue, 19 Jul 2016 17:23:20 +0000 Subject: [PATCH] Narrow the BPF read filter rules so only packets sent to the interface's LLADDR pass. Rely on dhclient's existing ability to detect and react to LLADDR changes. This limits the number of packets that get dropped as a result of dhclient setting BIOCSFILDROP on the bpf descriptor. Problem with bridges and multiple dhclients noted by stsp@. ok mpi@ stsp@ deraadt@ henning@ --- sbin/dhclient/bpf.c | 31 +++++++++++++++++++++++++++++-- sbin/dhclient/dhclient.c | 3 ++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 8185bd92a9d..379af942279 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.c,v 1.40 2016/05/08 08:20:50 natano Exp $ */ +/* $OpenBSD: bpf.c,v 1.41 2016/07/19 17:23:20 krw Exp $ */ /* BPF socket interface code, originally contributed by Archie Cobbs. */ @@ -114,8 +114,27 @@ if_register_send(void) * * XXX: Changes to the filter program may require changes to the * constant offsets used in if_register_receive to patch the BPF program! + * + * Adapted from script shown by + * + * tcpdump -d 'ether dst 00:00:00:00:00:00 ip proto \udp dst port 67' + * + * NOTE: tcpdump shows absolute jumps and relative jumps are required here! */ struct bpf_insn dhcp_bpf_filter[] = { + /* + * Make sure this is directed to our MAC. + * a) compare last 4 octets + * b) compare first 2 octets + * + * NOTE: MAC value must be patched in! + */ + + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 2), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x00000000, 0, 12), /* patch */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 0), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 0, 10), /* patch */ + /* 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), @@ -190,6 +209,8 @@ if_register_receive(void) struct bpf_version v; struct bpf_program p; int flag = 1, sz; + uint32_t bits; + uint16_t bits16; /* Open a BPF device and hang it on this interface. */ ifi->bfdesc = if_register_bpf(); @@ -235,7 +256,13 @@ if_register_receive(void) * XXX: changes to filter program may require changes to the * insn number(s) used below! */ - dhcp_bpf_filter[8].k = LOCAL_PORT; + memcpy(&bits, ((uint8_t *)&ifi->hw_address) + 2, sizeof(bits)); + dhcp_bpf_filter[1].k = ntohl(bits); + + memcpy(&bits16, ((uint8_t *)&ifi->hw_address), sizeof(bits16)); + dhcp_bpf_filter[3].k = ntohs(bits16); + + dhcp_bpf_filter[12].k = LOCAL_PORT; if (ioctl(ifi->bfdesc, BIOCSETF, &p) < 0) error("Can't install packet filter program: %s", diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index f4d98ac5200..7f89b1d5777 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.373 2016/04/28 17:34:49 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.374 2016/07/19 17:23:20 krw Exp $ */ /* * Copyright 2004 Henning Brauer @@ -603,6 +603,7 @@ main(int argc, char *argv[]) error("setsockopt(ROUTE_TABLEFILTER): %s", strerror(errno)); /* Register the interface. */ + get_hw_address(); if_register_receive(); if_register_send(); -- 2.20.1