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 | } |
