[strongSwan-dev] farp plugin bpf filter

Sven Kuhnert sven.qnerd at googlemail.com
Mon May 31 20:24:04 CEST 2010


Hi list.

I tried to use charons new farp plugin. Unfortunately it does not work
in my environment. If I sniff the network traffic, I can see an ARP
request to the broadcast but the ipsec gateway do not answer that. The
UML-Test for this module seems to work. By viewing the source code I
found out, that the BPF filter in farp_spoofer.c does not work properly
for me. I am not a pro in kernel based socket programming but I thought
that this filter is used for performance reasons to capture only ARP
requests? So I tried to replace that filter rules with some more basic
ones (see the end of this mail) and the module works fine. The new
ruleset is quite similar to this:
http://dhcpcd.sourcearchive.com/documentation/3.2.3/socket_8c-source.html

It seems to be important, that these two lines are present:
    arp_request_filter_code[1].jf = 0; /* skip the IP packet type check */
    arp_request_filter_code[2].k -= ETH_HLEN;

The next strange thing for me is, that the old rules worked at all,
because I interpret these rules, that only IP packets (and even NOT arp)
are captured:
        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, protocol_type)),
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_P_IP, 0, 9),

Maybe this behaviour comes form some settings on the ipsec gateway
system (this is btw. a brand new Ubuntu 10.04 LTS)?



Greetings from Germany,

Sven Kuhnert



--- strongswan-4.4.0/src/libcharon/plugins/farp/farp_spoofer.c  
 2010-03-28 14:06:04.000000000 +0200
+++ farp_spoofer.c_final    2010-05-31 17:51:24.000000000 +0200
@@ -21,6 +21,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/filter.h>
+#include <net/ethernet.h>
 #include <sys/ioctl.h>
 
 #include <daemon.h>
@@ -147,19 +148,25 @@
 {
     private_farp_spoofer_t *this;
     struct sock_filter arp_request_filter_code[] = {
-        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, protocol_type)),
-        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_P_IP, 0, 9),
-        BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, hardware_size)),
-        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 7),
-        BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, protocol_size)),
-        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 4),
-        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)),
-        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3),
-        BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),
-        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 28, 0, 1),
-        BPF_STMT(BPF_RET+BPF_A, 0),
-        BPF_STMT(BPF_RET+BPF_K, 0),
+           /* 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),
+
+          /* 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_REQUEST, 0, 1),
+
+          /* If we passed all the tests, ask for the whole packet. */
+          BPF_STMT (BPF_RET + BPF_K, ~0U),
+
+          /* Otherwise, drop it. */
+          BPF_STMT (BPF_RET + BPF_K, 0),    
     };
+
+    
+    arp_request_filter_code[1].jf = 0; /* skip the IP packet type check */
+          arp_request_filter_code[2].k -= ETH_HLEN;
+
     struct sock_fprog arp_request_filter = {
         sizeof(arp_request_filter_code) / sizeof(struct sock_filter),
         arp_request_filter_code,




More information about the Dev mailing list