summaryrefslogtreecommitdiff
path: root/usr.sbin/dhcrelay/bpf.c
diff options
context:
space:
mode:
authorCan Erkin Acar <canacar@cvs.openbsd.org>2004-04-20 21:05:15 +0000
committerCan Erkin Acar <canacar@cvs.openbsd.org>2004-04-20 21:05:15 +0000
commitb0deafffb2645a4c2347a28cae351c86bc800187 (patch)
tree0542f83784d5272f106afd1f3904f5438eab3f49 /usr.sbin/dhcrelay/bpf.c
parente69f4ae27be5c5fe034e01d855e2927ae86deb9f (diff)
set write filter and lock the bpf descriptor after configuration.
ok henning@
Diffstat (limited to 'usr.sbin/dhcrelay/bpf.c')
-rw-r--r--usr.sbin/dhcrelay/bpf.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/usr.sbin/dhcrelay/bpf.c b/usr.sbin/dhcrelay/bpf.c
index 4c50976cdd0..c1be9ade057 100644
--- a/usr.sbin/dhcrelay/bpf.c
+++ b/usr.sbin/dhcrelay/bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bpf.c,v 1.3 2004/04/20 20:56:47 canacar Exp $ */
+/* $OpenBSD: bpf.c,v 1.4 2004/04/20 21:05:14 canacar Exp $ */
/* BPF socket interface code, originally contributed by Archie Cobbs. */
@@ -126,12 +126,45 @@ struct bpf_insn dhcp_bpf_filter[] = {
int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn);
+
+/*
+ * Packet write filter program: 'ip and udp and src port SERVER_PORT'
+ */
+struct bpf_insn dhcp_bpf_wfilter[] = {
+ /* 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),
+
+ /* 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),
+
+ /* 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),
+
+ /* Get the IP header length... */
+ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
+
+ /* Make sure it's from the right port... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SERVER_PORT, 0, 1),
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
+int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn);
+
void
if_register_receive(struct interface_info *info)
{
struct bpf_version v;
struct bpf_program p;
- int flag = 1, sz;
+ int flag = 1, sz, cmplt = 0;
/* Open a BPF device and hang it on this interface... */
info->rfdesc = if_register_bpf(info);
@@ -152,6 +185,10 @@ if_register_receive(struct interface_info *info)
if (ioctl(info->rfdesc, BIOCIMMEDIATE, &flag) < 0)
error("Can't set immediate mode on bpf device: %m");
+ /* make sure kernel fills in the source ethernet address */
+ if (ioctl(info->rfdesc, BIOCSHDRCMPLT, &cmplt) < 0)
+ error("Can't set header complete flag on bpf device: %m");
+
/* Get the required BPF buffer length from the kernel. */
if (ioctl(info->rfdesc, BIOCGBLEN, &sz) < 0)
error("Can't get bpf buffer length: %m");
@@ -169,6 +206,17 @@ if_register_receive(struct interface_info *info)
if (ioctl(info->rfdesc, BIOCSETF, &p) < 0)
error("Can't install packet filter program: %m");
+
+ /* Set up the bpf write filter program structure. */
+ p.bf_len = dhcp_bpf_wfilter_len;
+ p.bf_insns = dhcp_bpf_wfilter;
+
+ if (ioctl(info->rfdesc, BIOCSETWF, &p) < 0)
+ error("Can't install write filter program: %m");
+
+ /* make sure these settings cannot be changed after dropping privs */
+ if (ioctl(info->rfdesc, BIOCLOCK) < 0)
+ error("Failed to lock bpf descriptor: %m");
}
ssize_t