diff options
-rw-r--r-- | include/net/af_unix.h | 3 | ||||
-rw-r--r-- | net/unix/af_unix.c | 59 |
2 files changed, 39 insertions, 23 deletions
diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 63b17816e0ba..5a4e29b168c9 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h | |||
@@ -66,6 +66,9 @@ struct unix_sock { | |||
66 | 66 | ||
67 | #define peer_wait peer_wq.wait | 67 | #define peer_wait peer_wq.wait |
68 | 68 | ||
69 | long unix_inq_len(struct sock *sk); | ||
70 | long unix_outq_len(struct sock *sk); | ||
71 | |||
69 | #ifdef CONFIG_SYSCTL | 72 | #ifdef CONFIG_SYSCTL |
70 | extern int unix_sysctl_register(struct net *net); | 73 | extern int unix_sysctl_register(struct net *net); |
71 | extern void unix_sysctl_unregister(struct net *net); | 74 | extern void unix_sysctl_unregister(struct net *net); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e1b9358a211d..7cc3d7b23d1c 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -2065,6 +2065,36 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
2065 | return 0; | 2065 | return 0; |
2066 | } | 2066 | } |
2067 | 2067 | ||
2068 | long unix_inq_len(struct sock *sk) | ||
2069 | { | ||
2070 | struct sk_buff *skb; | ||
2071 | long amount = 0; | ||
2072 | |||
2073 | if (sk->sk_state == TCP_LISTEN) | ||
2074 | return -EINVAL; | ||
2075 | |||
2076 | spin_lock(&sk->sk_receive_queue.lock); | ||
2077 | if (sk->sk_type == SOCK_STREAM || | ||
2078 | sk->sk_type == SOCK_SEQPACKET) { | ||
2079 | skb_queue_walk(&sk->sk_receive_queue, skb) | ||
2080 | amount += skb->len; | ||
2081 | } else { | ||
2082 | skb = skb_peek(&sk->sk_receive_queue); | ||
2083 | if (skb) | ||
2084 | amount = skb->len; | ||
2085 | } | ||
2086 | spin_unlock(&sk->sk_receive_queue.lock); | ||
2087 | |||
2088 | return amount; | ||
2089 | } | ||
2090 | EXPORT_SYMBOL_GPL(unix_inq_len); | ||
2091 | |||
2092 | long unix_outq_len(struct sock *sk) | ||
2093 | { | ||
2094 | return sk_wmem_alloc_get(sk); | ||
2095 | } | ||
2096 | EXPORT_SYMBOL_GPL(unix_outq_len); | ||
2097 | |||
2068 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 2098 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
2069 | { | 2099 | { |
2070 | struct sock *sk = sock->sk; | 2100 | struct sock *sk = sock->sk; |
@@ -2073,33 +2103,16 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
2073 | 2103 | ||
2074 | switch (cmd) { | 2104 | switch (cmd) { |
2075 | case SIOCOUTQ: | 2105 | case SIOCOUTQ: |
2076 | amount = sk_wmem_alloc_get(sk); | 2106 | amount = unix_outq_len(sk); |
2077 | err = put_user(amount, (int __user *)arg); | 2107 | err = put_user(amount, (int __user *)arg); |
2078 | break; | 2108 | break; |
2079 | case SIOCINQ: | 2109 | case SIOCINQ: |
2080 | { | 2110 | amount = unix_inq_len(sk); |
2081 | struct sk_buff *skb; | 2111 | if (amount < 0) |
2082 | 2112 | err = amount; | |
2083 | if (sk->sk_state == TCP_LISTEN) { | 2113 | else |
2084 | err = -EINVAL; | ||
2085 | break; | ||
2086 | } | ||
2087 | |||
2088 | spin_lock(&sk->sk_receive_queue.lock); | ||
2089 | if (sk->sk_type == SOCK_STREAM || | ||
2090 | sk->sk_type == SOCK_SEQPACKET) { | ||
2091 | skb_queue_walk(&sk->sk_receive_queue, skb) | ||
2092 | amount += skb->len; | ||
2093 | } else { | ||
2094 | skb = skb_peek(&sk->sk_receive_queue); | ||
2095 | if (skb) | ||
2096 | amount = skb->len; | ||
2097 | } | ||
2098 | spin_unlock(&sk->sk_receive_queue.lock); | ||
2099 | err = put_user(amount, (int __user *)arg); | 2114 | err = put_user(amount, (int __user *)arg); |
2100 | break; | 2115 | break; |
2101 | } | ||
2102 | |||
2103 | default: | 2116 | default: |
2104 | err = -ENOIOCTLCMD; | 2117 | err = -ENOIOCTLCMD; |
2105 | break; | 2118 | break; |