datagram.c revision db543c1f973cd1d557cc32ceee76737c1e4d2898
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/** 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{ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 2123ab224be6d69de912ee21302745ea45a99274dbcHideo Aoki sk_mem_reclaim(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 2513305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu kfree_skb(skb); 2523ab224be6d69de912ee21302745ea45a99274dbcHideo Aoki sk_mem_reclaim(sk); 25327ab2568649d5ba6c5a20212079b7c4f6da4ca0dHerbert Xu return err; 2543305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu} 2553305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu 2563305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert XuEXPORT_SYMBOL(skb_kill_datagram); 2573305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu 2583305b80c214c642b89cd5c21af83bc91ec13f8bdHerbert Xu/** 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_datagram_iovec - Copy a datagram to an iovec. 2604dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: buffer to copy 2614dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @offset: offset in the buffer to start copying from 26267be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @to: io vector to copy to 2634dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @len: amount of data to copy from buffer to iovec 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: the iovec is modified during the copy. 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct iovec *to, int len) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2701a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int start = skb_headlen(skb); 2711a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int i, copy = start - offset; 272c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 273b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller /* Copy header. */ 274b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > 0) { 275b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > len) 276b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller copy = len; 277b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (memcpy_toiovec(to, skb->data + offset, copy)) 278b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller goto fault; 279b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((len -= copy) == 0) 280b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 281b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset += copy; 282b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 283c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 284b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller /* Copy paged appendix. Hmm... why does this look so complicated? */ 285b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 2861a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int end; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 288547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen WARN_ON(start > offset + len); 2891a028e50729b85d0a038fad13daf0ee201a37454David S. Miller 2901a028e50729b85d0a038fad13daf0ee201a37454David S. Miller end = start + skb_shinfo(skb)->frags[i].size; 291b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((copy = end - offset) > 0) { 292b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller int err; 293b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller u8 *vaddr; 294b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 295b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller struct page *page = frag->page; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 299b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller vaddr = kmap(page); 3001a028e50729b85d0a038fad13daf0ee201a37454David S. Miller err = memcpy_toiovec(to, vaddr + frag->page_offset + 3011a028e50729b85d0a038fad13daf0ee201a37454David S. Miller offset - start, copy); 302b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller kunmap(page); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3091a028e50729b85d0a038fad13daf0ee201a37454David S. Miller start = end; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 311b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 312b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (skb_shinfo(skb)->frag_list) { 313b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller struct sk_buff *list = skb_shinfo(skb)->frag_list; 314b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 315b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller for (; list; list = list->next) { 3161a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int end; 3171a028e50729b85d0a038fad13daf0ee201a37454David S. Miller 318547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen WARN_ON(start > offset + len); 319b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 3201a028e50729b85d0a038fad13daf0ee201a37454David S. Miller end = start + list->len; 321b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((copy = end - offset) > 0) { 322b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (copy > len) 323b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller copy = len; 3241a028e50729b85d0a038fad13daf0ee201a37454David S. Miller if (skb_copy_datagram_iovec(list, 3251a028e50729b85d0a038fad13daf0ee201a37454David S. Miller offset - start, 3261a028e50729b85d0a038fad13daf0ee201a37454David S. Miller to, copy)) 327b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller goto fault; 328b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if ((len -= copy) == 0) 329b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 330b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller offset += copy; 331b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 3321a028e50729b85d0a038fad13daf0ee201a37454David S. Miller start = end; 333b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller } 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 335b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller if (!len) 336b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller return 0; 337b4d9eda028e8becbb5057b554e63eea12e496a88David S. Miller 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 342db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell/** 343db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * skb_copy_datagram_from_iovec - Copy a datagram from an iovec. 344db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @skb: buffer to copy 345db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @offset: offset in the buffer to start copying to 346db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @from: io vector to copy to 347db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * @len: amount of data to copy to buffer from iovec 348db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * 349db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * Returns 0 or -EFAULT. 350db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell * Note: the iovec is modified during the copy. 351db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell */ 352db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russellint skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, 353db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell struct iovec *from, int len) 354db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell{ 355db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int start = skb_headlen(skb); 356db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int i, copy = start - offset; 357db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 358db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell /* Copy header. */ 359db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > 0) { 360db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > len) 361db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell copy = len; 362db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (memcpy_fromiovec(skb->data + offset, from, copy)) 363db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell goto fault; 364db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if ((len -= copy) == 0) 365db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 366db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset += copy; 367db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 368db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 369db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell /* Copy paged appendix. Hmm... why does this look so complicated? */ 370db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 371db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int end; 372db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 373db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell WARN_ON(start > offset + len); 374db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 375db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell end = start + skb_shinfo(skb)->frags[i].size; 376db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if ((copy = end - offset) > 0) { 377db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int err; 378db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell u8 *vaddr; 379db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 380db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell struct page *page = frag->page; 381db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 382db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > len) 383db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell copy = len; 384db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell vaddr = kmap(page); 385db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell err = memcpy_fromiovec(vaddr + frag->page_offset + 386db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset - start, from, copy); 387db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell kunmap(page); 388db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (err) 389db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell goto fault; 390db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 391db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (!(len -= copy)) 392db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 393db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset += copy; 394db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 395db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell start = end; 396db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 397db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 398db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (skb_shinfo(skb)->frag_list) { 399db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell struct sk_buff *list = skb_shinfo(skb)->frag_list; 400db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 401db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell for (; list; list = list->next) { 402db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell int end; 403db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 404db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell WARN_ON(start > offset + len); 405db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 406db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell end = start + list->len; 407db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if ((copy = end - offset) > 0) { 408db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (copy > len) 409db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell copy = len; 410db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (skb_copy_datagram_from_iovec(list, 411db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset - start, 412db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell from, copy)) 413db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell goto fault; 414db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if ((len -= copy) == 0) 415db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 416db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell offset += copy; 417db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 418db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell start = end; 419db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 420db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell } 421db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell if (!len) 422db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return 0; 423db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 424db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russellfault: 425db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell return -EFAULT; 426db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell} 427db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty RussellEXPORT_SYMBOL(skb_copy_datagram_from_iovec); 428db543c1f973cd1d557cc32ceee76737c1e4d2898Rusty Russell 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 __user *to, int len, 4315084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum *csump) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4331a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int start = skb_headlen(skb); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pos = 0; 4351a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int i, copy = start - offset; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Copy header. */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > 0) { 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_and_copy_to_user(skb->data + offset, to, copy, 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump, &err); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos = copy; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 4541a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int end; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 456547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen WARN_ON(start > offset + len); 4571a028e50729b85d0a038fad13daf0ee201a37454David S. Miller 4581a028e50729b85d0a038fad13daf0ee201a37454David S. Miller end = start + skb_shinfo(skb)->frags[i].size; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 4605084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum csum2; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *vaddr; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct page *page = frag->page; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vaddr = kmap(page); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum2 = csum_and_copy_to_user(vaddr + 4701a028e50729b85d0a038fad13daf0ee201a37454David S. Miller frag->page_offset + 4711a028e50729b85d0a038fad13daf0ee201a37454David S. Miller offset - start, 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 0, &err); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kunmap(page); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4831a028e50729b85d0a038fad13daf0ee201a37454David S. Miller start = end; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_shinfo(skb)->frag_list) { 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *list = skb_shinfo(skb)->frag_list; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; list; list=list->next) { 4901a028e50729b85d0a038fad13daf0ee201a37454David S. Miller int end; 4911a028e50729b85d0a038fad13daf0ee201a37454David S. Miller 492547b792cac0a038b9dbf958d3c120df3740b5572Ilpo Järvinen WARN_ON(start > offset + len); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941a028e50729b85d0a038fad13daf0ee201a37454David S. Miller end = start + list->len; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 4965084205faf45384fff25c4cf77dd5c96279283adAl Viro __wsum csum2 = 0; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 4991a028e50729b85d0a038fad13daf0ee201a37454David S. Miller if (skb_copy_and_csum_datagram(list, 5001a028e50729b85d0a038fad13daf0ee201a37454David S. Miller offset - start, 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &csum2)) 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5111a028e50729b85d0a038fad13daf0ee201a37454David S. Miller start = end; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!len) 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) 522fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu{ 523d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro __sum16 sum; 524fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu 525759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu sum = csum_fold(skb_checksum(skb, 0, len, skb->csum)); 526fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu if (likely(!sum)) { 52784fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 528fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu netdev_rx_csum_fault(skb->dev); 529fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu skb->ip_summed = CHECKSUM_UNNECESSARY; 530fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu } 531fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu return sum; 532fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu} 533759e5d006462d53fb708daa8284b4ad909415da1Herbert XuEXPORT_SYMBOL(__skb_checksum_complete_head); 534759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu 535759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu__sum16 __skb_checksum_complete(struct sk_buff *skb) 536759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu{ 537759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu return __skb_checksum_complete_head(skb, skb->len); 538759e5d006462d53fb708daa8284b4ad909415da1Herbert Xu} 539fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert XuEXPORT_SYMBOL(__skb_checksum_complete); 540fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. 5434dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: skbuff 5444dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @hlen: hardware length 54567be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @iov: io vector 5464ec93edb14fe5fdee9fae6335f2cbba204627eacYOSHIFUJI Hideaki * 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Caller _must_ check that skb will fit to this iovec. 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 0 - success. 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - checksum failure. 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - fault during copy. Beware, in this case iovec 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be modified! 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 554fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xuint skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hlen, struct iovec *iov) 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 557d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro __wsum csum; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chunk = skb->len - hlen; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 560ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu if (!chunk) 561ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu return 0; 562ef8aef55ce61fd0e2af798695f7386ac756ae1e7Herbert Xu 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Skip filled elements. 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pretty silly, look at memcpy_toiovec, though 8) 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!iov->iov_len) 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov++; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (iov->iov_len < chunk) { 570fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu if (__skb_checksum_complete(skb)) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum = csum_partial(skb->data, hlen, skb->csum); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chunk, &csum)) 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 579d3bc23e7ee9db8023dff5a86bb3b0069ed018789Al Viro if (csum_fold(csum)) 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 58184fa7933a33f806bbbaae6775e87459b1ec584c0Patrick McHardy if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 582fb286bb2990a107009dbf25f6ffebeb7df77f9beHerbert Xu netdev_rx_csum_fault(skb->dev); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_len -= chunk; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_base += chunk; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscsum_error: 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * datagram_poll - generic datagram poll 5954dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @file: file struct 5964dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @sock: socket 5974dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @wait: poll table 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Datagram poll: Again totally generic. This also handles 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sequenced packet sockets providing the socket receive queue 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is only ever holding data ready to receive. 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: when you _don't_ use this routine for this protocol, 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and you use a different write policy from sock_writeable() 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then please supply your own write_space callback. 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int datagram_poll(struct file *file, struct socket *sock, 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_table *wait) 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mask; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, sk->sk_sleep, wait); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = 0; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* exceptional events? */ 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLERR; 619f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi if (sk->sk_shutdown & RCV_SHUTDOWN) 620f348d70a324e15afc701a494f32ec468abb7d1ebDavide Libenzi mask |= POLLRDHUP; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown == SHUTDOWN_MASK) 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* readable? */ 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_queue_empty(&sk->sk_receive_queue) || 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sk->sk_shutdown & RCV_SHUTDOWN)) 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLIN | POLLRDNORM; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Connection-based need to check for termination and startup */ 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (connection_based(sk)) { 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_CLOSE) 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* connection hasn't started yet? */ 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_SYN_SENT) 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* writable? */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock_writeable(sk)) 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(datagram_poll); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_datagram_iovec); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_free_datagram); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_recv_datagram); 652