14
14
#define MAX_PAYLOAD_LEN 5000
15
15
#define MAX_HDR_LEN 64
16
16
17
+ extern int bpf_xdp_pull_data (struct xdp_md * xdp , __u32 len ,
18
+ __u64 flags ) __ksym __weak ;
19
+
17
20
enum {
18
21
XDP_MODE = 0 ,
19
22
XDP_PORT = 1 ,
@@ -68,30 +71,57 @@ static void record_stats(struct xdp_md *ctx, __u32 stat_type)
68
71
69
72
static struct udphdr * filter_udphdr (struct xdp_md * ctx , __u16 port )
70
73
{
71
- void * data_end = (void * )(long )ctx -> data_end ;
72
- void * data = (void * )(long )ctx -> data ;
73
74
struct udphdr * udph = NULL ;
74
- struct ethhdr * eth = data ;
75
+ void * data , * data_end ;
76
+ struct ethhdr * eth ;
77
+ int err ;
78
+
79
+ err = bpf_xdp_pull_data (ctx , sizeof (* eth ), 0 );
80
+ if (err )
81
+ return NULL ;
82
+
83
+ data_end = (void * )(long )ctx -> data_end ;
84
+ data = eth = (void * )(long )ctx -> data ;
75
85
76
86
if (data + sizeof (* eth ) > data_end )
77
87
return NULL ;
78
88
79
89
if (eth -> h_proto == bpf_htons (ETH_P_IP )) {
80
- struct iphdr * iph = data + sizeof (* eth );
90
+ struct iphdr * iph ;
91
+
92
+ err = bpf_xdp_pull_data (ctx , sizeof (* eth ) + sizeof (* iph ) +
93
+ sizeof (* udph ), 0 );
94
+ if (err )
95
+ return NULL ;
96
+
97
+ data_end = (void * )(long )ctx -> data_end ;
98
+ data = (void * )(long )ctx -> data ;
99
+
100
+ iph = data + sizeof (* eth );
81
101
82
102
if (iph + 1 > (struct iphdr * )data_end ||
83
103
iph -> protocol != IPPROTO_UDP )
84
104
return NULL ;
85
105
86
- udph = (void * )eth + sizeof (* iph ) + sizeof (* eth );
87
- } else if (eth -> h_proto == bpf_htons (ETH_P_IPV6 )) {
88
- struct ipv6hdr * ipv6h = data + sizeof (* eth );
106
+ udph = data + sizeof (* iph ) + sizeof (* eth );
107
+ } else if (eth -> h_proto == bpf_htons (ETH_P_IPV6 )) {
108
+ struct ipv6hdr * ipv6h ;
109
+
110
+ err = bpf_xdp_pull_data (ctx , sizeof (* eth ) + sizeof (* ipv6h ) +
111
+ sizeof (* udph ), 0 );
112
+ if (err )
113
+ return NULL ;
114
+
115
+ data_end = (void * )(long )ctx -> data_end ;
116
+ data = (void * )(long )ctx -> data ;
117
+
118
+ ipv6h = data + sizeof (* eth );
89
119
90
120
if (ipv6h + 1 > (struct ipv6hdr * )data_end ||
91
121
ipv6h -> nexthdr != IPPROTO_UDP )
92
122
return NULL ;
93
123
94
- udph = ( void * ) eth + sizeof (* ipv6h ) + sizeof (* eth );
124
+ udph = data + sizeof (* ipv6h ) + sizeof (* eth );
95
125
} else {
96
126
return NULL ;
97
127
}
@@ -145,17 +175,34 @@ static void swap_machdr(void *data)
145
175
146
176
static int xdp_mode_tx_handler (struct xdp_md * ctx , __u16 port )
147
177
{
148
- void * data_end = (void * )(long )ctx -> data_end ;
149
- void * data = (void * )(long )ctx -> data ;
150
178
struct udphdr * udph = NULL ;
151
- struct ethhdr * eth = data ;
179
+ void * data , * data_end ;
180
+ struct ethhdr * eth ;
181
+ int err ;
182
+
183
+ err = bpf_xdp_pull_data (ctx , sizeof (* eth ), 0 );
184
+ if (err )
185
+ return XDP_PASS ;
186
+
187
+ data_end = (void * )(long )ctx -> data_end ;
188
+ data = eth = (void * )(long )ctx -> data ;
152
189
153
190
if (data + sizeof (* eth ) > data_end )
154
191
return XDP_PASS ;
155
192
156
193
if (eth -> h_proto == bpf_htons (ETH_P_IP )) {
157
- struct iphdr * iph = data + sizeof (* eth );
158
- __be32 tmp_ip = iph -> saddr ;
194
+ struct iphdr * iph ;
195
+ __be32 tmp_ip ;
196
+
197
+ err = bpf_xdp_pull_data (ctx , sizeof (* eth ) + sizeof (* iph ) +
198
+ sizeof (* udph ), 0 );
199
+ if (err )
200
+ return XDP_PASS ;
201
+
202
+ data_end = (void * )(long )ctx -> data_end ;
203
+ data = (void * )(long )ctx -> data ;
204
+
205
+ iph = data + sizeof (* eth );
159
206
160
207
if (iph + 1 > (struct iphdr * )data_end ||
161
208
iph -> protocol != IPPROTO_UDP )
@@ -169,18 +216,30 @@ static int xdp_mode_tx_handler(struct xdp_md *ctx, __u16 port)
169
216
return XDP_PASS ;
170
217
171
218
record_stats (ctx , STATS_RX );
219
+ eth = data ;
172
220
swap_machdr ((void * )eth );
173
221
222
+ tmp_ip = iph -> saddr ;
174
223
iph -> saddr = iph -> daddr ;
175
224
iph -> daddr = tmp_ip ;
176
225
177
226
record_stats (ctx , STATS_TX );
178
227
179
228
return XDP_TX ;
180
229
181
- } else if (eth -> h_proto == bpf_htons (ETH_P_IPV6 )) {
182
- struct ipv6hdr * ipv6h = data + sizeof (* eth );
230
+ } else if (eth -> h_proto == bpf_htons (ETH_P_IPV6 )) {
183
231
struct in6_addr tmp_ipv6 ;
232
+ struct ipv6hdr * ipv6h ;
233
+
234
+ err = bpf_xdp_pull_data (ctx , sizeof (* eth ) + sizeof (* ipv6h ) +
235
+ sizeof (* udph ), 0 );
236
+ if (err )
237
+ return XDP_PASS ;
238
+
239
+ data_end = (void * )(long )ctx -> data_end ;
240
+ data = (void * )(long )ctx -> data ;
241
+
242
+ ipv6h = data + sizeof (* eth );
184
243
185
244
if (ipv6h + 1 > (struct ipv6hdr * )data_end ||
186
245
ipv6h -> nexthdr != IPPROTO_UDP )
@@ -194,6 +253,7 @@ static int xdp_mode_tx_handler(struct xdp_md *ctx, __u16 port)
194
253
return XDP_PASS ;
195
254
196
255
record_stats (ctx , STATS_RX );
256
+ eth = data ;
197
257
swap_machdr ((void * )eth );
198
258
199
259
__builtin_memcpy (& tmp_ipv6 , & ipv6h -> saddr , sizeof (tmp_ipv6 ));
0 commit comments