udp.h 8.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 * INET		An implementation of the TCP/IP protocol suite for the LINUX
 *		operating system.  INET is implemented using the  BSD Socket
 *		interface as the means of communication with the user level.
 *
 *		Definitions for the UDP module.
 *
 * Version:	@(#)udp.h	1.0.2	05/07/93
 *
10
 * Authors:	Ross Biro
L
Linus Torvalds 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *
 * Fixes:
 *		Alan Cox	: Turned on udp checksums. I don't want to
 *				  chase 'memory corruption' bugs that aren't!
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 */
#ifndef _UDP_H
#define _UDP_H

#include <linux/list.h>
26
#include <linux/bug.h>
27
#include <net/inet_sock.h>
L
Linus Torvalds 已提交
28 29
#include <net/sock.h>
#include <net/snmp.h>
30 31
#include <net/ip.h>
#include <linux/ipv6.h>
L
Linus Torvalds 已提交
32
#include <linux/seq_file.h>
A
Al Viro 已提交
33
#include <linux/poll.h>
L
Linus Torvalds 已提交
34

35 36 37 38 39 40 41 42 43 44
/**
 *	struct udp_skb_cb  -  UDP(-Lite) private variables
 *
 *	@header:      private variables used by IPv4/IPv6
 *	@cscov:       checksum coverage length (UDP-Lite only)
 *	@partial_cov: if set indicates partial csum coverage
 */
struct udp_skb_cb {
	union {
		struct inet_skb_parm	h4;
E
Eric Dumazet 已提交
45
#if IS_ENABLED(CONFIG_IPV6)
46 47 48 49 50 51 52
		struct inet6_skb_parm	h6;
#endif
	} header;
	__u16		cscov;
	__u8		partial_cov;
};
#define UDP_SKB_CB(__skb)	((struct udp_skb_cb *)((__skb)->cb))
L
Linus Torvalds 已提交
53

E
Eric Dumazet 已提交
54 55 56 57 58 59 60
/**
 *	struct udp_hslot - UDP hash slot
 *
 *	@head:	head of list of sockets
 *	@count:	number of sockets in 'head' list
 *	@lock:	spinlock protecting changes to head/count
 */
61
struct udp_hslot {
62
	struct hlist_nulls_head	head;
E
Eric Dumazet 已提交
63
	int			count;
64 65
	spinlock_t		lock;
} __attribute__((aligned(2 * sizeof(long))));
66

67 68 69 70 71 72 73 74
/**
 *	struct udp_table - UDP table
 *
 *	@hash:	hash table, sockets are hashed on (local port)
 *	@hash2:	hash table, sockets are hashed on (local port, local address)
 *	@mask:	number of slots in hash tables, minus 1
 *	@log:	log2(number of slots in hash table)
 */
75
struct udp_table {
76
	struct udp_hslot	*hash;
77 78 79
	struct udp_hslot	*hash2;
	unsigned int		mask;
	unsigned int		log;
80 81
};
extern struct udp_table udp_table;
82
void udp_table_init(struct udp_table *, const char *);
83
static inline struct udp_hslot *udp_hashslot(struct udp_table *table,
84
					     struct net *net, unsigned int num)
85 86 87
{
	return &table->hash[udp_hashfn(net, num, table->mask)];
}
88 89 90 91 92 93 94 95 96
/*
 * For secondary hash, net_hash_mix() is performed before calling
 * udp_hashslot2(), this explains difference with udp_hashslot()
 */
static inline struct udp_hslot *udp_hashslot2(struct udp_table *table,
					      unsigned int hash)
{
	return &table->hash2[hash & table->mask];
}
L
Linus Torvalds 已提交
97 98 99

extern struct proto udp_prot;

E
Eric Dumazet 已提交
100
extern atomic_long_t udp_memory_allocated;
H
Hideo Aoki 已提交
101 102

/* sysctl variables for udp */
E
Eric Dumazet 已提交
103
extern long sysctl_udp_mem[3];
H
Hideo Aoki 已提交
104 105 106
extern int sysctl_udp_rmem_min;
extern int sysctl_udp_wmem_min;

107
struct sk_buff;
L
Linus Torvalds 已提交
108

109 110 111
/*
 *	Generic checksumming routines for UDP(-Lite) v4 and v6
 */
112
static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
113
{
114
	return __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov);
115 116
}

117
static inline int udp_lib_checksum_complete(struct sk_buff *skb)
118
{
119
	return !skb_csum_unnecessary(skb) &&
120 121 122 123 124 125 126 127 128
		__udp_lib_checksum_complete(skb);
}

/**
 * 	udp_csum_outgoing  -  compute UDPv4/v6 checksum over fragments
 * 	@sk: 	socket we are writing to
 * 	@skb: 	sk_buff containing the filled-in UDP header
 * 	        (checksum field must be zeroed out)
 */
129
static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb)
130
{
131 132
	__wsum csum = csum_partial(skb_transport_header(skb),
				   sizeof(struct udphdr), 0);
133 134 135 136 137 138
	skb_queue_walk(&sk->sk_write_queue, skb) {
		csum = csum_add(csum, skb->csum);
	}
	return csum;
}

H
Herbert Xu 已提交
139 140 141 142 143 144 145 146 147 148 149
static inline __wsum udp_csum(struct sk_buff *skb)
{
	__wsum csum = csum_partial(skb_transport_header(skb),
				   sizeof(struct udphdr), skb->csum);

	for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) {
		csum = csum_add(csum, skb->csum);
	}
	return csum;
}

150 151 152 153 154 155 156 157 158
static inline __sum16 udp_v4_check(int len, __be32 saddr,
				   __be32 daddr, __wsum base)
{
	return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
}

void udp_set_csum(bool nocheck, struct sk_buff *skb,
		  __be32 saddr, __be32 daddr, int len);

159 160 161 162 163 164
/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
static inline void udp_lib_hash(struct sock *sk)
{
	BUG();
}

165 166
void udp_lib_unhash(struct sock *sk);
void udp_lib_rehash(struct sock *sk, u16 new_hash);
167 168 169 170 171 172

static inline void udp_lib_close(struct sock *sk, long timeout)
{
	sk_common_release(sk);
}

173 174 175
int udp_lib_get_port(struct sock *sk, unsigned short snum,
		     int (*)(const struct sock *, const struct sock *),
		     unsigned int hash2_nulladdr);
176 177

/* net/ipv4/udp.c */
S
Shawn Bohrer 已提交
178
void udp_v4_early_demux(struct sk_buff *skb);
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
int udp_get_port(struct sock *sk, unsigned short snum,
		 int (*saddr_cmp)(const struct sock *,
				  const struct sock *));
void udp_err(struct sk_buff *, u32);
int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
		size_t len);
int udp_push_pending_frames(struct sock *sk);
void udp_flush_pending_frames(struct sock *sk);
void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
int udp_rcv(struct sk_buff *skb);
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
int udp_disconnect(struct sock *sk, int flags);
unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait);
struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
				       netdev_features_t features);
int udp_lib_getsockopt(struct sock *sk, int level, int optname,
		       char __user *optval, int __user *optlen);
int udp_lib_setsockopt(struct sock *sk, int level, int optname,
		       char __user *optval, unsigned int optlen,
		       int (*push_pending_frames)(struct sock *));
struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
			     __be32 daddr, __be16 dport, int dif);
struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
			       __be32 daddr, __be16 dport, int dif,
			       struct udp_table *tbl);
struct sock *udp6_lib_lookup(struct net *net,
			     const struct in6_addr *saddr, __be16 sport,
			     const struct in6_addr *daddr, __be16 dport,
			     int dif);
struct sock *__udp6_lib_lookup(struct net *net,
			       const struct in6_addr *saddr, __be16 sport,
			       const struct in6_addr *daddr, __be16 dport,
			       int dif, struct udp_table *tbl);
212

213 214 215
/*
 * 	SNMP statistics for UDP and UDP-Lite
 */
216
#define UDP_INC_STATS_USER(net, field, is_udplite)	      do { \
217
	if (is_udplite) SNMP_INC_STATS_USER((net)->mib.udplite_statistics, field);       \
218 219
	else		SNMP_INC_STATS_USER((net)->mib.udp_statistics, field);  }  while(0)
#define UDP_INC_STATS_BH(net, field, is_udplite) 	      do { \
220
	if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_statistics, field);         \
221
	else		SNMP_INC_STATS_BH((net)->mib.udp_statistics, field);    }  while(0)
L
Linus Torvalds 已提交
222

223
#define UDP6_INC_STATS_BH(net, field, is_udplite) 	    do { \
224
	if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_stats_in6, field);\
225 226
	else		SNMP_INC_STATS_BH((net)->mib.udp_stats_in6, field);  \
} while(0)
227 228 229
#define UDP6_INC_STATS_USER(net, field, __lite)		    do { \
	if (__lite) SNMP_INC_STATS_USER((net)->mib.udplite_stats_in6, field);  \
	else	    SNMP_INC_STATS_USER((net)->mib.udp_stats_in6, field);      \
230
} while(0)
231

E
Eric Dumazet 已提交
232
#if IS_ENABLED(CONFIG_IPV6)
233 234 235 236 237 238 239
#define UDPX_INC_STATS_BH(sk, field)					\
do {									\
	if ((sk)->sk_family == AF_INET)					\
		UDP_INC_STATS_BH(sock_net(sk), field, 0);		\
	else								\
		UDP6_INC_STATS_BH(sock_net(sk), field, 0);		\
} while (0)
240
#else
241
#define UDPX_INC_STATS_BH(sk, field) UDP_INC_STATS_BH(sock_net(sk), field, 0)
242 243
#endif

L
Linus Torvalds 已提交
244
/* /proc */
245 246
int udp_seq_open(struct inode *inode, struct file *file);

L
Linus Torvalds 已提交
247
struct udp_seq_afinfo {
248 249 250 251 252
	char				*name;
	sa_family_t			family;
	struct udp_table		*udp_table;
	const struct file_operations	*seq_fops;
	struct seq_operations		seq_ops;
L
Linus Torvalds 已提交
253 254 255
};

struct udp_iter_state {
256
	struct seq_net_private  p;
L
Linus Torvalds 已提交
257 258
	sa_family_t		family;
	int			bucket;
259
	struct udp_table	*udp_table;
L
Linus Torvalds 已提交
260 261
};

262
#ifdef CONFIG_PROC_FS
263 264
int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
265

266 267
int udp4_proc_init(void);
void udp4_proc_exit(void);
268
#endif
H
Hideo Aoki 已提交
269

270
int udpv4_offload_init(void);
271

272
void udp_init(void);
273

274
void udp_encap_enable(void);
275
#if IS_ENABLED(CONFIG_IPV6)
276
void udpv6_encap_enable(void);
277
#endif
L
Linus Torvalds 已提交
278
#endif	/* _UDP_H */