diff options
Diffstat (limited to 'common/bpf.c')
-rw-r--r-- | common/bpf.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/common/bpf.c b/common/bpf.c index dc41f809..16076fea 100644 --- a/common/bpf.c +++ b/common/bpf.c @@ -192,12 +192,51 @@ struct bpf_insn dhcp_bpf_filter [] = { BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ /* If we passed all the tests, ask for the whole packet. */ - BPF_STMT(BPF_RET+BPF_K, (u_int)-1), + BPF_STMT (BPF_RET + BPF_K, (u_int)-1), /* Otherwise, drop it. */ - BPF_STMT(BPF_RET+BPF_K, 0), + BPF_STMT (BPF_RET + BPF_K, 0), }; +#if defined(RELAY_PORT) +/* + * For relay port extension + */ +struct bpf_insn dhcp_bpf_relay_filter [] = { + /* 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, 10), + + /* 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, 8), + + /* 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, 6, 0), + + /* Get the IP header length... */ + BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), + + /* 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, 67, 2, 0), /* patch */ + + /* relay can have an alternative port... */ + BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ + + /* 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_relay_filter_len = + sizeof dhcp_bpf_relay_filter / sizeof (struct bpf_insn); +#endif + #if defined (DEC_FDDI) struct bpf_insn *bpf_fddi_filter = NULL; #endif @@ -309,7 +348,19 @@ void if_register_receive (info) /* Patch the server port into the BPF program... XXX changes to filter program may require changes to the insn number(s) used below! XXX */ - dhcp_bpf_filter [8].k = ntohs (local_port); +#if defined(RELAY_PORT) + if (relay_port) { + /* + * If user defined relay UDP port, we need to filter + * also on the user UDP port. + */ + p.bf_len = dhcp_bpf_relay_filter_len; + p.bf_insns = dhcp_bpf_relay_filter; + + dhcp_bpf_relay_filter [10].k = ntohs (relay_port); + } +#endif + p.bf_insns [8].k = ntohs (local_port); if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0) log_fatal ("Can't install packet filter program: %m"); |