]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
net: fib_rules: add extack support
authorRoopa Prabhu <roopa@cumulusnetworks.com>
Sat, 21 Apr 2018 16:41:31 +0000 (09:41 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 23 Apr 2018 14:21:24 +0000 (10:21 -0400)
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/fib_rules.h
net/core/fib_rules.c
net/decnet/dn_rules.c
net/ipv4/fib_rules.c
net/ipv4/ipmr.c
net/ipv6/fib6_rules.c
net/ipv6/ip6mr.c

index e5cfcfc7dd93c96b08c57458b71baf15418ff8ab..b473df5b95121f3f810d8ffe29f858369f5c8fd5 100644 (file)
@@ -75,7 +75,8 @@ struct fib_rules_ops {
        int                     (*configure)(struct fib_rule *,
                                             struct sk_buff *,
                                             struct fib_rule_hdr *,
-                                            struct nlattr **);
+                                            struct nlattr **,
+                                            struct netlink_ext_ack *);
        int                     (*delete)(struct fib_rule *);
        int                     (*compare)(struct fib_rule *,
                                           struct fib_rule_hdr *,
index 67801104e9a8c972460fc77b60d9f155cac5851a..ebd9351b213a966de581d4a1265c85ef057c4cbb 100644 (file)
@@ -469,14 +469,18 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (frh->src_len)
                if (!tb[FRA_SRC] ||
                    frh->src_len > (ops->addr_size * 8) ||
-                   nla_len(tb[FRA_SRC]) != ops->addr_size)
+                   nla_len(tb[FRA_SRC]) != ops->addr_size) {
+                       NL_SET_ERR_MSG(extack, "Invalid source address");
                        goto errout;
+       }
 
        if (frh->dst_len)
                if (!tb[FRA_DST] ||
                    frh->dst_len > (ops->addr_size * 8) ||
-                   nla_len(tb[FRA_DST]) != ops->addr_size)
+                   nla_len(tb[FRA_DST]) != ops->addr_size) {
+                       NL_SET_ERR_MSG(extack, "Invalid dst address");
                        goto errout;
+       }
 
        nlrule = kzalloc(ops->rule_size, GFP_KERNEL);
        if (!nlrule) {
@@ -537,6 +541,7 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
                nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]);
                if (nlrule->l3mdev != 1)
 #endif
+                       NL_SET_ERR_MSG(extack, "Invalid l3mdev");
                        goto errout_free;
        }
 
@@ -554,31 +559,41 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
                nlrule->suppress_ifgroup = -1;
 
        if (tb[FRA_GOTO]) {
-               if (nlrule->action != FR_ACT_GOTO)
+               if (nlrule->action != FR_ACT_GOTO) {
+                       NL_SET_ERR_MSG(extack, "Unexpected goto");
                        goto errout_free;
+               }
 
                nlrule->target = nla_get_u32(tb[FRA_GOTO]);
                /* Backward jumps are prohibited to avoid endless loops */
-               if (nlrule->target <= nlrule->pref)
+               if (nlrule->target <= nlrule->pref) {
+                       NL_SET_ERR_MSG(extack, "Backward goto not supported");
                        goto errout_free;
+               }
        } else if (nlrule->action == FR_ACT_GOTO) {
+               NL_SET_ERR_MSG(extack, "Missing goto target for action goto");
                goto errout_free;
        }
 
-       if (nlrule->l3mdev && nlrule->table)
+       if (nlrule->l3mdev && nlrule->table) {
+               NL_SET_ERR_MSG(extack, "l3mdev and table are mutually exclusive");
                goto errout_free;
+       }
 
        if (tb[FRA_UID_RANGE]) {
                if (current_user_ns() != net->user_ns) {
                        err = -EPERM;
+                       NL_SET_ERR_MSG(extack, "No permission to set uid");
                        goto errout_free;
                }
 
                nlrule->uid_range = nla_get_kuid_range(tb);
 
                if (!uid_range_set(&nlrule->uid_range) ||
-                   !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end))
+                   !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) {
+                       NL_SET_ERR_MSG(extack, "Invalid uid range");
                        goto errout_free;
+               }
        } else {
                nlrule->uid_range = fib_kuid_range_unset;
        }
@@ -589,15 +604,19 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (tb[FRA_SPORT_RANGE]) {
                err = nla_get_port_range(tb[FRA_SPORT_RANGE],
                                         &nlrule->sport_range);
-               if (err)
+               if (err) {
+                       NL_SET_ERR_MSG(extack, "Invalid sport range");
                        goto errout_free;
+               }
        }
 
        if (tb[FRA_DPORT_RANGE]) {
                err = nla_get_port_range(tb[FRA_DPORT_RANGE],
                                         &nlrule->dport_range);
-               if (err)
+               if (err) {
+                       NL_SET_ERR_MSG(extack, "Invalid dport range");
                        goto errout_free;
+               }
        }
 
        *rule = nlrule;
@@ -621,18 +640,23 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
        int err = -EINVAL, unresolved = 0;
        bool user_priority = false;
 
-       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
+       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) {
+               NL_SET_ERR_MSG(extack, "Invalid msg length");
                goto errout;
+       }
 
        ops = lookup_rules_ops(net, frh->family);
        if (!ops) {
                err = -EAFNOSUPPORT;
+               NL_SET_ERR_MSG(extack, "Rule family not supported");
                goto errout;
        }
 
        err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack);
-       if (err < 0)
+       if (err < 0) {
+               NL_SET_ERR_MSG(extack, "Error parsing msg");
                goto errout;
+       }
 
        err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority);
        if (err)
@@ -644,7 +668,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
                goto errout_free;
        }
 
-       err = ops->configure(rule, skb, frh, tb);
+       err = ops->configure(rule, skb, frh, tb, extack);
        if (err < 0)
                goto errout_free;
 
@@ -723,18 +747,23 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
        int err = -EINVAL;
        bool user_priority = false;
 
-       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
+       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) {
+               NL_SET_ERR_MSG(extack, "Invalid msg length");
                goto errout;
+       }
 
        ops = lookup_rules_ops(net, frh->family);
        if (ops == NULL) {
                err = -EAFNOSUPPORT;
+               NL_SET_ERR_MSG(extack, "Rule family not supported");
                goto errout;
        }
 
        err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack);
-       if (err < 0)
+       if (err < 0) {
+               NL_SET_ERR_MSG(extack, "Error parsing msg");
                goto errout;
+       }
 
        err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority);
        if (err)
index c795c3f509c9494486463f1839c4c9dcadff797c..72236695db3db2fb27e3b3414feafde008bfd8c6 100644 (file)
@@ -121,13 +121,16 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 
 static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
                                 struct fib_rule_hdr *frh,
-                                struct nlattr **tb)
+                                struct nlattr **tb,
+                                struct netlink_ext_ack *extack)
 {
        int err = -EINVAL;
        struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
 
-       if (frh->tos)
+       if (frh->tos) {
+               NL_SET_ERR_MSG(extack, "Invalid tos value");
                goto  errout;
+       }
 
        if (rule->table == RT_TABLE_UNSPEC) {
                if (rule->action == FR_ACT_TO_TBL) {
index 737d11bc8838bc175df587db4acd3fce3146c60d..f8eb78d042a48e658792fa38d7466a87eca944aa 100644 (file)
@@ -213,14 +213,17 @@ static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
 
 static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
                               struct fib_rule_hdr *frh,
-                              struct nlattr **tb)
+                              struct nlattr **tb,
+                              struct netlink_ext_ack *extack)
 {
        struct net *net = sock_net(skb->sk);
        int err = -EINVAL;
        struct fib4_rule *rule4 = (struct fib4_rule *) rule;
 
-       if (frh->tos & ~IPTOS_TOS_MASK)
+       if (frh->tos & ~IPTOS_TOS_MASK) {
+               NL_SET_ERR_MSG(extack, "Invalid tos");
                goto errout;
+       }
 
        /* split local/main if they are not already split */
        err = fib_unmerge(net);
index 2fb4de3f7f66120a10ed69e1c0020acd229c4e29..38e092eafc97ea08e5530d9c9675c883aa2fd1ba 100644 (file)
@@ -201,7 +201,8 @@ static const struct nla_policy ipmr_rule_policy[FRA_MAX + 1] = {
 };
 
 static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
-                              struct fib_rule_hdr *frh, struct nlattr **tb)
+                              struct fib_rule_hdr *frh, struct nlattr **tb,
+                              struct netlink_ext_ack *extack)
 {
        return 0;
 }
index df113c7b5fc82dbddc33ce5ed6865630a545b296..6547fc6491a63af0ccbab6fd4ca04c8c64c8622b 100644 (file)
@@ -245,15 +245,18 @@ static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
 
 static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
                               struct fib_rule_hdr *frh,
-                              struct nlattr **tb)
+                              struct nlattr **tb,
+                              struct netlink_ext_ack *extack)
 {
        int err = -EINVAL;
        struct net *net = sock_net(skb->sk);
        struct fib6_rule *rule6 = (struct fib6_rule *) rule;
 
        if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) {
-               if (rule->table == RT6_TABLE_UNSPEC)
+               if (rule->table == RT6_TABLE_UNSPEC) {
+                       NL_SET_ERR_MSG(extack, "Invalid table");
                        goto errout;
+               }
 
                if (fib6_new_table(net, rule->table) == NULL) {
                        err = -ENOBUFS;
index 298fd8b6ed17fa1ce95c6a1b2b831bf68201671a..20a419ee800057a4fb6ad4c66ff7bf71dff44d3a 100644 (file)
@@ -180,7 +180,8 @@ static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
 };
 
 static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
-                               struct fib_rule_hdr *frh, struct nlattr **tb)
+                               struct fib_rule_hdr *frh, struct nlattr **tb,
+                               struct netlink_ext_ack *extack)
 {
        return 0;
 }