diff options
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r-- | net/netlink/af_netlink.c | 20 |
1 files changed, 17 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, | |||
683 | struct netlink_sock *nlk = nlk_sk(sk); | 683 | struct netlink_sock *nlk = nlk_sk(sk); |
684 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; | 684 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
685 | 685 | ||
686 | if (alen < sizeof(addr->sa_family)) | ||
687 | return -EINVAL; | ||
688 | |||
686 | if (addr->sa_family == AF_UNSPEC) { | 689 | if (addr->sa_family == AF_UNSPEC) { |
687 | sk->sk_state = NETLINK_UNCONNECTED; | 690 | sk->sk_state = NETLINK_UNCONNECTED; |
688 | nlk->dst_pid = 0; | 691 | nlk->dst_pid = 0; |
@@ -1093,6 +1096,7 @@ static inline int do_one_set_err(struct sock *sk, | |||
1093 | struct netlink_set_err_data *p) | 1096 | struct netlink_set_err_data *p) |
1094 | { | 1097 | { |
1095 | struct netlink_sock *nlk = nlk_sk(sk); | 1098 | struct netlink_sock *nlk = nlk_sk(sk); |
1099 | int ret = 0; | ||
1096 | 1100 | ||
1097 | if (sk == p->exclude_sk) | 1101 | if (sk == p->exclude_sk) |
1098 | goto out; | 1102 | goto out; |
@@ -1104,10 +1108,15 @@ static inline int do_one_set_err(struct sock *sk, | |||
1104 | !test_bit(p->group - 1, nlk->groups)) | 1108 | !test_bit(p->group - 1, nlk->groups)) |
1105 | goto out; | 1109 | goto out; |
1106 | 1110 | ||
1111 | if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { | ||
1112 | ret = 1; | ||
1113 | goto out; | ||
1114 | } | ||
1115 | |||
1107 | sk->sk_err = p->code; | 1116 | sk->sk_err = p->code; |
1108 | sk->sk_error_report(sk); | 1117 | sk->sk_error_report(sk); |
1109 | out: | 1118 | out: |
1110 | return 0; | 1119 | return ret; |
1111 | } | 1120 | } |
1112 | 1121 | ||
1113 | /** | 1122 | /** |
@@ -1116,12 +1125,16 @@ out: | |||
1116 | * @pid: the PID of a process that we want to skip (if any) | 1125 | * @pid: the PID of a process that we want to skip (if any) |
1117 | * @groups: the broadcast group that will notice the error | 1126 | * @groups: the broadcast group that will notice the error |
1118 | * @code: error code, must be negative (as usual in kernelspace) | 1127 | * @code: error code, must be negative (as usual in kernelspace) |
1128 | * | ||
1129 | * This function returns the number of broadcast listeners that have set the | ||
1130 | * NETLINK_RECV_NO_ENOBUFS socket option. | ||
1119 | */ | 1131 | */ |
1120 | void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | 1132 | int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) |
1121 | { | 1133 | { |
1122 | struct netlink_set_err_data info; | 1134 | struct netlink_set_err_data info; |
1123 | struct hlist_node *node; | 1135 | struct hlist_node *node; |
1124 | struct sock *sk; | 1136 | struct sock *sk; |
1137 | int ret = 0; | ||
1125 | 1138 | ||
1126 | info.exclude_sk = ssk; | 1139 | info.exclude_sk = ssk; |
1127 | info.pid = pid; | 1140 | info.pid = pid; |
@@ -1132,9 +1145,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | |||
1132 | read_lock(&nl_table_lock); | 1145 | read_lock(&nl_table_lock); |
1133 | 1146 | ||
1134 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) | 1147 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) |
1135 | do_one_set_err(sk, &info); | 1148 | ret += do_one_set_err(sk, &info); |
1136 | 1149 | ||
1137 | read_unlock(&nl_table_lock); | 1150 | read_unlock(&nl_table_lock); |
1151 | return ret; | ||
1138 | } | 1152 | } |
1139 | EXPORT_SYMBOL(netlink_set_err); | 1153 | EXPORT_SYMBOL(netlink_set_err); |
1140 | 1154 | ||