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>
10 #include <linux/ipv6.h>
12 #include <linux/tcp.h>
13 #include <linux/udp.h>
14 #include <uapi/linux/bpf.h>
16 #include "bpf_helpers.h"
18 #define DEFAULT_PKTGEN_UDP_PORT 9
21 static int tcp(void *data
, uint64_t tp_off
, void *data_end
)
23 struct tcphdr
*tcp
= data
+ tp_off
;
25 if (tcp
+ 1 > data_end
)
27 if (tcp
->dest
== htons(80) || tcp
->source
== htons(80))
32 static int udp(void *data
, uint64_t tp_off
, void *data_end
)
34 struct udphdr
*udp
= data
+ tp_off
;
36 if (udp
+ 1 > data_end
)
38 if (udp
->dest
== htons(DEFAULT_PKTGEN_UDP_PORT
) ||
39 udp
->source
== htons(DEFAULT_PKTGEN_UDP_PORT
)) {
41 char fmt
[] = "udp port 9 indeed\n";
43 bpf_trace_printk(fmt
, sizeof(fmt
));
50 static int parse_ipv4(void *data
, uint64_t nh_off
, void *data_end
)
56 if (iph
+ 1 > data_end
)
59 if (ip_is_fragment(iph
))
61 ihl_len
= iph
->ihl
* 4;
63 if (iph
->protocol
== IPPROTO_IPIP
) {
64 iph
= data
+ nh_off
+ ihl_len
;
65 if (iph
+ 1 > data_end
)
67 ihl_len
+= iph
->ihl
* 4;
70 if (iph
->protocol
== IPPROTO_TCP
)
71 return tcp(data
, nh_off
+ ihl_len
, data_end
);
72 else if (iph
->protocol
== IPPROTO_UDP
)
73 return udp(data
, nh_off
+ ihl_len
, data_end
);
77 static int parse_ipv6(void *data
, uint64_t nh_off
, void *data_end
)
81 uint64_t ihl_len
= sizeof(struct ipv6hdr
);
85 if (ip6h
+ 1 > data_end
)
88 nexthdr
= ip6h
->nexthdr
;
90 if (nexthdr
== IPPROTO_IPIP
) {
91 iph
= data
+ nh_off
+ ihl_len
;
92 if (iph
+ 1 > data_end
)
94 ihl_len
+= iph
->ihl
* 4;
95 nexthdr
= iph
->protocol
;
96 } else if (nexthdr
== IPPROTO_IPV6
) {
97 ip6h
= data
+ nh_off
+ ihl_len
;
98 if (ip6h
+ 1 > data_end
)
100 ihl_len
+= sizeof(struct ipv6hdr
);
101 nexthdr
= ip6h
->nexthdr
;
104 if (nexthdr
== IPPROTO_TCP
)
105 return tcp(data
, nh_off
+ ihl_len
, data_end
);
106 else if (nexthdr
== IPPROTO_UDP
)
107 return udp(data
, nh_off
+ ihl_len
, data_end
);
113 uint16_t h_vlan_encapsulated_proto
;
117 int handle_ingress(struct __sk_buff
*skb
)
119 void *data
= (void *)(long)skb
->data
;
120 struct ethhdr
*eth
= data
;
121 void *data_end
= (void *)(long)skb
->data_end
;
122 uint64_t h_proto
, nh_off
;
124 nh_off
= sizeof(*eth
);
125 if (data
+ nh_off
> data_end
)
128 h_proto
= eth
->h_proto
;
130 if (h_proto
== ETH_P_8021Q
|| h_proto
== ETH_P_8021AD
) {
131 struct vlan_hdr
*vhdr
;
133 vhdr
= data
+ nh_off
;
134 nh_off
+= sizeof(struct vlan_hdr
);
135 if (data
+ nh_off
> data_end
)
137 h_proto
= vhdr
->h_vlan_encapsulated_proto
;
139 if (h_proto
== ETH_P_8021Q
|| h_proto
== ETH_P_8021AD
) {
140 struct vlan_hdr
*vhdr
;
142 vhdr
= data
+ nh_off
;
143 nh_off
+= sizeof(struct vlan_hdr
);
144 if (data
+ nh_off
> data_end
)
146 h_proto
= vhdr
->h_vlan_encapsulated_proto
;
148 if (h_proto
== htons(ETH_P_IP
))
149 return parse_ipv4(data
, nh_off
, data_end
);
150 else if (h_proto
== htons(ETH_P_IPV6
))
151 return parse_ipv6(data
, nh_off
, data_end
);
154 char _license
[] SEC("license") = "GPL";