1 // Copyright (c) PLUMgrid, Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License")
3
4 #include <bcc/proto.h>
5
6 struct ipkey {
7 u32 client_ip;
8 };
9
10 BPF_HASH(learned_ips, struct ipkey, int, 1024);
11
12 // trivial action
pass(struct __sk_buff * skb)13 int pass(struct __sk_buff *skb) {
14 return 1;
15 }
16
17 // Process each wan packet, and determine if the packet is in the IP
18 // table or not. Learned IPs are rate-limited and unclassified are not.
19 // returns: > 0 when an IP is known
20 // = 0 when an IP is not known, or non-IP traffic
classify_wan(struct __sk_buff * skb)21 int classify_wan(struct __sk_buff *skb) {
22 u8 *cursor = 0;
23 ethernet: {
24 struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
25 switch (ethernet->type) {
26 case ETH_P_IP: goto ip;
27 default: goto EOP;
28 }
29 }
30 ip: {
31 struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
32 u32 dip = ip->dst;
33 struct ipkey key = {.client_ip=dip};
34 int *val = learned_ips.lookup(&key);
35 if (val)
36 return *val;
37 goto EOP;
38 }
39 EOP:
40 return 0;
41 }
42
43 // Process each neighbor packet, and store the source IP in the learned table.
44 // Mark the inserted entry with a non-zero value to be used by the classify_wan
45 // lookup.
classify_neighbor(struct __sk_buff * skb)46 int classify_neighbor(struct __sk_buff *skb) {
47 u8 *cursor = 0;
48 ethernet: {
49 struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
50 switch (ethernet->type) {
51 case ETH_P_IP: goto ip;
52 default: goto EOP;
53 }
54 }
55 ip: {
56 struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
57 u32 sip = ip->src;
58 struct ipkey key = {.client_ip=sip};
59 int val = 1;
60 learned_ips.insert(&key, &val);
61 goto EOP;
62 }
63 EOP:
64 return 1;
65 }
66