datagram.c revision 4ec93edb14fe5fdee9fae6335f2cbba204627eac
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{ 250b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int start = skb_headlen(skb); 251b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int i, copy = start - offset; 252c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 253b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller /* Copy header. */ 254b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > 0) { 255b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > len) 256b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller copy = len; 257b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (memcpy_toiovec(to, skb->data + offset, copy)) 258b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller goto fault; 259b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((len -= copy) == 0) 260b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 261b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset += copy; 262b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 263c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 264b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller /* Copy paged appendix. Hmm... why does this look so complicated? */ 265b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 266b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int end; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller BUG_TRAP(start <= offset + len); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 270b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller end = start + skb_shinfo(skb)->frags[i].size; 271b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((copy = end - offset) > 0) { 272b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int err; 273b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller u8 *vaddr; 274b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 275b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller struct page *page = frag->page; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 279b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller vaddr = kmap(page); 280b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller err = memcpy_toiovec(to, vaddr + frag->page_offset + 281b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset - start, copy); 282b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller kunmap(page); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 289b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller start = end; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 291b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 292b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (skb_shinfo(skb)->frag_list) { 293b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller struct sk_buff *list = skb_shinfo(skb)->frag_list; 294b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 295b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller for (; list; list = list->next) { 296b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int end; 297b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 298b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller BUG_TRAP(start <= offset + len); 299b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 300b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller end = start + list->len; 301b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((copy = end - offset) > 0) { 302b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > len) 303b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller copy = len; 304b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (skb_copy_datagram_iovec(list, 305b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset - start, 306b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller to, copy)) 307b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller goto fault; 308b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((len -= copy) == 0) 309b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 310b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset += copy; 311b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 312b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller start = end; 313b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 315b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (!len) 316b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 317b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 __user *to, int len, 3245084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum *csump) 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int start = skb_headlen(skb); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pos = 0; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, copy = start - offset; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Copy header. */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > 0) { 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_and_copy_to_user(skb->data + offset, to, copy, 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump, &err); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos = copy; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int end; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_TRAP(start <= offset + len); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = start + skb_shinfo(skb)->frags[i].size; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 3535084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum csum2; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *vaddr; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct page *page = frag->page; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vaddr = kmap(page); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum2 = csum_and_copy_to_user(vaddr + 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frag->page_offset + 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset - start, 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 0, &err); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kunmap(page); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = end; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_shinfo(skb)->frag_list) { 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *list = skb_shinfo(skb)->frag_list; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; list; list=list->next) { 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int end; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_TRAP(start <= offset + len); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = start + list->len; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 3895084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum csum2 = 0; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_and_csum_datagram(list, 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset - start, 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &csum2)) 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = end; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!len) 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 414b51655b958dfb1176bfcf99466231fdbef8751ffAl Viro__sum16 __skb_checksum_complete(struct sk_buff *skb) 415fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu{ 416d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro __sum16 sum; 417fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu 418d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro sum = csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); 419fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu if (likely(!sum)) { 42084fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 421fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu netdev_rx_csum_fault(skb->dev); 422fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu skb->ip_summed = CHECKSUM_UNNECESSARY; 423fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu } 424fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu return sum; 425fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu} 426fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert XuEXPORT_SYMBOL(__skb_checksum_complete); 427fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. 4304dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: skbuff 4314dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @hlen: hardware length 43267be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @iov: io vector 4334ec93edb14fe5fdee9fae6335f2cbba204627eacYOSHIFUJI Hideaki * 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Caller _must_ check that skb will fit to this iovec. 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 0 - success. 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - checksum failure. 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - fault during copy. Beware, in this case iovec 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be modified! 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 441fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xuint skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hlen, struct iovec *iov) 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 444d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro __wsum csum; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chunk = skb->len - hlen; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Skip filled elements. 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pretty silly, look at memcpy_toiovec, though 8) 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!iov->iov_len) 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov++; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (iov->iov_len < chunk) { 454fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu if (__skb_checksum_complete(skb)) 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum = csum_partial(skb->data, hlen, skb->csum); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chunk, &csum)) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 463d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro if (csum_fold(csum)) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 46584fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 466fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu netdev_rx_csum_fault(skb->dev); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_len -= chunk; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_base += chunk; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscsum_error: 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * datagram_poll - generic datagram poll 4794dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @file: file struct 4804dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @sock: socket 4814dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @wait: poll table 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Datagram poll: Again totally generic. This also handles 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sequenced packet sockets providing the socket receive queue 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is only ever holding data ready to receive. 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: when you _don't_ use this routine for this protocol, 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and you use a different write policy from sock_writeable() 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then please supply your own write_space callback. 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int datagram_poll(struct file *file, struct socket *sock, 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_table *wait) 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mask; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, sk->sk_sleep, wait); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = 0; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* exceptional events? */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLERR; 503f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi if (sk->sk_shutdown & RCV_SHUTDOWN) 504f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi mask |= POLLRDHUP; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown == SHUTDOWN_MASK) 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* readable? */ 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_queue_empty(&sk->sk_receive_queue) || 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sk->sk_shutdown & RCV_SHUTDOWN)) 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLIN | POLLRDNORM; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Connection-based need to check for termination and startup */ 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (connection_based(sk)) { 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_CLOSE) 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* connection hasn't started yet? */ 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_SYN_SENT) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* writable? */ 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock_writeable(sk)) 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(datagram_poll); 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_datagram_iovec); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_free_datagram); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_recv_datagram); 536