1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_VIRTIO_NET_H
3 #define _LINUX_VIRTIO_NET_H
4
5 #include <linux/if_vlan.h>
6 #include <linux/ip.h>
7 #include <linux/ipv6.h>
8 #include <linux/udp.h>
9 #include <net/tcp.h>
10 #include <uapi/linux/tcp.h>
11 #include <uapi/linux/virtio_net.h>
12
virtio_net_hdr_match_proto(__be16 protocol,__u8 gso_type)13 static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type)
14 {
15 switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
16 case VIRTIO_NET_HDR_GSO_TCPV4:
17 return protocol == cpu_to_be16(ETH_P_IP);
18 case VIRTIO_NET_HDR_GSO_TCPV6:
19 return protocol == cpu_to_be16(ETH_P_IPV6);
20 case VIRTIO_NET_HDR_GSO_UDP:
21 case VIRTIO_NET_HDR_GSO_UDP_L4:
22 return protocol == cpu_to_be16(ETH_P_IP) ||
23 protocol == cpu_to_be16(ETH_P_IPV6);
24 default:
25 return false;
26 }
27 }
28
virtio_net_hdr_set_proto(struct sk_buff * skb,const struct virtio_net_hdr * hdr)29 static inline int virtio_net_hdr_set_proto(struct sk_buff *skb,
30 const struct virtio_net_hdr *hdr)
31 {
32 if (skb->protocol)
33 return 0;
34
35 switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
36 case VIRTIO_NET_HDR_GSO_TCPV4:
37 case VIRTIO_NET_HDR_GSO_UDP:
38 case VIRTIO_NET_HDR_GSO_UDP_L4:
39 skb->protocol = cpu_to_be16(ETH_P_IP);
40 break;
41 case VIRTIO_NET_HDR_GSO_TCPV6:
42 skb->protocol = cpu_to_be16(ETH_P_IPV6);
43 break;
44 default:
45 return -EINVAL;
46 }
47
48 return 0;
49 }
50
__virtio_net_hdr_to_skb(struct sk_buff * skb,const struct virtio_net_hdr * hdr,bool little_endian,u8 hdr_gso_type)51 static inline int __virtio_net_hdr_to_skb(struct sk_buff *skb,
52 const struct virtio_net_hdr *hdr,
53 bool little_endian, u8 hdr_gso_type)
54 {
55 unsigned int nh_min_len = sizeof(struct iphdr);
56 unsigned int gso_type = 0;
57 unsigned int thlen = 0;
58 unsigned int p_off = 0;
59 unsigned int ip_proto;
60
61 if (hdr_gso_type != VIRTIO_NET_HDR_GSO_NONE) {
62 switch (hdr_gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
63 case VIRTIO_NET_HDR_GSO_TCPV4:
64 gso_type = SKB_GSO_TCPV4;
65 ip_proto = IPPROTO_TCP;
66 thlen = sizeof(struct tcphdr);
67 break;
68 case VIRTIO_NET_HDR_GSO_TCPV6:
69 gso_type = SKB_GSO_TCPV6;
70 ip_proto = IPPROTO_TCP;
71 thlen = sizeof(struct tcphdr);
72 nh_min_len = sizeof(struct ipv6hdr);
73 break;
74 case VIRTIO_NET_HDR_GSO_UDP:
75 gso_type = SKB_GSO_UDP;
76 ip_proto = IPPROTO_UDP;
77 thlen = sizeof(struct udphdr);
78 break;
79 case VIRTIO_NET_HDR_GSO_UDP_L4:
80 gso_type = SKB_GSO_UDP_L4;
81 ip_proto = IPPROTO_UDP;
82 thlen = sizeof(struct udphdr);
83 break;
84 default:
85 return -EINVAL;
86 }
87
88 if (hdr_gso_type & VIRTIO_NET_HDR_GSO_ECN)
89 gso_type |= SKB_GSO_TCP_ECN;
90
91 if (hdr->gso_size == 0)
92 return -EINVAL;
93 }
94
95 skb_reset_mac_header(skb);
96
97 if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
98 u32 start = __virtio16_to_cpu(little_endian, hdr->csum_start);
99 u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset);
100 u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16));
101
102 if (!pskb_may_pull(skb, needed))
103 return -EINVAL;
104
105 if (!skb_partial_csum_set(skb, start, off))
106 return -EINVAL;
107 if (skb_transport_offset(skb) < nh_min_len)
108 return -EINVAL;
109
110 nh_min_len = skb_transport_offset(skb);
111 p_off = nh_min_len + thlen;
112 if (!pskb_may_pull(skb, p_off))
113 return -EINVAL;
114 } else {
115 /* gso packets without NEEDS_CSUM do not set transport_offset.
116 * probe and drop if does not match one of the above types.
117 */
118 if (gso_type && skb->network_header) {
119 struct flow_keys_basic keys;
120
121 if (!skb->protocol) {
122 __be16 protocol = dev_parse_header_protocol(skb);
123
124 if (!protocol)
125 virtio_net_hdr_set_proto(skb, hdr);
126 else if (!virtio_net_hdr_match_proto(protocol,
127 hdr_gso_type))
128 return -EINVAL;
129 else
130 skb->protocol = protocol;
131 }
132 retry:
133 if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
134 NULL, 0, 0, 0,
135 0)) {
136 /* UFO does not specify ipv4 or 6: try both */
137 if (gso_type & SKB_GSO_UDP &&
138 skb->protocol == htons(ETH_P_IP)) {
139 skb->protocol = htons(ETH_P_IPV6);
140 goto retry;
141 }
142 return -EINVAL;
143 }
144
145 p_off = keys.control.thoff + thlen;
146 if (!pskb_may_pull(skb, p_off) ||
147 keys.basic.ip_proto != ip_proto)
148 return -EINVAL;
149
150 skb_set_transport_header(skb, keys.control.thoff);
151 } else if (gso_type) {
152 p_off = nh_min_len + thlen;
153 if (!pskb_may_pull(skb, p_off))
154 return -EINVAL;
155 }
156 }
157
158 if (hdr_gso_type != VIRTIO_NET_HDR_GSO_NONE) {
159 u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size);
160 unsigned int nh_off = p_off;
161 struct skb_shared_info *shinfo = skb_shinfo(skb);
162
163 switch (gso_type & ~SKB_GSO_TCP_ECN) {
164 case SKB_GSO_UDP:
165 /* UFO may not include transport header in gso_size. */
166 nh_off -= thlen;
167 break;
168 case SKB_GSO_UDP_L4:
169 if (!(hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM))
170 return -EINVAL;
171 if (skb->csum_offset != offsetof(struct udphdr, check))
172 return -EINVAL;
173 if (skb->len - p_off > gso_size * UDP_MAX_SEGMENTS)
174 return -EINVAL;
175 if (gso_type != SKB_GSO_UDP_L4)
176 return -EINVAL;
177 break;
178 case SKB_GSO_TCPV4:
179 case SKB_GSO_TCPV6:
180 if (skb->ip_summed == CHECKSUM_PARTIAL &&
181 skb->csum_offset != offsetof(struct tcphdr, check))
182 return -EINVAL;
183
184 BUILD_BUG_ON(TCP_MIN_GSO_SIZE * GSO_MAX_SEGS < GSO_MAX_SIZE);
185 gso_size = max(gso_size, TCP_MIN_GSO_SIZE);
186 break;
187 }
188
189 /* Kernel has a special handling for GSO_BY_FRAGS. */
190 if (gso_size == GSO_BY_FRAGS)
191 return -EINVAL;
192
193 /* Too small packets are not really GSO ones. */
194 if (skb->len - nh_off > gso_size) {
195 shinfo->gso_size = gso_size;
196 shinfo->gso_type = gso_type;
197
198 /* Header must be checked, and gso_segs computed. */
199 shinfo->gso_type |= SKB_GSO_DODGY;
200 shinfo->gso_segs = 0;
201 }
202 }
203
204 return 0;
205 }
206
virtio_net_hdr_to_skb(struct sk_buff * skb,const struct virtio_net_hdr * hdr,bool little_endian)207 static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
208 const struct virtio_net_hdr *hdr,
209 bool little_endian)
210 {
211 return __virtio_net_hdr_to_skb(skb, hdr, little_endian, hdr->gso_type);
212 }
213
214 /* This function must be called after virtio_net_hdr_from_skb(). */
__virtio_net_set_hdrlen(const struct sk_buff * skb,struct virtio_net_hdr * hdr,bool little_endian)215 static inline void __virtio_net_set_hdrlen(const struct sk_buff *skb,
216 struct virtio_net_hdr *hdr,
217 bool little_endian)
218 {
219 u16 hdr_len;
220
221 hdr_len = skb_transport_offset(skb);
222
223 if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4)
224 hdr_len += sizeof(struct udphdr);
225 else
226 hdr_len += tcp_hdrlen(skb);
227
228 hdr->hdr_len = __cpu_to_virtio16(little_endian, hdr_len);
229 }
230
231 /* This function must be called after virtio_net_hdr_from_skb(). */
__virtio_net_set_tnl_hdrlen(const struct sk_buff * skb,struct virtio_net_hdr * hdr)232 static inline void __virtio_net_set_tnl_hdrlen(const struct sk_buff *skb,
233 struct virtio_net_hdr *hdr)
234 {
235 u16 hdr_len;
236
237 hdr_len = skb_inner_transport_offset(skb);
238
239 if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4)
240 hdr_len += sizeof(struct udphdr);
241 else
242 hdr_len += inner_tcp_hdrlen(skb);
243
244 hdr->hdr_len = __cpu_to_virtio16(true, hdr_len);
245 }
246
virtio_net_hdr_from_skb(const struct sk_buff * skb,struct virtio_net_hdr * hdr,bool little_endian,bool has_data_valid,int vlan_hlen)247 static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
248 struct virtio_net_hdr *hdr,
249 bool little_endian,
250 bool has_data_valid,
251 int vlan_hlen)
252 {
253 memset(hdr, 0, sizeof(*hdr)); /* no info leak */
254
255 if (skb_is_gso(skb)) {
256 struct skb_shared_info *sinfo = skb_shinfo(skb);
257
258 /* This is a hint as to how much should be linear. */
259 hdr->hdr_len = __cpu_to_virtio16(little_endian,
260 skb_headlen(skb));
261 hdr->gso_size = __cpu_to_virtio16(little_endian,
262 sinfo->gso_size);
263 if (sinfo->gso_type & SKB_GSO_TCPV4)
264 hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
265 else if (sinfo->gso_type & SKB_GSO_TCPV6)
266 hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
267 else if (sinfo->gso_type & SKB_GSO_UDP_L4)
268 hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP_L4;
269 else
270 return -EINVAL;
271 if (sinfo->gso_type & SKB_GSO_TCP_ECN)
272 hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN;
273 } else
274 hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
275
276 if (skb->ip_summed == CHECKSUM_PARTIAL) {
277 hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
278 hdr->csum_start = __cpu_to_virtio16(little_endian,
279 skb_checksum_start_offset(skb) + vlan_hlen);
280 hdr->csum_offset = __cpu_to_virtio16(little_endian,
281 skb->csum_offset);
282 } else if (has_data_valid &&
283 skb->ip_summed == CHECKSUM_UNNECESSARY) {
284 hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
285 } /* else everything is zero */
286
287 return 0;
288 }
289
virtio_l3min(bool is_ipv6)290 static inline unsigned int virtio_l3min(bool is_ipv6)
291 {
292 return is_ipv6 ? sizeof(struct ipv6hdr) : sizeof(struct iphdr);
293 }
294
295 static inline int
virtio_net_hdr_tnl_to_skb(struct sk_buff * skb,const struct virtio_net_hdr_v1_hash_tunnel * vhdr,bool tnl_hdr_negotiated,bool tnl_csum_negotiated,bool little_endian)296 virtio_net_hdr_tnl_to_skb(struct sk_buff *skb,
297 const struct virtio_net_hdr_v1_hash_tunnel *vhdr,
298 bool tnl_hdr_negotiated,
299 bool tnl_csum_negotiated,
300 bool little_endian)
301 {
302 const struct virtio_net_hdr *hdr = (const struct virtio_net_hdr *)vhdr;
303 unsigned int inner_nh, outer_th, inner_th;
304 unsigned int inner_l3min, outer_l3min;
305 u8 gso_inner_type, gso_tunnel_type;
306 bool outer_isv6, inner_isv6;
307 int ret;
308
309 gso_tunnel_type = hdr->gso_type & VIRTIO_NET_HDR_GSO_UDP_TUNNEL;
310 if (!gso_tunnel_type)
311 return virtio_net_hdr_to_skb(skb, hdr, little_endian);
312
313 /* Tunnel not supported/negotiated, but the hdr asks for it. */
314 if (!tnl_hdr_negotiated)
315 return -EINVAL;
316
317 /* Either ipv4 or ipv6. */
318 if (gso_tunnel_type == VIRTIO_NET_HDR_GSO_UDP_TUNNEL)
319 return -EINVAL;
320
321 /* The UDP tunnel must carry a GSO packet, but no UFO. */
322 gso_inner_type = hdr->gso_type & ~(VIRTIO_NET_HDR_GSO_ECN |
323 VIRTIO_NET_HDR_GSO_UDP_TUNNEL);
324 if (!gso_inner_type || gso_inner_type == VIRTIO_NET_HDR_GSO_UDP)
325 return -EINVAL;
326
327 /* Rely on csum being present. */
328 if (!(hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM))
329 return -EINVAL;
330
331 /* Validate offsets. */
332 outer_isv6 = gso_tunnel_type & VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6;
333 inner_isv6 = gso_inner_type == VIRTIO_NET_HDR_GSO_TCPV6;
334 inner_l3min = virtio_l3min(inner_isv6);
335 outer_l3min = ETH_HLEN + virtio_l3min(outer_isv6);
336
337 inner_th = __virtio16_to_cpu(little_endian, hdr->csum_start);
338 inner_nh = le16_to_cpu(vhdr->inner_nh_offset);
339 outer_th = le16_to_cpu(vhdr->outer_th_offset);
340 if (outer_th < outer_l3min ||
341 inner_nh < outer_th + sizeof(struct udphdr) ||
342 inner_th < inner_nh + inner_l3min)
343 return -EINVAL;
344
345 /* Let the basic parsing deal with plain GSO features. */
346 ret = __virtio_net_hdr_to_skb(skb, hdr, true,
347 hdr->gso_type & ~gso_tunnel_type);
348 if (ret)
349 return ret;
350
351 /* In case of USO, the inner protocol is still unknown and
352 * `inner_isv6` is just a guess, additional parsing is needed.
353 * The previous validation ensures that accessing an ipv4 inner
354 * network header is safe.
355 */
356 if (gso_inner_type == VIRTIO_NET_HDR_GSO_UDP_L4) {
357 struct iphdr *iphdr = (struct iphdr *)(skb->data + inner_nh);
358
359 inner_isv6 = iphdr->version == 6;
360 inner_l3min = virtio_l3min(inner_isv6);
361 if (inner_th < inner_nh + inner_l3min)
362 return -EINVAL;
363 }
364
365 skb_set_inner_protocol(skb, inner_isv6 ? htons(ETH_P_IPV6) :
366 htons(ETH_P_IP));
367 if (hdr->flags & VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM) {
368 if (!tnl_csum_negotiated)
369 return -EINVAL;
370
371 skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM;
372 } else {
373 skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
374 }
375
376 skb->inner_transport_header = inner_th + skb_headroom(skb);
377 skb->inner_network_header = inner_nh + skb_headroom(skb);
378 skb->inner_mac_header = inner_nh + skb_headroom(skb);
379 skb->transport_header = outer_th + skb_headroom(skb);
380 skb->encapsulation = 1;
381 return 0;
382 }
383
384 /* Checksum-related fields validation for the driver */
virtio_net_handle_csum_offload(struct sk_buff * skb,struct virtio_net_hdr * hdr,bool tnl_csum_negotiated)385 static inline int virtio_net_handle_csum_offload(struct sk_buff *skb,
386 struct virtio_net_hdr *hdr,
387 bool tnl_csum_negotiated)
388 {
389 if (!(hdr->gso_type & VIRTIO_NET_HDR_GSO_UDP_TUNNEL)) {
390 if (!(hdr->flags & VIRTIO_NET_HDR_F_DATA_VALID))
391 return 0;
392
393 skb->ip_summed = CHECKSUM_UNNECESSARY;
394 if (!(hdr->flags & VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM))
395 return 0;
396
397 /* tunnel csum packets are invalid when the related
398 * feature has not been negotiated
399 */
400 if (!tnl_csum_negotiated)
401 return -EINVAL;
402 skb->csum_level = 1;
403 return 0;
404 }
405
406 /* DATA_VALID is mutually exclusive with NEEDS_CSUM, and GSO
407 * over UDP tunnel requires the latter
408 */
409 if (hdr->flags & VIRTIO_NET_HDR_F_DATA_VALID)
410 return -EINVAL;
411 return 0;
412 }
413
414 /*
415 * vlan_hlen always refers to the outermost MAC header. That also
416 * means it refers to the only MAC header, if the packet does not carry
417 * any encapsulation.
418 */
419 static inline int
virtio_net_hdr_tnl_from_skb(const struct sk_buff * skb,struct virtio_net_hdr_v1_hash_tunnel * vhdr,bool tnl_hdr_negotiated,bool little_endian,int vlan_hlen,bool has_data_valid,bool feature_hdrlen)420 virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb,
421 struct virtio_net_hdr_v1_hash_tunnel *vhdr,
422 bool tnl_hdr_negotiated,
423 bool little_endian,
424 int vlan_hlen,
425 bool has_data_valid,
426 bool feature_hdrlen)
427 {
428 struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)vhdr;
429 unsigned int inner_nh, outer_th;
430 int tnl_gso_type;
431 int ret;
432
433 tnl_gso_type = skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL |
434 SKB_GSO_UDP_TUNNEL_CSUM);
435 if (!tnl_gso_type) {
436 ret = virtio_net_hdr_from_skb(skb, hdr, little_endian,
437 has_data_valid, vlan_hlen);
438 if (ret)
439 return ret;
440
441 if (feature_hdrlen && hdr->hdr_len)
442 __virtio_net_set_hdrlen(skb, hdr, little_endian);
443
444 return ret;
445 }
446
447 /* Tunnel support not negotiated but skb ask for it. */
448 if (!tnl_hdr_negotiated)
449 return -EINVAL;
450
451 vhdr->hash_hdr.hash_value_lo = 0;
452 vhdr->hash_hdr.hash_value_hi = 0;
453 vhdr->hash_hdr.hash_report = 0;
454 vhdr->hash_hdr.padding = 0;
455
456 /* Let the basic parsing deal with plain GSO features. */
457 skb_shinfo(skb)->gso_type &= ~tnl_gso_type;
458 ret = virtio_net_hdr_from_skb(skb, hdr, true, false, vlan_hlen);
459 skb_shinfo(skb)->gso_type |= tnl_gso_type;
460 if (ret)
461 return ret;
462
463 if (feature_hdrlen && hdr->hdr_len)
464 __virtio_net_set_tnl_hdrlen(skb, hdr);
465
466 if (skb->protocol == htons(ETH_P_IPV6))
467 hdr->gso_type |= VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6;
468 else
469 hdr->gso_type |= VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4;
470
471 if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
472 hdr->flags |= VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM;
473
474 inner_nh = skb->inner_network_header - skb_headroom(skb);
475 outer_th = skb->transport_header - skb_headroom(skb);
476 vhdr->inner_nh_offset = cpu_to_le16(inner_nh);
477 vhdr->outer_th_offset = cpu_to_le16(outer_th);
478 return 0;
479 }
480
481 #endif /* _LINUX_VIRTIO_NET_H */
482