diff options
-rw-r--r-- | include/linux/netlink.h | 1 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 38 |
2 files changed, 33 insertions, 6 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 1e6bf995435c..5ba398e90304 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -104,6 +104,7 @@ struct nlmsgerr | |||
104 | #define NETLINK_DROP_MEMBERSHIP 2 | 104 | #define NETLINK_DROP_MEMBERSHIP 2 |
105 | #define NETLINK_PKTINFO 3 | 105 | #define NETLINK_PKTINFO 3 |
106 | #define NETLINK_BROADCAST_ERROR 4 | 106 | #define NETLINK_BROADCAST_ERROR 4 |
107 | #define NETLINK_NO_ENOBUFS 5 | ||
107 | 108 | ||
108 | struct nl_pktinfo | 109 | struct nl_pktinfo |
109 | { | 110 | { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index b73d4e61c5ac..8b6bbb3032b0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -86,6 +86,7 @@ struct netlink_sock { | |||
86 | #define NETLINK_KERNEL_SOCKET 0x1 | 86 | #define NETLINK_KERNEL_SOCKET 0x1 |
87 | #define NETLINK_RECV_PKTINFO 0x2 | 87 | #define NETLINK_RECV_PKTINFO 0x2 |
88 | #define NETLINK_BROADCAST_SEND_ERROR 0x4 | 88 | #define NETLINK_BROADCAST_SEND_ERROR 0x4 |
89 | #define NETLINK_RECV_NO_ENOBUFS 0x8 | ||
89 | 90 | ||
90 | static inline struct netlink_sock *nlk_sk(struct sock *sk) | 91 | static inline struct netlink_sock *nlk_sk(struct sock *sk) |
91 | { | 92 | { |
@@ -717,10 +718,15 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, | |||
717 | 718 | ||
718 | static void netlink_overrun(struct sock *sk) | 719 | static void netlink_overrun(struct sock *sk) |
719 | { | 720 | { |
720 | if (!test_and_set_bit(0, &nlk_sk(sk)->state)) { | 721 | struct netlink_sock *nlk = nlk_sk(sk); |
721 | sk->sk_err = ENOBUFS; | 722 | |
722 | sk->sk_error_report(sk); | 723 | if (!(nlk->flags & NETLINK_RECV_NO_ENOBUFS)) { |
724 | if (!test_and_set_bit(0, &nlk_sk(sk)->state)) { | ||
725 | sk->sk_err = ENOBUFS; | ||
726 | sk->sk_error_report(sk); | ||
727 | } | ||
723 | } | 728 | } |
729 | atomic_inc(&sk->sk_drops); | ||
724 | } | 730 | } |
725 | 731 | ||
726 | static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) | 732 | static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) |
@@ -1182,6 +1188,15 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
1182 | nlk->flags &= ~NETLINK_BROADCAST_SEND_ERROR; | 1188 | nlk->flags &= ~NETLINK_BROADCAST_SEND_ERROR; |
1183 | err = 0; | 1189 | err = 0; |
1184 | break; | 1190 | break; |
1191 | case NETLINK_NO_ENOBUFS: | ||
1192 | if (val) { | ||
1193 | nlk->flags |= NETLINK_RECV_NO_ENOBUFS; | ||
1194 | clear_bit(0, &nlk->state); | ||
1195 | wake_up_interruptible(&nlk->wait); | ||
1196 | } else | ||
1197 | nlk->flags &= ~NETLINK_RECV_NO_ENOBUFS; | ||
1198 | err = 0; | ||
1199 | break; | ||
1185 | default: | 1200 | default: |
1186 | err = -ENOPROTOOPT; | 1201 | err = -ENOPROTOOPT; |
1187 | } | 1202 | } |
@@ -1224,6 +1239,16 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, | |||
1224 | return -EFAULT; | 1239 | return -EFAULT; |
1225 | err = 0; | 1240 | err = 0; |
1226 | break; | 1241 | break; |
1242 | case NETLINK_NO_ENOBUFS: | ||
1243 | if (len < sizeof(int)) | ||
1244 | return -EINVAL; | ||
1245 | len = sizeof(int); | ||
1246 | val = nlk->flags & NETLINK_RECV_NO_ENOBUFS ? 1 : 0; | ||
1247 | if (put_user(len, optlen) || | ||
1248 | put_user(val, optval)) | ||
1249 | return -EFAULT; | ||
1250 | err = 0; | ||
1251 | break; | ||
1227 | default: | 1252 | default: |
1228 | err = -ENOPROTOOPT; | 1253 | err = -ENOPROTOOPT; |
1229 | } | 1254 | } |
@@ -1879,12 +1904,12 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
1879 | if (v == SEQ_START_TOKEN) | 1904 | if (v == SEQ_START_TOKEN) |
1880 | seq_puts(seq, | 1905 | seq_puts(seq, |
1881 | "sk Eth Pid Groups " | 1906 | "sk Eth Pid Groups " |
1882 | "Rmem Wmem Dump Locks\n"); | 1907 | "Rmem Wmem Dump Locks Drops\n"); |
1883 | else { | 1908 | else { |
1884 | struct sock *s = v; | 1909 | struct sock *s = v; |
1885 | struct netlink_sock *nlk = nlk_sk(s); | 1910 | struct netlink_sock *nlk = nlk_sk(s); |
1886 | 1911 | ||
1887 | seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %d\n", | 1912 | seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n", |
1888 | s, | 1913 | s, |
1889 | s->sk_protocol, | 1914 | s->sk_protocol, |
1890 | nlk->pid, | 1915 | nlk->pid, |
@@ -1892,7 +1917,8 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
1892 | atomic_read(&s->sk_rmem_alloc), | 1917 | atomic_read(&s->sk_rmem_alloc), |
1893 | atomic_read(&s->sk_wmem_alloc), | 1918 | atomic_read(&s->sk_wmem_alloc), |
1894 | nlk->cb, | 1919 | nlk->cb, |
1895 | atomic_read(&s->sk_refcnt) | 1920 | atomic_read(&s->sk_refcnt), |
1921 | atomic_read(&s->sk_drops) | ||
1896 | ); | 1922 | ); |
1897 | 1923 | ||
1898 | } | 1924 | } |