aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2012-02-21 02:31:34 -0500
committerDavid S. Miller <davem@davemloft.net>2012-02-21 15:03:48 -0500
commitef64a54f6e558155b4f149bb10666b9e914b6c54 (patch)
treebd7adba8d802aff2aaec0f5f2a9e2ba5431cafcc
parentda5ef6e51b327b41180b5d1000c06e8d3595a936 (diff)
sock: Introduce the SO_PEEK_OFF sock option
This one specifies where to start MSG_PEEK-ing queue data from. When set to negative value means that MSG_PEEK works as ususally -- peeks from the head of the queue always. When some bytes are peeked from queue and the peeking offset is non negative it is moved forward so that the next peek will return next portion of data. When non-peeking recvmsg occurs and the peeking offset is non negative is is moved backward so that the next peek will still peek the proper data (i.e. the one that would have been picked if there were no non peeking recv in between). The offset is set using per-proto opteration to let the protocol handle the locking issues and to check whether the peeking offset feature is supported by the protocol the socket belongs to. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/alpha/include/asm/socket.h1
-rw-r--r--arch/arm/include/asm/socket.h1
-rw-r--r--arch/avr32/include/asm/socket.h1
-rw-r--r--arch/cris/include/asm/socket.h1
-rw-r--r--arch/frv/include/asm/socket.h1
-rw-r--r--arch/h8300/include/asm/socket.h1
-rw-r--r--arch/ia64/include/asm/socket.h1
-rw-r--r--arch/m32r/include/asm/socket.h1
-rw-r--r--arch/m68k/include/asm/socket.h1
-rw-r--r--arch/mips/include/asm/socket.h1
-rw-r--r--arch/mn10300/include/asm/socket.h1
-rw-r--r--arch/parisc/include/asm/socket.h1
-rw-r--r--arch/powerpc/include/asm/socket.h1
-rw-r--r--arch/s390/include/asm/socket.h1
-rw-r--r--arch/sparc/include/asm/socket.h1
-rw-r--r--arch/xtensa/include/asm/socket.h1
-rw-r--r--include/asm-generic/socket.h1
-rw-r--r--include/linux/net.h1
-rw-r--r--include/net/sock.h25
-rw-r--r--net/core/sock.c13
20 files changed, 56 insertions, 0 deletions
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 082355f159e6..16449d330dae 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -71,6 +71,7 @@
71 71
72#define SO_WIFI_STATUS 41 72#define SO_WIFI_STATUS 41
73#define SCM_WIFI_STATUS SO_WIFI_STATUS 73#define SCM_WIFI_STATUS SO_WIFI_STATUS
74#define SO_PEEK_OFF 42
74 75
75/* O_NONBLOCK clashes with the bits used for socket types. Therefore we 76/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
76 * have to define SOCK_NONBLOCK to a different value here. 77 * have to define SOCK_NONBLOCK to a different value here.
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
index dec6f9afb3cf..d958c74e5260 100644
--- a/arch/arm/include/asm/socket.h
+++ b/arch/arm/include/asm/socket.h
@@ -64,5 +64,6 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* _ASM_SOCKET_H */ 69#endif /* _ASM_SOCKET_H */
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h
index 247b88c760be..30078f98b3ab 100644
--- a/arch/avr32/include/asm/socket.h
+++ b/arch/avr32/include/asm/socket.h
@@ -64,5 +64,6 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* __ASM_AVR32_SOCKET_H */ 69#endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
index e269264df7c4..048aba64600c 100644
--- a/arch/cris/include/asm/socket.h
+++ b/arch/cris/include/asm/socket.h
@@ -66,6 +66,7 @@
66 66
67#define SO_WIFI_STATUS 41 67#define SO_WIFI_STATUS 41
68#define SCM_WIFI_STATUS SO_WIFI_STATUS 68#define SCM_WIFI_STATUS SO_WIFI_STATUS
69#define SO_PEEK_OFF 42
69 70
70#endif /* _ASM_SOCKET_H */ 71#endif /* _ASM_SOCKET_H */
71 72
diff --git a/arch/frv/include/asm/socket.h b/arch/frv/include/asm/socket.h
index ce80fdadcce5..7a361810f3cc 100644
--- a/arch/frv/include/asm/socket.h
+++ b/arch/frv/include/asm/socket.h
@@ -64,6 +64,7 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* _ASM_SOCKET_H */ 69#endif /* _ASM_SOCKET_H */
69 70
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index cf1daab6f27e..e7bbfcee5b99 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -64,5 +64,6 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* _ASM_SOCKET_H */ 69#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h
index 4b03664e3fb5..ced62de9d5a9 100644
--- a/arch/ia64/include/asm/socket.h
+++ b/arch/ia64/include/asm/socket.h
@@ -73,5 +73,6 @@
73 73
74#define SO_WIFI_STATUS 41 74#define SO_WIFI_STATUS 41
75#define SCM_WIFI_STATUS SO_WIFI_STATUS 75#define SCM_WIFI_STATUS SO_WIFI_STATUS
76#define SO_PEEK_OFF 42
76 77
77#endif /* _ASM_IA64_SOCKET_H */ 78#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index e8b8c5bb053c..696cb4c7ca4e 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -64,5 +64,6 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* _ASM_M32R_SOCKET_H */ 69#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
index d4708ce466e0..e8b41a6775f9 100644
--- a/arch/m68k/include/asm/socket.h
+++ b/arch/m68k/include/asm/socket.h
@@ -64,5 +64,6 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* _ASM_SOCKET_H */ 69#endif /* _ASM_SOCKET_H */
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h
index ad5c0a7a02a7..52104872e9e3 100644
--- a/arch/mips/include/asm/socket.h
+++ b/arch/mips/include/asm/socket.h
@@ -84,6 +84,7 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
84 84
85#define SO_WIFI_STATUS 41 85#define SO_WIFI_STATUS 41
86#define SCM_WIFI_STATUS SO_WIFI_STATUS 86#define SCM_WIFI_STATUS SO_WIFI_STATUS
87#define SO_PEEK_OFF 42
87 88
88#ifdef __KERNEL__ 89#ifdef __KERNEL__
89 90
diff --git a/arch/mn10300/include/asm/socket.h b/arch/mn10300/include/asm/socket.h
index 876356d78522..013fcc51698f 100644
--- a/arch/mn10300/include/asm/socket.h
+++ b/arch/mn10300/include/asm/socket.h
@@ -64,5 +64,6 @@
64 64
65#define SO_WIFI_STATUS 41 65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS 66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#define SO_PEEK_OFF 42
67 68
68#endif /* _ASM_SOCKET_H */ 69#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h
index d28c51b61067..f717c9bec16f 100644
--- a/arch/parisc/include/asm/socket.h
+++ b/arch/parisc/include/asm/socket.h
@@ -63,6 +63,7 @@
63 63
64#define SO_WIFI_STATUS 0x4022 64#define SO_WIFI_STATUS 0x4022
65#define SCM_WIFI_STATUS SO_WIFI_STATUS 65#define SCM_WIFI_STATUS SO_WIFI_STATUS
66#define SO_PEEK_OFF 0x4023
66 67
67/* O_NONBLOCK clashes with the bits used for socket types. Therefore we 68/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
68 * have to define SOCK_NONBLOCK to a different value here. 69 * have to define SOCK_NONBLOCK to a different value here.
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h
index 2fc2af8fbf59..fe1c0b478fd7 100644
--- a/arch/powerpc/include/asm/socket.h
+++ b/arch/powerpc/include/asm/socket.h
@@ -71,5 +71,6 @@
71 71
72#define SO_WIFI_STATUS 41 72#define SO_WIFI_STATUS 41
73#define SCM_WIFI_STATUS SO_WIFI_STATUS 73#define SCM_WIFI_STATUS SO_WIFI_STATUS
74#define SO_PEEK_OFF 42
74 75
75#endif /* _ASM_POWERPC_SOCKET_H */ 76#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h
index 67b5c1b14b51..581702fa1b0c 100644
--- a/arch/s390/include/asm/socket.h
+++ b/arch/s390/include/asm/socket.h
@@ -72,5 +72,6 @@
72 72
73#define SO_WIFI_STATUS 41 73#define SO_WIFI_STATUS 41
74#define SCM_WIFI_STATUS SO_WIFI_STATUS 74#define SCM_WIFI_STATUS SO_WIFI_STATUS
75#define SO_PEEK_OFF 42
75 76
76#endif /* _ASM_SOCKET_H */ 77#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h
index 8af1b64168b3..68e2e2746f6f 100644
--- a/arch/sparc/include/asm/socket.h
+++ b/arch/sparc/include/asm/socket.h
@@ -60,6 +60,7 @@
60 60
61#define SO_WIFI_STATUS 0x0025 61#define SO_WIFI_STATUS 0x0025
62#define SCM_WIFI_STATUS SO_WIFI_STATUS 62#define SCM_WIFI_STATUS SO_WIFI_STATUS
63#define SO_PEEK_OFF 0x0026
63 64
64/* Security levels - as per NRL IPv6 - don't actually do anything */ 65/* Security levels - as per NRL IPv6 - don't actually do anything */
65#define SO_SECURITY_AUTHENTICATION 0x5001 66#define SO_SECURITY_AUTHENTICATION 0x5001
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h
index bb06968be227..74818b161362 100644
--- a/arch/xtensa/include/asm/socket.h
+++ b/arch/xtensa/include/asm/socket.h
@@ -75,5 +75,6 @@
75 75
76#define SO_WIFI_STATUS 41 76#define SO_WIFI_STATUS 41
77#define SCM_WIFI_STATUS SO_WIFI_STATUS 77#define SCM_WIFI_STATUS SO_WIFI_STATUS
78#define SO_PEEK_OFF 42
78 79
79#endif /* _XTENSA_SOCKET_H */ 80#endif /* _XTENSA_SOCKET_H */
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h
index 49c1704173e7..d9aaac0c36d4 100644
--- a/include/asm-generic/socket.h
+++ b/include/asm-generic/socket.h
@@ -67,4 +67,5 @@
67 67
68#define SO_WIFI_STATUS 41 68#define SO_WIFI_STATUS 41
69#define SCM_WIFI_STATUS SO_WIFI_STATUS 69#define SCM_WIFI_STATUS SO_WIFI_STATUS
70#define SO_PEEK_OFF 42
70#endif /* __ASM_GENERIC_SOCKET_H */ 71#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/linux/net.h b/include/linux/net.h
index b29923006b11..be60c7f5e145 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -206,6 +206,7 @@ struct proto_ops {
206 int offset, size_t size, int flags); 206 int offset, size_t size, int flags);
207 ssize_t (*splice_read)(struct socket *sock, loff_t *ppos, 207 ssize_t (*splice_read)(struct socket *sock, loff_t *ppos,
208 struct pipe_inode_info *pipe, size_t len, unsigned int flags); 208 struct pipe_inode_info *pipe, size_t len, unsigned int flags);
209 void (*set_peek_off)(struct sock *sk, int val);
209}; 210};
210 211
211#define DECLARE_SOCKADDR(type, dst, src) \ 212#define DECLARE_SOCKADDR(type, dst, src) \
diff --git a/include/net/sock.h b/include/net/sock.h
index 91c1c8baf020..9c0553b9e451 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -357,6 +357,7 @@ struct sock {
357 struct page *sk_sndmsg_page; 357 struct page *sk_sndmsg_page;
358 struct sk_buff *sk_send_head; 358 struct sk_buff *sk_send_head;
359 __u32 sk_sndmsg_off; 359 __u32 sk_sndmsg_off;
360 __s32 sk_peek_off;
360 int sk_write_pending; 361 int sk_write_pending;
361#ifdef CONFIG_SECURITY 362#ifdef CONFIG_SECURITY
362 void *sk_security; 363 void *sk_security;
@@ -373,6 +374,30 @@ struct sock {
373 void (*sk_destruct)(struct sock *sk); 374 void (*sk_destruct)(struct sock *sk);
374}; 375};
375 376
377static inline int sk_peek_offset(struct sock *sk, int flags)
378{
379 if ((flags & MSG_PEEK) && (sk->sk_peek_off >= 0))
380 return sk->sk_peek_off;
381 else
382 return 0;
383}
384
385static inline void sk_peek_offset_bwd(struct sock *sk, int val)
386{
387 if (sk->sk_peek_off >= 0) {
388 if (sk->sk_peek_off >= val)
389 sk->sk_peek_off -= val;
390 else
391 sk->sk_peek_off = 0;
392 }
393}
394
395static inline void sk_peek_offset_fwd(struct sock *sk, int val)
396{
397 if (sk->sk_peek_off >= 0)
398 sk->sk_peek_off += val;
399}
400
376/* 401/*
377 * Hashed lists helper routines 402 * Hashed lists helper routines
378 */ 403 */
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;