xref: /linux/net/ipv4/udp.c (revision 4bedb45203eab92a87b4c863fe2d0cded633427f)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * INET		An implementation of the TCP/IP protocol suite for the LINUX
31da177e4SLinus Torvalds  *		operating system.  INET is implemented using the  BSD Socket
41da177e4SLinus Torvalds  *		interface as the means of communication with the user level.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *		The User Datagram Protocol (UDP).
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * Version:	$Id: udp.c,v 1.102 2002/02/01 22:01:04 davem Exp $
91da177e4SLinus Torvalds  *
1002c30a84SJesper Juhl  * Authors:	Ross Biro
111da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
121da177e4SLinus Torvalds  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
131da177e4SLinus Torvalds  *		Alan Cox, <Alan.Cox@linux.org>
141da177e4SLinus Torvalds  *		Hirokazu Takahashi, <taka@valinux.co.jp>
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  * Fixes:
171da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() calls
181da177e4SLinus Torvalds  *		Alan Cox	: 	stopped close while in use off icmp
191da177e4SLinus Torvalds  *					messages. Not a fix but a botch that
201da177e4SLinus Torvalds  *					for udp at least is 'valid'.
211da177e4SLinus Torvalds  *		Alan Cox	:	Fixed icmp handling properly
221da177e4SLinus Torvalds  *		Alan Cox	: 	Correct error for oversized datagrams
231da177e4SLinus Torvalds  *		Alan Cox	:	Tidied select() semantics.
241da177e4SLinus Torvalds  *		Alan Cox	:	udp_err() fixed properly, also now
251da177e4SLinus Torvalds  *					select and read wake correctly on errors
261da177e4SLinus Torvalds  *		Alan Cox	:	udp_send verify_area moved to avoid mem leak
271da177e4SLinus Torvalds  *		Alan Cox	:	UDP can count its memory
281da177e4SLinus Torvalds  *		Alan Cox	:	send to an unknown connection causes
291da177e4SLinus Torvalds  *					an ECONNREFUSED off the icmp, but
301da177e4SLinus Torvalds  *					does NOT close.
311da177e4SLinus Torvalds  *		Alan Cox	:	Switched to new sk_buff handlers. No more backlog!
321da177e4SLinus Torvalds  *		Alan Cox	:	Using generic datagram code. Even smaller and the PEEK
331da177e4SLinus Torvalds  *					bug no longer crashes it.
341da177e4SLinus Torvalds  *		Fred Van Kempen	: 	Net2e support for sk->broadcast.
351da177e4SLinus Torvalds  *		Alan Cox	:	Uses skb_free_datagram
361da177e4SLinus Torvalds  *		Alan Cox	:	Added get/set sockopt support.
371da177e4SLinus Torvalds  *		Alan Cox	:	Broadcasting without option set returns EACCES.
381da177e4SLinus Torvalds  *		Alan Cox	:	No wakeup calls. Instead we now use the callbacks.
391da177e4SLinus Torvalds  *		Alan Cox	:	Use ip_tos and ip_ttl
401da177e4SLinus Torvalds  *		Alan Cox	:	SNMP Mibs
411da177e4SLinus Torvalds  *		Alan Cox	:	MSG_DONTROUTE, and 0.0.0.0 support.
421da177e4SLinus Torvalds  *		Matt Dillon	:	UDP length checks.
431da177e4SLinus Torvalds  *		Alan Cox	:	Smarter af_inet used properly.
441da177e4SLinus Torvalds  *		Alan Cox	:	Use new kernel side addressing.
451da177e4SLinus Torvalds  *		Alan Cox	:	Incorrect return on truncated datagram receive.
461da177e4SLinus Torvalds  *	Arnt Gulbrandsen 	:	New udp_send and stuff
471da177e4SLinus Torvalds  *		Alan Cox	:	Cache last socket
481da177e4SLinus Torvalds  *		Alan Cox	:	Route cache
491da177e4SLinus Torvalds  *		Jon Peatfield	:	Minor efficiency fix to sendto().
501da177e4SLinus Torvalds  *		Mike Shaver	:	RFC1122 checks.
511da177e4SLinus Torvalds  *		Alan Cox	:	Nonblocking error fix.
521da177e4SLinus Torvalds  *	Willy Konynenberg	:	Transparent proxying support.
531da177e4SLinus Torvalds  *		Mike McLagan	:	Routing by source
541da177e4SLinus Torvalds  *		David S. Miller	:	New socket lookup architecture.
551da177e4SLinus Torvalds  *					Last socket cache retained as it
561da177e4SLinus Torvalds  *					does have a high hit rate.
571da177e4SLinus Torvalds  *		Olaf Kirch	:	Don't linearise iovec on sendmsg.
581da177e4SLinus Torvalds  *		Andi Kleen	:	Some cleanups, cache destination entry
591da177e4SLinus Torvalds  *					for connect.
601da177e4SLinus Torvalds  *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.
611da177e4SLinus Torvalds  *		Melvin Smith	:	Check msg_name not msg_namelen in sendto(),
621da177e4SLinus Torvalds  *					return ENOTCONN for unconnected sockets (POSIX)
631da177e4SLinus Torvalds  *		Janos Farkas	:	don't deliver multi/broadcasts to a different
641da177e4SLinus Torvalds  *					bound-to-device socket
651da177e4SLinus Torvalds  *	Hirokazu Takahashi	:	HW checksumming for outgoing UDP
661da177e4SLinus Torvalds  *					datagrams.
671da177e4SLinus Torvalds  *	Hirokazu Takahashi	:	sendfile() on UDP works now.
681da177e4SLinus Torvalds  *		Arnaldo C. Melo :	convert /proc/net/udp to seq_file
691da177e4SLinus Torvalds  *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
701da177e4SLinus Torvalds  *	Alexey Kuznetsov:		allow both IPv4 and IPv6 sockets to bind
711da177e4SLinus Torvalds  *					a single port at the same time.
721da177e4SLinus Torvalds  *	Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
731da177e4SLinus Torvalds  *
741da177e4SLinus Torvalds  *
751da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
761da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
771da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
781da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
791da177e4SLinus Torvalds  */
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds #include <asm/system.h>
821da177e4SLinus Torvalds #include <asm/uaccess.h>
831da177e4SLinus Torvalds #include <asm/ioctls.h>
841da177e4SLinus Torvalds #include <linux/types.h>
851da177e4SLinus Torvalds #include <linux/fcntl.h>
861da177e4SLinus Torvalds #include <linux/module.h>
871da177e4SLinus Torvalds #include <linux/socket.h>
881da177e4SLinus Torvalds #include <linux/sockios.h>
8914c85021SArnaldo Carvalho de Melo #include <linux/igmp.h>
901da177e4SLinus Torvalds #include <linux/in.h>
911da177e4SLinus Torvalds #include <linux/errno.h>
921da177e4SLinus Torvalds #include <linux/timer.h>
931da177e4SLinus Torvalds #include <linux/mm.h>
941da177e4SLinus Torvalds #include <linux/inet.h>
951da177e4SLinus Torvalds #include <linux/netdevice.h>
96c752f073SArnaldo Carvalho de Melo #include <net/tcp_states.h>
971da177e4SLinus Torvalds #include <linux/skbuff.h>
981da177e4SLinus Torvalds #include <linux/proc_fs.h>
991da177e4SLinus Torvalds #include <linux/seq_file.h>
1001da177e4SLinus Torvalds #include <net/icmp.h>
1011da177e4SLinus Torvalds #include <net/route.h>
1021da177e4SLinus Torvalds #include <net/checksum.h>
1031da177e4SLinus Torvalds #include <net/xfrm.h>
104ba4e58ecSGerrit Renker #include "udp_impl.h"
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds /*
1071da177e4SLinus Torvalds  *	Snmp MIB for the UDP layer
1081da177e4SLinus Torvalds  */
1091da177e4SLinus Torvalds 
110ba89966cSEric Dumazet DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds struct hlist_head udp_hash[UDP_HTABLE_SIZE];
1131da177e4SLinus Torvalds DEFINE_RWLOCK(udp_hash_lock);
1141da177e4SLinus Torvalds 
115bed53ea7SDavid S. Miller static int udp_port_rover;
1161da177e4SLinus Torvalds 
1178e5200f5SAl Viro static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
11825030a7fSGerrit Renker {
11925030a7fSGerrit Renker 	struct sock *sk;
12025030a7fSGerrit Renker 	struct hlist_node *node;
12125030a7fSGerrit Renker 
122ba4e58ecSGerrit Renker 	sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
12395f30b33SEric Dumazet 		if (sk->sk_hash == num)
12425030a7fSGerrit Renker 			return 1;
12525030a7fSGerrit Renker 	return 0;
12625030a7fSGerrit Renker }
12725030a7fSGerrit Renker 
12825030a7fSGerrit Renker /**
129ba4e58ecSGerrit Renker  *  __udp_lib_get_port  -  UDP/-Lite port lookup for IPv4 and IPv6
13025030a7fSGerrit Renker  *
13125030a7fSGerrit Renker  *  @sk:          socket struct in question
13225030a7fSGerrit Renker  *  @snum:        port number to look up
133ba4e58ecSGerrit Renker  *  @udptable:    hash list table, must be of UDP_HTABLE_SIZE
134ba4e58ecSGerrit Renker  *  @port_rover:  pointer to record of last unallocated port
13525030a7fSGerrit Renker  *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
13625030a7fSGerrit Renker  */
137ba4e58ecSGerrit Renker int __udp_lib_get_port(struct sock *sk, unsigned short snum,
138ba4e58ecSGerrit Renker 		       struct hlist_head udptable[], int *port_rover,
139ba4e58ecSGerrit Renker 		       int (*saddr_comp)(const struct sock *sk1,
140ba4e58ecSGerrit Renker 					 const struct sock *sk2 )    )
1411da177e4SLinus Torvalds {
1421da177e4SLinus Torvalds 	struct hlist_node *node;
14325030a7fSGerrit Renker 	struct hlist_head *head;
1441da177e4SLinus Torvalds 	struct sock *sk2;
14525030a7fSGerrit Renker 	int    error = 1;
1461da177e4SLinus Torvalds 
1471da177e4SLinus Torvalds 	write_lock_bh(&udp_hash_lock);
1481da177e4SLinus Torvalds 	if (snum == 0) {
1491da177e4SLinus Torvalds 		int best_size_so_far, best, result, i;
1501da177e4SLinus Torvalds 
151ba4e58ecSGerrit Renker 		if (*port_rover > sysctl_local_port_range[1] ||
152ba4e58ecSGerrit Renker 		    *port_rover < sysctl_local_port_range[0])
153ba4e58ecSGerrit Renker 			*port_rover = sysctl_local_port_range[0];
1541da177e4SLinus Torvalds 		best_size_so_far = 32767;
155ba4e58ecSGerrit Renker 		best = result = *port_rover;
1561da177e4SLinus Torvalds 		for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
1571da177e4SLinus Torvalds 			int size;
1581da177e4SLinus Torvalds 
159ba4e58ecSGerrit Renker 			head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
16025030a7fSGerrit Renker 			if (hlist_empty(head)) {
1611da177e4SLinus Torvalds 				if (result > sysctl_local_port_range[1])
1621da177e4SLinus Torvalds 					result = sysctl_local_port_range[0] +
1631da177e4SLinus Torvalds 						((result - sysctl_local_port_range[0]) &
1641da177e4SLinus Torvalds 						 (UDP_HTABLE_SIZE - 1));
1651da177e4SLinus Torvalds 				goto gotit;
1661da177e4SLinus Torvalds 			}
1671da177e4SLinus Torvalds 			size = 0;
1685c668704SDavid S. Miller 			sk_for_each(sk2, node, head) {
1695c668704SDavid S. Miller 				if (++size >= best_size_so_far)
1705c668704SDavid S. Miller 					goto next;
1715c668704SDavid S. Miller 			}
1721da177e4SLinus Torvalds 			best_size_so_far = size;
1731da177e4SLinus Torvalds 			best = result;
1745c668704SDavid S. Miller 		next:
1755c668704SDavid S. Miller 			;
1761da177e4SLinus Torvalds 		}
1771da177e4SLinus Torvalds 		result = best;
1786516c655SStephen Hemminger 		for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE;
1796516c655SStephen Hemminger 		     i++, result += UDP_HTABLE_SIZE) {
1801da177e4SLinus Torvalds 			if (result > sysctl_local_port_range[1])
1811da177e4SLinus Torvalds 				result = sysctl_local_port_range[0]
1821da177e4SLinus Torvalds 					+ ((result - sysctl_local_port_range[0]) &
1831da177e4SLinus Torvalds 					   (UDP_HTABLE_SIZE - 1));
184ba4e58ecSGerrit Renker 			if (! __udp_lib_lport_inuse(result, udptable))
1851da177e4SLinus Torvalds 				break;
1861da177e4SLinus Torvalds 		}
1871da177e4SLinus Torvalds 		if (i >= (1 << 16) / UDP_HTABLE_SIZE)
1881da177e4SLinus Torvalds 			goto fail;
1891da177e4SLinus Torvalds gotit:
190ba4e58ecSGerrit Renker 		*port_rover = snum = result;
1911da177e4SLinus Torvalds 	} else {
192ba4e58ecSGerrit Renker 		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
1931da177e4SLinus Torvalds 
19425030a7fSGerrit Renker 		sk_for_each(sk2, node, head)
19595f30b33SEric Dumazet 			if (sk2->sk_hash == snum                             &&
1961da177e4SLinus Torvalds 			    sk2 != sk                                        &&
19725030a7fSGerrit Renker 			    (!sk2->sk_reuse        || !sk->sk_reuse)         &&
19825030a7fSGerrit Renker 			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
19925030a7fSGerrit Renker 			     || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
200ba4e58ecSGerrit Renker 			    (*saddr_comp)(sk, sk2)                             )
2011da177e4SLinus Torvalds 				goto fail;
2021da177e4SLinus Torvalds 	}
20325030a7fSGerrit Renker 	inet_sk(sk)->num = snum;
20495f30b33SEric Dumazet 	sk->sk_hash = snum;
2051da177e4SLinus Torvalds 	if (sk_unhashed(sk)) {
206ba4e58ecSGerrit Renker 		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
20725030a7fSGerrit Renker 		sk_add_node(sk, head);
2081da177e4SLinus Torvalds 		sock_prot_inc_use(sk->sk_prot);
2091da177e4SLinus Torvalds 	}
21025030a7fSGerrit Renker 	error = 0;
2111da177e4SLinus Torvalds fail:
2121da177e4SLinus Torvalds 	write_unlock_bh(&udp_hash_lock);
21325030a7fSGerrit Renker 	return error;
2141da177e4SLinus Torvalds }
2151da177e4SLinus Torvalds 
2163fbe070aSStephen Hemminger int udp_get_port(struct sock *sk, unsigned short snum,
217ba4e58ecSGerrit Renker 			int (*scmp)(const struct sock *, const struct sock *))
218ba4e58ecSGerrit Renker {
219ba4e58ecSGerrit Renker 	return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
220ba4e58ecSGerrit Renker }
221ba4e58ecSGerrit Renker 
2223fbe070aSStephen Hemminger int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
22325030a7fSGerrit Renker {
22425030a7fSGerrit Renker 	struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
22525030a7fSGerrit Renker 
22625030a7fSGerrit Renker 	return 	( !ipv6_only_sock(sk2)  &&
22725030a7fSGerrit Renker 		  (!inet1->rcv_saddr || !inet2->rcv_saddr ||
22825030a7fSGerrit Renker 		   inet1->rcv_saddr == inet2->rcv_saddr      ));
22925030a7fSGerrit Renker }
23025030a7fSGerrit Renker 
23125030a7fSGerrit Renker static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
23225030a7fSGerrit Renker {
23325030a7fSGerrit Renker 	return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
23425030a7fSGerrit Renker }
23525030a7fSGerrit Renker 
2361da177e4SLinus Torvalds /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
2371da177e4SLinus Torvalds  * harder than this. -DaveM
2381da177e4SLinus Torvalds  */
239ba4e58ecSGerrit Renker static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
240ba4e58ecSGerrit Renker 				      __be32 daddr, __be16 dport,
241ba4e58ecSGerrit Renker 				      int dif, struct hlist_head udptable[])
2421da177e4SLinus Torvalds {
2431da177e4SLinus Torvalds 	struct sock *sk, *result = NULL;
2441da177e4SLinus Torvalds 	struct hlist_node *node;
2451da177e4SLinus Torvalds 	unsigned short hnum = ntohs(dport);
2461da177e4SLinus Torvalds 	int badness = -1;
2471da177e4SLinus Torvalds 
248ba4e58ecSGerrit Renker 	read_lock(&udp_hash_lock);
249ba4e58ecSGerrit Renker 	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
2501da177e4SLinus Torvalds 		struct inet_sock *inet = inet_sk(sk);
2511da177e4SLinus Torvalds 
25295f30b33SEric Dumazet 		if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
2531da177e4SLinus Torvalds 			int score = (sk->sk_family == PF_INET ? 1 : 0);
2541da177e4SLinus Torvalds 			if (inet->rcv_saddr) {
2551da177e4SLinus Torvalds 				if (inet->rcv_saddr != daddr)
2561da177e4SLinus Torvalds 					continue;
2571da177e4SLinus Torvalds 				score+=2;
2581da177e4SLinus Torvalds 			}
2591da177e4SLinus Torvalds 			if (inet->daddr) {
2601da177e4SLinus Torvalds 				if (inet->daddr != saddr)
2611da177e4SLinus Torvalds 					continue;
2621da177e4SLinus Torvalds 				score+=2;
2631da177e4SLinus Torvalds 			}
2641da177e4SLinus Torvalds 			if (inet->dport) {
2651da177e4SLinus Torvalds 				if (inet->dport != sport)
2661da177e4SLinus Torvalds 					continue;
2671da177e4SLinus Torvalds 				score+=2;
2681da177e4SLinus Torvalds 			}
2691da177e4SLinus Torvalds 			if (sk->sk_bound_dev_if) {
2701da177e4SLinus Torvalds 				if (sk->sk_bound_dev_if != dif)
2711da177e4SLinus Torvalds 					continue;
2721da177e4SLinus Torvalds 				score+=2;
2731da177e4SLinus Torvalds 			}
2741da177e4SLinus Torvalds 			if (score == 9) {
2751da177e4SLinus Torvalds 				result = sk;
2761da177e4SLinus Torvalds 				break;
2771da177e4SLinus Torvalds 			} else if (score > badness) {
2781da177e4SLinus Torvalds 				result = sk;
2791da177e4SLinus Torvalds 				badness = score;
2801da177e4SLinus Torvalds 			}
2811da177e4SLinus Torvalds 		}
2821da177e4SLinus Torvalds 	}
283ba4e58ecSGerrit Renker 	if (result)
284ba4e58ecSGerrit Renker 		sock_hold(result);
2851da177e4SLinus Torvalds 	read_unlock(&udp_hash_lock);
286ba4e58ecSGerrit Renker 	return result;
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds static inline struct sock *udp_v4_mcast_next(struct sock *sk,
290734ab87fSAl Viro 					     __be16 loc_port, __be32 loc_addr,
291734ab87fSAl Viro 					     __be16 rmt_port, __be32 rmt_addr,
2921da177e4SLinus Torvalds 					     int dif)
2931da177e4SLinus Torvalds {
2941da177e4SLinus Torvalds 	struct hlist_node *node;
2951da177e4SLinus Torvalds 	struct sock *s = sk;
2961da177e4SLinus Torvalds 	unsigned short hnum = ntohs(loc_port);
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds 	sk_for_each_from(s, node) {
2991da177e4SLinus Torvalds 		struct inet_sock *inet = inet_sk(s);
3001da177e4SLinus Torvalds 
30195f30b33SEric Dumazet 		if (s->sk_hash != hnum					||
3021da177e4SLinus Torvalds 		    (inet->daddr && inet->daddr != rmt_addr)		||
3031da177e4SLinus Torvalds 		    (inet->dport != rmt_port && inet->dport)		||
3041da177e4SLinus Torvalds 		    (inet->rcv_saddr && inet->rcv_saddr != loc_addr)	||
3051da177e4SLinus Torvalds 		    ipv6_only_sock(s)					||
3061da177e4SLinus Torvalds 		    (s->sk_bound_dev_if && s->sk_bound_dev_if != dif))
3071da177e4SLinus Torvalds 			continue;
3081da177e4SLinus Torvalds 		if (!ip_mc_sf_allow(s, loc_addr, rmt_addr, dif))
3091da177e4SLinus Torvalds 			continue;
3101da177e4SLinus Torvalds 		goto found;
3111da177e4SLinus Torvalds 	}
3121da177e4SLinus Torvalds 	s = NULL;
3131da177e4SLinus Torvalds found:
3141da177e4SLinus Torvalds 	return s;
3151da177e4SLinus Torvalds }
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds /*
3181da177e4SLinus Torvalds  * This routine is called by the ICMP module when it gets some
3191da177e4SLinus Torvalds  * sort of error condition.  If err < 0 then the socket should
3201da177e4SLinus Torvalds  * be closed and the error returned to the user.  If err > 0
3211da177e4SLinus Torvalds  * it's just the icmp type << 8 | icmp code.
3221da177e4SLinus Torvalds  * Header points to the ip header of the error packet. We move
3231da177e4SLinus Torvalds  * on past this. Then (as it used to claim before adjustment)
3241da177e4SLinus Torvalds  * header points to the first 8 bytes of the udp header.  We need
3251da177e4SLinus Torvalds  * to find the appropriate port.
3261da177e4SLinus Torvalds  */
3271da177e4SLinus Torvalds 
328ba4e58ecSGerrit Renker void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
3291da177e4SLinus Torvalds {
3301da177e4SLinus Torvalds 	struct inet_sock *inet;
3311da177e4SLinus Torvalds 	struct iphdr *iph = (struct iphdr*)skb->data;
3321da177e4SLinus Torvalds 	struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2));
3331da177e4SLinus Torvalds 	int type = skb->h.icmph->type;
3341da177e4SLinus Torvalds 	int code = skb->h.icmph->code;
3351da177e4SLinus Torvalds 	struct sock *sk;
3361da177e4SLinus Torvalds 	int harderr;
3371da177e4SLinus Torvalds 	int err;
3381da177e4SLinus Torvalds 
339ba4e58ecSGerrit Renker 	sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
340ba4e58ecSGerrit Renker 			       skb->dev->ifindex, udptable		    );
3411da177e4SLinus Torvalds 	if (sk == NULL) {
3421da177e4SLinus Torvalds 		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
3431da177e4SLinus Torvalds 		return;	/* No socket for error */
3441da177e4SLinus Torvalds 	}
3451da177e4SLinus Torvalds 
3461da177e4SLinus Torvalds 	err = 0;
3471da177e4SLinus Torvalds 	harderr = 0;
3481da177e4SLinus Torvalds 	inet = inet_sk(sk);
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds 	switch (type) {
3511da177e4SLinus Torvalds 	default:
3521da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
3531da177e4SLinus Torvalds 		err = EHOSTUNREACH;
3541da177e4SLinus Torvalds 		break;
3551da177e4SLinus Torvalds 	case ICMP_SOURCE_QUENCH:
3561da177e4SLinus Torvalds 		goto out;
3571da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
3581da177e4SLinus Torvalds 		err = EPROTO;
3591da177e4SLinus Torvalds 		harderr = 1;
3601da177e4SLinus Torvalds 		break;
3611da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
3621da177e4SLinus Torvalds 		if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
3631da177e4SLinus Torvalds 			if (inet->pmtudisc != IP_PMTUDISC_DONT) {
3641da177e4SLinus Torvalds 				err = EMSGSIZE;
3651da177e4SLinus Torvalds 				harderr = 1;
3661da177e4SLinus Torvalds 				break;
3671da177e4SLinus Torvalds 			}
3681da177e4SLinus Torvalds 			goto out;
3691da177e4SLinus Torvalds 		}
3701da177e4SLinus Torvalds 		err = EHOSTUNREACH;
3711da177e4SLinus Torvalds 		if (code <= NR_ICMP_UNREACH) {
3721da177e4SLinus Torvalds 			harderr = icmp_err_convert[code].fatal;
3731da177e4SLinus Torvalds 			err = icmp_err_convert[code].errno;
3741da177e4SLinus Torvalds 		}
3751da177e4SLinus Torvalds 		break;
3761da177e4SLinus Torvalds 	}
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds 	/*
3791da177e4SLinus Torvalds 	 *      RFC1122: OK.  Passes ICMP errors back to application, as per
3801da177e4SLinus Torvalds 	 *	4.1.3.3.
3811da177e4SLinus Torvalds 	 */
3821da177e4SLinus Torvalds 	if (!inet->recverr) {
3831da177e4SLinus Torvalds 		if (!harderr || sk->sk_state != TCP_ESTABLISHED)
3841da177e4SLinus Torvalds 			goto out;
3851da177e4SLinus Torvalds 	} else {
3861da177e4SLinus Torvalds 		ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
3871da177e4SLinus Torvalds 	}
3881da177e4SLinus Torvalds 	sk->sk_err = err;
3891da177e4SLinus Torvalds 	sk->sk_error_report(sk);
3901da177e4SLinus Torvalds out:
3911da177e4SLinus Torvalds 	sock_put(sk);
3921da177e4SLinus Torvalds }
3931da177e4SLinus Torvalds 
3943fbe070aSStephen Hemminger void udp_err(struct sk_buff *skb, u32 info)
395ba4e58ecSGerrit Renker {
396ba4e58ecSGerrit Renker 	return __udp4_lib_err(skb, info, udp_hash);
397ba4e58ecSGerrit Renker }
398ba4e58ecSGerrit Renker 
3991da177e4SLinus Torvalds /*
4001da177e4SLinus Torvalds  * Throw away all pending data and cancel the corking. Socket is locked.
4011da177e4SLinus Torvalds  */
4021da177e4SLinus Torvalds static void udp_flush_pending_frames(struct sock *sk)
4031da177e4SLinus Torvalds {
4041da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds 	if (up->pending) {
4071da177e4SLinus Torvalds 		up->len = 0;
4081da177e4SLinus Torvalds 		up->pending = 0;
4091da177e4SLinus Torvalds 		ip_flush_pending_frames(sk);
4101da177e4SLinus Torvalds 	}
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds 
413ba4e58ecSGerrit Renker /**
414ba4e58ecSGerrit Renker  * 	udp4_hwcsum_outgoing  -  handle outgoing HW checksumming
415ba4e58ecSGerrit Renker  * 	@sk: 	socket we are sending on
416ba4e58ecSGerrit Renker  * 	@skb: 	sk_buff containing the filled-in UDP header
417ba4e58ecSGerrit Renker  * 	        (checksum field must be zeroed out)
418ba4e58ecSGerrit Renker  */
419ba4e58ecSGerrit Renker static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
420ba4e58ecSGerrit Renker 				 __be32 src, __be32 dst, int len      )
421ba4e58ecSGerrit Renker {
4226b11687eSAl Viro 	unsigned int offset;
423*4bedb452SArnaldo Carvalho de Melo 	struct udphdr *uh = udp_hdr(skb);
4246b11687eSAl Viro 	__wsum csum = 0;
425ba4e58ecSGerrit Renker 
426ba4e58ecSGerrit Renker 	if (skb_queue_len(&sk->sk_write_queue) == 1) {
427ba4e58ecSGerrit Renker 		/*
428ba4e58ecSGerrit Renker 		 * Only one fragment on the socket.
429ba4e58ecSGerrit Renker 		 */
430ff1dcadbSAl Viro 		skb->csum_offset = offsetof(struct udphdr, check);
431ba4e58ecSGerrit Renker 		uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);
432ba4e58ecSGerrit Renker 	} else {
433ba4e58ecSGerrit Renker 		/*
434ba4e58ecSGerrit Renker 		 * HW-checksum won't work as there are two or more
435ba4e58ecSGerrit Renker 		 * fragments on the socket so that all csums of sk_buffs
436ba4e58ecSGerrit Renker 		 * should be together
437ba4e58ecSGerrit Renker 		 */
438ea2ae17dSArnaldo Carvalho de Melo 		offset = skb_transport_offset(skb);
439ba4e58ecSGerrit Renker 		skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
440ba4e58ecSGerrit Renker 
441ba4e58ecSGerrit Renker 		skb->ip_summed = CHECKSUM_NONE;
442ba4e58ecSGerrit Renker 
443ba4e58ecSGerrit Renker 		skb_queue_walk(&sk->sk_write_queue, skb) {
444ba4e58ecSGerrit Renker 			csum = csum_add(csum, skb->csum);
445ba4e58ecSGerrit Renker 		}
446ba4e58ecSGerrit Renker 
447ba4e58ecSGerrit Renker 		uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum);
448ba4e58ecSGerrit Renker 		if (uh->check == 0)
449f6ab0288SAl Viro 			uh->check = CSUM_MANGLED_0;
450ba4e58ecSGerrit Renker 	}
451ba4e58ecSGerrit Renker }
452ba4e58ecSGerrit Renker 
4531da177e4SLinus Torvalds /*
4541da177e4SLinus Torvalds  * Push out all pending data as one UDP datagram. Socket is locked.
4551da177e4SLinus Torvalds  */
4564c0a6cb0SGerrit Renker static int udp_push_pending_frames(struct sock *sk)
4571da177e4SLinus Torvalds {
4584c0a6cb0SGerrit Renker 	struct udp_sock  *up = udp_sk(sk);
4591da177e4SLinus Torvalds 	struct inet_sock *inet = inet_sk(sk);
4601da177e4SLinus Torvalds 	struct flowi *fl = &inet->cork.fl;
4611da177e4SLinus Torvalds 	struct sk_buff *skb;
4621da177e4SLinus Torvalds 	struct udphdr *uh;
4631da177e4SLinus Torvalds 	int err = 0;
4648e5200f5SAl Viro 	__wsum csum = 0;
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds 	/* Grab the skbuff where UDP header space exists. */
4671da177e4SLinus Torvalds 	if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
4681da177e4SLinus Torvalds 		goto out;
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds 	/*
4711da177e4SLinus Torvalds 	 * Create a UDP header
4721da177e4SLinus Torvalds 	 */
473*4bedb452SArnaldo Carvalho de Melo 	uh = udp_hdr(skb);
4741da177e4SLinus Torvalds 	uh->source = fl->fl_ip_sport;
4751da177e4SLinus Torvalds 	uh->dest = fl->fl_ip_dport;
4761da177e4SLinus Torvalds 	uh->len = htons(up->len);
4771da177e4SLinus Torvalds 	uh->check = 0;
4781da177e4SLinus Torvalds 
479ba4e58ecSGerrit Renker 	if (up->pcflag)  				 /*     UDP-Lite      */
480ba4e58ecSGerrit Renker 		csum  = udplite_csum_outgoing(sk, skb);
481ba4e58ecSGerrit Renker 
482ba4e58ecSGerrit Renker 	else if (sk->sk_no_check == UDP_CSUM_NOXMIT) {   /* UDP csum disabled */
483ba4e58ecSGerrit Renker 
4841da177e4SLinus Torvalds 		skb->ip_summed = CHECKSUM_NONE;
4851da177e4SLinus Torvalds 		goto send;
4861da177e4SLinus Torvalds 
487ba4e58ecSGerrit Renker 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
488ba4e58ecSGerrit Renker 
489ba4e58ecSGerrit Renker 		udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len);
490ba4e58ecSGerrit Renker 		goto send;
491ba4e58ecSGerrit Renker 
492ba4e58ecSGerrit Renker 	} else						 /*   `normal' UDP    */
493ba4e58ecSGerrit Renker 		csum = udp_csum_outgoing(sk, skb);
494ba4e58ecSGerrit Renker 
495ba4e58ecSGerrit Renker 	/* add protocol-dependent pseudo-header */
496ba4e58ecSGerrit Renker 	uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,
497ba4e58ecSGerrit Renker 				      sk->sk_protocol, csum             );
4981da177e4SLinus Torvalds 	if (uh->check == 0)
499f6ab0288SAl Viro 		uh->check = CSUM_MANGLED_0;
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds send:
5021da177e4SLinus Torvalds 	err = ip_push_pending_frames(sk);
5031da177e4SLinus Torvalds out:
5041da177e4SLinus Torvalds 	up->len = 0;
5051da177e4SLinus Torvalds 	up->pending = 0;
5061da177e4SLinus Torvalds 	return err;
5071da177e4SLinus Torvalds }
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
5101da177e4SLinus Torvalds 		size_t len)
5111da177e4SLinus Torvalds {
5121da177e4SLinus Torvalds 	struct inet_sock *inet = inet_sk(sk);
5131da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
5141da177e4SLinus Torvalds 	int ulen = len;
5151da177e4SLinus Torvalds 	struct ipcm_cookie ipc;
5161da177e4SLinus Torvalds 	struct rtable *rt = NULL;
5171da177e4SLinus Torvalds 	int free = 0;
5181da177e4SLinus Torvalds 	int connected = 0;
5193ca3c68eSAl Viro 	__be32 daddr, faddr, saddr;
520734ab87fSAl Viro 	__be16 dport;
5211da177e4SLinus Torvalds 	u8  tos;
522ba4e58ecSGerrit Renker 	int err, is_udplite = up->pcflag;
5231da177e4SLinus Torvalds 	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
524ba4e58ecSGerrit Renker 	int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 	if (len > 0xFFFF)
5271da177e4SLinus Torvalds 		return -EMSGSIZE;
5281da177e4SLinus Torvalds 
5291da177e4SLinus Torvalds 	/*
5301da177e4SLinus Torvalds 	 *	Check the flags.
5311da177e4SLinus Torvalds 	 */
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds 	if (msg->msg_flags&MSG_OOB)	/* Mirror BSD error message compatibility */
5341da177e4SLinus Torvalds 		return -EOPNOTSUPP;
5351da177e4SLinus Torvalds 
5361da177e4SLinus Torvalds 	ipc.opt = NULL;
5371da177e4SLinus Torvalds 
5381da177e4SLinus Torvalds 	if (up->pending) {
5391da177e4SLinus Torvalds 		/*
5401da177e4SLinus Torvalds 		 * There are pending frames.
5411da177e4SLinus Torvalds 		 * The socket lock must be held while it's corked.
5421da177e4SLinus Torvalds 		 */
5431da177e4SLinus Torvalds 		lock_sock(sk);
5441da177e4SLinus Torvalds 		if (likely(up->pending)) {
5451da177e4SLinus Torvalds 			if (unlikely(up->pending != AF_INET)) {
5461da177e4SLinus Torvalds 				release_sock(sk);
5471da177e4SLinus Torvalds 				return -EINVAL;
5481da177e4SLinus Torvalds 			}
5491da177e4SLinus Torvalds 			goto do_append_data;
5501da177e4SLinus Torvalds 		}
5511da177e4SLinus Torvalds 		release_sock(sk);
5521da177e4SLinus Torvalds 	}
5531da177e4SLinus Torvalds 	ulen += sizeof(struct udphdr);
5541da177e4SLinus Torvalds 
5551da177e4SLinus Torvalds 	/*
5561da177e4SLinus Torvalds 	 *	Get and verify the address.
5571da177e4SLinus Torvalds 	 */
5581da177e4SLinus Torvalds 	if (msg->msg_name) {
5591da177e4SLinus Torvalds 		struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
5601da177e4SLinus Torvalds 		if (msg->msg_namelen < sizeof(*usin))
5611da177e4SLinus Torvalds 			return -EINVAL;
5621da177e4SLinus Torvalds 		if (usin->sin_family != AF_INET) {
5631da177e4SLinus Torvalds 			if (usin->sin_family != AF_UNSPEC)
5641da177e4SLinus Torvalds 				return -EAFNOSUPPORT;
5651da177e4SLinus Torvalds 		}
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds 		daddr = usin->sin_addr.s_addr;
5681da177e4SLinus Torvalds 		dport = usin->sin_port;
5691da177e4SLinus Torvalds 		if (dport == 0)
5701da177e4SLinus Torvalds 			return -EINVAL;
5711da177e4SLinus Torvalds 	} else {
5721da177e4SLinus Torvalds 		if (sk->sk_state != TCP_ESTABLISHED)
5731da177e4SLinus Torvalds 			return -EDESTADDRREQ;
5741da177e4SLinus Torvalds 		daddr = inet->daddr;
5751da177e4SLinus Torvalds 		dport = inet->dport;
5761da177e4SLinus Torvalds 		/* Open fast path for connected socket.
5771da177e4SLinus Torvalds 		   Route will not be used, if at least one option is set.
5781da177e4SLinus Torvalds 		 */
5791da177e4SLinus Torvalds 		connected = 1;
5801da177e4SLinus Torvalds 	}
5811da177e4SLinus Torvalds 	ipc.addr = inet->saddr;
5821da177e4SLinus Torvalds 
5831da177e4SLinus Torvalds 	ipc.oif = sk->sk_bound_dev_if;
5841da177e4SLinus Torvalds 	if (msg->msg_controllen) {
5851da177e4SLinus Torvalds 		err = ip_cmsg_send(msg, &ipc);
5861da177e4SLinus Torvalds 		if (err)
5871da177e4SLinus Torvalds 			return err;
5881da177e4SLinus Torvalds 		if (ipc.opt)
5891da177e4SLinus Torvalds 			free = 1;
5901da177e4SLinus Torvalds 		connected = 0;
5911da177e4SLinus Torvalds 	}
5921da177e4SLinus Torvalds 	if (!ipc.opt)
5931da177e4SLinus Torvalds 		ipc.opt = inet->opt;
5941da177e4SLinus Torvalds 
5951da177e4SLinus Torvalds 	saddr = ipc.addr;
5961da177e4SLinus Torvalds 	ipc.addr = faddr = daddr;
5971da177e4SLinus Torvalds 
5981da177e4SLinus Torvalds 	if (ipc.opt && ipc.opt->srr) {
5991da177e4SLinus Torvalds 		if (!daddr)
6001da177e4SLinus Torvalds 			return -EINVAL;
6011da177e4SLinus Torvalds 		faddr = ipc.opt->faddr;
6021da177e4SLinus Torvalds 		connected = 0;
6031da177e4SLinus Torvalds 	}
6041da177e4SLinus Torvalds 	tos = RT_TOS(inet->tos);
6051da177e4SLinus Torvalds 	if (sock_flag(sk, SOCK_LOCALROUTE) ||
6061da177e4SLinus Torvalds 	    (msg->msg_flags & MSG_DONTROUTE) ||
6071da177e4SLinus Torvalds 	    (ipc.opt && ipc.opt->is_strictroute)) {
6081da177e4SLinus Torvalds 		tos |= RTO_ONLINK;
6091da177e4SLinus Torvalds 		connected = 0;
6101da177e4SLinus Torvalds 	}
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	if (MULTICAST(daddr)) {
6131da177e4SLinus Torvalds 		if (!ipc.oif)
6141da177e4SLinus Torvalds 			ipc.oif = inet->mc_index;
6151da177e4SLinus Torvalds 		if (!saddr)
6161da177e4SLinus Torvalds 			saddr = inet->mc_addr;
6171da177e4SLinus Torvalds 		connected = 0;
6181da177e4SLinus Torvalds 	}
6191da177e4SLinus Torvalds 
6201da177e4SLinus Torvalds 	if (connected)
6211da177e4SLinus Torvalds 		rt = (struct rtable*)sk_dst_check(sk, 0);
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds 	if (rt == NULL) {
6241da177e4SLinus Torvalds 		struct flowi fl = { .oif = ipc.oif,
6251da177e4SLinus Torvalds 				    .nl_u = { .ip4_u =
6261da177e4SLinus Torvalds 					      { .daddr = faddr,
6271da177e4SLinus Torvalds 						.saddr = saddr,
6281da177e4SLinus Torvalds 						.tos = tos } },
629ba4e58ecSGerrit Renker 				    .proto = sk->sk_protocol,
6301da177e4SLinus Torvalds 				    .uli_u = { .ports =
6311da177e4SLinus Torvalds 					       { .sport = inet->sport,
6321da177e4SLinus Torvalds 						 .dport = dport } } };
633beb8d13bSVenkat Yekkirala 		security_sk_classify_flow(sk, &fl);
6348eb9086fSDavid S. Miller 		err = ip_route_output_flow(&rt, &fl, sk, 1);
6351da177e4SLinus Torvalds 		if (err)
6361da177e4SLinus Torvalds 			goto out;
6371da177e4SLinus Torvalds 
6381da177e4SLinus Torvalds 		err = -EACCES;
6391da177e4SLinus Torvalds 		if ((rt->rt_flags & RTCF_BROADCAST) &&
6401da177e4SLinus Torvalds 		    !sock_flag(sk, SOCK_BROADCAST))
6411da177e4SLinus Torvalds 			goto out;
6421da177e4SLinus Torvalds 		if (connected)
6431da177e4SLinus Torvalds 			sk_dst_set(sk, dst_clone(&rt->u.dst));
6441da177e4SLinus Torvalds 	}
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 	if (msg->msg_flags&MSG_CONFIRM)
6471da177e4SLinus Torvalds 		goto do_confirm;
6481da177e4SLinus Torvalds back_from_confirm:
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 	saddr = rt->rt_src;
6511da177e4SLinus Torvalds 	if (!ipc.addr)
6521da177e4SLinus Torvalds 		daddr = ipc.addr = rt->rt_dst;
6531da177e4SLinus Torvalds 
6541da177e4SLinus Torvalds 	lock_sock(sk);
6551da177e4SLinus Torvalds 	if (unlikely(up->pending)) {
6561da177e4SLinus Torvalds 		/* The socket is already corked while preparing it. */
6571da177e4SLinus Torvalds 		/* ... which is an evident application bug. --ANK */
6581da177e4SLinus Torvalds 		release_sock(sk);
6591da177e4SLinus Torvalds 
66064ce2073SPatrick McHardy 		LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n");
6611da177e4SLinus Torvalds 		err = -EINVAL;
6621da177e4SLinus Torvalds 		goto out;
6631da177e4SLinus Torvalds 	}
6641da177e4SLinus Torvalds 	/*
6651da177e4SLinus Torvalds 	 *	Now cork the socket to pend data.
6661da177e4SLinus Torvalds 	 */
6671da177e4SLinus Torvalds 	inet->cork.fl.fl4_dst = daddr;
6681da177e4SLinus Torvalds 	inet->cork.fl.fl_ip_dport = dport;
6691da177e4SLinus Torvalds 	inet->cork.fl.fl4_src = saddr;
6701da177e4SLinus Torvalds 	inet->cork.fl.fl_ip_sport = inet->sport;
6711da177e4SLinus Torvalds 	up->pending = AF_INET;
6721da177e4SLinus Torvalds 
6731da177e4SLinus Torvalds do_append_data:
6741da177e4SLinus Torvalds 	up->len += ulen;
675ba4e58ecSGerrit Renker 	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
676ba4e58ecSGerrit Renker 	err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
6771da177e4SLinus Torvalds 			sizeof(struct udphdr), &ipc, rt,
6781da177e4SLinus Torvalds 			corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
6791da177e4SLinus Torvalds 	if (err)
6801da177e4SLinus Torvalds 		udp_flush_pending_frames(sk);
6811da177e4SLinus Torvalds 	else if (!corkreq)
6824c0a6cb0SGerrit Renker 		err = udp_push_pending_frames(sk);
6831e0c14f4SHerbert Xu 	else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
6841e0c14f4SHerbert Xu 		up->pending = 0;
6851da177e4SLinus Torvalds 	release_sock(sk);
6861da177e4SLinus Torvalds 
6871da177e4SLinus Torvalds out:
6881da177e4SLinus Torvalds 	ip_rt_put(rt);
6891da177e4SLinus Torvalds 	if (free)
6901da177e4SLinus Torvalds 		kfree(ipc.opt);
6911da177e4SLinus Torvalds 	if (!err) {
692ba4e58ecSGerrit Renker 		UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
6931da177e4SLinus Torvalds 		return len;
6941da177e4SLinus Torvalds 	}
69581aa646cSMartin Bligh 	/*
69681aa646cSMartin Bligh 	 * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space.  Reporting
69781aa646cSMartin Bligh 	 * ENOBUFS might not be good (it's not tunable per se), but otherwise
69881aa646cSMartin Bligh 	 * we don't have a good statistic (IpOutDiscards but it can be too many
69981aa646cSMartin Bligh 	 * things).  We could add another new stat but at least for now that
70081aa646cSMartin Bligh 	 * seems like overkill.
70181aa646cSMartin Bligh 	 */
70281aa646cSMartin Bligh 	if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
703ba4e58ecSGerrit Renker 		UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
70481aa646cSMartin Bligh 	}
7051da177e4SLinus Torvalds 	return err;
7061da177e4SLinus Torvalds 
7071da177e4SLinus Torvalds do_confirm:
7081da177e4SLinus Torvalds 	dst_confirm(&rt->u.dst);
7091da177e4SLinus Torvalds 	if (!(msg->msg_flags&MSG_PROBE) || len)
7101da177e4SLinus Torvalds 		goto back_from_confirm;
7111da177e4SLinus Torvalds 	err = 0;
7121da177e4SLinus Torvalds 	goto out;
7131da177e4SLinus Torvalds }
7141da177e4SLinus Torvalds 
715ba4e58ecSGerrit Renker int udp_sendpage(struct sock *sk, struct page *page, int offset,
7161da177e4SLinus Torvalds 		 size_t size, int flags)
7171da177e4SLinus Torvalds {
7181da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
7191da177e4SLinus Torvalds 	int ret;
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds 	if (!up->pending) {
7221da177e4SLinus Torvalds 		struct msghdr msg = {	.msg_flags = flags|MSG_MORE };
7231da177e4SLinus Torvalds 
7241da177e4SLinus Torvalds 		/* Call udp_sendmsg to specify destination address which
7251da177e4SLinus Torvalds 		 * sendpage interface can't pass.
7261da177e4SLinus Torvalds 		 * This will succeed only when the socket is connected.
7271da177e4SLinus Torvalds 		 */
7281da177e4SLinus Torvalds 		ret = udp_sendmsg(NULL, sk, &msg, 0);
7291da177e4SLinus Torvalds 		if (ret < 0)
7301da177e4SLinus Torvalds 			return ret;
7311da177e4SLinus Torvalds 	}
7321da177e4SLinus Torvalds 
7331da177e4SLinus Torvalds 	lock_sock(sk);
7341da177e4SLinus Torvalds 
7351da177e4SLinus Torvalds 	if (unlikely(!up->pending)) {
7361da177e4SLinus Torvalds 		release_sock(sk);
7371da177e4SLinus Torvalds 
73864ce2073SPatrick McHardy 		LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 3\n");
7391da177e4SLinus Torvalds 		return -EINVAL;
7401da177e4SLinus Torvalds 	}
7411da177e4SLinus Torvalds 
7421da177e4SLinus Torvalds 	ret = ip_append_page(sk, page, offset, size, flags);
7431da177e4SLinus Torvalds 	if (ret == -EOPNOTSUPP) {
7441da177e4SLinus Torvalds 		release_sock(sk);
7451da177e4SLinus Torvalds 		return sock_no_sendpage(sk->sk_socket, page, offset,
7461da177e4SLinus Torvalds 					size, flags);
7471da177e4SLinus Torvalds 	}
7481da177e4SLinus Torvalds 	if (ret < 0) {
7491da177e4SLinus Torvalds 		udp_flush_pending_frames(sk);
7501da177e4SLinus Torvalds 		goto out;
7511da177e4SLinus Torvalds 	}
7521da177e4SLinus Torvalds 
7531da177e4SLinus Torvalds 	up->len += size;
7541da177e4SLinus Torvalds 	if (!(up->corkflag || (flags&MSG_MORE)))
7554c0a6cb0SGerrit Renker 		ret = udp_push_pending_frames(sk);
7561da177e4SLinus Torvalds 	if (!ret)
7571da177e4SLinus Torvalds 		ret = size;
7581da177e4SLinus Torvalds out:
7591da177e4SLinus Torvalds 	release_sock(sk);
7601da177e4SLinus Torvalds 	return ret;
7611da177e4SLinus Torvalds }
7621da177e4SLinus Torvalds 
7631da177e4SLinus Torvalds /*
7641da177e4SLinus Torvalds  *	IOCTL requests applicable to the UDP protocol
7651da177e4SLinus Torvalds  */
7661da177e4SLinus Torvalds 
7671da177e4SLinus Torvalds int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
7681da177e4SLinus Torvalds {
7696516c655SStephen Hemminger 	switch (cmd) {
7701da177e4SLinus Torvalds 	case SIOCOUTQ:
7711da177e4SLinus Torvalds 	{
7721da177e4SLinus Torvalds 		int amount = atomic_read(&sk->sk_wmem_alloc);
7731da177e4SLinus Torvalds 		return put_user(amount, (int __user *)arg);
7741da177e4SLinus Torvalds 	}
7751da177e4SLinus Torvalds 
7761da177e4SLinus Torvalds 	case SIOCINQ:
7771da177e4SLinus Torvalds 	{
7781da177e4SLinus Torvalds 		struct sk_buff *skb;
7791da177e4SLinus Torvalds 		unsigned long amount;
7801da177e4SLinus Torvalds 
7811da177e4SLinus Torvalds 		amount = 0;
782208d8984SHerbert Xu 		spin_lock_bh(&sk->sk_receive_queue.lock);
7831da177e4SLinus Torvalds 		skb = skb_peek(&sk->sk_receive_queue);
7841da177e4SLinus Torvalds 		if (skb != NULL) {
7851da177e4SLinus Torvalds 			/*
7861da177e4SLinus Torvalds 			 * We will only return the amount
7871da177e4SLinus Torvalds 			 * of this packet since that is all
7881da177e4SLinus Torvalds 			 * that will be read.
7891da177e4SLinus Torvalds 			 */
7901da177e4SLinus Torvalds 			amount = skb->len - sizeof(struct udphdr);
7911da177e4SLinus Torvalds 		}
792208d8984SHerbert Xu 		spin_unlock_bh(&sk->sk_receive_queue.lock);
7931da177e4SLinus Torvalds 		return put_user(amount, (int __user *)arg);
7941da177e4SLinus Torvalds 	}
7951da177e4SLinus Torvalds 
7961da177e4SLinus Torvalds 	default:
7971da177e4SLinus Torvalds 		return -ENOIOCTLCMD;
7981da177e4SLinus Torvalds 	}
7996516c655SStephen Hemminger 
8006516c655SStephen Hemminger 	return 0;
8011da177e4SLinus Torvalds }
8021da177e4SLinus Torvalds 
8031da177e4SLinus Torvalds /*
8041da177e4SLinus Torvalds  * 	This should be easy, if there is something there we
8051da177e4SLinus Torvalds  * 	return it, otherwise we block.
8061da177e4SLinus Torvalds  */
8071da177e4SLinus Torvalds 
808ba4e58ecSGerrit Renker int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
8091da177e4SLinus Torvalds 		size_t len, int noblock, int flags, int *addr_len)
8101da177e4SLinus Torvalds {
8111da177e4SLinus Torvalds 	struct inet_sock *inet = inet_sk(sk);
8121da177e4SLinus Torvalds 	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
8131da177e4SLinus Torvalds 	struct sk_buff *skb;
814759e5d00SHerbert Xu 	unsigned int ulen, copied;
815759e5d00SHerbert Xu 	int err;
816759e5d00SHerbert Xu 	int is_udplite = IS_UDPLITE(sk);
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds 	/*
8191da177e4SLinus Torvalds 	 *	Check any passed addresses
8201da177e4SLinus Torvalds 	 */
8211da177e4SLinus Torvalds 	if (addr_len)
8221da177e4SLinus Torvalds 		*addr_len=sizeof(*sin);
8231da177e4SLinus Torvalds 
8241da177e4SLinus Torvalds 	if (flags & MSG_ERRQUEUE)
8251da177e4SLinus Torvalds 		return ip_recv_error(sk, msg, len);
8261da177e4SLinus Torvalds 
8271da177e4SLinus Torvalds try_again:
8281da177e4SLinus Torvalds 	skb = skb_recv_datagram(sk, flags, noblock, &err);
8291da177e4SLinus Torvalds 	if (!skb)
8301da177e4SLinus Torvalds 		goto out;
8311da177e4SLinus Torvalds 
832759e5d00SHerbert Xu 	ulen = skb->len - sizeof(struct udphdr);
8331da177e4SLinus Torvalds 	copied = len;
834759e5d00SHerbert Xu 	if (copied > ulen)
835759e5d00SHerbert Xu 		copied = ulen;
836759e5d00SHerbert Xu 	else if (copied < ulen)
8371da177e4SLinus Torvalds 		msg->msg_flags |= MSG_TRUNC;
8381da177e4SLinus Torvalds 
839ba4e58ecSGerrit Renker 	/*
840759e5d00SHerbert Xu 	 * If checksum is needed at all, try to do it while copying the
841759e5d00SHerbert Xu 	 * data.  If the data is truncated, or if we only want a partial
842759e5d00SHerbert Xu 	 * coverage checksum (UDP-Lite), do it before the copy.
843ba4e58ecSGerrit Renker 	 */
844ba4e58ecSGerrit Renker 
845759e5d00SHerbert Xu 	if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
846759e5d00SHerbert Xu 		if (udp_lib_checksum_complete(skb))
8471da177e4SLinus Torvalds 			goto csum_copy_err;
848ba4e58ecSGerrit Renker 	}
849ba4e58ecSGerrit Renker 
850759e5d00SHerbert Xu 	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
851ba4e58ecSGerrit Renker 		err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
852ba4e58ecSGerrit Renker 					      msg->msg_iov, copied       );
853ba4e58ecSGerrit Renker 	else {
8541da177e4SLinus Torvalds 		err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
8551da177e4SLinus Torvalds 
8561da177e4SLinus Torvalds 		if (err == -EINVAL)
8571da177e4SLinus Torvalds 			goto csum_copy_err;
8581da177e4SLinus Torvalds 	}
8591da177e4SLinus Torvalds 
8601da177e4SLinus Torvalds 	if (err)
8611da177e4SLinus Torvalds 		goto out_free;
8621da177e4SLinus Torvalds 
8631da177e4SLinus Torvalds 	sock_recv_timestamp(msg, sk, skb);
8641da177e4SLinus Torvalds 
8651da177e4SLinus Torvalds 	/* Copy the address. */
8661da177e4SLinus Torvalds 	if (sin)
8671da177e4SLinus Torvalds 	{
8681da177e4SLinus Torvalds 		sin->sin_family = AF_INET;
869*4bedb452SArnaldo Carvalho de Melo 		sin->sin_port = udp_hdr(skb)->source;
870eddc9ec5SArnaldo Carvalho de Melo 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
8711da177e4SLinus Torvalds 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
8721da177e4SLinus Torvalds 	}
8731da177e4SLinus Torvalds 	if (inet->cmsg_flags)
8741da177e4SLinus Torvalds 		ip_cmsg_recv(msg, skb);
8751da177e4SLinus Torvalds 
8761da177e4SLinus Torvalds 	err = copied;
8771da177e4SLinus Torvalds 	if (flags & MSG_TRUNC)
878759e5d00SHerbert Xu 		err = ulen;
8791da177e4SLinus Torvalds 
8801da177e4SLinus Torvalds out_free:
8811da177e4SLinus Torvalds 	skb_free_datagram(sk, skb);
8821da177e4SLinus Torvalds out:
8831da177e4SLinus Torvalds 	return err;
8841da177e4SLinus Torvalds 
8851da177e4SLinus Torvalds csum_copy_err:
886ba4e58ecSGerrit Renker 	UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
8871da177e4SLinus Torvalds 
8883305b80cSHerbert Xu 	skb_kill_datagram(sk, skb, flags);
8891da177e4SLinus Torvalds 
8901da177e4SLinus Torvalds 	if (noblock)
8911da177e4SLinus Torvalds 		return -EAGAIN;
8921da177e4SLinus Torvalds 	goto try_again;
8931da177e4SLinus Torvalds }
8941da177e4SLinus Torvalds 
8951da177e4SLinus Torvalds 
8961da177e4SLinus Torvalds int udp_disconnect(struct sock *sk, int flags)
8971da177e4SLinus Torvalds {
8981da177e4SLinus Torvalds 	struct inet_sock *inet = inet_sk(sk);
8991da177e4SLinus Torvalds 	/*
9001da177e4SLinus Torvalds 	 *	1003.1g - break association.
9011da177e4SLinus Torvalds 	 */
9021da177e4SLinus Torvalds 
9031da177e4SLinus Torvalds 	sk->sk_state = TCP_CLOSE;
9041da177e4SLinus Torvalds 	inet->daddr = 0;
9051da177e4SLinus Torvalds 	inet->dport = 0;
9061da177e4SLinus Torvalds 	sk->sk_bound_dev_if = 0;
9071da177e4SLinus Torvalds 	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
9081da177e4SLinus Torvalds 		inet_reset_saddr(sk);
9091da177e4SLinus Torvalds 
9101da177e4SLinus Torvalds 	if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) {
9111da177e4SLinus Torvalds 		sk->sk_prot->unhash(sk);
9121da177e4SLinus Torvalds 		inet->sport = 0;
9131da177e4SLinus Torvalds 	}
9141da177e4SLinus Torvalds 	sk_dst_reset(sk);
9151da177e4SLinus Torvalds 	return 0;
9161da177e4SLinus Torvalds }
9171da177e4SLinus Torvalds 
9181da177e4SLinus Torvalds /* return:
9191da177e4SLinus Torvalds  * 	1  if the the UDP system should process it
9201da177e4SLinus Torvalds  *	0  if we should drop this packet
9211da177e4SLinus Torvalds  * 	-1 if it should get processed by xfrm4_rcv_encap
9221da177e4SLinus Torvalds  */
9231da177e4SLinus Torvalds static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
9241da177e4SLinus Torvalds {
9251da177e4SLinus Torvalds #ifndef CONFIG_XFRM
9261da177e4SLinus Torvalds 	return 1;
9271da177e4SLinus Torvalds #else
9281da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
929753eab76SOlaf Kirch 	struct udphdr *uh;
9301da177e4SLinus Torvalds 	struct iphdr *iph;
9311da177e4SLinus Torvalds 	int iphlen, len;
9321da177e4SLinus Torvalds 
933753eab76SOlaf Kirch 	__u8 *udpdata;
934753eab76SOlaf Kirch 	__be32 *udpdata32;
9351da177e4SLinus Torvalds 	__u16 encap_type = up->encap_type;
9361da177e4SLinus Torvalds 
9371da177e4SLinus Torvalds 	/* if we're overly short, let UDP handle it */
938753eab76SOlaf Kirch 	len = skb->len - sizeof(struct udphdr);
939753eab76SOlaf Kirch 	if (len <= 0)
9401da177e4SLinus Torvalds 		return 1;
9411da177e4SLinus Torvalds 
9421da177e4SLinus Torvalds 	/* if this is not encapsulated socket, then just return now */
9431da177e4SLinus Torvalds 	if (!encap_type)
9441da177e4SLinus Torvalds 		return 1;
9451da177e4SLinus Torvalds 
946753eab76SOlaf Kirch 	/* If this is a paged skb, make sure we pull up
947753eab76SOlaf Kirch 	 * whatever data we need to look at. */
948753eab76SOlaf Kirch 	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
949753eab76SOlaf Kirch 		return 1;
950753eab76SOlaf Kirch 
951753eab76SOlaf Kirch 	/* Now we can get the pointers */
952*4bedb452SArnaldo Carvalho de Melo 	uh = udp_hdr(skb);
953753eab76SOlaf Kirch 	udpdata = (__u8 *)uh + sizeof(struct udphdr);
954753eab76SOlaf Kirch 	udpdata32 = (__be32 *)udpdata;
9551da177e4SLinus Torvalds 
9561da177e4SLinus Torvalds 	switch (encap_type) {
9571da177e4SLinus Torvalds 	default:
9581da177e4SLinus Torvalds 	case UDP_ENCAP_ESPINUDP:
9591da177e4SLinus Torvalds 		/* Check if this is a keepalive packet.  If so, eat it. */
9601da177e4SLinus Torvalds 		if (len == 1 && udpdata[0] == 0xff) {
9611da177e4SLinus Torvalds 			return 0;
9621da177e4SLinus Torvalds 		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
9631da177e4SLinus Torvalds 			/* ESP Packet without Non-ESP header */
9641da177e4SLinus Torvalds 			len = sizeof(struct udphdr);
9651da177e4SLinus Torvalds 		} else
9661da177e4SLinus Torvalds 			/* Must be an IKE packet.. pass it through */
9671da177e4SLinus Torvalds 			return 1;
9681da177e4SLinus Torvalds 		break;
9691da177e4SLinus Torvalds 	case UDP_ENCAP_ESPINUDP_NON_IKE:
9701da177e4SLinus Torvalds 		/* Check if this is a keepalive packet.  If so, eat it. */
9711da177e4SLinus Torvalds 		if (len == 1 && udpdata[0] == 0xff) {
9721da177e4SLinus Torvalds 			return 0;
9731da177e4SLinus Torvalds 		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
9741da177e4SLinus Torvalds 			   udpdata32[0] == 0 && udpdata32[1] == 0) {
9751da177e4SLinus Torvalds 
9761da177e4SLinus Torvalds 			/* ESP Packet with Non-IKE marker */
9771da177e4SLinus Torvalds 			len = sizeof(struct udphdr) + 2 * sizeof(u32);
9781da177e4SLinus Torvalds 		} else
9791da177e4SLinus Torvalds 			/* Must be an IKE packet.. pass it through */
9801da177e4SLinus Torvalds 			return 1;
9811da177e4SLinus Torvalds 		break;
9821da177e4SLinus Torvalds 	}
9831da177e4SLinus Torvalds 
9841da177e4SLinus Torvalds 	/* At this point we are sure that this is an ESPinUDP packet,
9851da177e4SLinus Torvalds 	 * so we need to remove 'len' bytes from the packet (the UDP
9861da177e4SLinus Torvalds 	 * header and optional ESP marker bytes) and then modify the
9871da177e4SLinus Torvalds 	 * protocol to ESP, and then call into the transform receiver.
9881da177e4SLinus Torvalds 	 */
9894d78b6c7SHerbert Xu 	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
9904d78b6c7SHerbert Xu 		return 0;
9911da177e4SLinus Torvalds 
9921da177e4SLinus Torvalds 	/* Now we can update and verify the packet length... */
993eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
9941da177e4SLinus Torvalds 	iphlen = iph->ihl << 2;
9951da177e4SLinus Torvalds 	iph->tot_len = htons(ntohs(iph->tot_len) - len);
9961da177e4SLinus Torvalds 	if (skb->len < iphlen + len) {
9971da177e4SLinus Torvalds 		/* packet is too small!?! */
9981da177e4SLinus Torvalds 		return 0;
9991da177e4SLinus Torvalds 	}
10001da177e4SLinus Torvalds 
10011da177e4SLinus Torvalds 	/* pull the data buffer up to the ESP header and set the
10021da177e4SLinus Torvalds 	 * transport header to point to ESP.  Keep UDP on the stack
10031da177e4SLinus Torvalds 	 * for later.
10041da177e4SLinus Torvalds 	 */
1005badff6d0SArnaldo Carvalho de Melo 	__skb_pull(skb, len);
1006badff6d0SArnaldo Carvalho de Melo 	skb_reset_transport_header(skb);
10071da177e4SLinus Torvalds 
10081da177e4SLinus Torvalds 	/* modify the protocol (it's ESP!) */
10091da177e4SLinus Torvalds 	iph->protocol = IPPROTO_ESP;
10101da177e4SLinus Torvalds 
10111da177e4SLinus Torvalds 	/* and let the caller know to send this into the ESP processor... */
10121da177e4SLinus Torvalds 	return -1;
10131da177e4SLinus Torvalds #endif
10141da177e4SLinus Torvalds }
10151da177e4SLinus Torvalds 
10161da177e4SLinus Torvalds /* returns:
10171da177e4SLinus Torvalds  *  -1: error
10181da177e4SLinus Torvalds  *   0: success
10191da177e4SLinus Torvalds  *  >0: "udp encap" protocol resubmission
10201da177e4SLinus Torvalds  *
10211da177e4SLinus Torvalds  * Note that in the success and error cases, the skb is assumed to
10221da177e4SLinus Torvalds  * have either been requeued or freed.
10231da177e4SLinus Torvalds  */
1024ba4e58ecSGerrit Renker int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
10251da177e4SLinus Torvalds {
10261da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
102781aa646cSMartin Bligh 	int rc;
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds 	/*
10301da177e4SLinus Torvalds 	 *	Charge it to the socket, dropping if the queue is full.
10311da177e4SLinus Torvalds 	 */
1032ba4e58ecSGerrit Renker 	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
1033ba4e58ecSGerrit Renker 		goto drop;
1034b59c2701SPatrick McHardy 	nf_reset(skb);
10351da177e4SLinus Torvalds 
10361da177e4SLinus Torvalds 	if (up->encap_type) {
10371da177e4SLinus Torvalds 		/*
10381da177e4SLinus Torvalds 		 * This is an encapsulation socket, so let's see if this is
10391da177e4SLinus Torvalds 		 * an encapsulated packet.
10401da177e4SLinus Torvalds 		 * If it's a keepalive packet, then just eat it.
10411da177e4SLinus Torvalds 		 * If it's an encapsulateed packet, then pass it to the
10421da177e4SLinus Torvalds 		 * IPsec xfrm input and return the response
10431da177e4SLinus Torvalds 		 * appropriately.  Otherwise, just fall through and
10441da177e4SLinus Torvalds 		 * pass this up the UDP socket.
10451da177e4SLinus Torvalds 		 */
10461da177e4SLinus Torvalds 		int ret;
10471da177e4SLinus Torvalds 
10481da177e4SLinus Torvalds 		ret = udp_encap_rcv(sk, skb);
10491da177e4SLinus Torvalds 		if (ret == 0) {
10501da177e4SLinus Torvalds 			/* Eat the packet .. */
10511da177e4SLinus Torvalds 			kfree_skb(skb);
10521da177e4SLinus Torvalds 			return 0;
10531da177e4SLinus Torvalds 		}
10541da177e4SLinus Torvalds 		if (ret < 0) {
10551da177e4SLinus Torvalds 			/* process the ESP packet */
10561da177e4SLinus Torvalds 			ret = xfrm4_rcv_encap(skb, up->encap_type);
1057ba4e58ecSGerrit Renker 			UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
10581da177e4SLinus Torvalds 			return -ret;
10591da177e4SLinus Torvalds 		}
10601da177e4SLinus Torvalds 		/* FALLTHROUGH -- it's a UDP Packet */
10611da177e4SLinus Torvalds 	}
10621da177e4SLinus Torvalds 
1063ba4e58ecSGerrit Renker 	/*
1064ba4e58ecSGerrit Renker 	 * 	UDP-Lite specific tests, ignored on UDP sockets
1065ba4e58ecSGerrit Renker 	 */
1066ba4e58ecSGerrit Renker 	if ((up->pcflag & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
1067ba4e58ecSGerrit Renker 
1068ba4e58ecSGerrit Renker 		/*
1069ba4e58ecSGerrit Renker 		 * MIB statistics other than incrementing the error count are
1070ba4e58ecSGerrit Renker 		 * disabled for the following two types of errors: these depend
1071ba4e58ecSGerrit Renker 		 * on the application settings, not on the functioning of the
1072ba4e58ecSGerrit Renker 		 * protocol stack as such.
1073ba4e58ecSGerrit Renker 		 *
1074ba4e58ecSGerrit Renker 		 * RFC 3828 here recommends (sec 3.3): "There should also be a
1075ba4e58ecSGerrit Renker 		 * way ... to ... at least let the receiving application block
1076ba4e58ecSGerrit Renker 		 * delivery of packets with coverage values less than a value
1077ba4e58ecSGerrit Renker 		 * provided by the application."
1078ba4e58ecSGerrit Renker 		 */
1079ba4e58ecSGerrit Renker 		if (up->pcrlen == 0) {          /* full coverage was set  */
1080ba4e58ecSGerrit Renker 			LIMIT_NETDEBUG(KERN_WARNING "UDPLITE: partial coverage "
1081ba4e58ecSGerrit Renker 				"%d while full coverage %d requested\n",
1082ba4e58ecSGerrit Renker 				UDP_SKB_CB(skb)->cscov, skb->len);
1083ba4e58ecSGerrit Renker 			goto drop;
10841da177e4SLinus Torvalds 		}
1085ba4e58ecSGerrit Renker 		/* The next case involves violating the min. coverage requested
1086ba4e58ecSGerrit Renker 		 * by the receiver. This is subtle: if receiver wants x and x is
1087ba4e58ecSGerrit Renker 		 * greater than the buffersize/MTU then receiver will complain
1088ba4e58ecSGerrit Renker 		 * that it wants x while sender emits packets of smaller size y.
1089ba4e58ecSGerrit Renker 		 * Therefore the above ...()->partial_cov statement is essential.
1090ba4e58ecSGerrit Renker 		 */
1091ba4e58ecSGerrit Renker 		if (UDP_SKB_CB(skb)->cscov  <  up->pcrlen) {
1092ba4e58ecSGerrit Renker 			LIMIT_NETDEBUG(KERN_WARNING
1093ba4e58ecSGerrit Renker 				"UDPLITE: coverage %d too small, need min %d\n",
1094ba4e58ecSGerrit Renker 				UDP_SKB_CB(skb)->cscov, up->pcrlen);
1095ba4e58ecSGerrit Renker 			goto drop;
1096ba4e58ecSGerrit Renker 		}
1097ba4e58ecSGerrit Renker 	}
1098ba4e58ecSGerrit Renker 
1099759e5d00SHerbert Xu 	if (sk->sk_filter) {
1100759e5d00SHerbert Xu 		if (udp_lib_checksum_complete(skb))
1101ba4e58ecSGerrit Renker 			goto drop;
11021da177e4SLinus Torvalds 	}
11031da177e4SLinus Torvalds 
110481aa646cSMartin Bligh 	if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
110581aa646cSMartin Bligh 		/* Note that an ENOMEM error is charged twice */
110681aa646cSMartin Bligh 		if (rc == -ENOMEM)
1107ba4e58ecSGerrit Renker 			UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
1108ba4e58ecSGerrit Renker 		goto drop;
1109ba4e58ecSGerrit Renker 	}
1110ba4e58ecSGerrit Renker 
1111ba4e58ecSGerrit Renker 	UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
1112ba4e58ecSGerrit Renker 	return 0;
1113ba4e58ecSGerrit Renker 
1114ba4e58ecSGerrit Renker drop:
1115ba4e58ecSGerrit Renker 	UDP_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
11161da177e4SLinus Torvalds 	kfree_skb(skb);
11171da177e4SLinus Torvalds 	return -1;
11181da177e4SLinus Torvalds }
11191da177e4SLinus Torvalds 
11201da177e4SLinus Torvalds /*
11211da177e4SLinus Torvalds  *	Multicasts and broadcasts go to each listener.
11221da177e4SLinus Torvalds  *
11231da177e4SLinus Torvalds  *	Note: called only from the BH handler context,
11241da177e4SLinus Torvalds  *	so we don't need to lock the hashes.
11251da177e4SLinus Torvalds  */
1126ba4e58ecSGerrit Renker static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
1127ba4e58ecSGerrit Renker 				    struct udphdr  *uh,
1128ba4e58ecSGerrit Renker 				    __be32 saddr, __be32 daddr,
1129ba4e58ecSGerrit Renker 				    struct hlist_head udptable[])
11301da177e4SLinus Torvalds {
11311da177e4SLinus Torvalds 	struct sock *sk;
11321da177e4SLinus Torvalds 	int dif;
11331da177e4SLinus Torvalds 
11341da177e4SLinus Torvalds 	read_lock(&udp_hash_lock);
1135ba4e58ecSGerrit Renker 	sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
11361da177e4SLinus Torvalds 	dif = skb->dev->ifindex;
11371da177e4SLinus Torvalds 	sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
11381da177e4SLinus Torvalds 	if (sk) {
11391da177e4SLinus Torvalds 		struct sock *sknext = NULL;
11401da177e4SLinus Torvalds 
11411da177e4SLinus Torvalds 		do {
11421da177e4SLinus Torvalds 			struct sk_buff *skb1 = skb;
11431da177e4SLinus Torvalds 
11441da177e4SLinus Torvalds 			sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr,
11451da177e4SLinus Torvalds 						   uh->source, saddr, dif);
11461da177e4SLinus Torvalds 			if (sknext)
11471da177e4SLinus Torvalds 				skb1 = skb_clone(skb, GFP_ATOMIC);
11481da177e4SLinus Torvalds 
11491da177e4SLinus Torvalds 			if (skb1) {
11501da177e4SLinus Torvalds 				int ret = udp_queue_rcv_skb(sk, skb1);
11511da177e4SLinus Torvalds 				if (ret > 0)
11521da177e4SLinus Torvalds 					/* we should probably re-process instead
11531da177e4SLinus Torvalds 					 * of dropping packets here. */
11541da177e4SLinus Torvalds 					kfree_skb(skb1);
11551da177e4SLinus Torvalds 			}
11561da177e4SLinus Torvalds 			sk = sknext;
11571da177e4SLinus Torvalds 		} while (sknext);
11581da177e4SLinus Torvalds 	} else
11591da177e4SLinus Torvalds 		kfree_skb(skb);
11601da177e4SLinus Torvalds 	read_unlock(&udp_hash_lock);
11611da177e4SLinus Torvalds 	return 0;
11621da177e4SLinus Torvalds }
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds /* Initialize UDP checksum. If exited with zero value (success),
11651da177e4SLinus Torvalds  * CHECKSUM_UNNECESSARY means, that no more checks are required.
11661da177e4SLinus Torvalds  * Otherwise, csum completion requires chacksumming packet body,
11671da177e4SLinus Torvalds  * including udp header and folding it to skb->csum.
11681da177e4SLinus Torvalds  */
1169759e5d00SHerbert Xu static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
1170759e5d00SHerbert Xu 				 int proto)
11711da177e4SLinus Torvalds {
1172eddc9ec5SArnaldo Carvalho de Melo 	const struct iphdr *iph;
1173759e5d00SHerbert Xu 	int err;
1174759e5d00SHerbert Xu 
1175759e5d00SHerbert Xu 	UDP_SKB_CB(skb)->partial_cov = 0;
1176759e5d00SHerbert Xu 	UDP_SKB_CB(skb)->cscov = skb->len;
1177759e5d00SHerbert Xu 
1178759e5d00SHerbert Xu 	if (proto == IPPROTO_UDPLITE) {
1179759e5d00SHerbert Xu 		err = udplite_checksum_init(skb, uh);
1180759e5d00SHerbert Xu 		if (err)
1181759e5d00SHerbert Xu 			return err;
1182759e5d00SHerbert Xu 	}
1183759e5d00SHerbert Xu 
1184eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
11851da177e4SLinus Torvalds 	if (uh->check == 0) {
11861da177e4SLinus Torvalds 		skb->ip_summed = CHECKSUM_UNNECESSARY;
118784fa7933SPatrick McHardy 	} else if (skb->ip_summed == CHECKSUM_COMPLETE) {
1188eddc9ec5SArnaldo Carvalho de Melo 	       if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
1189eddc9ec5SArnaldo Carvalho de Melo 				      proto, skb->csum))
1190fb286bb2SHerbert Xu 			skb->ip_summed = CHECKSUM_UNNECESSARY;
11911da177e4SLinus Torvalds 	}
11921da177e4SLinus Torvalds 	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
1193eddc9ec5SArnaldo Carvalho de Melo 		skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
1194759e5d00SHerbert Xu 					       skb->len, proto, 0);
11951da177e4SLinus Torvalds 	/* Probably, we should checksum udp header (it should be in cache
11961da177e4SLinus Torvalds 	 * in any case) and data in tiny packets (< rx copybreak).
11971da177e4SLinus Torvalds 	 */
1198ba4e58ecSGerrit Renker 
1199759e5d00SHerbert Xu 	return 0;
12001da177e4SLinus Torvalds }
12011da177e4SLinus Torvalds 
12021da177e4SLinus Torvalds /*
12031da177e4SLinus Torvalds  *	All we need to do is get the socket, and then do a checksum.
12041da177e4SLinus Torvalds  */
12051da177e4SLinus Torvalds 
1206ba4e58ecSGerrit Renker int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1207759e5d00SHerbert Xu 		   int proto)
12081da177e4SLinus Torvalds {
12091da177e4SLinus Torvalds 	struct sock *sk;
1210*4bedb452SArnaldo Carvalho de Melo 	struct udphdr *uh = udp_hdr(skb);
12111da177e4SLinus Torvalds 	unsigned short ulen;
12121da177e4SLinus Torvalds 	struct rtable *rt = (struct rtable*)skb->dst;
1213eddc9ec5SArnaldo Carvalho de Melo 	__be32 saddr = ip_hdr(skb)->saddr;
1214eddc9ec5SArnaldo Carvalho de Melo 	__be32 daddr = ip_hdr(skb)->daddr;
12151da177e4SLinus Torvalds 
12161da177e4SLinus Torvalds 	/*
1217ba4e58ecSGerrit Renker 	 *  Validate the packet.
12181da177e4SLinus Torvalds 	 */
12191da177e4SLinus Torvalds 	if (!pskb_may_pull(skb, sizeof(struct udphdr)))
1220ba4e58ecSGerrit Renker 		goto drop;		/* No space for header. */
12211da177e4SLinus Torvalds 
12221da177e4SLinus Torvalds 	ulen = ntohs(uh->len);
1223ba4e58ecSGerrit Renker 	if (ulen > skb->len)
12241da177e4SLinus Torvalds 		goto short_packet;
12251da177e4SLinus Torvalds 
1226759e5d00SHerbert Xu 	if (proto == IPPROTO_UDP) {
1227759e5d00SHerbert Xu 		/* UDP validates ulen. */
1228ba4e58ecSGerrit Renker 		if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
12291da177e4SLinus Torvalds 			goto short_packet;
1230*4bedb452SArnaldo Carvalho de Melo 		uh = udp_hdr(skb);
1231ba4e58ecSGerrit Renker 	}
12321da177e4SLinus Torvalds 
1233759e5d00SHerbert Xu 	if (udp4_csum_init(skb, uh, proto))
1234759e5d00SHerbert Xu 		goto csum_error;
1235759e5d00SHerbert Xu 
12361da177e4SLinus Torvalds 	if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
1237ba4e58ecSGerrit Renker 		return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
12381da177e4SLinus Torvalds 
1239ba4e58ecSGerrit Renker 	sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
1240ba4e58ecSGerrit Renker 			       skb->dev->ifindex, udptable        );
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds 	if (sk != NULL) {
12431da177e4SLinus Torvalds 		int ret = udp_queue_rcv_skb(sk, skb);
12441da177e4SLinus Torvalds 		sock_put(sk);
12451da177e4SLinus Torvalds 
12461da177e4SLinus Torvalds 		/* a return value > 0 means to resubmit the input, but
1247ba4e58ecSGerrit Renker 		 * it wants the return to be -protocol, or 0
12481da177e4SLinus Torvalds 		 */
12491da177e4SLinus Torvalds 		if (ret > 0)
12501da177e4SLinus Torvalds 			return -ret;
12511da177e4SLinus Torvalds 		return 0;
12521da177e4SLinus Torvalds 	}
12531da177e4SLinus Torvalds 
12541da177e4SLinus Torvalds 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
12551da177e4SLinus Torvalds 		goto drop;
1256b59c2701SPatrick McHardy 	nf_reset(skb);
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 	/* No socket. Drop packet silently, if checksum is wrong */
1259ba4e58ecSGerrit Renker 	if (udp_lib_checksum_complete(skb))
12601da177e4SLinus Torvalds 		goto csum_error;
12611da177e4SLinus Torvalds 
1262759e5d00SHerbert Xu 	UDP_INC_STATS_BH(UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
12631da177e4SLinus Torvalds 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
12641da177e4SLinus Torvalds 
12651da177e4SLinus Torvalds 	/*
12661da177e4SLinus Torvalds 	 * Hmm.  We got an UDP packet to a port to which we
12671da177e4SLinus Torvalds 	 * don't wanna listen.  Ignore it.
12681da177e4SLinus Torvalds 	 */
12691da177e4SLinus Torvalds 	kfree_skb(skb);
12706516c655SStephen Hemminger 	return 0;
12711da177e4SLinus Torvalds 
12721da177e4SLinus Torvalds short_packet:
1273ba4e58ecSGerrit Renker 	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
1274759e5d00SHerbert Xu 		       proto == IPPROTO_UDPLITE ? "-Lite" : "",
12751da177e4SLinus Torvalds 		       NIPQUAD(saddr),
12761da177e4SLinus Torvalds 		       ntohs(uh->source),
12771da177e4SLinus Torvalds 		       ulen,
1278ba4e58ecSGerrit Renker 		       skb->len,
12791da177e4SLinus Torvalds 		       NIPQUAD(daddr),
128064ce2073SPatrick McHardy 		       ntohs(uh->dest));
1281ba4e58ecSGerrit Renker 	goto drop;
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds csum_error:
12841da177e4SLinus Torvalds 	/*
12851da177e4SLinus Torvalds 	 * RFC1122: OK.  Discards the bad packet silently (as far as
12861da177e4SLinus Torvalds 	 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
12871da177e4SLinus Torvalds 	 */
1288ba4e58ecSGerrit Renker 	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
1289759e5d00SHerbert Xu 		       proto == IPPROTO_UDPLITE ? "-Lite" : "",
12901da177e4SLinus Torvalds 		       NIPQUAD(saddr),
12911da177e4SLinus Torvalds 		       ntohs(uh->source),
12921da177e4SLinus Torvalds 		       NIPQUAD(daddr),
12931da177e4SLinus Torvalds 		       ntohs(uh->dest),
129464ce2073SPatrick McHardy 		       ulen);
12951da177e4SLinus Torvalds drop:
1296759e5d00SHerbert Xu 	UDP_INC_STATS_BH(UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
12971da177e4SLinus Torvalds 	kfree_skb(skb);
12986516c655SStephen Hemminger 	return 0;
12991da177e4SLinus Torvalds }
13001da177e4SLinus Torvalds 
13013fbe070aSStephen Hemminger int udp_rcv(struct sk_buff *skb)
1302ba4e58ecSGerrit Renker {
1303759e5d00SHerbert Xu 	return __udp4_lib_rcv(skb, udp_hash, IPPROTO_UDP);
1304ba4e58ecSGerrit Renker }
1305ba4e58ecSGerrit Renker 
1306ba4e58ecSGerrit Renker int udp_destroy_sock(struct sock *sk)
13071da177e4SLinus Torvalds {
13081da177e4SLinus Torvalds 	lock_sock(sk);
13091da177e4SLinus Torvalds 	udp_flush_pending_frames(sk);
13101da177e4SLinus Torvalds 	release_sock(sk);
13111da177e4SLinus Torvalds 	return 0;
13121da177e4SLinus Torvalds }
13131da177e4SLinus Torvalds 
13141da177e4SLinus Torvalds /*
13151da177e4SLinus Torvalds  *	Socket option code for UDP
13161da177e4SLinus Torvalds  */
13174c0a6cb0SGerrit Renker int udp_lib_setsockopt(struct sock *sk, int level, int optname,
13184c0a6cb0SGerrit Renker 		       char __user *optval, int optlen,
13194c0a6cb0SGerrit Renker 		       int (*push_pending_frames)(struct sock *))
13201da177e4SLinus Torvalds {
13211da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
13221da177e4SLinus Torvalds 	int val;
13231da177e4SLinus Torvalds 	int err = 0;
13241da177e4SLinus Torvalds 
13251da177e4SLinus Torvalds 	if (optlen<sizeof(int))
13261da177e4SLinus Torvalds 		return -EINVAL;
13271da177e4SLinus Torvalds 
13281da177e4SLinus Torvalds 	if (get_user(val, (int __user *)optval))
13291da177e4SLinus Torvalds 		return -EFAULT;
13301da177e4SLinus Torvalds 
13311da177e4SLinus Torvalds 	switch (optname) {
13321da177e4SLinus Torvalds 	case UDP_CORK:
13331da177e4SLinus Torvalds 		if (val != 0) {
13341da177e4SLinus Torvalds 			up->corkflag = 1;
13351da177e4SLinus Torvalds 		} else {
13361da177e4SLinus Torvalds 			up->corkflag = 0;
13371da177e4SLinus Torvalds 			lock_sock(sk);
13384c0a6cb0SGerrit Renker 			(*push_pending_frames)(sk);
13391da177e4SLinus Torvalds 			release_sock(sk);
13401da177e4SLinus Torvalds 		}
13411da177e4SLinus Torvalds 		break;
13421da177e4SLinus Torvalds 
13431da177e4SLinus Torvalds 	case UDP_ENCAP:
13441da177e4SLinus Torvalds 		switch (val) {
13451da177e4SLinus Torvalds 		case 0:
13461da177e4SLinus Torvalds 		case UDP_ENCAP_ESPINUDP:
13471da177e4SLinus Torvalds 		case UDP_ENCAP_ESPINUDP_NON_IKE:
13481da177e4SLinus Torvalds 			up->encap_type = val;
13491da177e4SLinus Torvalds 			break;
13501da177e4SLinus Torvalds 		default:
13511da177e4SLinus Torvalds 			err = -ENOPROTOOPT;
13521da177e4SLinus Torvalds 			break;
13531da177e4SLinus Torvalds 		}
13541da177e4SLinus Torvalds 		break;
13551da177e4SLinus Torvalds 
1356ba4e58ecSGerrit Renker 	/*
1357ba4e58ecSGerrit Renker 	 * 	UDP-Lite's partial checksum coverage (RFC 3828).
1358ba4e58ecSGerrit Renker 	 */
1359ba4e58ecSGerrit Renker 	/* The sender sets actual checksum coverage length via this option.
1360ba4e58ecSGerrit Renker 	 * The case coverage > packet length is handled by send module. */
1361ba4e58ecSGerrit Renker 	case UDPLITE_SEND_CSCOV:
1362ba4e58ecSGerrit Renker 		if (!up->pcflag)         /* Disable the option on UDP sockets */
1363ba4e58ecSGerrit Renker 			return -ENOPROTOOPT;
1364ba4e58ecSGerrit Renker 		if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
1365ba4e58ecSGerrit Renker 			val = 8;
1366ba4e58ecSGerrit Renker 		up->pcslen = val;
1367ba4e58ecSGerrit Renker 		up->pcflag |= UDPLITE_SEND_CC;
1368ba4e58ecSGerrit Renker 		break;
1369ba4e58ecSGerrit Renker 
1370ba4e58ecSGerrit Renker 	/* The receiver specifies a minimum checksum coverage value. To make
1371ba4e58ecSGerrit Renker 	 * sense, this should be set to at least 8 (as done below). If zero is
1372ba4e58ecSGerrit Renker 	 * used, this again means full checksum coverage.                     */
1373ba4e58ecSGerrit Renker 	case UDPLITE_RECV_CSCOV:
1374ba4e58ecSGerrit Renker 		if (!up->pcflag)         /* Disable the option on UDP sockets */
1375ba4e58ecSGerrit Renker 			return -ENOPROTOOPT;
1376ba4e58ecSGerrit Renker 		if (val != 0 && val < 8) /* Avoid silly minimal values.       */
1377ba4e58ecSGerrit Renker 			val = 8;
1378ba4e58ecSGerrit Renker 		up->pcrlen = val;
1379ba4e58ecSGerrit Renker 		up->pcflag |= UDPLITE_RECV_CC;
1380ba4e58ecSGerrit Renker 		break;
1381ba4e58ecSGerrit Renker 
13821da177e4SLinus Torvalds 	default:
13831da177e4SLinus Torvalds 		err = -ENOPROTOOPT;
13841da177e4SLinus Torvalds 		break;
13856516c655SStephen Hemminger 	}
13861da177e4SLinus Torvalds 
13871da177e4SLinus Torvalds 	return err;
13881da177e4SLinus Torvalds }
13891da177e4SLinus Torvalds 
1390ba4e58ecSGerrit Renker int udp_setsockopt(struct sock *sk, int level, int optname,
13913fdadf7dSDmitry Mishin 		   char __user *optval, int optlen)
13923fdadf7dSDmitry Mishin {
1393ba4e58ecSGerrit Renker 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
13944c0a6cb0SGerrit Renker 		return udp_lib_setsockopt(sk, level, optname, optval, optlen,
13954c0a6cb0SGerrit Renker 					  udp_push_pending_frames);
1396ba4e58ecSGerrit Renker 	return ip_setsockopt(sk, level, optname, optval, optlen);
13973fdadf7dSDmitry Mishin }
13983fdadf7dSDmitry Mishin 
13993fdadf7dSDmitry Mishin #ifdef CONFIG_COMPAT
1400ba4e58ecSGerrit Renker int compat_udp_setsockopt(struct sock *sk, int level, int optname,
14013fdadf7dSDmitry Mishin 			  char __user *optval, int optlen)
14023fdadf7dSDmitry Mishin {
1403ba4e58ecSGerrit Renker 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
14044c0a6cb0SGerrit Renker 		return udp_lib_setsockopt(sk, level, optname, optval, optlen,
14054c0a6cb0SGerrit Renker 					  udp_push_pending_frames);
1406ba4e58ecSGerrit Renker 	return compat_ip_setsockopt(sk, level, optname, optval, optlen);
14073fdadf7dSDmitry Mishin }
14083fdadf7dSDmitry Mishin #endif
14093fdadf7dSDmitry Mishin 
14104c0a6cb0SGerrit Renker int udp_lib_getsockopt(struct sock *sk, int level, int optname,
14111da177e4SLinus Torvalds 		       char __user *optval, int __user *optlen)
14121da177e4SLinus Torvalds {
14131da177e4SLinus Torvalds 	struct udp_sock *up = udp_sk(sk);
14141da177e4SLinus Torvalds 	int val, len;
14151da177e4SLinus Torvalds 
14161da177e4SLinus Torvalds 	if (get_user(len,optlen))
14171da177e4SLinus Torvalds 		return -EFAULT;
14181da177e4SLinus Torvalds 
14191da177e4SLinus Torvalds 	len = min_t(unsigned int, len, sizeof(int));
14201da177e4SLinus Torvalds 
14211da177e4SLinus Torvalds 	if (len < 0)
14221da177e4SLinus Torvalds 		return -EINVAL;
14231da177e4SLinus Torvalds 
14241da177e4SLinus Torvalds 	switch (optname) {
14251da177e4SLinus Torvalds 	case UDP_CORK:
14261da177e4SLinus Torvalds 		val = up->corkflag;
14271da177e4SLinus Torvalds 		break;
14281da177e4SLinus Torvalds 
14291da177e4SLinus Torvalds 	case UDP_ENCAP:
14301da177e4SLinus Torvalds 		val = up->encap_type;
14311da177e4SLinus Torvalds 		break;
14321da177e4SLinus Torvalds 
1433ba4e58ecSGerrit Renker 	/* The following two cannot be changed on UDP sockets, the return is
1434ba4e58ecSGerrit Renker 	 * always 0 (which corresponds to the full checksum coverage of UDP). */
1435ba4e58ecSGerrit Renker 	case UDPLITE_SEND_CSCOV:
1436ba4e58ecSGerrit Renker 		val = up->pcslen;
1437ba4e58ecSGerrit Renker 		break;
1438ba4e58ecSGerrit Renker 
1439ba4e58ecSGerrit Renker 	case UDPLITE_RECV_CSCOV:
1440ba4e58ecSGerrit Renker 		val = up->pcrlen;
1441ba4e58ecSGerrit Renker 		break;
1442ba4e58ecSGerrit Renker 
14431da177e4SLinus Torvalds 	default:
14441da177e4SLinus Torvalds 		return -ENOPROTOOPT;
14456516c655SStephen Hemminger 	}
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	if (put_user(len, optlen))
14481da177e4SLinus Torvalds 		return -EFAULT;
14491da177e4SLinus Torvalds 	if (copy_to_user(optval, &val,len))
14501da177e4SLinus Torvalds 		return -EFAULT;
14511da177e4SLinus Torvalds 	return 0;
14521da177e4SLinus Torvalds }
14531da177e4SLinus Torvalds 
1454ba4e58ecSGerrit Renker int udp_getsockopt(struct sock *sk, int level, int optname,
14553fdadf7dSDmitry Mishin 		   char __user *optval, int __user *optlen)
14563fdadf7dSDmitry Mishin {
1457ba4e58ecSGerrit Renker 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
14584c0a6cb0SGerrit Renker 		return udp_lib_getsockopt(sk, level, optname, optval, optlen);
1459ba4e58ecSGerrit Renker 	return ip_getsockopt(sk, level, optname, optval, optlen);
14603fdadf7dSDmitry Mishin }
14613fdadf7dSDmitry Mishin 
14623fdadf7dSDmitry Mishin #ifdef CONFIG_COMPAT
1463ba4e58ecSGerrit Renker int compat_udp_getsockopt(struct sock *sk, int level, int optname,
14643fdadf7dSDmitry Mishin 				 char __user *optval, int __user *optlen)
14653fdadf7dSDmitry Mishin {
1466ba4e58ecSGerrit Renker 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
14674c0a6cb0SGerrit Renker 		return udp_lib_getsockopt(sk, level, optname, optval, optlen);
1468ba4e58ecSGerrit Renker 	return compat_ip_getsockopt(sk, level, optname, optval, optlen);
14693fdadf7dSDmitry Mishin }
14703fdadf7dSDmitry Mishin #endif
14711da177e4SLinus Torvalds /**
14721da177e4SLinus Torvalds  * 	udp_poll - wait for a UDP event.
14731da177e4SLinus Torvalds  *	@file - file struct
14741da177e4SLinus Torvalds  *	@sock - socket
14751da177e4SLinus Torvalds  *	@wait - poll table
14761da177e4SLinus Torvalds  *
14771da177e4SLinus Torvalds  *	This is same as datagram poll, except for the special case of
14781da177e4SLinus Torvalds  *	blocking sockets. If application is using a blocking fd
14791da177e4SLinus Torvalds  *	and a packet with checksum error is in the queue;
14801da177e4SLinus Torvalds  *	then it could get return from select indicating data available
14811da177e4SLinus Torvalds  *	but then block when reading it. Add special case code
14821da177e4SLinus Torvalds  *	to work around these arguably broken applications.
14831da177e4SLinus Torvalds  */
14841da177e4SLinus Torvalds unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
14851da177e4SLinus Torvalds {
14861da177e4SLinus Torvalds 	unsigned int mask = datagram_poll(file, sock, wait);
14871da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
1488ba4e58ecSGerrit Renker 	int 	is_lite = IS_UDPLITE(sk);
14891da177e4SLinus Torvalds 
14901da177e4SLinus Torvalds 	/* Check for false positives due to checksum errors */
14911da177e4SLinus Torvalds 	if ( (mask & POLLRDNORM) &&
14921da177e4SLinus Torvalds 	     !(file->f_flags & O_NONBLOCK) &&
14931da177e4SLinus Torvalds 	     !(sk->sk_shutdown & RCV_SHUTDOWN)){
14941da177e4SLinus Torvalds 		struct sk_buff_head *rcvq = &sk->sk_receive_queue;
14951da177e4SLinus Torvalds 		struct sk_buff *skb;
14961da177e4SLinus Torvalds 
1497208d8984SHerbert Xu 		spin_lock_bh(&rcvq->lock);
1498759e5d00SHerbert Xu 		while ((skb = skb_peek(rcvq)) != NULL &&
1499759e5d00SHerbert Xu 		       udp_lib_checksum_complete(skb)) {
1500ba4e58ecSGerrit Renker 			UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite);
15011da177e4SLinus Torvalds 			__skb_unlink(skb, rcvq);
15021da177e4SLinus Torvalds 			kfree_skb(skb);
15031da177e4SLinus Torvalds 		}
1504208d8984SHerbert Xu 		spin_unlock_bh(&rcvq->lock);
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds 		/* nothing to see, move along */
15071da177e4SLinus Torvalds 		if (skb == NULL)
15081da177e4SLinus Torvalds 			mask &= ~(POLLIN | POLLRDNORM);
15091da177e4SLinus Torvalds 	}
15101da177e4SLinus Torvalds 
15111da177e4SLinus Torvalds 	return mask;
15121da177e4SLinus Torvalds 
15131da177e4SLinus Torvalds }
15141da177e4SLinus Torvalds 
15151da177e4SLinus Torvalds struct proto udp_prot = {
15161da177e4SLinus Torvalds 	.name		   = "UDP",
15171da177e4SLinus Torvalds 	.owner		   = THIS_MODULE,
1518ba4e58ecSGerrit Renker 	.close		   = udp_lib_close,
15191da177e4SLinus Torvalds 	.connect	   = ip4_datagram_connect,
15201da177e4SLinus Torvalds 	.disconnect	   = udp_disconnect,
15211da177e4SLinus Torvalds 	.ioctl		   = udp_ioctl,
15221da177e4SLinus Torvalds 	.destroy	   = udp_destroy_sock,
15231da177e4SLinus Torvalds 	.setsockopt	   = udp_setsockopt,
15241da177e4SLinus Torvalds 	.getsockopt	   = udp_getsockopt,
15251da177e4SLinus Torvalds 	.sendmsg	   = udp_sendmsg,
15261da177e4SLinus Torvalds 	.recvmsg	   = udp_recvmsg,
15271da177e4SLinus Torvalds 	.sendpage	   = udp_sendpage,
15281da177e4SLinus Torvalds 	.backlog_rcv	   = udp_queue_rcv_skb,
1529ba4e58ecSGerrit Renker 	.hash		   = udp_lib_hash,
1530ba4e58ecSGerrit Renker 	.unhash		   = udp_lib_unhash,
15311da177e4SLinus Torvalds 	.get_port	   = udp_v4_get_port,
15321da177e4SLinus Torvalds 	.obj_size	   = sizeof(struct udp_sock),
1533543d9cfeSArnaldo Carvalho de Melo #ifdef CONFIG_COMPAT
1534543d9cfeSArnaldo Carvalho de Melo 	.compat_setsockopt = compat_udp_setsockopt,
1535543d9cfeSArnaldo Carvalho de Melo 	.compat_getsockopt = compat_udp_getsockopt,
1536543d9cfeSArnaldo Carvalho de Melo #endif
15371da177e4SLinus Torvalds };
15381da177e4SLinus Torvalds 
15391da177e4SLinus Torvalds /* ------------------------------------------------------------------------ */
15401da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
15411da177e4SLinus Torvalds 
15421da177e4SLinus Torvalds static struct sock *udp_get_first(struct seq_file *seq)
15431da177e4SLinus Torvalds {
15441da177e4SLinus Torvalds 	struct sock *sk;
15451da177e4SLinus Torvalds 	struct udp_iter_state *state = seq->private;
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds 	for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
15481da177e4SLinus Torvalds 		struct hlist_node *node;
1549ba4e58ecSGerrit Renker 		sk_for_each(sk, node, state->hashtable + state->bucket) {
15501da177e4SLinus Torvalds 			if (sk->sk_family == state->family)
15511da177e4SLinus Torvalds 				goto found;
15521da177e4SLinus Torvalds 		}
15531da177e4SLinus Torvalds 	}
15541da177e4SLinus Torvalds 	sk = NULL;
15551da177e4SLinus Torvalds found:
15561da177e4SLinus Torvalds 	return sk;
15571da177e4SLinus Torvalds }
15581da177e4SLinus Torvalds 
15591da177e4SLinus Torvalds static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
15601da177e4SLinus Torvalds {
15611da177e4SLinus Torvalds 	struct udp_iter_state *state = seq->private;
15621da177e4SLinus Torvalds 
15631da177e4SLinus Torvalds 	do {
15641da177e4SLinus Torvalds 		sk = sk_next(sk);
15651da177e4SLinus Torvalds try_again:
15661da177e4SLinus Torvalds 		;
15671da177e4SLinus Torvalds 	} while (sk && sk->sk_family != state->family);
15681da177e4SLinus Torvalds 
15691da177e4SLinus Torvalds 	if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
1570ba4e58ecSGerrit Renker 		sk = sk_head(state->hashtable + state->bucket);
15711da177e4SLinus Torvalds 		goto try_again;
15721da177e4SLinus Torvalds 	}
15731da177e4SLinus Torvalds 	return sk;
15741da177e4SLinus Torvalds }
15751da177e4SLinus Torvalds 
15761da177e4SLinus Torvalds static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos)
15771da177e4SLinus Torvalds {
15781da177e4SLinus Torvalds 	struct sock *sk = udp_get_first(seq);
15791da177e4SLinus Torvalds 
15801da177e4SLinus Torvalds 	if (sk)
15811da177e4SLinus Torvalds 		while (pos && (sk = udp_get_next(seq, sk)) != NULL)
15821da177e4SLinus Torvalds 			--pos;
15831da177e4SLinus Torvalds 	return pos ? NULL : sk;
15841da177e4SLinus Torvalds }
15851da177e4SLinus Torvalds 
15861da177e4SLinus Torvalds static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
15871da177e4SLinus Torvalds {
15881da177e4SLinus Torvalds 	read_lock(&udp_hash_lock);
15891da177e4SLinus Torvalds 	return *pos ? udp_get_idx(seq, *pos-1) : (void *)1;
15901da177e4SLinus Torvalds }
15911da177e4SLinus Torvalds 
15921da177e4SLinus Torvalds static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
15931da177e4SLinus Torvalds {
15941da177e4SLinus Torvalds 	struct sock *sk;
15951da177e4SLinus Torvalds 
15961da177e4SLinus Torvalds 	if (v == (void *)1)
15971da177e4SLinus Torvalds 		sk = udp_get_idx(seq, 0);
15981da177e4SLinus Torvalds 	else
15991da177e4SLinus Torvalds 		sk = udp_get_next(seq, v);
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 	++*pos;
16021da177e4SLinus Torvalds 	return sk;
16031da177e4SLinus Torvalds }
16041da177e4SLinus Torvalds 
16051da177e4SLinus Torvalds static void udp_seq_stop(struct seq_file *seq, void *v)
16061da177e4SLinus Torvalds {
16071da177e4SLinus Torvalds 	read_unlock(&udp_hash_lock);
16081da177e4SLinus Torvalds }
16091da177e4SLinus Torvalds 
16101da177e4SLinus Torvalds static int udp_seq_open(struct inode *inode, struct file *file)
16111da177e4SLinus Torvalds {
16121da177e4SLinus Torvalds 	struct udp_seq_afinfo *afinfo = PDE(inode)->data;
16131da177e4SLinus Torvalds 	struct seq_file *seq;
16141da177e4SLinus Torvalds 	int rc = -ENOMEM;
16150da974f4SPanagiotis Issaris 	struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
16161da177e4SLinus Torvalds 
16171da177e4SLinus Torvalds 	if (!s)
16181da177e4SLinus Torvalds 		goto out;
16191da177e4SLinus Torvalds 	s->family		= afinfo->family;
1620ba4e58ecSGerrit Renker 	s->hashtable		= afinfo->hashtable;
16211da177e4SLinus Torvalds 	s->seq_ops.start	= udp_seq_start;
16221da177e4SLinus Torvalds 	s->seq_ops.next		= udp_seq_next;
16231da177e4SLinus Torvalds 	s->seq_ops.show		= afinfo->seq_show;
16241da177e4SLinus Torvalds 	s->seq_ops.stop		= udp_seq_stop;
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds 	rc = seq_open(file, &s->seq_ops);
16271da177e4SLinus Torvalds 	if (rc)
16281da177e4SLinus Torvalds 		goto out_kfree;
16291da177e4SLinus Torvalds 
16301da177e4SLinus Torvalds 	seq	     = file->private_data;
16311da177e4SLinus Torvalds 	seq->private = s;
16321da177e4SLinus Torvalds out:
16331da177e4SLinus Torvalds 	return rc;
16341da177e4SLinus Torvalds out_kfree:
16351da177e4SLinus Torvalds 	kfree(s);
16361da177e4SLinus Torvalds 	goto out;
16371da177e4SLinus Torvalds }
16381da177e4SLinus Torvalds 
16391da177e4SLinus Torvalds /* ------------------------------------------------------------------------ */
16401da177e4SLinus Torvalds int udp_proc_register(struct udp_seq_afinfo *afinfo)
16411da177e4SLinus Torvalds {
16421da177e4SLinus Torvalds 	struct proc_dir_entry *p;
16431da177e4SLinus Torvalds 	int rc = 0;
16441da177e4SLinus Torvalds 
16451da177e4SLinus Torvalds 	if (!afinfo)
16461da177e4SLinus Torvalds 		return -EINVAL;
16471da177e4SLinus Torvalds 	afinfo->seq_fops->owner		= afinfo->owner;
16481da177e4SLinus Torvalds 	afinfo->seq_fops->open		= udp_seq_open;
16491da177e4SLinus Torvalds 	afinfo->seq_fops->read		= seq_read;
16501da177e4SLinus Torvalds 	afinfo->seq_fops->llseek	= seq_lseek;
16511da177e4SLinus Torvalds 	afinfo->seq_fops->release	= seq_release_private;
16521da177e4SLinus Torvalds 
16531da177e4SLinus Torvalds 	p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
16541da177e4SLinus Torvalds 	if (p)
16551da177e4SLinus Torvalds 		p->data = afinfo;
16561da177e4SLinus Torvalds 	else
16571da177e4SLinus Torvalds 		rc = -ENOMEM;
16581da177e4SLinus Torvalds 	return rc;
16591da177e4SLinus Torvalds }
16601da177e4SLinus Torvalds 
16611da177e4SLinus Torvalds void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
16621da177e4SLinus Torvalds {
16631da177e4SLinus Torvalds 	if (!afinfo)
16641da177e4SLinus Torvalds 		return;
16651da177e4SLinus Torvalds 	proc_net_remove(afinfo->name);
16661da177e4SLinus Torvalds 	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
16671da177e4SLinus Torvalds }
16681da177e4SLinus Torvalds 
16691da177e4SLinus Torvalds /* ------------------------------------------------------------------------ */
16701da177e4SLinus Torvalds static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
16711da177e4SLinus Torvalds {
16721da177e4SLinus Torvalds 	struct inet_sock *inet = inet_sk(sp);
1673734ab87fSAl Viro 	__be32 dest = inet->daddr;
1674734ab87fSAl Viro 	__be32 src  = inet->rcv_saddr;
16751da177e4SLinus Torvalds 	__u16 destp	  = ntohs(inet->dport);
16761da177e4SLinus Torvalds 	__u16 srcp	  = ntohs(inet->sport);
16771da177e4SLinus Torvalds 
16781da177e4SLinus Torvalds 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
16791da177e4SLinus Torvalds 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
16801da177e4SLinus Torvalds 		bucket, src, srcp, dest, destp, sp->sk_state,
16811da177e4SLinus Torvalds 		atomic_read(&sp->sk_wmem_alloc),
16821da177e4SLinus Torvalds 		atomic_read(&sp->sk_rmem_alloc),
16831da177e4SLinus Torvalds 		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
16841da177e4SLinus Torvalds 		atomic_read(&sp->sk_refcnt), sp);
16851da177e4SLinus Torvalds }
16861da177e4SLinus Torvalds 
1687ba4e58ecSGerrit Renker int udp4_seq_show(struct seq_file *seq, void *v)
16881da177e4SLinus Torvalds {
16891da177e4SLinus Torvalds 	if (v == SEQ_START_TOKEN)
16901da177e4SLinus Torvalds 		seq_printf(seq, "%-127s\n",
16911da177e4SLinus Torvalds 			   "  sl  local_address rem_address   st tx_queue "
16921da177e4SLinus Torvalds 			   "rx_queue tr tm->when retrnsmt   uid  timeout "
16931da177e4SLinus Torvalds 			   "inode");
16941da177e4SLinus Torvalds 	else {
16951da177e4SLinus Torvalds 		char tmpbuf[129];
16961da177e4SLinus Torvalds 		struct udp_iter_state *state = seq->private;
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 		udp4_format_sock(v, tmpbuf, state->bucket);
16991da177e4SLinus Torvalds 		seq_printf(seq, "%-127s\n", tmpbuf);
17001da177e4SLinus Torvalds 	}
17011da177e4SLinus Torvalds 	return 0;
17021da177e4SLinus Torvalds }
17031da177e4SLinus Torvalds 
17041da177e4SLinus Torvalds /* ------------------------------------------------------------------------ */
17051da177e4SLinus Torvalds static struct file_operations udp4_seq_fops;
17061da177e4SLinus Torvalds static struct udp_seq_afinfo udp4_seq_afinfo = {
17071da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
17081da177e4SLinus Torvalds 	.name		= "udp",
17091da177e4SLinus Torvalds 	.family		= AF_INET,
1710ba4e58ecSGerrit Renker 	.hashtable	= udp_hash,
17111da177e4SLinus Torvalds 	.seq_show	= udp4_seq_show,
17121da177e4SLinus Torvalds 	.seq_fops	= &udp4_seq_fops,
17131da177e4SLinus Torvalds };
17141da177e4SLinus Torvalds 
17151da177e4SLinus Torvalds int __init udp4_proc_init(void)
17161da177e4SLinus Torvalds {
17171da177e4SLinus Torvalds 	return udp_proc_register(&udp4_seq_afinfo);
17181da177e4SLinus Torvalds }
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds void udp4_proc_exit(void)
17211da177e4SLinus Torvalds {
17221da177e4SLinus Torvalds 	udp_proc_unregister(&udp4_seq_afinfo);
17231da177e4SLinus Torvalds }
17241da177e4SLinus Torvalds #endif /* CONFIG_PROC_FS */
17251da177e4SLinus Torvalds 
17261da177e4SLinus Torvalds EXPORT_SYMBOL(udp_disconnect);
17271da177e4SLinus Torvalds EXPORT_SYMBOL(udp_hash);
17281da177e4SLinus Torvalds EXPORT_SYMBOL(udp_hash_lock);
17291da177e4SLinus Torvalds EXPORT_SYMBOL(udp_ioctl);
173025030a7fSGerrit Renker EXPORT_SYMBOL(udp_get_port);
17311da177e4SLinus Torvalds EXPORT_SYMBOL(udp_prot);
17321da177e4SLinus Torvalds EXPORT_SYMBOL(udp_sendmsg);
17334c0a6cb0SGerrit Renker EXPORT_SYMBOL(udp_lib_getsockopt);
17344c0a6cb0SGerrit Renker EXPORT_SYMBOL(udp_lib_setsockopt);
17351da177e4SLinus Torvalds EXPORT_SYMBOL(udp_poll);
17361da177e4SLinus Torvalds 
17371da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
17381da177e4SLinus Torvalds EXPORT_SYMBOL(udp_proc_register);
17391da177e4SLinus Torvalds EXPORT_SYMBOL(udp_proc_unregister);
17401da177e4SLinus Torvalds #endif
1741