.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | /* |
---|
2 | 3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
---|
3 | 4 | * operating system. INET is implemented using the BSD Socket |
---|
.. | .. |
---|
13 | 14 | * Fixes: |
---|
14 | 15 | * Alan Cox : Turned on udp checksums. I don't want to |
---|
15 | 16 | * chase 'memory corruption' bugs that aren't! |
---|
16 | | - * |
---|
17 | | - * This program is free software; you can redistribute it and/or |
---|
18 | | - * modify it under the terms of the GNU General Public License |
---|
19 | | - * as published by the Free Software Foundation; either version |
---|
20 | | - * 2 of the License, or (at your option) any later version. |
---|
21 | 17 | */ |
---|
22 | 18 | #ifndef _UDP_H |
---|
23 | 19 | #define _UDP_H |
---|
.. | .. |
---|
31 | 27 | #include <linux/ipv6.h> |
---|
32 | 28 | #include <linux/seq_file.h> |
---|
33 | 29 | #include <linux/poll.h> |
---|
| 30 | +#include <linux/indirect_call_wrapper.h> |
---|
34 | 31 | |
---|
35 | 32 | /** |
---|
36 | 33 | * struct udp_skb_cb - UDP(-Lite) private variables |
---|
.. | .. |
---|
170 | 167 | typedef struct sock *(*udp_lookup_t)(struct sk_buff *skb, __be16 sport, |
---|
171 | 168 | __be16 dport); |
---|
172 | 169 | |
---|
| 170 | +INDIRECT_CALLABLE_DECLARE(struct sk_buff *udp4_gro_receive(struct list_head *, |
---|
| 171 | + struct sk_buff *)); |
---|
| 172 | +INDIRECT_CALLABLE_DECLARE(int udp4_gro_complete(struct sk_buff *, int)); |
---|
| 173 | +INDIRECT_CALLABLE_DECLARE(struct sk_buff *udp6_gro_receive(struct list_head *, |
---|
| 174 | + struct sk_buff *)); |
---|
| 175 | +INDIRECT_CALLABLE_DECLARE(int udp6_gro_complete(struct sk_buff *, int)); |
---|
173 | 176 | struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb, |
---|
174 | | - struct udphdr *uh, udp_lookup_t lookup); |
---|
| 177 | + struct udphdr *uh, struct sock *sk); |
---|
175 | 178 | int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup); |
---|
| 179 | +void udp_v6_early_demux(struct sk_buff *skb); |
---|
176 | 180 | |
---|
177 | 181 | struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, |
---|
178 | | - netdev_features_t features); |
---|
| 182 | + netdev_features_t features, bool is_ipv6); |
---|
179 | 183 | |
---|
180 | 184 | static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb) |
---|
181 | 185 | { |
---|
.. | .. |
---|
252 | 256 | return sk_rmem_alloc_get(sk) - READ_ONCE(udp_sk(sk)->forward_deficit); |
---|
253 | 257 | } |
---|
254 | 258 | |
---|
| 259 | +static inline bool udp_sk_bound_dev_eq(struct net *net, int bound_dev_if, |
---|
| 260 | + int dif, int sdif) |
---|
| 261 | +{ |
---|
| 262 | +#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) |
---|
| 263 | + return inet_bound_dev_eq(!!READ_ONCE(net->ipv4.sysctl_udp_l3mdev_accept), |
---|
| 264 | + bound_dev_if, dif, sdif); |
---|
| 265 | +#else |
---|
| 266 | + return inet_bound_dev_eq(true, bound_dev_if, dif, sdif); |
---|
| 267 | +#endif |
---|
| 268 | +} |
---|
| 269 | + |
---|
255 | 270 | /* net/ipv4/udp.c */ |
---|
256 | | -void udp_destruct_sock(struct sock *sk); |
---|
| 271 | +void udp_destruct_common(struct sock *sk); |
---|
257 | 272 | void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len); |
---|
258 | 273 | int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb); |
---|
259 | 274 | void udp_skb_destructor(struct sock *sk, struct sk_buff *skb); |
---|
260 | 275 | struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags, |
---|
261 | | - int noblock, int *peeked, int *off, int *err); |
---|
| 276 | + int noblock, int *off, int *err); |
---|
262 | 277 | static inline struct sk_buff *skb_recv_udp(struct sock *sk, unsigned int flags, |
---|
263 | 278 | int noblock, int *err) |
---|
264 | 279 | { |
---|
265 | | - int peeked, off = 0; |
---|
| 280 | + int off = 0; |
---|
266 | 281 | |
---|
267 | | - return __skb_recv_udp(sk, flags, noblock, &peeked, &off, err); |
---|
| 282 | + return __skb_recv_udp(sk, flags, noblock, &off, err); |
---|
268 | 283 | } |
---|
269 | 284 | |
---|
270 | 285 | int udp_v4_early_demux(struct sk_buff *skb); |
---|
.. | .. |
---|
272 | 287 | int udp_get_port(struct sock *sk, unsigned short snum, |
---|
273 | 288 | int (*saddr_cmp)(const struct sock *, |
---|
274 | 289 | const struct sock *)); |
---|
275 | | -void udp_err(struct sk_buff *, u32); |
---|
| 290 | +int udp_err(struct sk_buff *, u32); |
---|
276 | 291 | int udp_abort(struct sock *sk, int err); |
---|
277 | 292 | int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); |
---|
278 | 293 | int udp_push_pending_frames(struct sock *sk); |
---|
.. | .. |
---|
292 | 307 | int udp_lib_getsockopt(struct sock *sk, int level, int optname, |
---|
293 | 308 | char __user *optval, int __user *optlen); |
---|
294 | 309 | int udp_lib_setsockopt(struct sock *sk, int level, int optname, |
---|
295 | | - char __user *optval, unsigned int optlen, |
---|
| 310 | + sockptr_t optval, unsigned int optlen, |
---|
296 | 311 | int (*push_pending_frames)(struct sock *)); |
---|
297 | 312 | struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, |
---|
298 | 313 | __be32 daddr, __be16 dport, int dif); |
---|
.. | .. |
---|
406 | 421 | } while(0) |
---|
407 | 422 | |
---|
408 | 423 | #if IS_ENABLED(CONFIG_IPV6) |
---|
409 | | -#define __UDPX_INC_STATS(sk, field) \ |
---|
410 | | -do { \ |
---|
411 | | - if ((sk)->sk_family == AF_INET) \ |
---|
412 | | - __UDP_INC_STATS(sock_net(sk), field, 0); \ |
---|
413 | | - else \ |
---|
414 | | - __UDP6_INC_STATS(sock_net(sk), field, 0); \ |
---|
415 | | -} while (0) |
---|
| 424 | +#define __UDPX_MIB(sk, ipv4) \ |
---|
| 425 | +({ \ |
---|
| 426 | + ipv4 ? (IS_UDPLITE(sk) ? sock_net(sk)->mib.udplite_statistics : \ |
---|
| 427 | + sock_net(sk)->mib.udp_statistics) : \ |
---|
| 428 | + (IS_UDPLITE(sk) ? sock_net(sk)->mib.udplite_stats_in6 : \ |
---|
| 429 | + sock_net(sk)->mib.udp_stats_in6); \ |
---|
| 430 | +}) |
---|
416 | 431 | #else |
---|
417 | | -#define __UDPX_INC_STATS(sk, field) __UDP_INC_STATS(sock_net(sk), field, 0) |
---|
| 432 | +#define __UDPX_MIB(sk, ipv4) \ |
---|
| 433 | +({ \ |
---|
| 434 | + IS_UDPLITE(sk) ? sock_net(sk)->mib.udplite_statistics : \ |
---|
| 435 | + sock_net(sk)->mib.udp_statistics; \ |
---|
| 436 | +}) |
---|
418 | 437 | #endif |
---|
| 438 | + |
---|
| 439 | +#define __UDPX_INC_STATS(sk, field) \ |
---|
| 440 | + __SNMP_INC_STATS(__UDPX_MIB(sk, (sk)->sk_family == AF_INET), field) |
---|
419 | 441 | |
---|
420 | 442 | #ifdef CONFIG_PROC_FS |
---|
421 | 443 | struct udp_seq_afinfo { |
---|
.. | .. |
---|
426 | 448 | struct udp_iter_state { |
---|
427 | 449 | struct seq_net_private p; |
---|
428 | 450 | int bucket; |
---|
| 451 | + struct udp_seq_afinfo *bpf_seq_afinfo; |
---|
429 | 452 | }; |
---|
430 | 453 | |
---|
431 | 454 | void *udp_seq_start(struct seq_file *seq, loff_t *pos); |
---|
.. | .. |
---|
443 | 466 | |
---|
444 | 467 | void udp_init(void); |
---|
445 | 468 | |
---|
| 469 | +DECLARE_STATIC_KEY_FALSE(udp_encap_needed_key); |
---|
446 | 470 | void udp_encap_enable(void); |
---|
| 471 | +void udp_encap_disable(void); |
---|
447 | 472 | #if IS_ENABLED(CONFIG_IPV6) |
---|
| 473 | +DECLARE_STATIC_KEY_FALSE(udpv6_encap_needed_key); |
---|
448 | 474 | void udpv6_encap_enable(void); |
---|
449 | 475 | #endif |
---|
450 | 476 | |
---|
| 477 | +static inline struct sk_buff *udp_rcv_segment(struct sock *sk, |
---|
| 478 | + struct sk_buff *skb, bool ipv4) |
---|
| 479 | +{ |
---|
| 480 | + netdev_features_t features = NETIF_F_SG; |
---|
| 481 | + struct sk_buff *segs; |
---|
| 482 | + |
---|
| 483 | + /* Avoid csum recalculation by skb_segment unless userspace explicitly |
---|
| 484 | + * asks for the final checksum values |
---|
| 485 | + */ |
---|
| 486 | + if (!inet_get_convert_csum(sk)) |
---|
| 487 | + features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; |
---|
| 488 | + |
---|
| 489 | + /* UDP segmentation expects packets of type CHECKSUM_PARTIAL or |
---|
| 490 | + * CHECKSUM_NONE in __udp_gso_segment. UDP GRO indeed builds partial |
---|
| 491 | + * packets in udp_gro_complete_segment. As does UDP GSO, verified by |
---|
| 492 | + * udp_send_skb. But when those packets are looped in dev_loopback_xmit |
---|
| 493 | + * their ip_summed CHECKSUM_NONE is changed to CHECKSUM_UNNECESSARY. |
---|
| 494 | + * Reset in this specific case, where PARTIAL is both correct and |
---|
| 495 | + * required. |
---|
| 496 | + */ |
---|
| 497 | + if (skb->pkt_type == PACKET_LOOPBACK) |
---|
| 498 | + skb->ip_summed = CHECKSUM_PARTIAL; |
---|
| 499 | + |
---|
| 500 | + /* the GSO CB lays after the UDP one, no need to save and restore any |
---|
| 501 | + * CB fragment |
---|
| 502 | + */ |
---|
| 503 | + segs = __skb_gso_segment(skb, features, false); |
---|
| 504 | + if (IS_ERR_OR_NULL(segs)) { |
---|
| 505 | + int segs_nr = skb_shinfo(skb)->gso_segs; |
---|
| 506 | + |
---|
| 507 | + atomic_add(segs_nr, &sk->sk_drops); |
---|
| 508 | + SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, segs_nr); |
---|
| 509 | + kfree_skb(skb); |
---|
| 510 | + return NULL; |
---|
| 511 | + } |
---|
| 512 | + |
---|
| 513 | + consume_skb(skb); |
---|
| 514 | + return segs; |
---|
| 515 | +} |
---|
| 516 | + |
---|
| 517 | +#ifdef CONFIG_BPF_STREAM_PARSER |
---|
| 518 | +struct sk_psock; |
---|
| 519 | +struct proto *udp_bpf_get_proto(struct sock *sk, struct sk_psock *psock); |
---|
| 520 | +#endif /* BPF_STREAM_PARSER */ |
---|
| 521 | + |
---|
451 | 522 | #endif /* _UDP_H */ |
---|