diff options
-rw-r--r-- | include/net/act_api.h | 4 | ||||
-rw-r--r-- | net/sched/act_api.c | 71 | ||||
-rw-r--r-- | net/sched/cls_api.c | 14 |
3 files changed, 48 insertions, 41 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h index c5ac61ada94f..565eed8fe496 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h | |||
@@ -114,8 +114,8 @@ extern int tcf_register_action(struct tc_action_ops *a); | |||
114 | extern int tcf_unregister_action(struct tc_action_ops *a); | 114 | extern int tcf_unregister_action(struct tc_action_ops *a); |
115 | extern void tcf_action_destroy(struct tc_action *a, int bind); | 115 | extern void tcf_action_destroy(struct tc_action *a, int bind); |
116 | extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res); | 116 | extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res); |
117 | extern struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind, int *err); | 117 | extern struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind); |
118 | extern struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind, int *err); | 118 | extern struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind); |
119 | extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int); | 119 | extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int); |
120 | extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); | 120 | extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); |
121 | extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); | 121 | extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 2fe0345ddcb1..ea80f82dbb6a 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/kmod.h> | 20 | #include <linux/kmod.h> |
21 | #include <linux/err.h> | ||
21 | #include <net/net_namespace.h> | 22 | #include <net/net_namespace.h> |
22 | #include <net/sock.h> | 23 | #include <net/sock.h> |
23 | #include <net/sch_generic.h> | 24 | #include <net/sch_generic.h> |
@@ -463,15 +464,16 @@ errout: | |||
463 | } | 464 | } |
464 | 465 | ||
465 | struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, | 466 | struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, |
466 | char *name, int ovr, int bind, int *err) | 467 | char *name, int ovr, int bind) |
467 | { | 468 | { |
468 | struct tc_action *a; | 469 | struct tc_action *a; |
469 | struct tc_action_ops *a_o; | 470 | struct tc_action_ops *a_o; |
470 | char act_name[IFNAMSIZ]; | 471 | char act_name[IFNAMSIZ]; |
471 | struct nlattr *tb[TCA_ACT_MAX+1]; | 472 | struct nlattr *tb[TCA_ACT_MAX+1]; |
472 | struct nlattr *kind; | 473 | struct nlattr *kind; |
474 | int err; | ||
473 | 475 | ||
474 | *err = -EINVAL; | 476 | err = -EINVAL; |
475 | 477 | ||
476 | if (name == NULL) { | 478 | if (name == NULL) { |
477 | if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0) | 479 | if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0) |
@@ -502,36 +504,35 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, | |||
502 | * indicate this using -EAGAIN. | 504 | * indicate this using -EAGAIN. |
503 | */ | 505 | */ |
504 | if (a_o != NULL) { | 506 | if (a_o != NULL) { |
505 | *err = -EAGAIN; | 507 | err = -EAGAIN; |
506 | goto err_mod; | 508 | goto err_mod; |
507 | } | 509 | } |
508 | #endif | 510 | #endif |
509 | *err = -ENOENT; | 511 | err = -ENOENT; |
510 | goto err_out; | 512 | goto err_out; |
511 | } | 513 | } |
512 | 514 | ||
513 | *err = -ENOMEM; | 515 | err = -ENOMEM; |
514 | a = kzalloc(sizeof(*a), GFP_KERNEL); | 516 | a = kzalloc(sizeof(*a), GFP_KERNEL); |
515 | if (a == NULL) | 517 | if (a == NULL) |
516 | goto err_mod; | 518 | goto err_mod; |
517 | 519 | ||
518 | /* backward compatibility for policer */ | 520 | /* backward compatibility for policer */ |
519 | if (name == NULL) | 521 | if (name == NULL) |
520 | *err = a_o->init(tb[TCA_ACT_OPTIONS], est, a, ovr, bind); | 522 | err = a_o->init(tb[TCA_ACT_OPTIONS], est, a, ovr, bind); |
521 | else | 523 | else |
522 | *err = a_o->init(nla, est, a, ovr, bind); | 524 | err = a_o->init(nla, est, a, ovr, bind); |
523 | if (*err < 0) | 525 | if (err < 0) |
524 | goto err_free; | 526 | goto err_free; |
525 | 527 | ||
526 | /* module count goes up only when brand new policy is created | 528 | /* module count goes up only when brand new policy is created |
527 | if it exists and is only bound to in a_o->init() then | 529 | if it exists and is only bound to in a_o->init() then |
528 | ACT_P_CREATED is not returned (a zero is). | 530 | ACT_P_CREATED is not returned (a zero is). |
529 | */ | 531 | */ |
530 | if (*err != ACT_P_CREATED) | 532 | if (err != ACT_P_CREATED) |
531 | module_put(a_o->owner); | 533 | module_put(a_o->owner); |
532 | a->ops = a_o; | 534 | a->ops = a_o; |
533 | 535 | ||
534 | *err = 0; | ||
535 | return a; | 536 | return a; |
536 | 537 | ||
537 | err_free: | 538 | err_free: |
@@ -539,24 +540,22 @@ err_free: | |||
539 | err_mod: | 540 | err_mod: |
540 | module_put(a_o->owner); | 541 | module_put(a_o->owner); |
541 | err_out: | 542 | err_out: |
542 | return NULL; | 543 | return ERR_PTR(err); |
543 | } | 544 | } |
544 | 545 | ||
545 | struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, | 546 | struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, |
546 | char *name, int ovr, int bind, int *err) | 547 | char *name, int ovr, int bind) |
547 | { | 548 | { |
548 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; | 549 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; |
549 | struct tc_action *head = NULL, *act, *act_prev = NULL; | 550 | struct tc_action *head = NULL, *act, *act_prev = NULL; |
550 | int i; | 551 | int i; |
551 | 552 | ||
552 | if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0) { | 553 | if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0) |
553 | *err = -EINVAL; | 554 | return ERR_PTR(-EINVAL); |
554 | return head; | ||
555 | } | ||
556 | 555 | ||
557 | for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { | 556 | for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { |
558 | act = tcf_action_init_1(tb[i], est, name, ovr, bind, err); | 557 | act = tcf_action_init_1(tb[i], est, name, ovr, bind); |
559 | if (act == NULL) | 558 | if (IS_ERR(act)) |
560 | goto err; | 559 | goto err; |
561 | act->order = i; | 560 | act->order = i; |
562 | 561 | ||
@@ -571,7 +570,7 @@ struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, | |||
571 | err: | 570 | err: |
572 | if (head != NULL) | 571 | if (head != NULL) |
573 | tcf_action_destroy(head, bind); | 572 | tcf_action_destroy(head, bind); |
574 | return NULL; | 573 | return act; |
575 | } | 574 | } |
576 | 575 | ||
577 | int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | 576 | int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, |
@@ -668,44 +667,46 @@ act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) | |||
668 | } | 667 | } |
669 | 668 | ||
670 | static struct tc_action * | 669 | static struct tc_action * |
671 | tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int *err) | 670 | tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid) |
672 | { | 671 | { |
673 | struct nlattr *tb[TCA_ACT_MAX+1]; | 672 | struct nlattr *tb[TCA_ACT_MAX+1]; |
674 | struct tc_action *a; | 673 | struct tc_action *a; |
675 | int index; | 674 | int index; |
675 | int err; | ||
676 | 676 | ||
677 | *err = -EINVAL; | 677 | err = -EINVAL; |
678 | if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0) | 678 | if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0) |
679 | return NULL; | 679 | goto err_out; |
680 | 680 | ||
681 | if (tb[TCA_ACT_INDEX] == NULL || | 681 | if (tb[TCA_ACT_INDEX] == NULL || |
682 | nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) | 682 | nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) |
683 | return NULL; | 683 | goto err_out; |
684 | index = *(int *)nla_data(tb[TCA_ACT_INDEX]); | 684 | index = *(int *)nla_data(tb[TCA_ACT_INDEX]); |
685 | 685 | ||
686 | *err = -ENOMEM; | 686 | err = -ENOMEM; |
687 | a = kzalloc(sizeof(struct tc_action), GFP_KERNEL); | 687 | a = kzalloc(sizeof(struct tc_action), GFP_KERNEL); |
688 | if (a == NULL) | 688 | if (a == NULL) |
689 | return NULL; | 689 | goto err_out; |
690 | 690 | ||
691 | *err = -EINVAL; | 691 | err = -EINVAL; |
692 | a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); | 692 | a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); |
693 | if (a->ops == NULL) | 693 | if (a->ops == NULL) |
694 | goto err_free; | 694 | goto err_free; |
695 | if (a->ops->lookup == NULL) | 695 | if (a->ops->lookup == NULL) |
696 | goto err_mod; | 696 | goto err_mod; |
697 | *err = -ENOENT; | 697 | err = -ENOENT; |
698 | if (a->ops->lookup(a, index) == 0) | 698 | if (a->ops->lookup(a, index) == 0) |
699 | goto err_mod; | 699 | goto err_mod; |
700 | 700 | ||
701 | module_put(a->ops->owner); | 701 | module_put(a->ops->owner); |
702 | *err = 0; | ||
703 | return a; | 702 | return a; |
703 | |||
704 | err_mod: | 704 | err_mod: |
705 | module_put(a->ops->owner); | 705 | module_put(a->ops->owner); |
706 | err_free: | 706 | err_free: |
707 | kfree(a); | 707 | kfree(a); |
708 | return NULL; | 708 | err_out: |
709 | return ERR_PTR(err); | ||
709 | } | 710 | } |
710 | 711 | ||
711 | static void cleanup_a(struct tc_action *act) | 712 | static void cleanup_a(struct tc_action *act) |
@@ -816,9 +817,11 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
816 | } | 817 | } |
817 | 818 | ||
818 | for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { | 819 | for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { |
819 | act = tcf_action_get_1(tb[i], n, pid, &ret); | 820 | act = tcf_action_get_1(tb[i], n, pid); |
820 | if (act == NULL) | 821 | if (IS_ERR(act)) { |
822 | ret = PTR_ERR(act); | ||
821 | goto err; | 823 | goto err; |
824 | } | ||
822 | act->order = i; | 825 | act->order = i; |
823 | 826 | ||
824 | if (head == NULL) | 827 | if (head == NULL) |
@@ -912,9 +915,13 @@ tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr) | |||
912 | struct tc_action *a; | 915 | struct tc_action *a; |
913 | u32 seq = n->nlmsg_seq; | 916 | u32 seq = n->nlmsg_seq; |
914 | 917 | ||
915 | act = tcf_action_init(nla, NULL, NULL, ovr, 0, &ret); | 918 | act = tcf_action_init(nla, NULL, NULL, ovr, 0); |
916 | if (act == NULL) | 919 | if (act == NULL) |
917 | goto done; | 920 | goto done; |
921 | if (IS_ERR(act)) { | ||
922 | ret = PTR_ERR(act); | ||
923 | goto done; | ||
924 | } | ||
918 | 925 | ||
919 | /* dump then free all the actions after update; inserted policy | 926 | /* dump then free all the actions after update; inserted policy |
920 | * stays intact | 927 | * stays intact |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index d870478e3640..92fa1559c211 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/kmod.h> | 24 | #include <linux/kmod.h> |
25 | #include <linux/netlink.h> | 25 | #include <linux/netlink.h> |
26 | #include <linux/err.h> | ||
26 | #include <net/net_namespace.h> | 27 | #include <net/net_namespace.h> |
27 | #include <net/sock.h> | 28 | #include <net/sock.h> |
28 | #include <net/netlink.h> | 29 | #include <net/netlink.h> |
@@ -487,23 +488,22 @@ int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb, | |||
487 | 488 | ||
488 | #ifdef CONFIG_NET_CLS_ACT | 489 | #ifdef CONFIG_NET_CLS_ACT |
489 | { | 490 | { |
490 | int err; | ||
491 | struct tc_action *act; | 491 | struct tc_action *act; |
492 | 492 | ||
493 | if (map->police && tb[map->police]) { | 493 | if (map->police && tb[map->police]) { |
494 | act = tcf_action_init_1(tb[map->police], rate_tlv, | 494 | act = tcf_action_init_1(tb[map->police], rate_tlv, |
495 | "police", TCA_ACT_NOREPLACE, | 495 | "police", TCA_ACT_NOREPLACE, |
496 | TCA_ACT_BIND, &err); | 496 | TCA_ACT_BIND); |
497 | if (act == NULL) | 497 | if (IS_ERR(act)) |
498 | return err; | 498 | return PTR_ERR(act); |
499 | 499 | ||
500 | act->type = TCA_OLD_COMPAT; | 500 | act->type = TCA_OLD_COMPAT; |
501 | exts->action = act; | 501 | exts->action = act; |
502 | } else if (map->action && tb[map->action]) { | 502 | } else if (map->action && tb[map->action]) { |
503 | act = tcf_action_init(tb[map->action], rate_tlv, NULL, | 503 | act = tcf_action_init(tb[map->action], rate_tlv, NULL, |
504 | TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err); | 504 | TCA_ACT_NOREPLACE, TCA_ACT_BIND); |
505 | if (act == NULL) | 505 | if (IS_ERR(act)) |
506 | return err; | 506 | return PTR_ERR(act); |
507 | 507 | ||
508 | exts->action = act; | 508 | exts->action = act; |
509 | } | 509 | } |