Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
71390391
Commit
71390391
authored
Jan 14, 2015
by
Marcin Siodelski
Browse files
[3547] Updated BPF program to filter out the packets using dest IP address.
parent
f8b8d39b
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/pkt_filter_bpf.cc
View file @
71390391
...
...
@@ -56,18 +56,18 @@ const unsigned int BPF_LOCAL_LOOPBACK_HEADER_LEN = 4;
struct
bpf_insn
ethernet_ip_udp_filter
[]
=
{
// Make sure this is an IP packet: check the half-word (two bytes)
// at offset 12 in the packet (the Ethernet packet type). If it
// is, advance to the next instruction. If not, advance
8
// is, advance to the next instruction. If not, advance
11
// instructions (which takes execution to the last instruction in
// the sequence: "drop it").
BPF_STMT
(
BPF_LD
+
BPF_H
+
BPF_ABS
,
ETHERNET_PACKET_TYPE_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
ETHERTYPE_IP
,
0
,
8
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
ETHERTYPE_IP
,
0
,
11
),
// Make sure it's a UDP packet. The IP protocol is at offset
// 9 in the IP header so, adding the Ethernet packet header size
// of 14 bytes gives an absolute byte offset in the packet of 23.
BPF_STMT
(
BPF_LD
+
BPF_B
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_PROTO_TYPE_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
IPPROTO_UDP
,
0
,
6
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
IPPROTO_UDP
,
0
,
9
),
// Make sure this isn't a fragment by checking that the fragment
// offset field in the IP header is zero. This field is the
...
...
@@ -75,7 +75,22 @@ struct bpf_insn ethernet_ip_udp_filter [] = {
// the IP header, so the half-word at offset 20 (6 + size of
// Ethernet header) is loaded and an appropriate mask applied.
BPF_STMT
(
BPF_LD
+
BPF_H
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_FLAGS_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JSET
+
BPF_K
,
0x1fff
,
4
,
0
),
BPF_JUMP
(
BPF_JMP
+
BPF_JSET
+
BPF_K
,
0x1fff
,
7
,
0
),
// Check the packet's destination address. The program will only
// allow the packets sent to the broadcast address or unicast
// to the specific address on the interface. By default, this
// address is set to 0 and must be set to the specific value
// when the raw socket is created and the program is attached
// to it. The caller must assign the address to the
// prog.bf_insns[8].k in the network byte order.
BPF_STMT
(
BPF_LD
+
BPF_W
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_DEST_ADDR_OFFSET
),
// If this is a broadcast address, skip the next check.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0xffffffff
,
1
,
0
),
// If this is not broadcast address, compare it with the unicast
// address specified for the interface.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0x00000000
,
0
,
4
),
// Get the IP header length. This is achieved by the following
// (special) instruction that, given the offset of the start
...
...
@@ -91,7 +106,7 @@ struct bpf_insn ethernet_ip_udp_filter [] = {
// The following instruction tests against the default DHCP server port,
// but the action port is actually set in PktFilterBPF::openSocket().
// N.B. The code in that method assumes that this instruction is at
// offset
8
in the program. If this is changed, openSocket() must be
// offset
11
in the program. If this is changed, openSocket() must be
// updated.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
DHCP4_SERVER_PORT
,
0
,
1
),
...
...
@@ -113,14 +128,14 @@ struct bpf_insn loopback_ip_udp_filter [] = {
// AF_INET. The default value used here (0xFFFFFFFF) must be overriden
// with htonl(AF_INET) from within the openSocket function.
BPF_STMT
(
BPF_LD
+
BPF_W
+
BPF_ABS
,
0
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0xFFFFFFFF
,
0
,
8
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0xFFFFFFFF
,
0
,
11
),
// Make sure it's a UDP packet. The IP protocol is at offset
// 9 in the IP header so, adding the pseudo header size 4 bytes
// gives an absolute byte offset in the packet of 13.
BPF_STMT
(
BPF_LD
+
BPF_B
+
BPF_ABS
,
BPF_LOCAL_LOOPBACK_HEADER_LEN
+
IP_PROTO_TYPE_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
IPPROTO_UDP
,
0
,
6
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
IPPROTO_UDP
,
0
,
9
),
// Make sure this isn't a fragment by checking that the fragment
// offset field in the IP header is zero. This field is the
...
...
@@ -129,7 +144,22 @@ struct bpf_insn loopback_ip_udp_filter [] = {
// pseudo header) is loaded and an appropriate mask applied.
BPF_STMT
(
BPF_LD
+
BPF_H
+
BPF_ABS
,
BPF_LOCAL_LOOPBACK_HEADER_LEN
+
IP_FLAGS_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JSET
+
BPF_K
,
0x1fff
,
4
,
0
),
BPF_JUMP
(
BPF_JMP
+
BPF_JSET
+
BPF_K
,
0x1fff
,
7
,
0
),
// Check the packet's destination address. The program will only
// allow the packets sent to the broadcast address or unicast
// to the specific address on the interface. By default, this
// address is set to 0 and must be set to the specific value
// when the raw socket is created and the program is attached
// to it. The caller must assign the address to the
// prog.bf_insns[8].k in the network byte order.
BPF_STMT
(
BPF_LD
+
BPF_W
+
BPF_ABS
,
BPF_LOCAL_LOOPBACK_HEADER_LEN
+
IP_DEST_ADDR_OFFSET
),
// If this is a broadcast address, skip the next check.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0xffffffff
,
1
,
0
),
// If this is not broadcast address, compare it with the unicast
// address specified for the interface.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0x00000000
,
0
,
4
),
// Get the IP header length. This is achieved by the following
// (special) instruction that, given the offset of the start
...
...
@@ -146,7 +176,7 @@ struct bpf_insn loopback_ip_udp_filter [] = {
// The following instruction tests against the default DHCP server port,
// but the action port is actually set in PktFilterBPF::openSocket().
// N.B. The code in that method assumes that this instruction is at
// offset
8
in the program. If this is changed, openSocket() must be
// offset
11
in the program. If this is changed, openSocket() must be
// updated.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
DHCP4_SERVER_PORT
,
0
,
1
),
...
...
@@ -230,7 +260,7 @@ PktFilterBPF::openSocket(Iface& iface,
if
((
ver
.
bv_major
!=
BPF_MAJOR_VERSION
)
||
(
ver
.
bv_minor
<
BPF_MINOR_VERSION
))
{
close
(
fallback
);
close
(
sock
);
close
(
sock
);
isc_throw
(
SocketConfigError
,
"Invalid BPF version: "
<<
ver
.
bv_major
<<
"."
<<
ver
.
bv_minor
<<
" Expected at least version:"
...
...
@@ -273,8 +303,13 @@ PktFilterBPF::openSocket(Iface& iface,
prog
.
bf_len
=
sizeof
(
ethernet_ip_udp_filter
)
/
sizeof
(
struct
bpf_insn
);
}
// Configure the BPF program to receive unicast packets sent to the
// specified address. The program will also allow packets sent to the
// 255.255.255.255 broadcast address.
prog
.
bf_insns
[
8
].
k
=
static_cast
<
uint32_t
>
(
addr
);
// Configure the BPF program to receive packets on the specified port.
prog
.
bf_insns
[
8
].
k
=
port
;
prog
.
bf_insns
[
11
].
k
=
port
;
// Actually set the filter program for the device.
if
(
ioctl
(
sock
,
BIOCSETF
,
&
prog
)
<
0
)
{
...
...
src/lib/dhcp/pkt_filter_lpf.cc
View file @
71390391
...
...
@@ -50,17 +50,18 @@ using namespace isc::dhcp;
struct
sock_filter
dhcp_sock_filter
[]
=
{
// Make sure this is an IP packet: check the half-word (two bytes)
// at offset 12 in the packet (the Ethernet packet type). If it
// is, advance to the next instruction. If not, advance
8
// is, advance to the next instruction. If not, advance
11
// instructions (which takes execution to the last instruction in
// the sequence: "drop it").
BPF_STMT
(
BPF_LD
+
BPF_H
+
BPF_ABS
,
ETHERNET_PACKET_TYPE_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
ETHERTYPE_IP
,
0
,
8
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
ETHERTYPE_IP
,
0
,
11
),
// Make sure it's a UDP packet. The IP protocol is at offset
// 9 in the IP header so, adding the Ethernet packet header size
// of 14 bytes gives an absolute byte offset in the packet of 23.
BPF_STMT
(
BPF_LD
+
BPF_B
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_PROTO_TYPE_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
IPPROTO_UDP
,
0
,
6
),
BPF_STMT
(
BPF_LD
+
BPF_B
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_PROTO_TYPE_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
IPPROTO_UDP
,
0
,
9
),
// Make sure this isn't a fragment by checking that the fragment
// offset field in the IP header is zero. This field is the
...
...
@@ -68,7 +69,22 @@ struct sock_filter dhcp_sock_filter [] = {
// the IP header, so the half-word at offset 20 (6 + size of
// Ethernet header) is loaded and an appropriate mask applied.
BPF_STMT
(
BPF_LD
+
BPF_H
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_FLAGS_OFFSET
),
BPF_JUMP
(
BPF_JMP
+
BPF_JSET
+
BPF_K
,
0x1fff
,
4
,
0
),
BPF_JUMP
(
BPF_JMP
+
BPF_JSET
+
BPF_K
,
0x1fff
,
7
,
0
),
// Check the packet's destination address. The program will only
// allow the packets sent to the broadcast address or unicast
// to the specific address on the interface. By default, this
// address is set to 0 and must be set to the specific value
// when the raw socket is created and the program is attached
// to it. The caller must assign the address to the
// prog.bf_insns[8].k in the network byte order.
BPF_STMT
(
BPF_LD
+
BPF_W
+
BPF_ABS
,
ETHERNET_HEADER_LEN
+
IP_DEST_ADDR_OFFSET
),
// If this is a broadcast address, skip the next check.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0xffffffff
,
1
,
0
),
// If this is not broadcast address, compare it with the unicast
// address specified for the interface.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
0x00000000
,
0
,
4
),
// Get the IP header length. This is achieved by the following
// (special) instruction that, given the offset of the start
...
...
@@ -82,9 +98,9 @@ struct sock_filter dhcp_sock_filter [] = {
// of the UDP destination port (2) within the UDP header.
BPF_STMT
(
BPF_LD
+
BPF_H
+
BPF_IND
,
ETHERNET_HEADER_LEN
+
UDP_DEST_PORT
),
// The following instruction tests against the default DHCP server port,
// but the action port is actually set in PktFilter
L
PF::openSocket().
// but the action port is actually set in PktFilter
B
PF::openSocket().
// N.B. The code in that method assumes that this instruction is at
// offset
8
in the program. If this is changed, openSocket() must be
// offset
11
in the program. If this is changed, openSocket() must be
// updated.
BPF_JUMP
(
BPF_JMP
+
BPF_JEQ
+
BPF_K
,
DHCP4_SERVER_PORT
,
0
,
1
),
...
...
@@ -129,8 +145,14 @@ PktFilterLPF::openSocket(Iface& iface,
filter_program
.
filter
=
dhcp_sock_filter
;
filter_program
.
len
=
sizeof
(
dhcp_sock_filter
)
/
sizeof
(
struct
sock_filter
);
// Configure the filter program to receive unicast packets sent to the
// specified address. The program will also allow packets sent to the
// 255.255.255.255 broadcast address.
prog
.
bf_insns
[
8
].
k
=
static_cast
<
uint32_t
>
(
addr
);
// Override the default port value.
dhcp_sock_filter
[
8
].
k
=
port
;
dhcp_sock_filter
[
11
].
k
=
port
;
// Apply the filter.
if
(
setsockopt
(
sock
,
SOL_SOCKET
,
SO_ATTACH_FILTER
,
&
filter_program
,
sizeof
(
filter_program
))
<
0
)
{
...
...
src/lib/dhcp/protocol_util.h
View file @
71390391
...
...
@@ -56,6 +56,8 @@ static const size_t IP_FLAGS_OFFSET = 6;
static
const
size_t
IP_PROTO_TYPE_OFFSET
=
9
;
/// Offset of source address in the IPv4 header.
static
const
size_t
IP_SRC_ADDR_OFFSET
=
12
;
/// Offset of destination address in the IPv4 header.
static
const
size_t
IP_DEST_ADDR_OFFSET
=
16
;
/// UDP header length.
static
const
size_t
UDP_HEADER_LEN
=
8
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment