|
@@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk,
|
|
struct netlink_set_err_data *p)
|
|
struct netlink_set_err_data *p)
|
|
{
|
|
{
|
|
struct netlink_sock *nlk = nlk_sk(sk);
|
|
struct netlink_sock *nlk = nlk_sk(sk);
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
if (sk == p->exclude_sk)
|
|
if (sk == p->exclude_sk)
|
|
goto out;
|
|
goto out;
|
|
@@ -1104,10 +1105,15 @@ static inline int do_one_set_err(struct sock *sk,
|
|
!test_bit(p->group - 1, nlk->groups))
|
|
!test_bit(p->group - 1, nlk->groups))
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
|
|
+ if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
|
|
|
|
+ ret = 1;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
sk->sk_err = p->code;
|
|
sk->sk_err = p->code;
|
|
sk->sk_error_report(sk);
|
|
sk->sk_error_report(sk);
|
|
out:
|
|
out:
|
|
- return 0;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1116,12 +1122,16 @@ out:
|
|
* @pid: the PID of a process that we want to skip (if any)
|
|
* @pid: the PID of a process that we want to skip (if any)
|
|
* @groups: the broadcast group that will notice the error
|
|
* @groups: the broadcast group that will notice the error
|
|
* @code: error code, must be negative (as usual in kernelspace)
|
|
* @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 netlink_set_err_data info;
|
|
struct hlist_node *node;
|
|
struct hlist_node *node;
|
|
struct sock *sk;
|
|
struct sock *sk;
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
info.exclude_sk = ssk;
|
|
info.exclude_sk = ssk;
|
|
info.pid = pid;
|
|
info.pid = pid;
|
|
@@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
|
|
read_lock(&nl_table_lock);
|
|
read_lock(&nl_table_lock);
|
|
|
|
|
|
sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
|
|
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);
|
|
read_unlock(&nl_table_lock);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(netlink_set_err);
|
|
EXPORT_SYMBOL(netlink_set_err);
|
|
|
|
|