datagram.c revision 3305b80c214c642b89cd5c21af83bc91ec13f8bd
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	SUCS NET3:
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Generic datagram handling routines. These are generic for all
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	protocols. Possibly a generic IP version on top of these would
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	make sense. Not tonight however 8-).
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This is used because UDP, RAW, PACKET, DDP, IPX, AX.25 and
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	NetROM layer all have identical poll code and mostly
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	identical recvmsg() code. So we share it here. The poll was
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	shared before but buried in udp.c so I moved it.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Authors:	Alan Cox <alan@redhat.com>. (datagram_poll() from old
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *						     udp.c code)
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Fixes:
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Alan Cox	:	NULL return from skb_peek_copy()
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					understood
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Alan Cox	:	Rewrote skb_read_datagram to avoid the
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					skb_peek_copy stuff.
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Alan Cox	:	Added support for SOCK_SEQPACKET.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					IPX can no longer use the SO_TYPE hack
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					but AX.25 now works right, and SPX is
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					feasible.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Alan Cox	:	Fixed write poll of non IP protocol
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					crash.
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Florian  La Roche:	Changed for my new skbuff handling.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Darryl Miles	:	Fixed non-blocking SOCK_SEQPACKET.
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Linus Torvalds	:	BSD semantic fixes.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Alan Cox	:	Datagram iovec handling
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Darryl Miles	:	Fixed non-blocking SOCK_STREAM.
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Alan Cox	:	POSIXisms
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Pete Wyckoff    :       Unconnected accept() fix.
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/inet.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h>
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h>
503305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu#include <linux/spinlock.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/protocol.h>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55c752f0739f09b803aed191c4765a3b6650a08653Arnaldo Carvalho de Melo#include <net/checksum.h>
56c752f0739f09b803aed191c4765a3b6650a08653Arnaldo Carvalho de Melo#include <net/sock.h>
57c752f0739f09b803aed191c4765a3b6650a08653Arnaldo Carvalho de Melo#include <net/tcp_states.h>
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Is a socket 'connection oriented' ?
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int connection_based(struct sock *sk)
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait for a packet..
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_for_packet(struct sock *sk, int *err, long *timeo_p)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEFINE_WAIT(wait);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Socket errors? */
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = sock_error(sk);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error)
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_err;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb_queue_empty(&sk->sk_receive_queue))
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Socket shut down? */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sk->sk_shutdown & RCV_SHUTDOWN)
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_noerr;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Sequenced packets can come disconnected.
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If so we report the problem
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = -ENOTCONN;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (connection_based(sk) &&
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN))
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_err;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* handle signals */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (signal_pending(current))
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto interrupted;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = 0;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*timeo_p = schedule_timeout(*timeo_p);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	finish_wait(sk->sk_sleep, &wait);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinterrupted:
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = sock_intr_errno(*timeo_p);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_err:
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*err = error;
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto out;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_noerr:
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*err = 0;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = 1;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto out;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	skb_recv_datagram - Receive a datagram skbuff
1194dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@sk: socket
1204dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@flags: MSG_ flags
1214dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@noblock: blocking operation?
1224dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@err: error code returned
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Get a datagram skbuff, understands the peeking, nonblocking wakeups
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	and possible races. This replaces identical code in packet, raw and
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	udp, as well as the IPX AX.25 and Appletalk. It also finally fixes
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	the long standing peek and read race for datagram sockets. If you
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	alter this routine remember it must be re-entrant.
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This function will lock the socket if a skb is returned, so the caller
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	needs to unlock the socket in that case (usually by calling
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	skb_free_datagram)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	* It does not lock socket since today. This function is
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	* free of race conditions. This measure should/can improve
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	* significantly datagram socket latencies at high loads,
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	* when data copying to user space takes lots of time.
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	* (BTW I've just killed the last cli() in IP/IPv6/core/netlink/packet
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	*  8) Great win.)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	*			                    --ANK (980729)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The order of the tests when we find no data waiting are specified
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	quite explicitly by POSIX 1003.1g, don't change them without having
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	the standard around please.
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  int noblock, int *err)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long timeo;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Caller is allowed not to check sk->sk_err before skb_recv_datagram()
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = sock_error(sk);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto no_packet;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timeo = sock_rcvtimeo(sk, noblock);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Again only user level code calls this function, so nothing
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * interrupt level will suddenly eat the receive_queue.
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Look at current nfs client by the way...
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * However, this function was corrent in any case. 8)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flags & MSG_PEEK) {
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long cpu_flags;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock_irqsave(&sk->sk_receive_queue.lock,
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  cpu_flags);
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb = skb_peek(&sk->sk_receive_queue);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (skb)
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				atomic_inc(&skb->users);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&sk->sk_receive_queue.lock,
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       cpu_flags);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb = skb_dequeue(&sk->sk_receive_queue);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb)
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return skb;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* User doesn't want to wait */
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = -EAGAIN;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!timeo)
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto no_packet;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (!wait_for_packet(sk, err, &timeo));
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_packet:
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*err = error;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid skb_free_datagram(struct sock *sk, struct sk_buff *skb)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree_skb(skb);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2043305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	skb_kill_datagram - Free a datagram skbuff forcibly
2053305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	@sk: socket
2063305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	@skb: datagram skbuff
2073305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	@flags: MSG_ flags
2083305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *
2093305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	This function frees a datagram skbuff that was received by
2103305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	skb_recv_datagram.  The flags argument must match the one
2113305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	used for skb_recv_datagram.
2123305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *
2133305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	If the MSG_PEEK flag is set, and the packet is still on the
2143305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	receive queue of the socket, it will be taken off the queue
2153305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	before it is freed.
2163305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *
2173305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	This function currently only disables BH when acquiring the
2183305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	sk_receive_queue lock.  Therefore it must not be used in a
2193305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	context where that lock is acquired in an IRQ context.
2203305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu */
2213305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
2223305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xuvoid skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
2233305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu{
2243305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu	if (flags & MSG_PEEK) {
2253305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		spin_lock_bh(&sk->sk_receive_queue.lock);
2263305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		if (skb == skb_peek(&sk->sk_receive_queue)) {
2273305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu			__skb_unlink(skb, &sk->sk_receive_queue);
2283305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu			atomic_dec(&skb->users);
2293305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		}
2303305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		spin_unlock_bh(&sk->sk_receive_queue.lock);
2313305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu	}
2323305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
2333305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu	kfree_skb(skb);
2343305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu}
2353305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
2363305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert XuEXPORT_SYMBOL(skb_kill_datagram);
2373305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
2383305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu/**
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	skb_copy_datagram_iovec - Copy a datagram to an iovec.
2404dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@skb: buffer to copy
2414dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@offset: offset in the buffer to start copying from
24267be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz *	@to: io vector to copy to
2434dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@len: amount of data to copy from buffer to iovec
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Note: the iovec is modified during the copy.
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct iovec *to, int len)
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
250bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips	int i, err, fraglen, end = 0;
251bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips	struct sk_buff *next = skb_shinfo(skb)->frag_list;
252c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu
253c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu	if (!len)
254c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu		return 0;
255c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu
256bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillipsnext_skb:
257bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips	fraglen = skb_headlen(skb);
258bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips	i = -1;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
260bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips	while (1) {
261bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		int start = end;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
263bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		if ((end += fraglen) > offset) {
264bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips			int copy = end - offset, o = offset - start;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (copy > len)
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				copy = len;
268bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips			if (i == -1)
269bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips				err = memcpy_toiovec(to, skb->data + o, copy);
270bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips			else {
271bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
272bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips				struct page *page = frag->page;
273bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips				void *p = kmap(page) + frag->page_offset + o;
274bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips				err = memcpy_toiovec(to, p, copy);
275bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips				kunmap(page);
276bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips			}
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto fault;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(len -= copy))
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			offset += copy;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
283bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		if (++i >= skb_shinfo(skb)->nr_frags)
284bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips			break;
285bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		fraglen = skb_shinfo(skb)->frags[i].size;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
287bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips	if (next) {
288bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		skb = next;
289bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		BUG_ON(skb_shinfo(skb)->frag_list);
290bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		next = skb->next;
291bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips		goto next_skb;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault:
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EFAULT;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      u8 __user *to, int len,
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      unsigned int *csump)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int start = skb_headlen(skb);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pos = 0;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, copy = start - offset;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Copy header. */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy > 0) {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int err = 0;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy > len)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			copy = len;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*csump = csum_and_copy_to_user(skb->data + offset, to, copy,
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       *csump, &err);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err)
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fault;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((len -= copy) == 0)
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		offset += copy;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += copy;
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pos = copy;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int end;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_TRAP(start <= offset + len);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end = start + skb_shinfo(skb)->frags[i].size;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((copy = end - offset) > 0) {
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned int csum2;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int err = 0;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8  *vaddr;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct page *page = frag->page;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (copy > len)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				copy = len;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vaddr = kmap(page);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			csum2 = csum_and_copy_to_user(vaddr +
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							frag->page_offset +
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							offset - start,
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						      to, copy, 0, &err);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kunmap(page);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto fault;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*csump = csum_block_add(*csump, csum2, pos);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(len -= copy))
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			offset += copy;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += copy;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pos += copy;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = end;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb_shinfo(skb)->frag_list) {
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct sk_buff *list = skb_shinfo(skb)->frag_list;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (; list; list=list->next) {
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int end;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG_TRAP(start <= offset + len);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			end = start + list->len;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((copy = end - offset) > 0) {
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				unsigned int csum2 = 0;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (copy > len)
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					copy = len;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (skb_copy_and_csum_datagram(list,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       offset - start,
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       to, copy,
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       &csum2))
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto fault;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*csump = csum_block_add(*csump, csum2, pos);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((len -= copy) == 0)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				offset += copy;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				to += copy;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pos += copy;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start = end;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!len)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault:
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EFAULT;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
389fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xuunsigned int __skb_checksum_complete(struct sk_buff *skb)
390fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu{
391fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	unsigned int sum;
392fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu
393fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
394fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	if (likely(!sum)) {
395fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu		if (unlikely(skb->ip_summed == CHECKSUM_HW))
396fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu			netdev_rx_csum_fault(skb->dev);
397fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu		skb->ip_summed = CHECKSUM_UNNECESSARY;
398fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	}
399fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	return sum;
400fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu}
401fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert XuEXPORT_SYMBOL(__skb_checksum_complete);
402fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec.
4054dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@skb: skbuff
4064dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@hlen: hardware length
40767be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz *	@iov: io vector
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Caller _must_ check that skb will fit to this iovec.
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Returns: 0       - success.
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		 -EINVAL - checksum failure.
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		 -EFAULT - fault during copy. Beware, in this case iovec
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   can be modified!
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
416fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xuint skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     int hlen, struct iovec *iov)
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int csum;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int chunk = skb->len - hlen;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Skip filled elements.
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Pretty silly, look at memcpy_toiovec, though 8)
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!iov->iov_len)
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov++;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (iov->iov_len < chunk) {
429fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu		if (__skb_checksum_complete(skb))
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto csum_error;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb_copy_datagram_iovec(skb, hlen, iov, chunk))
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fault;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		csum = csum_partial(skb->data, hlen, skb->csum);
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base,
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       chunk, &csum))
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fault;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((unsigned short)csum_fold(csum))
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto csum_error;
440fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu		if (unlikely(skb->ip_summed == CHECKSUM_HW))
441fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu			netdev_rx_csum_fault(skb->dev);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov->iov_len -= chunk;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov->iov_base += chunk;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscsum_error:
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault:
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EFAULT;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	datagram_poll - generic datagram poll
4544dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@file: file struct
4554dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@sock: socket
4564dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@wait: poll table
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Datagram poll: Again totally generic. This also handles
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	sequenced packet sockets providing the socket receive queue
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	is only ever holding data ready to receive.
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Note: when you _don't_ use this routine for this protocol,
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	and you use a different write policy from sock_writeable()
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	then please supply your own write_space callback.
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int datagram_poll(struct file *file, struct socket *sock,
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   poll_table *wait)
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sock *sk = sock->sk;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int mask;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poll_wait(file, sk->sk_sleep, wait);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 0;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* exceptional events? */
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLERR;
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sk->sk_shutdown == SHUTDOWN_MASK)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLHUP;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* readable? */
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb_queue_empty(&sk->sk_receive_queue) ||
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (sk->sk_shutdown & RCV_SHUTDOWN))
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLIN | POLLRDNORM;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Connection-based need to check for termination and startup */
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (connection_based(sk)) {
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sk->sk_state == TCP_CLOSE)
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mask |= POLLHUP;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* connection hasn't started yet? */
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sk->sk_state == TCP_SYN_SENT)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return mask;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* writable? */
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sock_writeable(sk))
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mask;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(datagram_poll);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_datagram_iovec);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_free_datagram);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_recv_datagram);
509