Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
0cd58f5f
Commit
0cd58f5f
authored
May 11, 2016
by
4ast
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #536 from valkum/master
Add new example with test case for for unroll, as requested.
parents
80a4e9ef
ce86b466
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
162 additions
and
0 deletions
+162
-0
examples/networking/dns_matching/dns_matching.c
examples/networking/dns_matching/dns_matching.c
+105
-0
examples/networking/dns_matching/dns_matching.py
examples/networking/dns_matching/dns_matching.py
+57
-0
No files found.
examples/networking/dns_matching/dns_matching.c
0 → 100644
View file @
0cd58f5f
/*
* dns_matching.c Drop DNS packets requesting DNS name contained in hash map
* For Linux, uses BCC, eBPF. See .py file.
*
* Copyright (c) 2016 Rudi Floren.
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 11-May-2016 Rudi Floren Created this.
*/
#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/if_packet.h>
#include <uapi/linux/ip.h>
#include <uapi/linux/in.h>
#include <uapi/linux/udp.h>
#include <bcc/proto.h>
#define ETH_LEN 14
struct
dns_hdr_t
{
uint16_t
id
;
uint16_t
flags
;
uint16_t
qdcount
;
uint16_t
ancount
;
uint16_t
nscount
;
uint16_t
arcount
;
}
BPF_PACKET_HEADER
;
struct
dns_query_flags_t
{
uint16_t
qtype
;
uint16_t
qclass
;
}
BPF_PACKET_HEADER
;
struct
dns_char_t
{
char
c
;
}
BPF_PACKET_HEADER
;
struct
Key
{
unsigned
char
p
[
32
];
};
struct
Leaf
{
// Not really needed in this example
unsigned
char
p
[
4
];
};
BPF_TABLE
(
"hash"
,
struct
Key
,
struct
Leaf
,
cache
,
128
);
int
dns_matching
(
struct
__sk_buff
*
skb
)
{
u8
*
cursor
=
0
;
struct
Key
key
=
{};
// Check of ethernet/IP frame.
struct
ethernet_t
*
ethernet
=
cursor_advance
(
cursor
,
sizeof
(
*
ethernet
));
if
(
ethernet
->
type
==
ETH_P_IP
)
{
// Check for UDP.
struct
ip_t
*
ip
=
cursor_advance
(
cursor
,
sizeof
(
*
ip
));
u16
hlen_bytes
=
ip
->
hlen
<<
2
;
if
(
ip
->
nextp
==
IPPROTO_UDP
)
{
// Check for Port 53, DNS packet.
struct
udp_t
*
udp
=
cursor_advance
(
cursor
,
sizeof
(
*
udp
));
if
(
udp
->
dport
==
53
){
// Our Cursor + the length of our udp packet - size of the udp header
// - the two 16bit values for QTYPE and QCLASS.
u8
*
sentinel
=
cursor
+
udp
->
length
-
sizeof
(
*
udp
)
-
4
;
struct
dns_hdr_t
*
dns_hdr
=
cursor_advance
(
cursor
,
sizeof
(
*
dns_hdr
));
// Do nothing if packet is not a request.
if
((
dns_hdr
->
flags
>>
15
)
!=
0
)
{
// Exit if this packet is not a request.
return
-
1
;
}
u16
i
=
0
;
struct
dns_char_t
*
c
;
// This unroll worked not in latest BCC version.
for
(
u8
j
=
0
;
i
<
255
;
i
++
){
if
(
cursor
==
sentinel
)
goto
end
;
c
=
cursor_advance
(
cursor
,
1
);
key
.
p
[
i
++
]
=
c
->
c
;
}
end:
{}
struct
Leaf
*
lookup_leaf
=
cache
.
lookup
(
&
key
);
// If DNS name is contained in our map, drop packet.
if
(
lookup_leaf
)
{
return
0
;
}
}
}
}
return
-
1
;
}
examples/networking/dns_matching/dns_matching.py
0 → 100644
View file @
0cd58f5f
#!/usr/bin/python
from
__future__
import
print_function
from
bcc
import
BPF
from
ctypes
import
*
import
sys
import
socket
import
os
import
struct
def
encode_dns
(
name
):
size
=
32
if
len
(
name
)
>
253
:
raise
Exception
(
"DNS Name too long."
)
b
=
bytearray
(
size
)
i
=
0
;
elements
=
name
.
split
(
"."
)
for
element
in
elements
:
b
[
i
]
=
struct
.
pack
(
"!B"
,
len
(
element
))
i
+=
1
for
j
in
range
(
0
,
len
(
element
)):
b
[
i
]
=
element
[
j
]
i
+=
1
return
(
c_ubyte
*
size
).
from_buffer
(
b
)
# initialize BPF - load source code from http-parse-simple.c
bpf
=
BPF
(
src_file
=
"dns_matching.c"
,
debug
=
0
)
# print(bpf.dump_func("dns_test"))
#load eBPF program http_filter of type SOCKET_FILTER into the kernel eBPF vm
#more info about eBPF program types
#http://man7.org/linux/man-pages/man2/bpf.2.html
function_dns_matching
=
bpf
.
load_func
(
"dns_matching"
,
BPF
.
SOCKET_FILTER
)
#create raw socket, bind it to eth0
#attach bpf program to socket created
BPF
.
attach_raw_socket
(
function_dns_matching
,
"eth1"
)
# Get the table.
cache
=
bpf
.
get_table
(
"cache"
)
# Create first entry for foo.bar
key
=
cache
.
Key
()
key
.
p
=
encode_dns
(
"foo.bar"
)
leaf
=
cache
.
Leaf
()
leaf
.
p
=
(
c_ubyte
*
4
).
from_buffer
(
bytearray
(
4
))
cache
[
key
]
=
leaf
bpf
.
trace_print
()
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