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