Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / decnet / dn_route.c
index 5ac0e153ef834ee04e46fab749e3d5e69a190f2d..fe32388ea24f7cc6811ea17ee3fb8d9f47042ee7 100644 (file)
@@ -1613,23 +1613,41 @@ errout:
        return -EMSGSIZE;
 }
 
+const struct nla_policy rtm_dn_policy[RTA_MAX + 1] = {
+       [RTA_DST]               = { .type = NLA_U16 },
+       [RTA_SRC]               = { .type = NLA_U16 },
+       [RTA_IIF]               = { .type = NLA_U32 },
+       [RTA_OIF]               = { .type = NLA_U32 },
+       [RTA_GATEWAY]           = { .type = NLA_U16 },
+       [RTA_PRIORITY]          = { .type = NLA_U32 },
+       [RTA_PREFSRC]           = { .type = NLA_U16 },
+       [RTA_METRICS]           = { .type = NLA_NESTED },
+       [RTA_MULTIPATH]         = { .type = NLA_NESTED },
+       [RTA_TABLE]             = { .type = NLA_U32 },
+       [RTA_MARK]              = { .type = NLA_U32 },
+};
+
 /*
  * This is called by both endnodes and routers now.
  */
-static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 {
        struct net *net = sock_net(in_skb->sk);
-       struct rtattr **rta = arg;
        struct rtmsg *rtm = nlmsg_data(nlh);
        struct dn_route *rt = NULL;
        struct dn_skb_cb *cb;
        int err;
        struct sk_buff *skb;
        struct flowidn fld;
+       struct nlattr *tb[RTA_MAX+1];
 
        if (!net_eq(net, &init_net))
                return -EINVAL;
 
+       err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_dn_policy);
+       if (err < 0)
+               return err;
+
        memset(&fld, 0, sizeof(fld));
        fld.flowidn_proto = DNPROTO_NSP;
 
@@ -1639,12 +1657,14 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
        skb_reset_mac_header(skb);
        cb = DN_SKB_CB(skb);
 
-       if (rta[RTA_SRC-1])
-               memcpy(&fld.saddr, RTA_DATA(rta[RTA_SRC-1]), 2);
-       if (rta[RTA_DST-1])
-               memcpy(&fld.daddr, RTA_DATA(rta[RTA_DST-1]), 2);
-       if (rta[RTA_IIF-1])
-               memcpy(&fld.flowidn_iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
+       if (tb[RTA_SRC])
+               fld.saddr = nla_get_le16(tb[RTA_SRC]);
+
+       if (tb[RTA_DST])
+               fld.daddr = nla_get_le16(tb[RTA_DST]);
+
+       if (tb[RTA_IIF])
+               fld.flowidn_iif = nla_get_u32(tb[RTA_IIF]);
 
        if (fld.flowidn_iif) {
                struct net_device *dev;
@@ -1669,10 +1689,9 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
                if (!err && -rt->dst.error)
                        err = rt->dst.error;
        } else {
-               int oif = 0;
-               if (rta[RTA_OIF - 1])
-                       memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
-               fld.flowidn_oif = oif;
+               if (tb[RTA_OIF])
+                       fld.flowidn_oif = nla_get_u32(tb[RTA_OIF]);
+
                err = dn_route_output_key((struct dst_entry **)&rt, &fld, 0);
        }