datagram.c revision 8facd5fb73c6e960555e5913743dfbb6c3d984a5
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 <linux/mm.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/inet.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h> 493305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu#include <linux/spinlock.h> 505a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.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> 58e9b3cc1b3779fe10a80de4c3e7404bd308d0eae3Neil Horman#include <trace/events/skb.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Is a socket 'connection oriented' ? 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int connection_based(struct sock *sk) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6895c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazetstatic int receiver_wake_function(wait_queue_t *wait, unsigned int mode, int sync, 69bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet void *key) 70bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet{ 71bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet unsigned long bits = (unsigned long)key; 72bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet 73bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet /* 74bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet * Avoid a wakeup if event not interesting for us 75bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet */ 76bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet if (bits && !(bits & (POLLIN | POLLERR))) 77bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet return 0; 78bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet return autoremove_wake_function(wait, mode, sync, key); 79bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet} 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait for a packet.. 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_for_packet(struct sock *sk, int *err, long *timeo_p) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 86bf368e4e70cd4e0f880923c44e95a4273d725ab4Eric Dumazet DEFINE_WAIT_FUNC(wait, receiver_wake_function); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 88aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Socket errors? */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sock_error(sk); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_err; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_queue_empty(&sk->sk_receive_queue)) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Socket shut down? */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown & RCV_SHUTDOWN) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_noerr; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Sequenced packets can come disconnected. 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If so we report the problem 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -ENOTCONN; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (connection_based(sk) && 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN)) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_err; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle signals */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto interrupted; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = 0; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *timeo_p = schedule_timeout(*timeo_p); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 117aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet finish_wait(sk_sleep(sk), &wait); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinterrupted: 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sock_intr_errno(*timeo_p); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_err: 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *err = error; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_noerr: 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *err = 0; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = 1; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 131a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu * __skb_recv_datagram - Receive a datagram skbuff 1324dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @sk: socket 1334dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @flags: MSG_ flags 1343f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov * @off: an offset in bytes to peek skb from. Returns an offset 1353f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov * within an skb where data actually starts 136a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu * @peeked: returns non-zero if this packet has been seen before 1374dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @err: error code returned 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get a datagram skbuff, understands the peeking, nonblocking wakeups 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and possible races. This replaces identical code in packet, raw and 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * udp, as well as the IPX AX.25 and Appletalk. It also finally fixes 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the long standing peek and read race for datagram sockets. If you 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * alter this routine remember it must be re-entrant. 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function will lock the socket if a skb is returned, so the caller 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * needs to unlock the socket in that case (usually by calling 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_free_datagram) 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * It does not lock socket since today. This function is 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * free of race conditions. This measure should/can improve 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * significantly datagram socket latencies at high loads, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * when data copying to user space takes lots of time. 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * (BTW I've just killed the last cli() in IP/IPv6/core/netlink/packet 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * 8) Great win.) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * --ANK (980729) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The order of the tests when we find no data waiting are specified 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * quite explicitly by POSIX 1003.1g, don't change them without having 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the standard around please. 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16195c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazetstruct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, 1623f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov int *peeked, int *off, int *err) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long timeo; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Caller is allowed not to check sk->sk_err before skb_recv_datagram() 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = sock_error(sk); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_packet; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 174a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Again only user level code calls this function, so nothing 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupt level will suddenly eat the receive_queue. 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Look at current nfs client by the way... 1818917a3c0b7d1557548f50bfe3f0e18e0354e38f6David Shwatrz * However, this function was correct in any case. 8) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 183a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu unsigned long cpu_flags; 1844934b0329f7150dcb5f90506860e2db32274c755Pavel Emelyanov struct sk_buff_head *queue = &sk->sk_receive_queue; 185a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu 1864934b0329f7150dcb5f90506860e2db32274c755Pavel Emelyanov spin_lock_irqsave(&queue->lock, cpu_flags); 1873f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov skb_queue_walk(queue, skb) { 188a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu *peeked = skb->peeked; 189a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu if (flags & MSG_PEEK) { 19077c1090f94d1b0b5186fb13a1b71b47b1343f87fEric Dumazet if (*off >= skb->len && skb->len) { 1913f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov *off -= skb->len; 1923f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov continue; 1933f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov } 194a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu skb->peeked = 1; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&skb->users); 196a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu } else 1974934b0329f7150dcb5f90506860e2db32274c755Pavel Emelyanov __skb_unlink(skb, queue); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1993f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov spin_unlock_irqrestore(&queue->lock, cpu_flags); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return skb; 2013f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov } 2023f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov spin_unlock_irqrestore(&queue->lock, cpu_flags); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* User doesn't want to wait */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -EAGAIN; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!timeo) 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_packet; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (!wait_for_packet(sk, err, &timeo)); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_packet: 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *err = error; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 217a59322be07c964e916d15be3df473fb7ba20c41eHerbert XuEXPORT_SYMBOL(__skb_recv_datagram); 218a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu 21995c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazetstruct sk_buff *skb_recv_datagram(struct sock *sk, unsigned int flags, 220a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu int noblock, int *err) 221a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu{ 2223f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov int peeked, off = 0; 223a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu 224a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), 2253f518bf745cbd6007d8069100fb9cb09e960c872Pavel Emelyanov &peeked, &off, err); 226a59322be07c964e916d15be3df473fb7ba20c41eHerbert Xu} 2279e34a5b51684bc90ac827ec4ba339f3892632eacEric DumazetEXPORT_SYMBOL(skb_recv_datagram); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid skb_free_datagram(struct sock *sk, struct sk_buff *skb) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 231ead2ceb0ec9f85cff19c43b5cdb2f8a054484431Neil Horman consume_skb(skb); 232270acefafeb74ce2fe93d35b75733870bf1e11e7Eric Dumazet sk_mem_reclaim_partial(sk); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2349d410c796067686b1e032d54ce475b7055537138Eric DumazetEXPORT_SYMBOL(skb_free_datagram); 2359d410c796067686b1e032d54ce475b7055537138Eric Dumazet 2369d410c796067686b1e032d54ce475b7055537138Eric Dumazetvoid skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) 2379d410c796067686b1e032d54ce475b7055537138Eric Dumazet{ 2388a74ad60a546b13bd1096b2a61a7a5c6fd9ae17cEric Dumazet bool slow; 2398a74ad60a546b13bd1096b2a61a7a5c6fd9ae17cEric Dumazet 24093bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet if (likely(atomic_read(&skb->users) == 1)) 24193bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet smp_rmb(); 24293bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet else if (likely(!atomic_dec_and_test(&skb->users))) 24393bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet return; 24493bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet 2458a74ad60a546b13bd1096b2a61a7a5c6fd9ae17cEric Dumazet slow = lock_sock_fast(sk); 2464b0b72f7dd617b13abd1b04c947e15873e011a24Eric Dumazet skb_orphan(skb); 2474b0b72f7dd617b13abd1b04c947e15873e011a24Eric Dumazet sk_mem_reclaim_partial(sk); 2488a74ad60a546b13bd1096b2a61a7a5c6fd9ae17cEric Dumazet unlock_sock_fast(sk, slow); 2494b0b72f7dd617b13abd1b04c947e15873e011a24Eric Dumazet 25093bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet /* skb is now orphaned, can be freed outside of locked section */ 25193bb64eac10aad3dae6178d7da94765f207d121fEric Dumazet __kfree_skb(skb); 2529d410c796067686b1e032d54ce475b7055537138Eric Dumazet} 2539d410c796067686b1e032d54ce475b7055537138Eric DumazetEXPORT_SYMBOL(skb_free_datagram_locked); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2563305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * skb_kill_datagram - Free a datagram skbuff forcibly 2573305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * @sk: socket 2583305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * @skb: datagram skbuff 2593305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * @flags: MSG_ flags 2603305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * 2613305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * This function frees a datagram skbuff that was received by 2623305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * skb_recv_datagram. The flags argument must match the one 2633305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * used for skb_recv_datagram. 2643305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * 2653305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * If the MSG_PEEK flag is set, and the packet is still on the 2663305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * receive queue of the socket, it will be taken off the queue 2673305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * before it is freed. 2683305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * 2693305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * This function currently only disables BH when acquiring the 2703305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * sk_receive_queue lock. Therefore it must not be used in a 2713305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu * context where that lock is acquired in an IRQ context. 27227ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu * 27327ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu * It returns 0 if the packet was removed by us. 2743305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu */ 2753305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu 27627ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xuint skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) 2773305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu{ 27827ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu int err = 0; 27927ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu 2803305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu if (flags & MSG_PEEK) { 28127ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu err = -ENOENT; 2823305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu spin_lock_bh(&sk->sk_receive_queue.lock); 2833305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu if (skb == skb_peek(&sk->sk_receive_queue)) { 2843305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu __skb_unlink(skb, &sk->sk_receive_queue); 2853305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu atomic_dec(&skb->users); 28627ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu err = 0; 2873305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu } 2883305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu spin_unlock_bh(&sk->sk_receive_queue.lock); 2893305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu } 2903305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu 29161de71c67caec39df0a854a1ef5be0c6be385c2aJohn Dykstra kfree_skb(skb); 2928edf19c2fe028563fc6ea9cb1995b8ee4172d4b6Eric Dumazet atomic_inc(&sk->sk_drops); 29361de71c67caec39df0a854a1ef5be0c6be385c2aJohn Dykstra sk_mem_reclaim_partial(sk); 29461de71c67caec39df0a854a1ef5be0c6be385c2aJohn Dykstra 29527ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu return err; 2963305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu} 2973305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert XuEXPORT_SYMBOL(skb_kill_datagram); 2983305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu 2993305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu/** 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_datagram_iovec - Copy a datagram to an iovec. 3014dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: buffer to copy 3024dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @offset: offset in the buffer to start copying from 30367be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @to: io vector to copy to 3044dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @len: amount of data to copy from buffer to iovec 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: the iovec is modified during the copy. 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct iovec *to, int len) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3111a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int start = skb_headlen(skb); 3121a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int i, copy = start - offset; 3135b1a002ade68173f21b2126a778278df72202ba6David S. Miller struct sk_buff *frag_iter; 314c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 315e9b3cc1b3779fe10a80de4c3e7404bd308d0eae3Neil Horman trace_skb_copy_datagram_iovec(skb, len); 316e9b3cc1b3779fe10a80de4c3e7404bd308d0eae3Neil Horman 317b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller /* Copy header. */ 318b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > 0) { 319b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > len) 320b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller copy = len; 321b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (memcpy_toiovec(to, skb->data + offset, copy)) 322b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller goto fault; 323b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((len -= copy) == 0) 324b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 325b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset += copy; 326b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 327c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 328b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller /* Copy paged appendix. Hmm... why does this look so complicated? */ 329b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 3301a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int end; 3319e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 333547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen WARN_ON(start > offset + len); 3341a028e50729b85d0a038fad13daf0ee201a37454David S. Miller 3359e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet end = start + skb_frag_size(frag); 336b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((copy = end - offset) > 0) { 337b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int err; 338b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller u8 *vaddr; 339ea2ab69379a941c6f8884e290fdd28c93936a778Ian Campbell struct page *page = skb_frag_page(frag); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 343b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller vaddr = kmap(page); 3441a028e50729b85d0a038fad13daf0ee201a37454David S. Miller err = memcpy_toiovec(to, vaddr + frag->page_offset + 3451a028e50729b85d0a038fad13daf0ee201a37454David S. Miller offset - start, copy); 346b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller kunmap(page); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3531a028e50729b85d0a038fad13daf0ee201a37454David S. Miller start = end; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 355b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 3565b1a002ade68173f21b2126a778278df72202ba6David S. Miller skb_walk_frags(skb, frag_iter) { 3575b1a002ade68173f21b2126a778278df72202ba6David S. Miller int end; 3585b1a002ade68173f21b2126a778278df72202ba6David S. Miller 3595b1a002ade68173f21b2126a778278df72202ba6David S. Miller WARN_ON(start > offset + len); 3605b1a002ade68173f21b2126a778278df72202ba6David S. Miller 3615b1a002ade68173f21b2126a778278df72202ba6David S. Miller end = start + frag_iter->len; 3625b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((copy = end - offset) > 0) { 3635b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (copy > len) 3645b1a002ade68173f21b2126a778278df72202ba6David S. Miller copy = len; 3655b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (skb_copy_datagram_iovec(frag_iter, 3665b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset - start, 3675b1a002ade68173f21b2126a778278df72202ba6David S. Miller to, copy)) 3685b1a002ade68173f21b2126a778278df72202ba6David S. Miller goto fault; 3695b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((len -= copy) == 0) 3705b1a002ade68173f21b2126a778278df72202ba6David S. Miller return 0; 3715b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset += copy; 372b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 3735b1a002ade68173f21b2126a778278df72202ba6David S. Miller start = end; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 375b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (!len) 376b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 377b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3819e34a5b51684bc90ac827ec4ba339f3892632eacEric DumazetEXPORT_SYMBOL(skb_copy_datagram_iovec); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 383db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell/** 3840a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * skb_copy_datagram_const_iovec - Copy a datagram to an iovec. 3850a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * @skb: buffer to copy 3860a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * @offset: offset in the buffer to start copying from 3870a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * @to: io vector to copy to 3880a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * @to_offset: offset in the io vector to start copying to 3890a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * @len: amount of data to copy from buffer to iovec 3900a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * 3910a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * Returns 0 or -EFAULT. 3920a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin * Note: the iovec is not modified during the copy. 3930a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin */ 3940a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkinint skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset, 3950a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin const struct iovec *to, int to_offset, 3960a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin int len) 3970a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin{ 3980a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin int start = skb_headlen(skb); 3990a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin int i, copy = start - offset; 4005b1a002ade68173f21b2126a778278df72202ba6David S. Miller struct sk_buff *frag_iter; 4010a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4020a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin /* Copy header. */ 4030a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (copy > 0) { 4040a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (copy > len) 4050a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin copy = len; 4060a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (memcpy_toiovecend(to, skb->data + offset, to_offset, copy)) 4070a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin goto fault; 4080a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if ((len -= copy) == 0) 4090a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin return 0; 4100a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin offset += copy; 4110a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin to_offset += copy; 4120a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin } 4130a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4140a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin /* Copy paged appendix. Hmm... why does this look so complicated? */ 4150a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 4160a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin int end; 4179e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 4180a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4190a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin WARN_ON(start > offset + len); 4200a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4219e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet end = start + skb_frag_size(frag); 4220a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if ((copy = end - offset) > 0) { 4230a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin int err; 4240a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin u8 *vaddr; 425ea2ab69379a941c6f8884e290fdd28c93936a778Ian Campbell struct page *page = skb_frag_page(frag); 4260a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4270a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (copy > len) 4280a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin copy = len; 4290a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin vaddr = kmap(page); 4300a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin err = memcpy_toiovecend(to, vaddr + frag->page_offset + 4310a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin offset - start, to_offset, copy); 4320a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin kunmap(page); 4330a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (err) 4340a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin goto fault; 4350a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (!(len -= copy)) 4360a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin return 0; 4370a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin offset += copy; 4380a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin to_offset += copy; 4390a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin } 4400a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin start = end; 4410a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin } 4420a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4435b1a002ade68173f21b2126a778278df72202ba6David S. Miller skb_walk_frags(skb, frag_iter) { 4445b1a002ade68173f21b2126a778278df72202ba6David S. Miller int end; 4455b1a002ade68173f21b2126a778278df72202ba6David S. Miller 4465b1a002ade68173f21b2126a778278df72202ba6David S. Miller WARN_ON(start > offset + len); 4475b1a002ade68173f21b2126a778278df72202ba6David S. Miller 4485b1a002ade68173f21b2126a778278df72202ba6David S. Miller end = start + frag_iter->len; 4495b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((copy = end - offset) > 0) { 4505b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (copy > len) 4515b1a002ade68173f21b2126a778278df72202ba6David S. Miller copy = len; 4525b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (skb_copy_datagram_const_iovec(frag_iter, 4535b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset - start, 4545b1a002ade68173f21b2126a778278df72202ba6David S. Miller to, to_offset, 4555b1a002ade68173f21b2126a778278df72202ba6David S. Miller copy)) 4565b1a002ade68173f21b2126a778278df72202ba6David S. Miller goto fault; 4575b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((len -= copy) == 0) 4585b1a002ade68173f21b2126a778278df72202ba6David S. Miller return 0; 4595b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset += copy; 4605b1a002ade68173f21b2126a778278df72202ba6David S. Miller to_offset += copy; 4610a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin } 4625b1a002ade68173f21b2126a778278df72202ba6David S. Miller start = end; 4630a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin } 4640a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin if (!len) 4650a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin return 0; 4660a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4670a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkinfault: 4680a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin return -EFAULT; 4690a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin} 4700a1ec07a67bd8b0033dace237249654d015efa21Michael S. TsirkinEXPORT_SYMBOL(skb_copy_datagram_const_iovec); 4710a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin 4720a1ec07a67bd8b0033dace237249654d015efa21Michael S. Tsirkin/** 473db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * skb_copy_datagram_from_iovec - Copy a datagram from an iovec. 474db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @skb: buffer to copy 475db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @offset: offset in the buffer to start copying to 476db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @from: io vector to copy to 4776f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin * @from_offset: offset in the io vector to start copying from 478db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @len: amount of data to copy to buffer from iovec 479db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * 480db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * Returns 0 or -EFAULT. 4816f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin * Note: the iovec is not modified during the copy. 482db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell */ 483db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russellint skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, 4846f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin const struct iovec *from, int from_offset, 4856f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin int len) 486db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell{ 487db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int start = skb_headlen(skb); 488db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int i, copy = start - offset; 4895b1a002ade68173f21b2126a778278df72202ba6David S. Miller struct sk_buff *frag_iter; 490db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 491db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell /* Copy header. */ 492db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > 0) { 493db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > len) 494db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell copy = len; 495d2d27bfd11659675fdd1c20b1c7f8f59873cad60Sridhar Samudrala if (memcpy_fromiovecend(skb->data + offset, from, from_offset, 496d2d27bfd11659675fdd1c20b1c7f8f59873cad60Sridhar Samudrala copy)) 497db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell goto fault; 498db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if ((len -= copy) == 0) 499db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 500db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset += copy; 5016f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin from_offset += copy; 502db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 503db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 504db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell /* Copy paged appendix. Hmm... why does this look so complicated? */ 505db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 506db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int end; 5079e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 508db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 509db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell WARN_ON(start > offset + len); 510db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 5119e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet end = start + skb_frag_size(frag); 512db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if ((copy = end - offset) > 0) { 513db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int err; 514db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell u8 *vaddr; 515ea2ab69379a941c6f8884e290fdd28c93936a778Ian Campbell struct page *page = skb_frag_page(frag); 516db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 517db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > len) 518db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell copy = len; 519db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell vaddr = kmap(page); 5206f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin err = memcpy_fromiovecend(vaddr + frag->page_offset + 5216f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin offset - start, 5226f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin from, from_offset, copy); 523db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell kunmap(page); 524db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (err) 525db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell goto fault; 526db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 527db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (!(len -= copy)) 528db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 529db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset += copy; 5306f26c9a7555e5bcca3560919db9b852015077daeMichael S. Tsirkin from_offset += copy; 531db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 532db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell start = end; 533db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 534db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 5355b1a002ade68173f21b2126a778278df72202ba6David S. Miller skb_walk_frags(skb, frag_iter) { 5365b1a002ade68173f21b2126a778278df72202ba6David S. Miller int end; 5375b1a002ade68173f21b2126a778278df72202ba6David S. Miller 5385b1a002ade68173f21b2126a778278df72202ba6David S. Miller WARN_ON(start > offset + len); 5395b1a002ade68173f21b2126a778278df72202ba6David S. Miller 5405b1a002ade68173f21b2126a778278df72202ba6David S. Miller end = start + frag_iter->len; 5415b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((copy = end - offset) > 0) { 5425b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (copy > len) 5435b1a002ade68173f21b2126a778278df72202ba6David S. Miller copy = len; 5445b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (skb_copy_datagram_from_iovec(frag_iter, 5455b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset - start, 5465b1a002ade68173f21b2126a778278df72202ba6David S. Miller from, 5475b1a002ade68173f21b2126a778278df72202ba6David S. Miller from_offset, 5485b1a002ade68173f21b2126a778278df72202ba6David S. Miller copy)) 5495b1a002ade68173f21b2126a778278df72202ba6David S. Miller goto fault; 5505b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((len -= copy) == 0) 5515b1a002ade68173f21b2126a778278df72202ba6David S. Miller return 0; 5525b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset += copy; 5535b1a002ade68173f21b2126a778278df72202ba6David S. Miller from_offset += copy; 554db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 5555b1a002ade68173f21b2126a778278df72202ba6David S. Miller start = end; 556db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 557db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (!len) 558db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 559db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 560db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russellfault: 561db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return -EFAULT; 562db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell} 563db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty RussellEXPORT_SYMBOL(skb_copy_datagram_from_iovec); 564db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 __user *to, int len, 5675084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum *csump) 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5691a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int start = skb_headlen(skb); 5701a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int i, copy = start - offset; 5715b1a002ade68173f21b2126a778278df72202ba6David S. Miller struct sk_buff *frag_iter; 5725b1a002ade68173f21b2126a778278df72202ba6David S. Miller int pos = 0; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Copy header. */ 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > 0) { 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_and_copy_to_user(skb->data + offset, to, copy, 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump, &err); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos = copy; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 5911a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int end; 5929e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 594547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen WARN_ON(start > offset + len); 5951a028e50729b85d0a038fad13daf0ee201a37454David S. Miller 5969e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet end = start + skb_frag_size(frag); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 5985084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum csum2; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *vaddr; 601ea2ab69379a941c6f8884e290fdd28c93936a778Ian Campbell struct page *page = skb_frag_page(frag); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vaddr = kmap(page); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum2 = csum_and_copy_to_user(vaddr + 6071a028e50729b85d0a038fad13daf0ee201a37454David S. Miller frag->page_offset + 6081a028e50729b85d0a038fad13daf0ee201a37454David S. Miller offset - start, 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 0, &err); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kunmap(page); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6201a028e50729b85d0a038fad13daf0ee201a37454David S. Miller start = end; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6235b1a002ade68173f21b2126a778278df72202ba6David S. Miller skb_walk_frags(skb, frag_iter) { 6245b1a002ade68173f21b2126a778278df72202ba6David S. Miller int end; 6255b1a002ade68173f21b2126a778278df72202ba6David S. Miller 6265b1a002ade68173f21b2126a778278df72202ba6David S. Miller WARN_ON(start > offset + len); 6275b1a002ade68173f21b2126a778278df72202ba6David S. Miller 6285b1a002ade68173f21b2126a778278df72202ba6David S. Miller end = start + frag_iter->len; 6295b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((copy = end - offset) > 0) { 6305b1a002ade68173f21b2126a778278df72202ba6David S. Miller __wsum csum2 = 0; 6315b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (copy > len) 6325b1a002ade68173f21b2126a778278df72202ba6David S. Miller copy = len; 6335b1a002ade68173f21b2126a778278df72202ba6David S. Miller if (skb_copy_and_csum_datagram(frag_iter, 6345b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset - start, 6355b1a002ade68173f21b2126a778278df72202ba6David S. Miller to, copy, 6365b1a002ade68173f21b2126a778278df72202ba6David S. Miller &csum2)) 6375b1a002ade68173f21b2126a778278df72202ba6David S. Miller goto fault; 6385b1a002ade68173f21b2126a778278df72202ba6David S. Miller *csump = csum_block_add(*csump, csum2, pos); 6395b1a002ade68173f21b2126a778278df72202ba6David S. Miller if ((len -= copy) == 0) 6405b1a002ade68173f21b2126a778278df72202ba6David S. Miller return 0; 6415b1a002ade68173f21b2126a778278df72202ba6David S. Miller offset += copy; 6425b1a002ade68173f21b2126a778278df72202ba6David S. Miller to += copy; 6435b1a002ade68173f21b2126a778278df72202ba6David S. Miller pos += copy; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6455b1a002ade68173f21b2126a778278df72202ba6David S. Miller start = end; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!len) 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 654759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) 655fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu{ 656d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro __sum16 sum; 657fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu 658759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu sum = csum_fold(skb_checksum(skb, 0, len, skb->csum)); 659fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu if (likely(!sum)) { 66084fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 661fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu netdev_rx_csum_fault(skb->dev); 662fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu skb->ip_summed = CHECKSUM_UNNECESSARY; 663fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu } 664fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu return sum; 665fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu} 666759e5d006462d53fb708daa8284b4ad909415da1Herbert XuEXPORT_SYMBOL(__skb_checksum_complete_head); 667759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu 668759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu__sum16 __skb_checksum_complete(struct sk_buff *skb) 669759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu{ 670759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu return __skb_checksum_complete_head(skb, skb->len); 671759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu} 672fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert XuEXPORT_SYMBOL(__skb_checksum_complete); 673fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. 6764dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: skbuff 6774dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @hlen: hardware length 67867be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @iov: io vector 6794ec93edb14fe5fdee9fae6335f2cbba204627eacYOSHIFUJI Hideaki * 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Caller _must_ check that skb will fit to this iovec. 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 0 - success. 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - checksum failure. 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - fault during copy. Beware, in this case iovec 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be modified! 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 687fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xuint skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hlen, struct iovec *iov) 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 690d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro __wsum csum; 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chunk = skb->len - hlen; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 693ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu if (!chunk) 694ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu return 0; 695ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Skip filled elements. 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pretty silly, look at memcpy_toiovec, though 8) 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!iov->iov_len) 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov++; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (iov->iov_len < chunk) { 703fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu if (__skb_checksum_complete(skb)) 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum = csum_partial(skb->data, hlen, skb->csum); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chunk, &csum)) 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 712d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro if (csum_fold(csum)) 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 71484fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 715fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu netdev_rx_csum_fault(skb->dev); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_len -= chunk; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_base += chunk; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscsum_error: 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7259e34a5b51684bc90ac827ec4ba339f3892632eacEric DumazetEXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * datagram_poll - generic datagram poll 7294dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @file: file struct 7304dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @sock: socket 7314dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @wait: poll table 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Datagram poll: Again totally generic. This also handles 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sequenced packet sockets providing the socket receive queue 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is only ever holding data ready to receive. 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: when you _don't_ use this routine for this protocol, 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and you use a different write policy from sock_writeable() 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then please supply your own write_space callback. 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int datagram_poll(struct file *file, struct socket *sock, 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_table *wait) 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mask; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 747aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet sock_poll_wait(file, sk_sleep(sk), wait); 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = 0; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* exceptional events? */ 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) 7527d4c04fc170087119727119074e72445f2bb192bKeller, Jacob E mask |= POLLERR | 7538facd5fb73c6e960555e5913743dfbb6c3d984a5Jacob Keller (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0); 7547d4c04fc170087119727119074e72445f2bb192bKeller, Jacob E 755f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi if (sk->sk_shutdown & RCV_SHUTDOWN) 756db40980fcdb560d7992b0511df16cdd3f7e381f3Eric Dumazet mask |= POLLRDHUP | POLLIN | POLLRDNORM; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown == SHUTDOWN_MASK) 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* readable? */ 761db40980fcdb560d7992b0511df16cdd3f7e381f3Eric Dumazet if (!skb_queue_empty(&sk->sk_receive_queue)) 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLIN | POLLRDNORM; 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Connection-based need to check for termination and startup */ 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (connection_based(sk)) { 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_CLOSE) 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* connection hasn't started yet? */ 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_SYN_SENT) 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* writable? */ 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock_writeable(sk)) 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(datagram_poll); 782