udp.c 16.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.
 *
 *		The User Datagram Protocol (UDP).
 *
 * Version:	$Id: udp.c,v 1.102 2002/02/01 22:01:04 davem Exp $
 *
10
 * Authors:	Ross Biro
L
Linus Torvalds 已提交
11 12 13 14 15 16 17 18 19 20 21 22
 *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
 *		Alan Cox, <Alan.Cox@linux.org>
 *		Hirokazu Takahashi, <taka@valinux.co.jp>
 *
 * Fixes:
 *		Alan Cox	:	verify_area() calls
 *		Alan Cox	: 	stopped close while in use off icmp
 *					messages. Not a fix but a botch that
 *					for udp at least is 'valid'.
 *		Alan Cox	:	Fixed icmp handling properly
 *		Alan Cox	: 	Correct error for oversized datagrams
23 24
 *		Alan Cox	:	Tidied select() semantics.
 *		Alan Cox	:	udp_err() fixed properly, also now
L
Linus Torvalds 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
 *					select and read wake correctly on errors
 *		Alan Cox	:	udp_send verify_area moved to avoid mem leak
 *		Alan Cox	:	UDP can count its memory
 *		Alan Cox	:	send to an unknown connection causes
 *					an ECONNREFUSED off the icmp, but
 *					does NOT close.
 *		Alan Cox	:	Switched to new sk_buff handlers. No more backlog!
 *		Alan Cox	:	Using generic datagram code. Even smaller and the PEEK
 *					bug no longer crashes it.
 *		Fred Van Kempen	: 	Net2e support for sk->broadcast.
 *		Alan Cox	:	Uses skb_free_datagram
 *		Alan Cox	:	Added get/set sockopt support.
 *		Alan Cox	:	Broadcasting without option set returns EACCES.
 *		Alan Cox	:	No wakeup calls. Instead we now use the callbacks.
 *		Alan Cox	:	Use ip_tos and ip_ttl
 *		Alan Cox	:	SNMP Mibs
 *		Alan Cox	:	MSG_DONTROUTE, and 0.0.0.0 support.
 *		Matt Dillon	:	UDP length checks.
 *		Alan Cox	:	Smarter af_inet used properly.
 *		Alan Cox	:	Use new kernel side addressing.
 *		Alan Cox	:	Incorrect return on truncated datagram receive.
 *	Arnt Gulbrandsen 	:	New udp_send and stuff
 *		Alan Cox	:	Cache last socket
 *		Alan Cox	:	Route cache
 *		Jon Peatfield	:	Minor efficiency fix to sendto().
 *		Mike Shaver	:	RFC1122 checks.
 *		Alan Cox	:	Nonblocking error fix.
 *	Willy Konynenberg	:	Transparent proxying support.
 *		Mike McLagan	:	Routing by source
 *		David S. Miller	:	New socket lookup architecture.
 *					Last socket cache retained as it
 *					does have a high hit rate.
 *		Olaf Kirch	:	Don't linearise iovec on sendmsg.
 *		Andi Kleen	:	Some cleanups, cache destination entry
59
 *					for connect.
L
Linus Torvalds 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72
 *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.
 *		Melvin Smith	:	Check msg_name not msg_namelen in sendto(),
 *					return ENOTCONN for unconnected sockets (POSIX)
 *		Janos Farkas	:	don't deliver multi/broadcasts to a different
 *					bound-to-device socket
 *	Hirokazu Takahashi	:	HW checksumming for outgoing UDP
 *					datagrams.
 *	Hirokazu Takahashi	:	sendfile() on UDP works now.
 *		Arnaldo C. Melo :	convert /proc/net/udp to seq_file
 *	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.
 *	Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
73
 *	James Chapman		:	Add L2TP encapsulation type.
L
Linus Torvalds 已提交
74 75 76 77 78 79 80
 *
 *
 *		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.
 */
81

L
Linus Torvalds 已提交
82 83 84
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
H
Hideo Aoki 已提交
85
#include <linux/bootmem.h>
L
Linus Torvalds 已提交
86 87 88 89 90
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/sockios.h>
91
#include <linux/igmp.h>
L
Linus Torvalds 已提交
92 93 94 95 96 97
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
98
#include <net/tcp_states.h>
L
Linus Torvalds 已提交
99 100 101
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
102
#include <net/net_namespace.h>
L
Linus Torvalds 已提交
103 104 105 106
#include <net/icmp.h>
#include <net/route.h>
#include <net/checksum.h>
#include <net/xfrm.h>
107
#include "udp_impl.h"
L
Linus Torvalds 已提交
108 109 110 111 112

/*
 *	Snmp MIB for the UDP layer
 */

113
DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
114
EXPORT_SYMBOL(udp_statistics);
L
Linus Torvalds 已提交
115

116 117 118
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
EXPORT_SYMBOL(udp_stats_in6);

L
Linus Torvalds 已提交
119 120 121
struct hlist_head udp_hash[UDP_HTABLE_SIZE];
DEFINE_RWLOCK(udp_hash_lock);

H
Hideo Aoki 已提交
122 123 124 125 126 127 128 129 130 131 132
int sysctl_udp_mem[3] __read_mostly;
int sysctl_udp_rmem_min __read_mostly;
int sysctl_udp_wmem_min __read_mostly;

EXPORT_SYMBOL(sysctl_udp_mem);
EXPORT_SYMBOL(sysctl_udp_rmem_min);
EXPORT_SYMBOL(sysctl_udp_wmem_min);

atomic_t udp_memory_allocated;
EXPORT_SYMBOL(udp_memory_allocated);

133
static inline int __udp_lib_lport_inuse(struct net *net, __u16 num,
134
					const struct hlist_head udptable[])
L
Linus Torvalds 已提交
135
{
136
	struct sock *sk;
L
Linus Torvalds 已提交
137
	struct hlist_node *node;
138

139
	sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
140
		if (sk->sk_net == net && sk->sk_hash == num)
141 142 143 144 145
			return 1;
	return 0;
}

/**
146
 *  __udp_lib_get_port  -  UDP/-Lite port lookup for IPv4 and IPv6
147 148 149
 *
 *  @sk:          socket struct in question
 *  @snum:        port number to look up
150
 *  @udptable:    hash list table, must be of UDP_HTABLE_SIZE
151
 *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
152
 */
153
int __udp_lib_get_port(struct sock *sk, unsigned short snum,
154
		       struct hlist_head udptable[],
155 156
		       int (*saddr_comp)(const struct sock *sk1,
					 const struct sock *sk2 )    )
157 158 159
{
	struct hlist_node *node;
	struct hlist_head *head;
L
Linus Torvalds 已提交
160
	struct sock *sk2;
161
	int    error = 1;
162
	struct net *net = sk->sk_net;
L
Linus Torvalds 已提交
163 164

	write_lock_bh(&udp_hash_lock);
165 166

	if (!snum) {
167
		int i, low, high, remaining;
168 169
		unsigned rover, best, best_size_so_far;

170
		inet_get_local_port_range(&low, &high);
171
		remaining = (high - low) + 1;
172

173
		best_size_so_far = UINT_MAX;
174
		best = rover = net_random() % remaining + low;
175 176 177 178 179 180 181

		/* 1st pass: look for empty (or shortest) hash chain */
		for (i = 0; i < UDP_HTABLE_SIZE; i++) {
			int size = 0;

			head = &udptable[rover & (UDP_HTABLE_SIZE - 1)];
			if (hlist_empty(head))
L
Linus Torvalds 已提交
182
				goto gotit;
183

184 185 186 187 188
			sk_for_each(sk2, node, head) {
				if (++size >= best_size_so_far)
					goto next;
			}
			best_size_so_far = size;
189
			best = rover;
190
		next:
191 192 193 194 195 196
			/* fold back if end of range */
			if (++rover > high)
				rover = low + ((rover - low)
					       & (UDP_HTABLE_SIZE - 1));


L
Linus Torvalds 已提交
197
		}
198 199 200 201

		/* 2nd pass: find hole in shortest hash chain */
		rover = best;
		for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) {
202
			if (! __udp_lib_lport_inuse(net, rover, udptable))
203 204 205 206 207
				goto gotit;
			rover += UDP_HTABLE_SIZE;
			if (rover > high)
				rover = low + ((rover - low)
					       & (UDP_HTABLE_SIZE - 1));
L
Linus Torvalds 已提交
208
		}
209 210 211 212 213


		/* All ports in use! */
		goto fail;

L
Linus Torvalds 已提交
214
gotit:
215
		snum = rover;
L
Linus Torvalds 已提交
216
	} else {
217
		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
218 219

		sk_for_each(sk2, node, head)
220 221
			if (sk2->sk_hash == snum                             &&
			    sk2 != sk                                        &&
222
			    sk2->sk_net == net				     &&
223 224 225 226
			    (!sk2->sk_reuse        || !sk->sk_reuse)         &&
			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
			     || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
			    (*saddr_comp)(sk, sk2)                             )
L
Linus Torvalds 已提交
227 228
				goto fail;
	}
229

230
	inet_sk(sk)->num = snum;
231
	sk->sk_hash = snum;
L
Linus Torvalds 已提交
232
	if (sk_unhashed(sk)) {
233
		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
234
		sk_add_node(sk, head);
235
		sock_prot_inuse_add(sk->sk_prot, 1);
L
Linus Torvalds 已提交
236
	}
237
	error = 0;
L
Linus Torvalds 已提交
238 239
fail:
	write_unlock_bh(&udp_hash_lock);
240 241 242
	return error;
}

S
Stephen Hemminger 已提交
243
int udp_get_port(struct sock *sk, unsigned short snum,
244
			int (*scmp)(const struct sock *, const struct sock *))
245
{
246
	return  __udp_lib_get_port(sk, snum, udp_hash, scmp);
247 248
}

L
Linus Torvalds 已提交
249 250 251
/*
 *	IOCTL requests applicable to the UDP protocol
 */
252

L
Linus Torvalds 已提交
253 254
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
255 256
	switch (cmd) {
	case SIOCOUTQ:
L
Linus Torvalds 已提交
257
	{
258 259 260
		int amount = atomic_read(&sk->sk_wmem_alloc);
		return put_user(amount, (int __user *)arg);
	}
L
Linus Torvalds 已提交
261

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
	case SIOCINQ:
	{
		struct sk_buff *skb;
		unsigned long amount;

		amount = 0;
		spin_lock_bh(&sk->sk_receive_queue.lock);
		skb = skb_peek(&sk->sk_receive_queue);
		if (skb != NULL) {
			/*
			 * We will only return the amount
			 * of this packet since that is all
			 * that will be read.
			 */
			amount = skb->len - sizeof(struct udphdr);
L
Linus Torvalds 已提交
277
		}
278 279 280
		spin_unlock_bh(&sk->sk_receive_queue.lock);
		return put_user(amount, (int __user *)arg);
	}
L
Linus Torvalds 已提交
281

282 283
	default:
		return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
284
	}
285 286

	return 0;
L
Linus Torvalds 已提交
287 288 289 290 291 292 293 294
}

int udp_disconnect(struct sock *sk, int flags)
{
	struct inet_sock *inet = inet_sk(sk);
	/*
	 *	1003.1g - break association.
	 */
295

L
Linus Torvalds 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
	sk->sk_state = TCP_CLOSE;
	inet->daddr = 0;
	inet->dport = 0;
	sk->sk_bound_dev_if = 0;
	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
		inet_reset_saddr(sk);

	if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) {
		sk->sk_prot->unhash(sk);
		inet->sport = 0;
	}
	sk_dst_reset(sk);
	return 0;
}

/*
 *	Socket option code for UDP
 */
314 315 316
int udp_lib_setsockopt(struct sock *sk, int level, int optname,
		       char __user *optval, int optlen,
		       int (*push_pending_frames)(struct sock *))
L
Linus Torvalds 已提交
317 318 319 320
{
	struct udp_sock *up = udp_sk(sk);
	int val;
	int err = 0;
321
#ifdef CONFIG_IP_UDPLITE
W
Wang Chen 已提交
322
	int is_udplite = IS_UDPLITE(sk);
323
#endif
L
Linus Torvalds 已提交
324

325
	if (optlen<sizeof(int))
L
Linus Torvalds 已提交
326 327 328 329 330
		return -EINVAL;

	if (get_user(val, (int __user *)optval))
		return -EFAULT;

331
	switch (optname) {
L
Linus Torvalds 已提交
332 333 334 335 336 337
	case UDP_CORK:
		if (val != 0) {
			up->corkflag = 1;
		} else {
			up->corkflag = 0;
			lock_sock(sk);
338
			(*push_pending_frames)(sk);
L
Linus Torvalds 已提交
339 340 341
			release_sock(sk);
		}
		break;
342

L
Linus Torvalds 已提交
343 344 345 346 347
	case UDP_ENCAP:
		switch (val) {
		case 0:
		case UDP_ENCAP_ESPINUDP:
		case UDP_ENCAP_ESPINUDP_NON_IKE:
348 349
			up->encap_rcv = xfrm4_udp_encap_rcv;
			/* FALLTHROUGH */
350
		case UDP_ENCAP_L2TPINUDP:
L
Linus Torvalds 已提交
351 352 353 354 355 356 357 358
			up->encap_type = val;
			break;
		default:
			err = -ENOPROTOOPT;
			break;
		}
		break;

359
#ifdef CONFIG_IP_UDPLITE
360 361 362 363 364 365
	/*
	 * 	UDP-Lite's partial checksum coverage (RFC 3828).
	 */
	/* The sender sets actual checksum coverage length via this option.
	 * The case coverage > packet length is handled by send module. */
	case UDPLITE_SEND_CSCOV:
W
Wang Chen 已提交
366
		if (!is_udplite)         /* Disable the option on UDP sockets */
367 368 369 370 371 372 373
			return -ENOPROTOOPT;
		if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
			val = 8;
		up->pcslen = val;
		up->pcflag |= UDPLITE_SEND_CC;
		break;

374 375
	/* The receiver specifies a minimum checksum coverage value. To make
	 * sense, this should be set to at least 8 (as done below). If zero is
376 377
	 * used, this again means full checksum coverage.                     */
	case UDPLITE_RECV_CSCOV:
W
Wang Chen 已提交
378
		if (!is_udplite)         /* Disable the option on UDP sockets */
379 380 381 382 383 384
			return -ENOPROTOOPT;
		if (val != 0 && val < 8) /* Avoid silly minimal values.       */
			val = 8;
		up->pcrlen = val;
		up->pcflag |= UDPLITE_RECV_CC;
		break;
385
#endif
386

L
Linus Torvalds 已提交
387 388 389
	default:
		err = -ENOPROTOOPT;
		break;
390
	}
L
Linus Torvalds 已提交
391 392 393 394

	return err;
}

395 396
int udp_lib_getsockopt(struct sock *sk, int level, int optname,
		       char __user *optval, int __user *optlen)
L
Linus Torvalds 已提交
397 398 399 400
{
	struct udp_sock *up = udp_sk(sk);
	int val, len;

401
	if (get_user(len,optlen))
L
Linus Torvalds 已提交
402 403 404
		return -EFAULT;

	len = min_t(unsigned int, len, sizeof(int));
405

406
	if (len < 0)
L
Linus Torvalds 已提交
407 408
		return -EINVAL;

409
	switch (optname) {
L
Linus Torvalds 已提交
410 411 412 413 414 415 416 417
	case UDP_CORK:
		val = up->corkflag;
		break;

	case UDP_ENCAP:
		val = up->encap_type;
		break;

418 419 420 421 422 423 424 425 426 427
	/* The following two cannot be changed on UDP sockets, the return is
	 * always 0 (which corresponds to the full checksum coverage of UDP). */
	case UDPLITE_SEND_CSCOV:
		val = up->pcslen;
		break;

	case UDPLITE_RECV_CSCOV:
		val = up->pcrlen;
		break;

L
Linus Torvalds 已提交
428 429
	default:
		return -ENOPROTOOPT;
430
	}
L
Linus Torvalds 已提交
431

432
	if (put_user(len, optlen))
433
		return -EFAULT;
434
	if (copy_to_user(optval, &val,len))
L
Linus Torvalds 已提交
435
		return -EFAULT;
436
	return 0;
L
Linus Torvalds 已提交
437 438 439 440 441 442 443 444
}

/**
 * 	udp_poll - wait for a UDP event.
 *	@file - file struct
 *	@sock - socket
 *	@wait - poll table
 *
445
 *	This is same as datagram poll, except for the special case of
L
Linus Torvalds 已提交
446 447 448 449 450 451 452 453 454 455
 *	blocking sockets. If application is using a blocking fd
 *	and a packet with checksum error is in the queue;
 *	then it could get return from select indicating data available
 *	but then block when reading it. Add special case code
 *	to work around these arguably broken applications.
 */
unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
{
	unsigned int mask = datagram_poll(file, sock, wait);
	struct sock *sk = sock->sk;
456 457
	int 	is_lite = IS_UDPLITE(sk);

L
Linus Torvalds 已提交
458 459 460 461 462 463 464
	/* Check for false positives due to checksum errors */
	if ( (mask & POLLRDNORM) &&
	     !(file->f_flags & O_NONBLOCK) &&
	     !(sk->sk_shutdown & RCV_SHUTDOWN)){
		struct sk_buff_head *rcvq = &sk->sk_receive_queue;
		struct sk_buff *skb;

465
		spin_lock_bh(&rcvq->lock);
466 467 468 469 470
		while ((skb = skb_peek(rcvq)) != NULL &&
		       udp_lib_checksum_complete(skb)) {
			UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite);
			__skb_unlink(skb, rcvq);
			kfree_skb(skb);
L
Linus Torvalds 已提交
471
		}
472
		spin_unlock_bh(&rcvq->lock);
L
Linus Torvalds 已提交
473 474 475 476 477 478 479

		/* nothing to see, move along */
		if (skb == NULL)
			mask &= ~(POLLIN | POLLRDNORM);
	}

	return mask;
480

L
Linus Torvalds 已提交
481 482 483 484 485 486 487 488 489 490 491 492 493
}


/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS

static struct sock *udp_get_first(struct seq_file *seq)
{
	struct sock *sk;
	struct udp_iter_state *state = seq->private;

	for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
		struct hlist_node *node;
494
		sk_for_each(sk, node, state->hashtable + state->bucket) {
L
Linus Torvalds 已提交
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
			if (sk->sk_family == state->family)
				goto found;
		}
	}
	sk = NULL;
found:
	return sk;
}

static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
{
	struct udp_iter_state *state = seq->private;

	do {
		sk = sk_next(sk);
try_again:
		;
	} while (sk && sk->sk_family != state->family);

	if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
515
		sk = sk_head(state->hashtable + state->bucket);
L
Linus Torvalds 已提交
516 517 518 519 520 521 522 523 524 525
		goto try_again;
	}
	return sk;
}

static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos)
{
	struct sock *sk = udp_get_first(seq);

	if (sk)
526
		while (pos && (sk = udp_get_next(seq, sk)) != NULL)
L
Linus Torvalds 已提交
527 528 529 530 531
			--pos;
	return pos ? NULL : sk;
}

static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
532
	__acquires(udp_hash_lock)
L
Linus Torvalds 已提交
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
{
	read_lock(&udp_hash_lock);
	return *pos ? udp_get_idx(seq, *pos-1) : (void *)1;
}

static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct sock *sk;

	if (v == (void *)1)
		sk = udp_get_idx(seq, 0);
	else
		sk = udp_get_next(seq, v);

	++*pos;
	return sk;
}

static void udp_seq_stop(struct seq_file *seq, void *v)
552
	__releases(udp_hash_lock)
L
Linus Torvalds 已提交
553 554 555 556 557 558 559 560 561
{
	read_unlock(&udp_hash_lock);
}

static int udp_seq_open(struct inode *inode, struct file *file)
{
	struct udp_seq_afinfo *afinfo = PDE(inode)->data;
	struct seq_file *seq;
	int rc = -ENOMEM;
562
	struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
L
Linus Torvalds 已提交
563 564 565 566

	if (!s)
		goto out;
	s->family		= afinfo->family;
567
	s->hashtable		= afinfo->hashtable;
L
Linus Torvalds 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
	s->seq_ops.start	= udp_seq_start;
	s->seq_ops.next		= udp_seq_next;
	s->seq_ops.show		= afinfo->seq_show;
	s->seq_ops.stop		= udp_seq_stop;

	rc = seq_open(file, &s->seq_ops);
	if (rc)
		goto out_kfree;

	seq	     = file->private_data;
	seq->private = s;
out:
	return rc;
out_kfree:
	kfree(s);
	goto out;
}

/* ------------------------------------------------------------------------ */
int udp_proc_register(struct udp_seq_afinfo *afinfo)
{
	struct proc_dir_entry *p;
	int rc = 0;

	if (!afinfo)
		return -EINVAL;
	afinfo->seq_fops->owner		= afinfo->owner;
	afinfo->seq_fops->open		= udp_seq_open;
	afinfo->seq_fops->read		= seq_read;
	afinfo->seq_fops->llseek	= seq_lseek;
	afinfo->seq_fops->release	= seq_release_private;

600
	p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
L
Linus Torvalds 已提交
601 602 603 604 605 606 607 608 609 610 611
	if (p)
		p->data = afinfo;
	else
		rc = -ENOMEM;
	return rc;
}

void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
{
	if (!afinfo)
		return;
612
	proc_net_remove(&init_net, afinfo->name);
L
Linus Torvalds 已提交
613 614 615 616
	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
}
#endif /* CONFIG_PROC_FS */

H
Hideo Aoki 已提交
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
void __init udp_init(void)
{
	unsigned long limit;

	/* Set the pressure threshold up by the same strategy of TCP. It is a
	 * fraction of global memory that is up to 1/2 at 256 MB, decreasing
	 * toward zero with the amount of memory, with a floor of 128 pages.
	 */
	limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
	limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
	limit = max(limit, 128UL);
	sysctl_udp_mem[0] = limit / 4 * 3;
	sysctl_udp_mem[1] = limit;
	sysctl_udp_mem[2] = sysctl_udp_mem[0] * 2;

	sysctl_udp_rmem_min = SK_MEM_QUANTUM;
	sysctl_udp_wmem_min = SK_MEM_QUANTUM;
}

L
Linus Torvalds 已提交
636 637 638 639
EXPORT_SYMBOL(udp_disconnect);
EXPORT_SYMBOL(udp_hash);
EXPORT_SYMBOL(udp_hash_lock);
EXPORT_SYMBOL(udp_ioctl);
640
EXPORT_SYMBOL(udp_get_port);
641 642
EXPORT_SYMBOL(udp_lib_getsockopt);
EXPORT_SYMBOL(udp_lib_setsockopt);
L
Linus Torvalds 已提交
643 644 645 646 647 648
EXPORT_SYMBOL(udp_poll);

#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(udp_proc_register);
EXPORT_SYMBOL(udp_proc_unregister);
#endif