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