diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-02-03 18:03:42 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-02-03 18:03:42 +0100 |
commit | e4785ca653d0e219926692c229673b2c1b8d6ac4 (patch) | |
tree | 69fc8a0a892bde0a0a9c83adf7567bbcbc8a9f74 /networking/udhcp | |
parent | fe8390e0fe7106aed9f586b3cf08215effc4450b (diff) | |
download | busybox-w32-e4785ca653d0e219926692c229673b2c1b8d6ac4.tar.gz busybox-w32-e4785ca653d0e219926692c229673b2c1b8d6ac4.tar.bz2 busybox-w32-e4785ca653d0e219926692c229673b2c1b8d6ac4.zip |
udhcpc: don't use BPF filter, users report problems (bugs 4598, 6746)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/udhcp')
-rw-r--r-- | networking/udhcp/dhcpc.c | 93 |
1 files changed, 46 insertions, 47 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 8dee916d9..ee19f5578 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -976,53 +976,6 @@ static int udhcp_raw_socket(int ifindex) | |||
976 | int fd; | 976 | int fd; |
977 | struct sockaddr_ll sock; | 977 | struct sockaddr_ll sock; |
978 | 978 | ||
979 | /* | ||
980 | * Comment: | ||
981 | * | ||
982 | * I've selected not to see LL header, so BPF doesn't see it, too. | ||
983 | * The filter may also pass non-IP and non-ARP packets, but we do | ||
984 | * a more complete check when receiving the message in userspace. | ||
985 | * | ||
986 | * and filter shamelessly stolen from: | ||
987 | * | ||
988 | * http://www.flamewarmaster.de/software/dhcpclient/ | ||
989 | * | ||
990 | * There are a few other interesting ideas on that page (look under | ||
991 | * "Motivation"). Use of netlink events is most interesting. Think | ||
992 | * of various network servers listening for events and reconfiguring. | ||
993 | * That would obsolete sending HUP signals and/or make use of restarts. | ||
994 | * | ||
995 | * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>. | ||
996 | * License: GPL v2. | ||
997 | * | ||
998 | * TODO: make conditional? | ||
999 | */ | ||
1000 | static const struct sock_filter filter_instr[] = { | ||
1001 | /* load 9th byte (protocol) */ | ||
1002 | BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9), | ||
1003 | /* jump to L1 if it is IPPROTO_UDP, else to L4 */ | ||
1004 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6), | ||
1005 | /* L1: load halfword from offset 6 (flags and frag offset) */ | ||
1006 | BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6), | ||
1007 | /* jump to L4 if any bits in frag offset field are set, else to L2 */ | ||
1008 | BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0), | ||
1009 | /* L2: skip IP header (load index reg with header len) */ | ||
1010 | BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), | ||
1011 | /* load udp destination port from halfword[header_len + 2] */ | ||
1012 | BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2), | ||
1013 | /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */ | ||
1014 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1), | ||
1015 | /* L3: accept packet */ | ||
1016 | BPF_STMT(BPF_RET|BPF_K, 0xffffffff), | ||
1017 | /* L4: discard packet */ | ||
1018 | BPF_STMT(BPF_RET|BPF_K, 0), | ||
1019 | }; | ||
1020 | static const struct sock_fprog filter_prog = { | ||
1021 | .len = sizeof(filter_instr) / sizeof(filter_instr[0]), | ||
1022 | /* casting const away: */ | ||
1023 | .filter = (struct sock_filter *) filter_instr, | ||
1024 | }; | ||
1025 | |||
1026 | log1("Opening raw socket on ifindex %d", ifindex); //log2? | 979 | log1("Opening raw socket on ifindex %d", ifindex); //log2? |
1027 | 980 | ||
1028 | fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); | 981 | fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); |
@@ -1033,13 +986,59 @@ static int udhcp_raw_socket(int ifindex) | |||
1033 | sock.sll_ifindex = ifindex; | 986 | sock.sll_ifindex = ifindex; |
1034 | xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); | 987 | xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); |
1035 | 988 | ||
989 | #if 0 /* Several users reported breakage when BPF filter is used */ | ||
1036 | if (CLIENT_PORT == 68) { | 990 | if (CLIENT_PORT == 68) { |
1037 | /* Use only if standard port is in use */ | 991 | /* Use only if standard port is in use */ |
992 | /* | ||
993 | * I've selected not to see LL header, so BPF doesn't see it, too. | ||
994 | * The filter may also pass non-IP and non-ARP packets, but we do | ||
995 | * a more complete check when receiving the message in userspace. | ||
996 | * | ||
997 | * and filter shamelessly stolen from: | ||
998 | * | ||
999 | * http://www.flamewarmaster.de/software/dhcpclient/ | ||
1000 | * | ||
1001 | * There are a few other interesting ideas on that page (look under | ||
1002 | * "Motivation"). Use of netlink events is most interesting. Think | ||
1003 | * of various network servers listening for events and reconfiguring. | ||
1004 | * That would obsolete sending HUP signals and/or make use of restarts. | ||
1005 | * | ||
1006 | * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>. | ||
1007 | * License: GPL v2. | ||
1008 | * | ||
1009 | * TODO: make conditional? | ||
1010 | */ | ||
1011 | static const struct sock_filter filter_instr[] = { | ||
1012 | /* load 9th byte (protocol) */ | ||
1013 | BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9), | ||
1014 | /* jump to L1 if it is IPPROTO_UDP, else to L4 */ | ||
1015 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6), | ||
1016 | /* L1: load halfword from offset 6 (flags and frag offset) */ | ||
1017 | BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6), | ||
1018 | /* jump to L4 if any bits in frag offset field are set, else to L2 */ | ||
1019 | BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0), | ||
1020 | /* L2: skip IP header (load index reg with header len) */ | ||
1021 | BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), | ||
1022 | /* load udp destination port from halfword[header_len + 2] */ | ||
1023 | BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2), | ||
1024 | /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */ | ||
1025 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1), | ||
1026 | /* L3: accept packet */ | ||
1027 | BPF_STMT(BPF_RET|BPF_K, 0xffffffff), | ||
1028 | /* L4: discard packet */ | ||
1029 | BPF_STMT(BPF_RET|BPF_K, 0), | ||
1030 | }; | ||
1031 | static const struct sock_fprog filter_prog = { | ||
1032 | .len = sizeof(filter_instr) / sizeof(filter_instr[0]), | ||
1033 | /* casting const away: */ | ||
1034 | .filter = (struct sock_filter *) filter_instr, | ||
1035 | }; | ||
1038 | /* Ignoring error (kernel may lack support for this) */ | 1036 | /* Ignoring error (kernel may lack support for this) */ |
1039 | if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, | 1037 | if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, |
1040 | sizeof(filter_prog)) >= 0) | 1038 | sizeof(filter_prog)) >= 0) |
1041 | log1("Attached filter to raw socket fd"); // log? | 1039 | log1("Attached filter to raw socket fd"); // log? |
1042 | } | 1040 | } |
1041 | #endif | ||
1043 | 1042 | ||
1044 | if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, | 1043 | if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, |
1045 | &const_int_1, sizeof(int)) < 0 | 1044 | &const_int_1, sizeof(int)) < 0 |