datagram.c revision c75d721c761ad0f2d8725c40af9e4f376efefd24
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> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/protocol.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 54c752f0739f09b803aed191c4765a3b6650a08653Arnaldo Carvalho de Melo#include <net/checksum.h> 55c752f0739f09b803aed191c4765a3b6650a08653Arnaldo Carvalho de Melo#include <net/sock.h> 56c752f0739f09b803aed191c4765a3b6650a08653Arnaldo Carvalho de Melo#include <net/tcp_states.h> 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Is a socket 'connection oriented' ? 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int connection_based(struct sock *sk) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait for a packet.. 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int wait_for_packet(struct sock *sk, int *err, long *timeo_p) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEFINE_WAIT(wait); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Socket errors? */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sock_error(sk); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_err; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_queue_empty(&sk->sk_receive_queue)) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Socket shut down? */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown & RCV_SHUTDOWN) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_noerr; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Sequenced packets can come disconnected. 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If so we report the problem 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -ENOTCONN; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (connection_based(sk) && 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN)) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_err; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle signals */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto interrupted; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *timeo_p = schedule_timeout(*timeo_p); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds finish_wait(sk->sk_sleep, &wait); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinterrupted: 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sock_intr_errno(*timeo_p); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_err: 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *err = error; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_noerr: 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *err = 0; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = 1; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_recv_datagram - Receive a datagram skbuff 1184dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @sk: socket 1194dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @flags: MSG_ flags 1204dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @noblock: blocking operation? 1214dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @err: error code returned 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get a datagram skbuff, understands the peeking, nonblocking wakeups 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and possible races. This replaces identical code in packet, raw and 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * udp, as well as the IPX AX.25 and Appletalk. It also finally fixes 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the long standing peek and read race for datagram sockets. If you 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * alter this routine remember it must be re-entrant. 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function will lock the socket if a skb is returned, so the caller 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * needs to unlock the socket in that case (usually by calling 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_free_datagram) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * It does not lock socket since today. This function is 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * free of race conditions. This measure should/can improve 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * significantly datagram socket latencies at high loads, 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * when data copying to user space takes lots of time. 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * (BTW I've just killed the last cli() in IP/IPv6/core/netlink/packet 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * 8) Great win.) 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * * --ANK (980729) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The order of the tests when we find no data waiting are specified 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * quite explicitly by POSIX 1003.1g, don't change them without having 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the standard around please. 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int noblock, int *err) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long timeo; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Caller is allowed not to check sk->sk_err before skb_recv_datagram() 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = sock_error(sk); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_packet; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeo = sock_rcvtimeo(sk, noblock); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Again only user level code calls this function, so nothing 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupt level will suddenly eat the receive_queue. 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Look at current nfs client by the way... 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * However, this function was corrent in any case. 8) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flags & MSG_PEEK) { 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long cpu_flags; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sk->sk_receive_queue.lock, 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_flags); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = skb_peek(&sk->sk_receive_queue); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&skb->users); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sk->sk_receive_queue.lock, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_flags); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = skb_dequeue(&sk->sk_receive_queue); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return skb; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* User doesn't want to wait */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = -EAGAIN; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!timeo) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_packet; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (!wait_for_packet(sk, err, &timeo)); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_packet: 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *err = error; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid skb_free_datagram(struct sock *sk, struct sk_buff *skb) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_datagram_iovec - Copy a datagram to an iovec. 2044dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: buffer to copy 2054dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @offset: offset in the buffer to start copying from 20667be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @to: io vector to copy to 2074dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @len: amount of data to copy from buffer to iovec 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: the iovec is modified during the copy. 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct iovec *to, int len) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 214bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips int i, err, fraglen, end = 0; 215bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips struct sk_buff *next = skb_shinfo(skb)->frag_list; 216c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 217c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu if (!len) 218c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu return 0; 219c75d721c761ad0f2d8725c40af9e4f376efefd24Herbert Xu 220bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillipsnext_skb: 221bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips fraglen = skb_headlen(skb); 222bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips i = -1; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 224bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips while (1) { 225bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips int start = end; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 227bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips if ((end += fraglen) > offset) { 228bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips int copy = end - offset, o = offset - start; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 232bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips if (i == -1) 233bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips err = memcpy_toiovec(to, skb->data + o, copy); 234bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips else { 235bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 236bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips struct page *page = frag->page; 237bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips void *p = kmap(page) + frag->page_offset + o; 238bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips err = memcpy_toiovec(to, p, copy); 239bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips kunmap(page); 240bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 247bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips if (++i >= skb_shinfo(skb)->nr_frags) 248bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips break; 249bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips fraglen = skb_shinfo(skb)->frags[i].size; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 251bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips if (next) { 252bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips skb = next; 253bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips BUG_ON(skb_shinfo(skb)->frag_list); 254bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips next = skb->next; 255bc8dfcb93970ad7139c976356bfc99d7e251deafDaniel Phillips goto next_skb; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 __user *to, int len, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int *csump) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int start = skb_headlen(skb); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pos = 0; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, copy = start - offset; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Copy header. */ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > 0) { 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_and_copy_to_user(skb->data + offset, to, copy, 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump, &err); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos = copy; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int end; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_TRAP(start <= offset + len); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = start + skb_shinfo(skb)->frags[i].size; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int csum2; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *vaddr; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct page *page = frag->page; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vaddr = kmap(page); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum2 = csum_and_copy_to_user(vaddr + 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frag->page_offset + 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset - start, 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 0, &err); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kunmap(page); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(len -= copy)) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = end; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_shinfo(skb)->frag_list) { 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *list = skb_shinfo(skb)->frag_list; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; list; list=list->next) { 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int end; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_TRAP(start <= offset + len); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = start + list->len; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((copy = end - offset) > 0) { 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int csum2 = 0; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy > len) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copy = len; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_and_csum_datagram(list, 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset - start, 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to, copy, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &csum2)) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csump = csum_block_add(*csump, csum2, pos); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= copy) == 0) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += copy; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += copy; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += copy; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = end; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!len) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. 3554dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @skb: skbuff 3564dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @hlen: hardware length 35767be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @iov: io vector 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Caller _must_ check that skb will fit to this iovec. 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 0 - success. 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EINVAL - checksum failure. 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -EFAULT - fault during copy. Beware, in this case iovec 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be modified! 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hlen, struct iovec *iov) 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int csum; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chunk = skb->len - hlen; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Skip filled elements. 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pretty silly, look at memcpy_toiovec, though 8) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!iov->iov_len) 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov++; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (iov->iov_len < chunk) { 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((unsigned short)csum_fold(skb_checksum(skb, 0, chunk + hlen, 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->csum))) 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csum = csum_partial(skb->data, hlen, skb->csum); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chunk, &csum)) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fault; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((unsigned short)csum_fold(csum)) 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto csum_error; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_len -= chunk; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iov->iov_base += chunk; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscsum_error: 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfault: 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * datagram_poll - generic datagram poll 4034dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @file: file struct 4044dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @sock: socket 4054dc3b16ba18c0f967ad100c52fa65b01a4f76ff0Pavel Pisa * @wait: poll table 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Datagram poll: Again totally generic. This also handles 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sequenced packet sockets providing the socket receive queue 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is only ever holding data ready to receive. 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: when you _don't_ use this routine for this protocol, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and you use a different write policy from sock_writeable() 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then please supply your own write_space callback. 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int datagram_poll(struct file *file, struct socket *sock, 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_table *wait) 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int mask; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, sk->sk_sleep, wait); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = 0; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* exceptional events? */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLERR; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown == SHUTDOWN_MASK) 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* readable? */ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_queue_empty(&sk->sk_receive_queue) || 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sk->sk_shutdown & RCV_SHUTDOWN)) 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLIN | POLLRDNORM; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Connection-based need to check for termination and startup */ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (connection_based(sk)) { 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_CLOSE) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLHUP; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* connection hasn't started yet? */ 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state == TCP_SYN_SENT) 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* writable? */ 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock_writeable(sk)) 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mask; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(datagram_poll); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_copy_datagram_iovec); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_free_datagram); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(skb_recv_datagram); 458