aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netlink.h1
-rw-r--r--net/netlink/af_netlink.c38
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
108struct nl_pktinfo 109struct 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
90static inline struct netlink_sock *nlk_sk(struct sock *sk) 91static 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
718static void netlink_overrun(struct sock *sk) 719static 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
726static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) 732static 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 }