diff options
author | Jiri Kosina <jkosina@suse.cz> | 2010-04-23 02:08:44 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-04-23 02:08:44 +0200 |
commit | 6c9468e9eb1252eaefd94ce7f06e1be9b0b641b1 (patch) | |
tree | 797676a336b050bfa1ef879377c07e541b9075d6 /net/netlink | |
parent | 4cb3ca7cd7e2cae8d1daf5345ec99a1e8502cf3f (diff) | |
parent | c81eddb0e3728661d1585fbc564449c94165cc36 (diff) | |
download | linux-6c9468e9eb1252eaefd94ce7f06e1be9b0b641b1.tar.bz2 |
Merge branch 'master' into for-next
Diffstat (limited to 'net/netlink')
-rw-r--r-- | net/netlink/af_netlink.c | 20 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 1 |
2 files changed, 18 insertions, 3 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 320d0423a240..795424396aff 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -683,6 +683,9 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, struct netlink_sock *nlk = nlk_sk(sk); struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; + if (alen < sizeof(addr->sa_family)) + return -EINVAL; + if (addr->sa_family == AF_UNSPEC) { sk->sk_state = NETLINK_UNCONNECTED; nlk->dst_pid = 0; @@ -1093,6 +1096,7 @@ static inline int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p) { struct netlink_sock *nlk = nlk_sk(sk); + int ret = 0; if (sk == p->exclude_sk) goto out; @@ -1104,10 +1108,15 @@ static inline int do_one_set_err(struct sock *sk, !test_bit(p->group - 1, nlk->groups)) goto out; + if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { + ret = 1; + goto out; + } + sk->sk_err = p->code; sk->sk_error_report(sk); out: - return 0; + return ret; } /** @@ -1116,12 +1125,16 @@ out: * @pid: the PID of a process that we want to skip (if any) * @groups: the broadcast group that will notice the error * @code: error code, must be negative (as usual in kernelspace) + * + * This function returns the number of broadcast listeners that have set the + * NETLINK_RECV_NO_ENOBUFS socket option. */ -void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) +int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) { struct netlink_set_err_data info; struct hlist_node *node; struct sock *sk; + int ret = 0; info.exclude_sk = ssk; info.pid = pid; @@ -1132,9 +1145,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) read_lock(&nl_table_lock); sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) - do_one_set_err(sk, &info); + ret += do_one_set_err(sk, &info); read_unlock(&nl_table_lock); + return ret; } EXPORT_SYMBOL(netlink_set_err); diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index a4b6e148c5de..06438fa2b1e5 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -8,6 +8,7 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> |