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