Created
April 24, 2011 00:47
-
-
Save msantos/939183 to your computer and use it in GitHub Desktop.
Erlang BPF filters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -module(filt). | |
| -include("bpf.hrl"). | |
| -export([ | |
| rarp/0, | |
| ip/0, | |
| finger/0, | |
| ip/1, | |
| tcp/2 | |
| ]). | |
| -define(ETHERTYPE_REVARP, 16#8035). | |
| -define(REVARP_REQUEST, 3). | |
| -define(SIZEOF_STRUCT_ETHER_ARP, 28). | |
| -define(SIZEOF_STRUCT_ETHER_HEADER, 14). | |
| -define(ETHERTYPE_IP, 16#0800). | |
| -define(IPVERSION, 4). | |
| -define(IPPROTO_TCP, 6). | |
| rarp() -> | |
| [ | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 12), | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?ETHERTYPE_REVARP, 0, 3), | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 20), | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?REVARP_REQUEST, 0, 1), | |
| ?BPF_STMT(?BPF_RET+?BPF_K, ?SIZEOF_STRUCT_ETHER_ARP + | |
| ?SIZEOF_STRUCT_ETHER_HEADER), | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 0) | |
| ]. | |
| ip() -> | |
| [ | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 12), % offset = Ethernet Type | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?ETHERTYPE_IP, 0, 8), % type = IP | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 26), % offset = Source IP address | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, 16#8003700f, 0, 2), % source = 128.3.112.15 | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 30), % offset = Destination IP address | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, 16#80037023, 3, 4), % dest = 128.3.112.35 | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, 16#80037023, 0, 3), % source = 128.3.112.35 | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 30), % offset = Destination IP address | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, 16#8003700f, 0, 1), % destination = 128.3.112.15 | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 16#FFFFFFFF), % Return up to 2^32-1 bytes | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 0) % Return 0 bytes: drop packet | |
| ]. | |
| finger() -> | |
| [ | |
| % Ethernet | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 12), % offset = Ethernet Type | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?ETHERTYPE_IP, 0, 10), % type = IP | |
| % IP | |
| ?BPF_STMT(?BPF_LD+?BPF_B+?BPF_ABS, 23), % offset = ip protocol | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?IPPROTO_TCP, 0, 8), % protocol = TCP | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 20), % offset = flags, frag offset | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JSET+?BPF_K, 16#1fff, 6, 0), % frag offset: mask the top 3 bits | |
| % and AND with 1's | |
| % If any non-0 value is returned from the | |
| % AND (i.e., frag offset is non-0), jump | |
| % to the end and drop the packet | |
| ?BPF_STMT(?BPF_LDX+?BPF_B+?BPF_MSH, 14), % offset = IP version, IP header length | |
| % Load the header length into the index | |
| % register | |
| % TCP | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_IND, 14), % offset = TCP source port | |
| % Move from offset 14 (start of IP packet) | |
| % plus the value held in the index register | |
| % (IP header length). Puts us at the start | |
| % of the TCP packet (at the source port) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, 79, 2, 0), % source port = 79 | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_IND, 16), % offset = destination port | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, 79, 0, 1), % destination port = 79 | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 16#FFFFFFFF), % return: entire packet | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 0) % return: drop packet | |
| ]. | |
| ip({A,B,C,D}) -> | |
| IP = (A bsl 24) + (B bsl 16) + (C bsl 8) + D, | |
| [ | |
| % Ethernet | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 12), % offset = Ethernet Type | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?ETHERTYPE_IP, 0, 5), % type = IP | |
| % IP | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 26), % offset = Source IP address | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, IP, 2, 0), % source = {A,B,C,D} | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 30), % offset = Destination IP address | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, IP, 0, 1), % destination = {A,B,C,D} | |
| % Amount of packet to return | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 16#FFFFFFFF), % Return up to 2^32-1 bytes | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 0) % Return 0 bytes: drop packet | |
| ]. | |
| %% | |
| %% TCP | |
| %% | |
| % (src host A.B.C.D or dst host A.B.C.D) and (src port 80 or dst port 80) | |
| tcp({A,B,C,D}, Port) when is_integer(A), is_integer(B), is_integer(C), is_integer(D), | |
| is_integer(Port), Port > 0, Port < 16#FFFF -> | |
| IP = (A bsl 24) + (B bsl 16) + (C bsl 8) + D, | |
| [ | |
| % Ethernet | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 12), % offset = Ethernet Type (2 bytes) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?ETHERTYPE_IP, 0, 16), % type = IP | |
| % IP | |
| ?BPF_STMT(?BPF_LD+?BPF_B+?BPF_ABS, 14), % offset = IP version (4 bits) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JSET+?BPF_K, 16#B0, 14, 0), % version = IPv4 | |
| % 0100 0101 = 4 5 | |
| % AND 1011 0000 = B 0 | |
| % 0 = false (is IPv4) | |
| % any other value = true (not IPv4) | |
| ?BPF_STMT(?BPF_LD+?BPF_B+?BPF_ABS, 23), % offset = IP protocol (1 byte) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, ?IPPROTO_TCP, 0, 12), % protocol = TCP | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 26), % offset = Source IP address (4 bytes) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, IP, 2, 0), % source = {A,B,C,D} | |
| ?BPF_STMT(?BPF_LD+?BPF_W+?BPF_ABS, 30), % offset = Destination IP address (4 bytes) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, IP, 0, 8), % destination = {A,B,C,D} | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_ABS, 20), % offset = flags, frag offset | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JSET+?BPF_K, 16#1fff, 6, 0), % frag offset: mask the top 3 bits | |
| % and AND with 1's | |
| % If any non-0 (true) value is returned from the | |
| % AND (i.e., frag offset is non-0), jump | |
| % to the end and drop the packet | |
| ?BPF_STMT(?BPF_LDX+?BPF_B+?BPF_MSH, 14), % offset = IP version, IP header length | |
| % Load the header length into the index | |
| % register | |
| % TCP | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_IND, 14), % offset = TCP source port | |
| % Move from offset 14 (start of IP packet) | |
| % plus the value held in the index register | |
| % (IP header length). Puts us at the start | |
| % of the TCP packet (at the source port) | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, Port, 2, 0), % source port = Port | |
| ?BPF_STMT(?BPF_LD+?BPF_H+?BPF_IND, 16), % offset = destination port | |
| ?BPF_JUMP(?BPF_JMP+?BPF_JEQ+?BPF_K, Port, 0, 1), % destination port = Port | |
| % Return | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 16#FFFFFFFF), % return: entire packet | |
| ?BPF_STMT(?BPF_RET+?BPF_K, 0) % return: drop packet | |
| ]. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment