diff options
author | Thomas Graf <tgraf@suug.ch> | 2007-03-23 02:30:12 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:27:30 -0400 |
commit | 1d00a4eb42bdade33a6ec0961cada93577a66ae6 (patch) | |
tree | a181b141818f594eb544601386bf09e45e6193bb /net/netlink | |
parent | 45e7ae7f716086994e4e747226881f901c67b031 (diff) |
[NETLINK]: Remove error pointer from netlink message handler
The error pointer argument in netlink message handlers is used
to signal the special case where processing has to be interrupted
because a dump was started but no error happened. Instead it is
simpler and more clear to return -EINTR and have netlink_run_queue()
deal with getting the queue right.
nfnetlink passed on this error pointer to its subsystem handlers
but only uses it to signal the start of a netlink dump. Therefore
it can be removed there as well.
This patch also cleans up the error handling in the affected
message handlers to be consistent since it had to be touched anyway.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink')
-rw-r--r-- | net/netlink/af_netlink.c | 21 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 56 |
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 | ||
1465 | static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | 1465 | static 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 | } |
1494 | skip: | 1492 | skip: |
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 | */ |
1519 | void netlink_run_queue(struct sock *sk, unsigned int *qlen, | 1522 | void 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 | ||
298 | static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, | 298 | static 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 | |||
364 | errout: | ||
365 | *errp = err; | ||
366 | return -1; | ||
367 | } | 351 | } |
368 | 352 | ||
369 | static void genl_rcv(struct sock *sk, int len) | 353 | static void genl_rcv(struct sock *sk, int len) |