linux/net/ipv6/udp.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *	UDP over IPv6
 *	Linux INET6 implementation
 *
 *	Authors:
 *	Pedro Roque		<[email protected]>
 *
 *	Based on linux/ipv4/udp.c
 *
 *	Fixes:
 *	Hideaki YOSHIFUJI	:	sin6_scope_id support
 *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
 *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
 *					a single port at the same time.
 *      Kazunori MIYAZAWA @USAGI:       change process style to use ip6_append_data
 *      YOSHIFUJI Hideaki @USAGI:	convert /proc/net/udp6 to seq_file.
 */

#include <linux/bpf-cgroup.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/indirect_call_wrapper.h>
#include <trace/events/udp.h>

#include <net/addrconf.h>
#include <net/ndisc.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
#include <net/ip6_route.h>
#include <net/raw.h>
#include <net/seg6.h>
#include <net/tcp_states.h>
#include <net/ip6_checksum.h>
#include <net/ip6_tunnel.h>
#include <net/xfrm.h>
#include <net/inet_hashtables.h>
#include <net/inet6_hashtables.h>
#include <net/busy_poll.h>
#include <net/sock_reuseport.h>
#include <net/gro.h>

#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <trace/events/skb.h>
#include "udp_impl.h"

static void udpv6_destruct_sock(struct sock *sk)
{}

int udpv6_init_sock(struct sock *sk)
{}

INDIRECT_CALLABLE_SCOPE
u32 udp6_ehashfn(const struct net *net,
		 const struct in6_addr *laddr,
		 const u16 lport,
		 const struct in6_addr *faddr,
		 const __be16 fport)
{}

int udp_v6_get_port(struct sock *sk, unsigned short snum)
{}

void udp_v6_rehash(struct sock *sk)
{}

static int compute_score(struct sock *sk, struct net *net,
			 const struct in6_addr *saddr, __be16 sport,
			 const struct in6_addr *daddr, unsigned short hnum,
			 int dif, int sdif)
{}

/* called with rcu_read_lock() */
static struct sock *udp6_lib_lookup2(struct net *net,
		const struct in6_addr *saddr, __be16 sport,
		const struct in6_addr *daddr, unsigned int hnum,
		int dif, int sdif, struct udp_hslot *hslot2,
		struct sk_buff *skb)
{}

/* rcu_read_lock() must be held */
struct sock *__udp6_lib_lookup(struct net *net,
			       const struct in6_addr *saddr, __be16 sport,
			       const struct in6_addr *daddr, __be16 dport,
			       int dif, int sdif, struct udp_table *udptable,
			       struct sk_buff *skb)
{}
EXPORT_SYMBOL_GPL();

static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
					  __be16 sport, __be16 dport,
					  struct udp_table *udptable)
{}

struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
				 __be16 sport, __be16 dport)
{}

/* Must be called under rcu_read_lock().
 * Does increment socket refcount.
 */
#if IS_ENABLED(CONFIG_NF_TPROXY_IPV6) || IS_ENABLED(CONFIG_NF_SOCKET_IPV6)
struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
			     const struct in6_addr *daddr, __be16 dport, int dif)
{}
EXPORT_SYMBOL_GPL();
#endif

/* do not use the scratch area len for jumbogram: their length execeeds the
 * scratch area space; note that the IP6CB flags is still in the first
 * cacheline, so checking for jumbograms is cheap
 */
static int udp6_skb_len(struct sk_buff *skb)
{}

/*
 *	This should be easy, if there is something there we
 *	return it, otherwise we block.
 */

int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
		  int flags, int *addr_len)
{}

DECLARE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
void udpv6_encap_enable(void)
{}
EXPORT_SYMBOL();

/* Handler for tunnels with arbitrary destination ports: no socket lookup, go
 * through error handlers in encapsulations looking for a match.
 */
static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
				      struct inet6_skb_parm *opt,
				      u8 type, u8 code, int offset, __be32 info)
{}

/* Try to match ICMP errors to UDP tunnels by looking up a socket without
 * reversing source and destination port: this will match tunnels that force the
 * same destination port on both endpoints (e.g. VXLAN, GENEVE). Note that
 * lwtunnels might actually break this assumption by being configured with
 * different destination ports on endpoints, in this case we won't be able to
 * trace ICMP messages back to them.
 *
 * If this doesn't match any socket, probe tunnels with arbitrary destination
 * ports (e.g. FoU, GUE): there, the receiving socket is useless, as the port
 * we've sent packets to won't necessarily match the local destination port.
 *
 * Then ask the tunnel implementation to match the error against a valid
 * association.
 *
 * Return an error if we can't find a match, the socket if we need further
 * processing, zero otherwise.
 */
static struct sock *__udp6_lib_err_encap(struct net *net,
					 const struct ipv6hdr *hdr, int offset,
					 struct udphdr *uh,
					 struct udp_table *udptable,
					 struct sock *sk,
					 struct sk_buff *skb,
					 struct inet6_skb_parm *opt,
					 u8 type, u8 code, __be32 info)
{}

int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
		   u8 type, u8 code, int offset, __be32 info,
		   struct udp_table *udptable)
{}

static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{}

static __inline__ int udpv6_err(struct sk_buff *skb,
				struct inet6_skb_parm *opt, u8 type,
				u8 code, int offset, __be32 info)
{}

static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
{}

static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{}

static bool __udp_v6_is_mcast_sock(struct net *net, const struct sock *sk,
				   __be16 loc_port, const struct in6_addr *loc_addr,
				   __be16 rmt_port, const struct in6_addr *rmt_addr,
				   int dif, int sdif, unsigned short hnum)
{}

static void udp6_csum_zero_error(struct sk_buff *skb)
{}

/*
 * Note: called only from the BH handler context,
 * so we don't need to lock the hashes.
 */
static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
		const struct in6_addr *saddr, const struct in6_addr *daddr,
		struct udp_table *udptable, int proto)
{}

static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
{}

/* wrapper for udp_queue_rcv_skb tacking care of csum conversion and
 * return code conversion for ip layer consumption
 */
static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
				struct udphdr *uh)
{}

int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
		   int proto)
{}


static struct sock *__udp6_lib_demux_lookup(struct net *net,
			__be16 loc_port, const struct in6_addr *loc_addr,
			__be16 rmt_port, const struct in6_addr *rmt_addr,
			int dif, int sdif)
{}

void udp_v6_early_demux(struct sk_buff *skb)
{}

INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb)
{}

/*
 * Throw away all pending data and cancel the corking. Socket is locked.
 */
static void udp_v6_flush_pending_frames(struct sock *sk)
{}

static int udpv6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
			     int addr_len)
{}

/**
 *	udp6_hwcsum_outgoing  -  handle outgoing HW checksumming
 *	@sk:	socket we are sending on
 *	@skb:	sk_buff containing the filled-in UDP header
 *		(checksum field must be zeroed out)
 *	@saddr: source address
 *	@daddr: destination address
 *	@len:	length of packet
 */
static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
				 const struct in6_addr *saddr,
				 const struct in6_addr *daddr, int len)
{}

/*
 *	Sending
 */

static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
			   struct inet_cork *cork)
{}

static int udp_v6_push_pending_frames(struct sock *sk)
{}

int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{}
EXPORT_SYMBOL();

static void udpv6_splice_eof(struct socket *sock)
{}

void udpv6_destroy_sock(struct sock *sk)
{}

/*
 *	Socket option code for UDP
 */
int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
		     unsigned int optlen)
{}

int udpv6_getsockopt(struct sock *sk, int level, int optname,
		     char __user *optval, int __user *optlen)
{}


/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
int udp6_seq_show(struct seq_file *seq, void *v)
{}

const struct seq_operations udp6_seq_ops =;
EXPORT_SYMBOL();

static struct udp_seq_afinfo udp6_seq_afinfo =;

int __net_init udp6_proc_init(struct net *net)
{}

void udp6_proc_exit(struct net *net)
{}
#endif /* CONFIG_PROC_FS */

/* ------------------------------------------------------------------------ */

struct proto udpv6_prot =;

static struct inet_protosw udpv6_protosw =;

int __init udpv6_init(void)
{}

void udpv6_exit(void)
{}