udp.h 8.4 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 115 116
	return (UDP_SKB_CB(skb)->cscov == skb->len ?
		__skb_checksum_complete(skb) :
		__skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov));
117 118
}

119
static inline int udp_lib_checksum_complete(struct sk_buff *skb)
120
{
121
	return !skb_csum_unnecessary(skb) &&
122 123 124 125 126 127 128 129 130
		__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)
 */
131
static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb)
132
{
133 134
	__wsum csum = csum_partial(skb_transport_header(skb),
				   sizeof(struct udphdr), 0);
135 136 137 138 139 140
	skb_queue_walk(&sk->sk_write_queue, skb) {
		csum = csum_add(csum, skb->csum);
	}
	return csum;
}

H
Herbert Xu 已提交
141 142 143 144 145 146 147 148 149 150 151
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;
}

152 153 154 155 156 157 158 159 160
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);

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

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

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

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

/* net/ipv4/udp.c */
S
Shawn Bohrer 已提交
180
void udp_v4_early_demux(struct sk_buff *skb);
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 212 213
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);
214

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

225
#define UDP6_INC_STATS_BH(net, field, is_udplite) 	    do { \
226
	if (is_udplite) SNMP_INC_STATS_BH((net)->mib.udplite_stats_in6, field);\
227 228
	else		SNMP_INC_STATS_BH((net)->mib.udp_stats_in6, field);  \
} while(0)
229 230 231
#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);      \
232
} while(0)
233

E
Eric Dumazet 已提交
234
#if IS_ENABLED(CONFIG_IPV6)
235 236 237 238 239 240 241
#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)
242
#else
243
#define UDPX_INC_STATS_BH(sk, field) UDP_INC_STATS_BH(sock_net(sk), field, 0)
244 245
#endif

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

L
Linus Torvalds 已提交
249
struct udp_seq_afinfo {
250 251 252 253 254
	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 已提交
255 256 257
};

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

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

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

272
int udpv4_offload_init(void);
273

274
void udp_init(void);
275

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