1414#define MAX_PAYLOAD_LEN 5000
1515#define MAX_HDR_LEN 64
1616
17+ extern int bpf_xdp_pull_data (struct xdp_md * xdp , __u32 len ,
18+ __u64 flags ) __ksym __weak ;
19+
1720enum {
1821 XDP_MODE = 0 ,
1922 XDP_PORT = 1 ,
@@ -68,30 +71,57 @@ static void record_stats(struct xdp_md *ctx, __u32 stat_type)
6871
6972static struct udphdr * filter_udphdr (struct xdp_md * ctx , __u16 port )
7073{
71- void * data_end = (void * )(long )ctx -> data_end ;
72- void * data = (void * )(long )ctx -> data ;
7374 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 ;
7585
7686 if (data + sizeof (* eth ) > data_end )
7787 return NULL ;
7888
7989 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 );
81101
82102 if (iph + 1 > (struct iphdr * )data_end ||
83103 iph -> protocol != IPPROTO_UDP )
84104 return NULL ;
85105
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 );
89119
90120 if (ipv6h + 1 > (struct ipv6hdr * )data_end ||
91121 ipv6h -> nexthdr != IPPROTO_UDP )
92122 return NULL ;
93123
94- udph = ( void * ) eth + sizeof (* ipv6h ) + sizeof (* eth );
124+ udph = data + sizeof (* ipv6h ) + sizeof (* eth );
95125 } else {
96126 return NULL ;
97127 }
@@ -145,17 +175,34 @@ static void swap_machdr(void *data)
145175
146176static int xdp_mode_tx_handler (struct xdp_md * ctx , __u16 port )
147177{
148- void * data_end = (void * )(long )ctx -> data_end ;
149- void * data = (void * )(long )ctx -> data ;
150178 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 ;
152189
153190 if (data + sizeof (* eth ) > data_end )
154191 return XDP_PASS ;
155192
156193 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 );
159206
160207 if (iph + 1 > (struct iphdr * )data_end ||
161208 iph -> protocol != IPPROTO_UDP )
@@ -169,18 +216,30 @@ static int xdp_mode_tx_handler(struct xdp_md *ctx, __u16 port)
169216 return XDP_PASS ;
170217
171218 record_stats (ctx , STATS_RX );
219+ eth = data ;
172220 swap_machdr ((void * )eth );
173221
222+ tmp_ip = iph -> saddr ;
174223 iph -> saddr = iph -> daddr ;
175224 iph -> daddr = tmp_ip ;
176225
177226 record_stats (ctx , STATS_TX );
178227
179228 return XDP_TX ;
180229
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 )) {
183231 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 );
184243
185244 if (ipv6h + 1 > (struct ipv6hdr * )data_end ||
186245 ipv6h -> nexthdr != IPPROTO_UDP )
@@ -194,6 +253,7 @@ static int xdp_mode_tx_handler(struct xdp_md *ctx, __u16 port)
194253 return XDP_PASS ;
195254
196255 record_stats (ctx , STATS_RX );
256+ eth = data ;
197257 swap_machdr ((void * )eth );
198258
199259 __builtin_memcpy (& tmp_ipv6 , & ipv6h -> saddr , sizeof (tmp_ipv6 ));
0 commit comments