aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/af_netlink.c21
-rw-r--r--net/netlink/genetlink.c56
2 files changed, 32 insertions, 45 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5d1079b1838c..1823b7c63156 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1463,7 +1463,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
1463} 1463}
1464 1464
1465static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, 1465static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
1466 struct nlmsghdr *, int *)) 1466 struct nlmsghdr *))
1467{ 1467{
1468 struct nlmsghdr *nlh; 1468 struct nlmsghdr *nlh;
1469 int err; 1469 int err;
@@ -1483,13 +1483,11 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
1483 if (nlh->nlmsg_type < NLMSG_MIN_TYPE) 1483 if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
1484 goto skip; 1484 goto skip;
1485 1485
1486 if (cb(skb, nlh, &err) < 0) { 1486 err = cb(skb, nlh);
1487 /* Not an error, but we have to interrupt processing 1487 if (err == -EINTR) {
1488 * here. Note: that in this case we do not pull 1488 /* Not an error, but we interrupt processing */
1489 * message from skb, it will be processed later. 1489 netlink_queue_skip(nlh, skb);
1490 */ 1490 return err;
1491 if (err == 0)
1492 return -1;
1493 } 1491 }
1494skip: 1492skip:
1495 if (nlh->nlmsg_flags & NLM_F_ACK || err) 1493 if (nlh->nlmsg_flags & NLM_F_ACK || err)
@@ -1515,9 +1513,14 @@ skip:
1515 * 1513 *
1516 * qlen must be initialized to 0 before the initial entry, afterwards 1514 * qlen must be initialized to 0 before the initial entry, afterwards
1517 * the function may be called repeatedly until qlen reaches 0. 1515 * the function may be called repeatedly until qlen reaches 0.
1516 *
1517 * The callback function may return -EINTR to signal that processing
1518 * of netlink messages shall be interrupted. In this case the message
1519 * currently being processed will NOT be requeued onto the receive
1520 * queue.
1518 */ 1521 */
1519void netlink_run_queue(struct sock *sk, unsigned int *qlen, 1522void netlink_run_queue(struct sock *sk, unsigned int *qlen,
1520 int (*cb)(struct sk_buff *, struct nlmsghdr *, int *)) 1523 int (*cb)(struct sk_buff *, struct nlmsghdr *))
1521{ 1524{
1522 struct sk_buff *skb; 1525 struct sk_buff *skb;
1523 1526
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 95391e609046..1b897bc92e61 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -295,60 +295,49 @@ int genl_unregister_family(struct genl_family *family)
295 return -ENOENT; 295 return -ENOENT;
296} 296}
297 297
298static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, 298static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
299 int *errp)
300{ 299{
301 struct genl_ops *ops; 300 struct genl_ops *ops;
302 struct genl_family *family; 301 struct genl_family *family;
303 struct genl_info info; 302 struct genl_info info;
304 struct genlmsghdr *hdr = nlmsg_data(nlh); 303 struct genlmsghdr *hdr = nlmsg_data(nlh);
305 int hdrlen, err = -EINVAL; 304 int hdrlen, err;
306 305
307 family = genl_family_find_byid(nlh->nlmsg_type); 306 family = genl_family_find_byid(nlh->nlmsg_type);
308 if (family == NULL) { 307 if (family == NULL)
309 err = -ENOENT; 308 return -ENOENT;
310 goto errout;
311 }
312 309
313 hdrlen = GENL_HDRLEN + family->hdrsize; 310 hdrlen = GENL_HDRLEN + family->hdrsize;
314 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) 311 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
315 goto errout; 312 return -EINVAL;
316 313
317 ops = genl_get_cmd(hdr->cmd, family); 314 ops = genl_get_cmd(hdr->cmd, family);
318 if (ops == NULL) { 315 if (ops == NULL)
319 err = -EOPNOTSUPP; 316 return -EOPNOTSUPP;
320 goto errout;
321 }
322 317
323 if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) { 318 if ((ops->flags & GENL_ADMIN_PERM) &&
324 err = -EPERM; 319 security_netlink_recv(skb, CAP_NET_ADMIN))
325 goto errout; 320 return -EPERM;
326 }
327 321
328 if (nlh->nlmsg_flags & NLM_F_DUMP) { 322 if (nlh->nlmsg_flags & NLM_F_DUMP) {
329 if (ops->dumpit == NULL) { 323 if (ops->dumpit == NULL)
330 err = -EOPNOTSUPP; 324 return -EOPNOTSUPP;
331 goto errout;
332 }
333 325
334 *errp = err = netlink_dump_start(genl_sock, skb, nlh, 326 err = netlink_dump_start(genl_sock, skb, nlh,
335 ops->dumpit, ops->done); 327 ops->dumpit, ops->done);
336 if (err == 0) 328 if (err == 0)
337 skb_pull(skb, min(NLMSG_ALIGN(nlh->nlmsg_len), 329 err = -EINTR;
338 skb->len)); 330 return err;
339 return -1;
340 } 331 }
341 332
342 if (ops->doit == NULL) { 333 if (ops->doit == NULL)
343 err = -EOPNOTSUPP; 334 return -EOPNOTSUPP;
344 goto errout;
345 }
346 335
347 if (family->attrbuf) { 336 if (family->attrbuf) {
348 err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, 337 err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr,
349 ops->policy); 338 ops->policy);
350 if (err < 0) 339 if (err < 0)
351 goto errout; 340 return err;
352 } 341 }
353 342
354 info.snd_seq = nlh->nlmsg_seq; 343 info.snd_seq = nlh->nlmsg_seq;
@@ -358,12 +347,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
358 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; 347 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
359 info.attrs = family->attrbuf; 348 info.attrs = family->attrbuf;
360 349
361 *errp = err = ops->doit(skb, &info); 350 return ops->doit(skb, &info);
362 return err;
363
364errout:
365 *errp = err;
366 return -1;
367} 351}
368 352
369static void genl_rcv(struct sock *sk, int len) 353static void genl_rcv(struct sock *sk, int len)