net: Add extack argument to ip_fib_metrics_init
authorDavid Ahern <dsahern@gmail.com>
Tue, 6 Nov 2018 20:51:15 +0000 (12:51 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 6 Nov 2018 23:00:45 +0000 (15:00 -0800)
Add extack argument to ip_fib_metrics_init and add messages for invalid
metrics.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip.h
net/ipv4/fib_semantics.c
net/ipv4/metrics.c
net/ipv6/route.c

index 72593e171d14c83cc2c005f219bf7277f25b24f5..462182f78236caed327c12e5080aefd5f73fe966 100644 (file)
@@ -421,7 +421,8 @@ static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
 }
 
 struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
-                                       int fc_mx_len);
+                                       int fc_mx_len,
+                                       struct netlink_ext_ack *extack);
 static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics)
 {
        if (fib_metrics != &dst_default_metrics &&
index b5c3937ca6ece6cb4717e199b6240491c138cec7..5022bc63863ad1b211770674a3edb897a4f4a9e1 100644 (file)
@@ -1076,7 +1076,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
        if (!fi)
                goto failure;
        fi->fib_metrics = ip_fib_metrics_init(fi->fib_net, cfg->fc_mx,
-                                             cfg->fc_mx_len);
+                                             cfg->fc_mx_len, extack);
        if (unlikely(IS_ERR(fi->fib_metrics))) {
                err = PTR_ERR(fi->fib_metrics);
                kfree(fi);
index 6d218f5a2e712582c5deea1aa3d50239031e090f..ca9a5fefdefaec89a218d0341a5638d7a9614ab8 100644 (file)
@@ -6,7 +6,8 @@
 #include <net/tcp.h>
 
 static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
-                             int fc_mx_len, u32 *metrics)
+                             int fc_mx_len, u32 *metrics,
+                             struct netlink_ext_ack *extack)
 {
        bool ecn_ca = false;
        struct nlattr *nla;
@@ -21,19 +22,26 @@ static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
 
                if (!type)
                        continue;
-               if (type > RTAX_MAX)
+               if (type > RTAX_MAX) {
+                       NL_SET_ERR_MSG(extack, "Invalid metric type");
                        return -EINVAL;
+               }
 
                if (type == RTAX_CC_ALGO) {
                        char tmp[TCP_CA_NAME_MAX];
 
                        nla_strlcpy(tmp, nla, sizeof(tmp));
                        val = tcp_ca_get_key_by_name(net, tmp, &ecn_ca);
-                       if (val == TCP_CA_UNSPEC)
+                       if (val == TCP_CA_UNSPEC) {
+                               NL_SET_ERR_MSG(extack, "Unknown tcp congestion algorithm");
                                return -EINVAL;
+                       }
                } else {
-                       if (nla_len(nla) != sizeof(u32))
+                       if (nla_len(nla) != sizeof(u32)) {
+                               NL_SET_ERR_MSG_ATTR(extack, nla,
+                                                   "Invalid attribute in metrics");
                                return -EINVAL;
+                       }
                        val = nla_get_u32(nla);
                }
                if (type == RTAX_ADVMSS && val > 65535 - 40)
@@ -42,8 +50,10 @@ static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
                        val = 65535 - 15;
                if (type == RTAX_HOPLIMIT && val > 255)
                        val = 255;
-               if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
+               if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) {
+                       NL_SET_ERR_MSG(extack, "Unknown flag set in feature mask in metrics attribute");
                        return -EINVAL;
+               }
                metrics[type - 1] = val;
        }
 
@@ -54,7 +64,8 @@ static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
 }
 
 struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
-                                       int fc_mx_len)
+                                       int fc_mx_len,
+                                       struct netlink_ext_ack *extack)
 {
        struct dst_metrics *fib_metrics;
        int err;
@@ -66,7 +77,8 @@ struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
        if (unlikely(!fib_metrics))
                return ERR_PTR(-ENOMEM);
 
-       err = ip_metrics_convert(net, fc_mx, fc_mx_len, fib_metrics->metrics);
+       err = ip_metrics_convert(net, fc_mx, fc_mx_len, fib_metrics->metrics,
+                                extack);
        if (!err) {
                refcount_set(&fib_metrics->refcnt, 1);
        } else {
index 2a7423c394560c0bc70d6f0398781a0b35fa9fa0..b2447b7c73031f28490a1d4aca2b710fd589648e 100644 (file)
@@ -2975,7 +2975,8 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
        if (!rt)
                goto out;
 
-       rt->fib6_metrics = ip_fib_metrics_init(net, cfg->fc_mx, cfg->fc_mx_len);
+       rt->fib6_metrics = ip_fib_metrics_init(net, cfg->fc_mx, cfg->fc_mx_len,
+                                              extack);
        if (IS_ERR(rt->fib6_metrics)) {
                err = PTR_ERR(rt->fib6_metrics);
                /* Do not leave garbage there. */
@@ -3708,7 +3709,7 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
        if (!f6i)
                return ERR_PTR(-ENOMEM);
 
-       f6i->fib6_metrics = ip_fib_metrics_init(net, NULL, 0);
+       f6i->fib6_metrics = ip_fib_metrics_init(net, NULL, 0, NULL);
        f6i->dst_nocount = true;
        f6i->dst_host = true;
        f6i->fib6_protocol = RTPROT_KERNEL;