diff options
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r-- | net/netlink/genetlink.c | 66 |
1 files changed, 19 insertions, 47 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index c2996794eb25..6e31234a4196 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -295,66 +295,46 @@ 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 | |||
307 | if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) | ||
308 | goto ignore; | ||
309 | |||
310 | if (nlh->nlmsg_type < NLMSG_MIN_TYPE) | ||
311 | goto ignore; | ||
312 | 305 | ||
313 | family = genl_family_find_byid(nlh->nlmsg_type); | 306 | family = genl_family_find_byid(nlh->nlmsg_type); |
314 | if (family == NULL) { | 307 | if (family == NULL) |
315 | err = -ENOENT; | 308 | return -ENOENT; |
316 | goto errout; | ||
317 | } | ||
318 | 309 | ||
319 | hdrlen = GENL_HDRLEN + family->hdrsize; | 310 | hdrlen = GENL_HDRLEN + family->hdrsize; |
320 | if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) | 311 | if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) |
321 | goto errout; | 312 | return -EINVAL; |
322 | 313 | ||
323 | ops = genl_get_cmd(hdr->cmd, family); | 314 | ops = genl_get_cmd(hdr->cmd, family); |
324 | if (ops == NULL) { | 315 | if (ops == NULL) |
325 | err = -EOPNOTSUPP; | 316 | return -EOPNOTSUPP; |
326 | goto errout; | ||
327 | } | ||
328 | 317 | ||
329 | if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) { | 318 | if ((ops->flags & GENL_ADMIN_PERM) && |
330 | err = -EPERM; | 319 | security_netlink_recv(skb, CAP_NET_ADMIN)) |
331 | goto errout; | 320 | return -EPERM; |
332 | } | ||
333 | 321 | ||
334 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 322 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
335 | if (ops->dumpit == NULL) { | 323 | if (ops->dumpit == NULL) |
336 | err = -EOPNOTSUPP; | 324 | return -EOPNOTSUPP; |
337 | goto errout; | ||
338 | } | ||
339 | 325 | ||
340 | *errp = err = netlink_dump_start(genl_sock, skb, nlh, | 326 | return netlink_dump_start(genl_sock, skb, nlh, |
341 | ops->dumpit, ops->done); | 327 | ops->dumpit, ops->done); |
342 | if (err == 0) | ||
343 | skb_pull(skb, min(NLMSG_ALIGN(nlh->nlmsg_len), | ||
344 | skb->len)); | ||
345 | return -1; | ||
346 | } | 328 | } |
347 | 329 | ||
348 | if (ops->doit == NULL) { | 330 | if (ops->doit == NULL) |
349 | err = -EOPNOTSUPP; | 331 | return -EOPNOTSUPP; |
350 | goto errout; | ||
351 | } | ||
352 | 332 | ||
353 | if (family->attrbuf) { | 333 | if (family->attrbuf) { |
354 | err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, | 334 | err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr, |
355 | ops->policy); | 335 | ops->policy); |
356 | if (err < 0) | 336 | if (err < 0) |
357 | goto errout; | 337 | return err; |
358 | } | 338 | } |
359 | 339 | ||
360 | info.snd_seq = nlh->nlmsg_seq; | 340 | info.snd_seq = nlh->nlmsg_seq; |
@@ -364,15 +344,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
364 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; | 344 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; |
365 | info.attrs = family->attrbuf; | 345 | info.attrs = family->attrbuf; |
366 | 346 | ||
367 | *errp = err = ops->doit(skb, &info); | 347 | return ops->doit(skb, &info); |
368 | return err; | ||
369 | |||
370 | ignore: | ||
371 | return 0; | ||
372 | |||
373 | errout: | ||
374 | *errp = err; | ||
375 | return -1; | ||
376 | } | 348 | } |
377 | 349 | ||
378 | static void genl_rcv(struct sock *sk, int len) | 350 | static void genl_rcv(struct sock *sk, int len) |
@@ -586,7 +558,7 @@ static int __init genl_init(void) | |||
586 | 558 | ||
587 | netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); | 559 | netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); |
588 | genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID, | 560 | genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID, |
589 | genl_rcv, THIS_MODULE); | 561 | genl_rcv, NULL, THIS_MODULE); |
590 | if (genl_sock == NULL) | 562 | if (genl_sock == NULL) |
591 | panic("GENL: Cannot initialize generic netlink\n"); | 563 | panic("GENL: Cannot initialize generic netlink\n"); |
592 | 564 | ||