Skip to content

Instantly share code, notes, and snippets.

@msantos
Created April 24, 2011 00:47
Show Gist options
  • Select an option

  • Save msantos/939183 to your computer and use it in GitHub Desktop.

Select an option

Save msantos/939183 to your computer and use it in GitHub Desktop.
Erlang BPF filters
-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