datagram.c revision 6f26c9a7555e5bcca3560919db9b852015077dae
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 *
12113aa838ec3a235d883f8357d31d90e16c47fc89Alan Cox *	Authors:	Alan Cox <alan@lxorguk.ukuu.org.uk>. (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/**
118a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu *	__skb_recv_datagram - Receive a datagram skbuff
1194dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@sk: socket
1204dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@flags: MSG_ flags
121a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu *	@peeked: returns non-zero if this packet has been seen before
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 */
146a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xustruct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
147a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu				    int *peeked, 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
159a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
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		 */
168a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu		unsigned long cpu_flags;
169a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu
170a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu		spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
171a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu		skb = skb_peek(&sk->sk_receive_queue);
172a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu		if (skb) {
173a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu			*peeked = skb->peeked;
174a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu			if (flags & MSG_PEEK) {
175a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu				skb->peeked = 1;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				atomic_inc(&skb->users);
177a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu			} else
178a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu				__skb_unlink(skb, &sk->sk_receive_queue);
179a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu		}
180a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu		spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return skb;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* User doesn't want to wait */
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = -EAGAIN;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!timeo)
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto no_packet;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (!wait_for_packet(sk, err, &timeo));
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_packet:
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*err = error;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
198a59322be07c964e916d15be3df473fb7ba20c41eHerbert XuEXPORT_SYMBOL(__skb_recv_datagram);
199a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu
200a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xustruct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
201a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu				  int noblock, int *err)
202a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu{
203a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu	int peeked;
204a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu
205a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu	return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
206a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu				   &peeked, err);
207a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu}
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid skb_free_datagram(struct sock *sk, struct sk_buff *skb)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
211ead2ceb0ec9f85cff19c43b5cdb2f8a054484431Neil Horman	consume_skb(skb);
212270acefafeb74ce2fe93d35b75733870bf1e11e7Eric Dumazet	sk_mem_reclaim_partial(sk);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2163305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	skb_kill_datagram - Free a datagram skbuff forcibly
2173305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	@sk: socket
2183305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	@skb: datagram skbuff
2193305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	@flags: MSG_ flags
2203305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *
2213305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	This function frees a datagram skbuff that was received by
2223305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	skb_recv_datagram.  The flags argument must match the one
2233305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	used for skb_recv_datagram.
2243305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *
2253305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	If the MSG_PEEK flag is set, and the packet is still on the
2263305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	receive queue of the socket, it will be taken off the queue
2273305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	before it is freed.
2283305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *
2293305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	This function currently only disables BH when acquiring the
2303305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	sk_receive_queue lock.  Therefore it must not be used in a
2313305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu *	context where that lock is acquired in an IRQ context.
23227ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu *
23327ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu *	It returns 0 if the packet was removed by us.
2343305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu */
2353305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
23627ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xuint skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
2373305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu{
23827ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu	int err = 0;
23927ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu
2403305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu	if (flags & MSG_PEEK) {
24127ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu		err = -ENOENT;
2423305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		spin_lock_bh(&sk->sk_receive_queue.lock);
2433305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		if (skb == skb_peek(&sk->sk_receive_queue)) {
2443305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu			__skb_unlink(skb, &sk->sk_receive_queue);
2453305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu			atomic_dec(&skb->users);
24627ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu			err = 0;
2473305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		}
2483305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu		spin_unlock_bh(&sk->sk_receive_queue.lock);
2493305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu	}
2503305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
251270acefafeb74ce2fe93d35b75733870bf1e11e7Eric Dumazet	skb_free_datagram(sk, skb);
25227ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu	return err;
2533305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu}
2543305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
2553305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert XuEXPORT_SYMBOL(skb_kill_datagram);
2563305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu
2573305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu/**
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	skb_copy_datagram_iovec - Copy a datagram to an iovec.
2594dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@skb: buffer to copy
2604dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@offset: offset in the buffer to start copying from
26167be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz *	@to: io vector to copy to
2624dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@len: amount of data to copy from buffer to iovec
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Note: the iovec is modified during the copy.
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct iovec *to, int len)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2691a028e50729b85d0a038fad13daf0ee201a37454David S. Miller	int start = skb_headlen(skb);
2701a028e50729b85d0a038fad13daf0ee201a37454David S. Miller	int i, copy = start - offset;
271c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu
272b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	/* Copy header. */
273b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	if (copy > 0) {
274b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		if (copy > len)
275b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			copy = len;
276b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		if (memcpy_toiovec(to, skb->data + offset, copy))
277b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			goto fault;
278b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		if ((len -= copy) == 0)
279b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			return 0;
280b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		offset += copy;
281b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	}
282c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu
283b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	/* Copy paged appendix. Hmm... why does this look so complicated? */
284b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
2851a028e50729b85d0a038fad13daf0ee201a37454David S. Miller		int end;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
287547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen		WARN_ON(start > offset + len);
2881a028e50729b85d0a038fad13daf0ee201a37454David S. Miller
2891a028e50729b85d0a038fad13daf0ee201a37454David S. Miller		end = start + skb_shinfo(skb)->frags[i].size;
290b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		if ((copy = end - offset) > 0) {
291b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			int err;
292b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			u8  *vaddr;
293b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
294b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			struct page *page = frag->page;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (copy > len)
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				copy = len;
298b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			vaddr = kmap(page);
2991a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			err = memcpy_toiovec(to, vaddr + frag->page_offset +
3001a028e50729b85d0a038fad13daf0ee201a37454David S. Miller					     offset - start, copy);
301b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			kunmap(page);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto fault;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(len -= copy))
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			offset += copy;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3081a028e50729b85d0a038fad13daf0ee201a37454David S. Miller		start = end;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
310b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller
311b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	if (skb_shinfo(skb)->frag_list) {
312b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		struct sk_buff *list = skb_shinfo(skb)->frag_list;
313b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller
314b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		for (; list; list = list->next) {
3151a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			int end;
3161a028e50729b85d0a038fad13daf0ee201a37454David S. Miller
317547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen			WARN_ON(start > offset + len);
318b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller
3191a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			end = start + list->len;
320b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			if ((copy = end - offset) > 0) {
321b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller				if (copy > len)
322b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller					copy = len;
3231a028e50729b85d0a038fad13daf0ee201a37454David S. Miller				if (skb_copy_datagram_iovec(list,
3241a028e50729b85d0a038fad13daf0ee201a37454David S. Miller							    offset - start,
3251a028e50729b85d0a038fad13daf0ee201a37454David S. Miller							    to, copy))
326b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller					goto fault;
327b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller				if ((len -= copy) == 0)
328b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller					return 0;
329b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller				offset += copy;
330b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller			}
3311a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			start = end;
332b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
334b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller	if (!len)
335b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller		return 0;
336b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault:
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EFAULT;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell/**
3420a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	skb_copy_datagram_const_iovec - Copy a datagram to an iovec.
3430a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	@skb: buffer to copy
3440a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	@offset: offset in the buffer to start copying from
3450a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	@to: io vector to copy to
3460a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	@to_offset: offset in the io vector to start copying to
3470a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	@len: amount of data to copy from buffer to iovec
3480a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *
3490a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	Returns 0 or -EFAULT.
3500a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin *	Note: the iovec is not modified during the copy.
3510a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin */
3520a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkinint skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset,
3530a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				  const struct iovec *to, int to_offset,
3540a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				  int len)
3550a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin{
3560a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	int start = skb_headlen(skb);
3570a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	int i, copy = start - offset;
3580a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
3590a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	/* Copy header. */
3600a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	if (copy > 0) {
3610a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		if (copy > len)
3620a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			copy = len;
3630a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		if (memcpy_toiovecend(to, skb->data + offset, to_offset, copy))
3640a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			goto fault;
3650a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		if ((len -= copy) == 0)
3660a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			return 0;
3670a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		offset += copy;
3680a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		to_offset += copy;
3690a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	}
3700a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
3710a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	/* Copy paged appendix. Hmm... why does this look so complicated? */
3720a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
3730a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		int end;
3740a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
3750a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		WARN_ON(start > offset + len);
3760a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
3770a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		end = start + skb_shinfo(skb)->frags[i].size;
3780a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		if ((copy = end - offset) > 0) {
3790a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			int err;
3800a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			u8  *vaddr;
3810a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
3820a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			struct page *page = frag->page;
3830a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
3840a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			if (copy > len)
3850a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				copy = len;
3860a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			vaddr = kmap(page);
3870a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			err = memcpy_toiovecend(to, vaddr + frag->page_offset +
3880a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin						offset - start, to_offset, copy);
3890a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			kunmap(page);
3900a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			if (err)
3910a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				goto fault;
3920a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			if (!(len -= copy))
3930a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				return 0;
3940a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			offset += copy;
3950a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			to_offset += copy;
3960a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		}
3970a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		start = end;
3980a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	}
3990a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
4000a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	if (skb_shinfo(skb)->frag_list) {
4010a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		struct sk_buff *list = skb_shinfo(skb)->frag_list;
4020a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
4030a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		for (; list; list = list->next) {
4040a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			int end;
4050a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
4060a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			WARN_ON(start > offset + len);
4070a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
4080a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			end = start + list->len;
4090a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			if ((copy = end - offset) > 0) {
4100a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				if (copy > len)
4110a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin					copy = len;
4120a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				if (skb_copy_datagram_const_iovec(list,
4130a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin							    offset - start,
4140a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin							    to, to_offset,
4150a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin							    copy))
4160a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin					goto fault;
4170a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				if ((len -= copy) == 0)
4180a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin					return 0;
4190a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				offset += copy;
4200a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin				to_offset += copy;
4210a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			}
4220a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin			start = end;
4230a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		}
4240a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	}
4250a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	if (!len)
4260a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin		return 0;
4270a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
4280a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkinfault:
4290a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin	return -EFAULT;
4300a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin}
4310a1ec07a67bd8b0033dace237249654d015efa21Michael S. TsirkinEXPORT_SYMBOL(skb_copy_datagram_const_iovec);
4320a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin
4330a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin/**
434db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *	skb_copy_datagram_from_iovec - Copy a datagram from an iovec.
435db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *	@skb: buffer to copy
436db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *	@offset: offset in the buffer to start copying to
437db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *	@from: io vector to copy to
4386f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin *	@from_offset: offset in the io vector to start copying from
439db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *	@len: amount of data to copy to buffer from iovec
440db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *
441db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell *	Returns 0 or -EFAULT.
4426f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin *	Note: the iovec is not modified during the copy.
443db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell */
444db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russellint skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
4456f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin				 const struct iovec *from, int from_offset,
4466f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin				 int len)
447db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell{
448db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	int start = skb_headlen(skb);
449db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	int i, copy = start - offset;
450db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
451db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	/* Copy header. */
452db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	if (copy > 0) {
453db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		if (copy > len)
454db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			copy = len;
4556f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin		if (memcpy_fromiovecend(skb->data + offset, from, 0, copy))
456db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			goto fault;
457db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		if ((len -= copy) == 0)
458db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			return 0;
459db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		offset += copy;
4606f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin		from_offset += copy;
461db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	}
462db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
463db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	/* Copy paged appendix. Hmm... why does this look so complicated? */
464db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
465db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		int end;
466db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
467db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		WARN_ON(start > offset + len);
468db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
469db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		end = start + skb_shinfo(skb)->frags[i].size;
470db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		if ((copy = end - offset) > 0) {
471db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			int err;
472db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			u8  *vaddr;
473db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
474db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			struct page *page = frag->page;
475db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
476db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			if (copy > len)
477db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				copy = len;
478db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			vaddr = kmap(page);
4796f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin			err = memcpy_fromiovecend(vaddr + frag->page_offset +
4806f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin						  offset - start,
4816f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin						  from, from_offset, copy);
482db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			kunmap(page);
483db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			if (err)
484db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				goto fault;
485db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
486db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			if (!(len -= copy))
487db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				return 0;
488db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			offset += copy;
4896f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin			from_offset += copy;
490db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		}
491db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		start = end;
492db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	}
493db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
494db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	if (skb_shinfo(skb)->frag_list) {
495db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		struct sk_buff *list = skb_shinfo(skb)->frag_list;
496db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
497db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		for (; list; list = list->next) {
498db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			int end;
499db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
500db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			WARN_ON(start > offset + len);
501db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
502db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			end = start + list->len;
503db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			if ((copy = end - offset) > 0) {
504db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				if (copy > len)
505db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell					copy = len;
506db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				if (skb_copy_datagram_from_iovec(list,
507db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell								 offset - start,
5086f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin								 from,
5096f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin								 from_offset,
5106f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin								 copy))
511db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell					goto fault;
512db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				if ((len -= copy) == 0)
513db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell					return 0;
514db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell				offset += copy;
5156f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin				from_offset += copy;
516db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			}
517db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell			start = end;
518db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		}
519db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	}
520db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	if (!len)
521db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell		return 0;
522db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
523db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russellfault:
524db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell	return -EFAULT;
525db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell}
526db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty RussellEXPORT_SYMBOL(skb_copy_datagram_from_iovec);
527db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      u8 __user *to, int len,
5305084205faf45384fff25c4cf77dd5c96279283adAl Viro				      __wsum *csump)
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5321a028e50729b85d0a038fad13daf0ee201a37454David S. Miller	int start = skb_headlen(skb);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pos = 0;
5341a028e50729b85d0a038fad13daf0ee201a37454David S. Miller	int i, copy = start - offset;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Copy header. */
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy > 0) {
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int err = 0;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy > len)
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			copy = len;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*csump = csum_and_copy_to_user(skb->data + offset, to, copy,
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       *csump, &err);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err)
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fault;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((len -= copy) == 0)
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		offset += copy;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += copy;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pos = copy;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5531a028e50729b85d0a038fad13daf0ee201a37454David S. Miller		int end;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
555547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen		WARN_ON(start > offset + len);
5561a028e50729b85d0a038fad13daf0ee201a37454David S. Miller
5571a028e50729b85d0a038fad13daf0ee201a37454David S. Miller		end = start + skb_shinfo(skb)->frags[i].size;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((copy = end - offset) > 0) {
5595084205faf45384fff25c4cf77dd5c96279283adAl Viro			__wsum csum2;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int err = 0;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8  *vaddr;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct page *page = frag->page;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (copy > len)
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				copy = len;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vaddr = kmap(page);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			csum2 = csum_and_copy_to_user(vaddr +
5691a028e50729b85d0a038fad13daf0ee201a37454David S. Miller							frag->page_offset +
5701a028e50729b85d0a038fad13daf0ee201a37454David S. Miller							offset - start,
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						      to, copy, 0, &err);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kunmap(page);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto fault;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*csump = csum_block_add(*csump, csum2, pos);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(len -= copy))
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			offset += copy;
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			to += copy;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pos += copy;
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5821a028e50729b85d0a038fad13daf0ee201a37454David S. Miller		start = end;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb_shinfo(skb)->frag_list) {
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct sk_buff *list = skb_shinfo(skb)->frag_list;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (; list; list=list->next) {
5891a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			int end;
5901a028e50729b85d0a038fad13daf0ee201a37454David S. Miller
591547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen			WARN_ON(start > offset + len);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			end = start + list->len;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((copy = end - offset) > 0) {
5955084205faf45384fff25c4cf77dd5c96279283adAl Viro				__wsum csum2 = 0;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (copy > len)
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					copy = len;
5981a028e50729b85d0a038fad13daf0ee201a37454David S. Miller				if (skb_copy_and_csum_datagram(list,
5991a028e50729b85d0a038fad13daf0ee201a37454David S. Miller							       offset - start,
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       to, copy,
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							       &csum2))
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto fault;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*csump = csum_block_add(*csump, csum2, pos);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((len -= copy) == 0)
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				offset += copy;
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				to += copy;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pos += copy;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6101a028e50729b85d0a038fad13daf0ee201a37454David S. Miller			start = end;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!len)
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault:
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EFAULT;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
620759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
621fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu{
622d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro	__sum16 sum;
623fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu
624759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu	sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
625fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	if (likely(!sum)) {
62684fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy		if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
627fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu			netdev_rx_csum_fault(skb->dev);
628fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu		skb->ip_summed = CHECKSUM_UNNECESSARY;
629fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	}
630fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu	return sum;
631fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu}
632759e5d006462d53fb708daa8284b4ad909415da1Herbert XuEXPORT_SYMBOL(__skb_checksum_complete_head);
633759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu
634759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu__sum16 __skb_checksum_complete(struct sk_buff *skb)
635759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu{
636759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu	return __skb_checksum_complete_head(skb, skb->len);
637759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu}
638fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert XuEXPORT_SYMBOL(__skb_checksum_complete);
639fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec.
6424dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@skb: skbuff
6434dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@hlen: hardware length
64467be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz *	@iov: io vector
6454ec93edb14fe5fdee9fae6335f2cbba204627eacYOSHIFUJI Hideaki *
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Caller _must_ check that skb will fit to this iovec.
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Returns: 0       - success.
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		 -EINVAL - checksum failure.
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		 -EFAULT - fault during copy. Beware, in this case iovec
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   can be modified!
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
653fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xuint skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     int hlen, struct iovec *iov)
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
656d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro	__wsum csum;
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int chunk = skb->len - hlen;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
659ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu	if (!chunk)
660ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu		return 0;
661ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Skip filled elements.
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Pretty silly, look at memcpy_toiovec, though 8)
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!iov->iov_len)
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov++;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (iov->iov_len < chunk) {
669fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu		if (__skb_checksum_complete(skb))
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto csum_error;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb_copy_datagram_iovec(skb, hlen, iov, chunk))
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fault;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		csum = csum_partial(skb->data, hlen, skb->csum);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base,
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       chunk, &csum))
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fault;
678d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro		if (csum_fold(csum))
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto csum_error;
68084fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy		if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
681fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu			netdev_rx_csum_fault(skb->dev);
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov->iov_len -= chunk;
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov->iov_base += chunk;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscsum_error:
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault:
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EFAULT;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	datagram_poll - generic datagram poll
6944dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@file: file struct
6954dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@sock: socket
6964dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa *	@wait: poll table
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Datagram poll: Again totally generic. This also handles
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	sequenced packet sockets providing the socket receive queue
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	is only ever holding data ready to receive.
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Note: when you _don't_ use this routine for this protocol,
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	and you use a different write policy from sock_writeable()
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	then please supply your own write_space callback.
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int datagram_poll(struct file *file, struct socket *sock,
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   poll_table *wait)
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sock *sk = sock->sk;
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int mask;
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poll_wait(file, sk->sk_sleep, wait);
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = 0;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* exceptional events? */
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLERR;
718f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi	if (sk->sk_shutdown & RCV_SHUTDOWN)
719f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi		mask |= POLLRDHUP;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sk->sk_shutdown == SHUTDOWN_MASK)
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLHUP;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* readable? */
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb_queue_empty(&sk->sk_receive_queue) ||
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (sk->sk_shutdown & RCV_SHUTDOWN))
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLIN | POLLRDNORM;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Connection-based need to check for termination and startup */
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (connection_based(sk)) {
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sk->sk_state == TCP_CLOSE)
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mask |= POLLHUP;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* connection hasn't started yet? */
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sk->sk_state == TCP_SYN_SENT)
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return mask;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* writable? */
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sock_writeable(sk))
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mask;
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(datagram_poll);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_datagram_iovec);
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_free_datagram);
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_recv_datagram);
751