aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/datagram.c26
-rw-r--r--net/core/sock.c13
-rw-r--r--net/ipv4/udp.c4
-rw-r--r--net/ipv6/udp.c4
-rw-r--r--net/unix/af_unix.c50
5 files changed, 76 insertions, 21 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 68bbf9f65cb0..d3cf12f62c8f 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -132,6 +132,8 @@ out_noerr:
132 * __skb_recv_datagram - Receive a datagram skbuff 132 * __skb_recv_datagram - Receive a datagram skbuff
133 * @sk: socket 133 * @sk: socket
134 * @flags: MSG_ flags 134 * @flags: MSG_ flags
135 * @off: an offset in bytes to peek skb from. Returns an offset
136 * within an skb where data actually starts
135 * @peeked: returns non-zero if this packet has been seen before 137 * @peeked: returns non-zero if this packet has been seen before
136 * @err: error code returned 138 * @err: error code returned
137 * 139 *
@@ -158,7 +160,7 @@ out_noerr:
158 * the standard around please. 160 * the standard around please.
159 */ 161 */
160struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, 162struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
161 int *peeked, int *err) 163 int *peeked, int *off, int *err)
162{ 164{
163 struct sk_buff *skb; 165 struct sk_buff *skb;
164 long timeo; 166 long timeo;
@@ -180,21 +182,25 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
180 * However, this function was correct in any case. 8) 182 * However, this function was correct in any case. 8)
181 */ 183 */
182 unsigned long cpu_flags; 184 unsigned long cpu_flags;
185 struct sk_buff_head *queue = &sk->sk_receive_queue;
183 186
184 spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags); 187 spin_lock_irqsave(&queue->lock, cpu_flags);
185 skb = skb_peek(&sk->sk_receive_queue); 188 skb_queue_walk(queue, skb) {
186 if (skb) {
187 *peeked = skb->peeked; 189 *peeked = skb->peeked;
188 if (flags & MSG_PEEK) { 190 if (flags & MSG_PEEK) {
191 if (*off >= skb->len) {
192 *off -= skb->len;
193 continue;
194 }
189 skb->peeked = 1; 195 skb->peeked = 1;
190 atomic_inc(&skb->users); 196 atomic_inc(&skb->users);
191 } else 197 } else
192 __skb_unlink(skb, &sk->sk_receive_queue); 198 __skb_unlink(skb, queue);
193 }
194 spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
195 199
196 if (skb) 200 spin_unlock_irqrestore(&queue->lock, cpu_flags);
197 return skb; 201 return skb;
202 }
203 spin_unlock_irqrestore(&queue->lock, cpu_flags);
198 204
199 /* User doesn't want to wait */ 205 /* User doesn't want to wait */
200 error = -EAGAIN; 206 error = -EAGAIN;
@@ -214,10 +220,10 @@ EXPORT_SYMBOL(__skb_recv_datagram);
214struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, 220struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
215 int noblock, int *err) 221 int noblock, int *err)
216{ 222{
217 int peeked; 223 int peeked, off = 0;
218 224
219 return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), 225 return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
220 &peeked, err); 226 &peeked, &off, err);
221} 227}
222EXPORT_SYMBOL(skb_recv_datagram); 228EXPORT_SYMBOL(skb_recv_datagram);
223 229
diff --git a/net/core/sock.c b/net/core/sock.c
index 02f8dfe320b7..19942d4bb6e6 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -793,6 +793,12 @@ set_rcvbuf:
793 sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool); 793 sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool);
794 break; 794 break;
795 795
796 case SO_PEEK_OFF:
797 if (sock->ops->set_peek_off)
798 sock->ops->set_peek_off(sk, val);
799 else
800 ret = -EOPNOTSUPP;
801 break;
796 default: 802 default:
797 ret = -ENOPROTOOPT; 803 ret = -ENOPROTOOPT;
798 break; 804 break;
@@ -1018,6 +1024,12 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
1018 v.val = !!sock_flag(sk, SOCK_WIFI_STATUS); 1024 v.val = !!sock_flag(sk, SOCK_WIFI_STATUS);
1019 break; 1025 break;
1020 1026
1027 case SO_PEEK_OFF:
1028 if (!sock->ops->set_peek_off)
1029 return -EOPNOTSUPP;
1030
1031 v.val = sk->sk_peek_off;
1032 break;
1021 default: 1033 default:
1022 return -ENOPROTOOPT; 1034 return -ENOPROTOOPT;
1023 } 1035 }
@@ -2092,6 +2104,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
2092 2104
2093 sk->sk_sndmsg_page = NULL; 2105 sk->sk_sndmsg_page = NULL;
2094 sk->sk_sndmsg_off = 0; 2106 sk->sk_sndmsg_off = 0;
2107 sk->sk_peek_off = -1;
2095 2108
2096 sk->sk_peer_pid = NULL; 2109 sk->sk_peer_pid = NULL;
2097 sk->sk_peer_cred = NULL; 2110 sk->sk_peer_cred = NULL;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index cd99f1a0f59f..7c41ab84e72e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1167,7 +1167,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1167 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; 1167 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
1168 struct sk_buff *skb; 1168 struct sk_buff *skb;
1169 unsigned int ulen, copied; 1169 unsigned int ulen, copied;
1170 int peeked; 1170 int peeked, off = 0;
1171 int err; 1171 int err;
1172 int is_udplite = IS_UDPLITE(sk); 1172 int is_udplite = IS_UDPLITE(sk);
1173 bool slow; 1173 bool slow;
@@ -1183,7 +1183,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
1183 1183
1184try_again: 1184try_again:
1185 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), 1185 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
1186 &peeked, &err); 1186 &peeked, &off, &err);
1187 if (!skb) 1187 if (!skb)
1188 goto out; 1188 goto out;
1189 1189
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 8aebf8f90436..37b0699e95e5 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -342,7 +342,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
342 struct inet_sock *inet = inet_sk(sk); 342 struct inet_sock *inet = inet_sk(sk);
343 struct sk_buff *skb; 343 struct sk_buff *skb;
344 unsigned int ulen, copied; 344 unsigned int ulen, copied;
345 int peeked; 345 int peeked, off = 0;
346 int err; 346 int err;
347 int is_udplite = IS_UDPLITE(sk); 347 int is_udplite = IS_UDPLITE(sk);
348 int is_udp4; 348 int is_udp4;
@@ -359,7 +359,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
359 359
360try_again: 360try_again:
361 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), 361 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
362 &peeked, &err); 362 &peeked, &off, &err);
363 if (!skb) 363 if (!skb)
364 goto out; 364 goto out;
365 365
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 85d3bb7490aa..0be4d24f6ae8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -530,6 +530,16 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
530static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, 530static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
531 struct msghdr *, size_t, int); 531 struct msghdr *, size_t, int);
532 532
533static void unix_set_peek_off(struct sock *sk, int val)
534{
535 struct unix_sock *u = unix_sk(sk);
536
537 mutex_lock(&u->readlock);
538 sk->sk_peek_off = val;
539 mutex_unlock(&u->readlock);
540}
541
542
533static const struct proto_ops unix_stream_ops = { 543static const struct proto_ops unix_stream_ops = {
534 .family = PF_UNIX, 544 .family = PF_UNIX,
535 .owner = THIS_MODULE, 545 .owner = THIS_MODULE,
@@ -549,6 +559,7 @@ static const struct proto_ops unix_stream_ops = {
549 .recvmsg = unix_stream_recvmsg, 559 .recvmsg = unix_stream_recvmsg,
550 .mmap = sock_no_mmap, 560 .mmap = sock_no_mmap,
551 .sendpage = sock_no_sendpage, 561 .sendpage = sock_no_sendpage,
562 .set_peek_off = unix_set_peek_off,
552}; 563};
553 564
554static const struct proto_ops unix_dgram_ops = { 565static const struct proto_ops unix_dgram_ops = {
@@ -570,6 +581,7 @@ static const struct proto_ops unix_dgram_ops = {
570 .recvmsg = unix_dgram_recvmsg, 581 .recvmsg = unix_dgram_recvmsg,
571 .mmap = sock_no_mmap, 582 .mmap = sock_no_mmap,
572 .sendpage = sock_no_sendpage, 583 .sendpage = sock_no_sendpage,
584 .set_peek_off = unix_set_peek_off,
573}; 585};
574 586
575static const struct proto_ops unix_seqpacket_ops = { 587static const struct proto_ops unix_seqpacket_ops = {
@@ -591,6 +603,7 @@ static const struct proto_ops unix_seqpacket_ops = {
591 .recvmsg = unix_seqpacket_recvmsg, 603 .recvmsg = unix_seqpacket_recvmsg,
592 .mmap = sock_no_mmap, 604 .mmap = sock_no_mmap,
593 .sendpage = sock_no_sendpage, 605 .sendpage = sock_no_sendpage,
606 .set_peek_off = unix_set_peek_off,
594}; 607};
595 608
596static struct proto unix_proto = { 609static struct proto unix_proto = {
@@ -1756,6 +1769,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1756 int noblock = flags & MSG_DONTWAIT; 1769 int noblock = flags & MSG_DONTWAIT;
1757 struct sk_buff *skb; 1770 struct sk_buff *skb;
1758 int err; 1771 int err;
1772 int peeked, skip;
1759 1773
1760 err = -EOPNOTSUPP; 1774 err = -EOPNOTSUPP;
1761 if (flags&MSG_OOB) 1775 if (flags&MSG_OOB)
@@ -1769,7 +1783,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1769 goto out; 1783 goto out;
1770 } 1784 }
1771 1785
1772 skb = skb_recv_datagram(sk, flags, noblock, &err); 1786 skip = sk_peek_offset(sk, flags);
1787
1788 skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
1773 if (!skb) { 1789 if (!skb) {
1774 unix_state_lock(sk); 1790 unix_state_lock(sk);
1775 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ 1791 /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
@@ -1786,12 +1802,12 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1786 if (msg->msg_name) 1802 if (msg->msg_name)
1787 unix_copy_addr(msg, skb->sk); 1803 unix_copy_addr(msg, skb->sk);
1788 1804
1789 if (size > skb->len) 1805 if (size > skb->len - skip)
1790 size = skb->len; 1806 size = skb->len - skip;
1791 else if (size < skb->len) 1807 else if (size < skb->len - skip)
1792 msg->msg_flags |= MSG_TRUNC; 1808 msg->msg_flags |= MSG_TRUNC;
1793 1809
1794 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); 1810 err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
1795 if (err) 1811 if (err)
1796 goto out_free; 1812 goto out_free;
1797 1813
@@ -1808,6 +1824,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1808 if (!(flags & MSG_PEEK)) { 1824 if (!(flags & MSG_PEEK)) {
1809 if (UNIXCB(skb).fp) 1825 if (UNIXCB(skb).fp)
1810 unix_detach_fds(siocb->scm, skb); 1826 unix_detach_fds(siocb->scm, skb);
1827
1828 sk_peek_offset_bwd(sk, skb->len);
1811 } else { 1829 } else {
1812 /* It is questionable: on PEEK we could: 1830 /* It is questionable: on PEEK we could:
1813 - do not return fds - good, but too simple 8) 1831 - do not return fds - good, but too simple 8)
@@ -1821,6 +1839,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1821 clearly however! 1839 clearly however!
1822 1840
1823 */ 1841 */
1842
1843 sk_peek_offset_fwd(sk, size);
1844
1824 if (UNIXCB(skb).fp) 1845 if (UNIXCB(skb).fp)
1825 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); 1846 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
1826 } 1847 }
@@ -1884,6 +1905,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1884 int target; 1905 int target;
1885 int err = 0; 1906 int err = 0;
1886 long timeo; 1907 long timeo;
1908 int skip;
1887 1909
1888 err = -EINVAL; 1910 err = -EINVAL;
1889 if (sk->sk_state != TCP_ESTABLISHED) 1911 if (sk->sk_state != TCP_ESTABLISHED)
@@ -1913,12 +1935,15 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1913 goto out; 1935 goto out;
1914 } 1936 }
1915 1937
1938 skip = sk_peek_offset(sk, flags);
1939
1916 do { 1940 do {
1917 int chunk; 1941 int chunk;
1918 struct sk_buff *skb; 1942 struct sk_buff *skb;
1919 1943
1920 unix_state_lock(sk); 1944 unix_state_lock(sk);
1921 skb = skb_peek(&sk->sk_receive_queue); 1945 skb = skb_peek(&sk->sk_receive_queue);
1946again:
1922 if (skb == NULL) { 1947 if (skb == NULL) {
1923 unix_sk(sk)->recursion_level = 0; 1948 unix_sk(sk)->recursion_level = 0;
1924 if (copied >= target) 1949 if (copied >= target)
@@ -1953,6 +1978,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1953 unix_state_unlock(sk); 1978 unix_state_unlock(sk);
1954 break; 1979 break;
1955 } 1980 }
1981
1982 if (skip >= skb->len) {
1983 skip -= skb->len;
1984 skb = skb_peek_next(skb, &sk->sk_receive_queue);
1985 goto again;
1986 }
1987
1956 unix_state_unlock(sk); 1988 unix_state_unlock(sk);
1957 1989
1958 if (check_creds) { 1990 if (check_creds) {
@@ -1972,8 +2004,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1972 sunaddr = NULL; 2004 sunaddr = NULL;
1973 } 2005 }
1974 2006
1975 chunk = min_t(unsigned int, skb->len, size); 2007 chunk = min_t(unsigned int, skb->len - skip, size);
1976 if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { 2008 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
1977 if (copied == 0) 2009 if (copied == 0)
1978 copied = -EFAULT; 2010 copied = -EFAULT;
1979 break; 2011 break;
@@ -1985,6 +2017,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1985 if (!(flags & MSG_PEEK)) { 2017 if (!(flags & MSG_PEEK)) {
1986 skb_pull(skb, chunk); 2018 skb_pull(skb, chunk);
1987 2019
2020 sk_peek_offset_bwd(sk, chunk);
2021
1988 if (UNIXCB(skb).fp) 2022 if (UNIXCB(skb).fp)
1989 unix_detach_fds(siocb->scm, skb); 2023 unix_detach_fds(siocb->scm, skb);
1990 2024
@@ -2002,6 +2036,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
2002 if (UNIXCB(skb).fp) 2036 if (UNIXCB(skb).fp)
2003 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); 2037 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2004 2038
2039 sk_peek_offset_fwd(sk, chunk);
2040
2005 break; 2041 break;
2006 } 2042 }
2007 } while (size); 2043 } while (size);