1 /* Copyright (c) 2016 Facebook
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
7 #define KBUILD_MODNAME "foo"
8 #include <linux/if_ether.h>
9 #include <linux/if_vlan.h>
11 #include <linux/ipv6.h>
13 #include <linux/tcp.h>
14 #include <linux/udp.h>
15 #include <uapi/linux/bpf.h>
17 #include "bpf_helpers.h"
19 #define DEFAULT_PKTGEN_UDP_PORT 9
22 static int tcp(void *data
, uint64_t tp_off
, void *data_end
)
24 struct tcphdr
*tcp
= data
+ tp_off
;
26 if (tcp
+ 1 > data_end
)
28 if (tcp
->dest
== htons(80) || tcp
->source
== htons(80))
33 static int udp(void *data
, uint64_t tp_off
, void *data_end
)
35 struct udphdr
*udp
= data
+ tp_off
;
37 if (udp
+ 1 > data_end
)
39 if (udp
->dest
== htons(DEFAULT_PKTGEN_UDP_PORT
) ||
40 udp
->source
== htons(DEFAULT_PKTGEN_UDP_PORT
)) {
42 char fmt
[] = "udp port 9 indeed\n";
44 bpf_trace_printk(fmt
, sizeof(fmt
));
51 static int parse_ipv4(void *data
, uint64_t nh_off
, void *data_end
)
57 if (iph
+ 1 > data_end
)
60 if (ip_is_fragment(iph
))
62 ihl_len
= iph
->ihl
* 4;
64 if (iph
->protocol
== IPPROTO_IPIP
) {
65 iph
= data
+ nh_off
+ ihl_len
;
66 if (iph
+ 1 > data_end
)
68 ihl_len
+= iph
->ihl
* 4;
71 if (iph
->protocol
== IPPROTO_TCP
)
72 return tcp(data
, nh_off
+ ihl_len
, data_end
);
73 else if (iph
->protocol
== IPPROTO_UDP
)
74 return udp(data
, nh_off
+ ihl_len
, data_end
);
78 static int parse_ipv6(void *data
, uint64_t nh_off
, void *data_end
)
82 uint64_t ihl_len
= sizeof(struct ipv6hdr
);
86 if (ip6h
+ 1 > data_end
)
89 nexthdr
= ip6h
->nexthdr
;
91 if (nexthdr
== IPPROTO_IPIP
) {
92 iph
= data
+ nh_off
+ ihl_len
;
93 if (iph
+ 1 > data_end
)
95 ihl_len
+= iph
->ihl
* 4;
96 nexthdr
= iph
->protocol
;
97 } else if (nexthdr
== IPPROTO_IPV6
) {
98 ip6h
= data
+ nh_off
+ ihl_len
;
99 if (ip6h
+ 1 > data_end
)
101 ihl_len
+= sizeof(struct ipv6hdr
);
102 nexthdr
= ip6h
->nexthdr
;
105 if (nexthdr
== IPPROTO_TCP
)
106 return tcp(data
, nh_off
+ ihl_len
, data_end
);
107 else if (nexthdr
== IPPROTO_UDP
)
108 return udp(data
, nh_off
+ ihl_len
, data_end
);
113 int handle_ingress(struct __sk_buff
*skb
)
115 void *data
= (void *)(long)skb
->data
;
116 struct ethhdr
*eth
= data
;
117 void *data_end
= (void *)(long)skb
->data_end
;
118 uint64_t h_proto
, nh_off
;
120 nh_off
= sizeof(*eth
);
121 if (data
+ nh_off
> data_end
)
124 h_proto
= eth
->h_proto
;
126 if (h_proto
== ETH_P_8021Q
|| h_proto
== ETH_P_8021AD
) {
127 struct vlan_hdr
*vhdr
;
129 vhdr
= data
+ nh_off
;
130 nh_off
+= sizeof(struct vlan_hdr
);
131 if (data
+ nh_off
> data_end
)
133 h_proto
= vhdr
->h_vlan_encapsulated_proto
;
135 if (h_proto
== ETH_P_8021Q
|| h_proto
== ETH_P_8021AD
) {
136 struct vlan_hdr
*vhdr
;
138 vhdr
= data
+ nh_off
;
139 nh_off
+= sizeof(struct vlan_hdr
);
140 if (data
+ nh_off
> data_end
)
142 h_proto
= vhdr
->h_vlan_encapsulated_proto
;
144 if (h_proto
== htons(ETH_P_IP
))
145 return parse_ipv4(data
, nh_off
, data_end
);
146 else if (h_proto
== htons(ETH_P_IPV6
))
147 return parse_ipv6(data
, nh_off
, data_end
);
150 char _license
[] SEC("license") = "GPL";