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