]> Pileus Git - ~andy/linux/blobdiff - net/decnet/dn_table.c
decnet: Parse netlink attributes on our own
[~andy/linux] / net / decnet / dn_table.c
index f968c1b58f47d1892ee392eea366d67f4c687397..fc42a0afd306a84947abfb828f875a9c2db75cb0 100644 (file)
@@ -224,26 +224,27 @@ static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
 }
 
 
-static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern_rta *rta, struct dn_fib_info *fi)
+static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct nlattr *attrs[], struct dn_fib_info *fi)
 {
        struct rtnexthop *nhp;
        int nhlen;
 
-       if (rta->rta_priority && *rta->rta_priority != fi->fib_priority)
+       if (attrs[RTA_PRIORITY] &&
+           nla_get_u32(attrs[RTA_PRIORITY]) != fi->fib_priority)
                return 1;
 
-       if (rta->rta_oif || rta->rta_gw) {
-               if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
-                   (!rta->rta_gw  || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 2) == 0))
+       if (attrs[RTA_OIF] || attrs[RTA_GATEWAY]) {
+               if ((!attrs[RTA_OIF] || nla_get_u32(attrs[RTA_OIF]) == fi->fib_nh->nh_oif) &&
+                   (!attrs[RTA_GATEWAY]  || nla_get_le16(attrs[RTA_GATEWAY]) != fi->fib_nh->nh_gw))
                        return 0;
                return 1;
        }
 
-       if (rta->rta_mp == NULL)
+       if (!attrs[RTA_MULTIPATH])
                return 0;
 
-       nhp = RTA_DATA(rta->rta_mp);
-       nhlen = RTA_PAYLOAD(rta->rta_mp);
+       nhp = nla_data(attrs[RTA_MULTIPATH]);
+       nhlen = nla_len(attrs[RTA_MULTIPATH]);
 
        for_nexthops(fi) {
                int attrlen = nhlen - sizeof(struct rtnexthop);
@@ -254,7 +255,10 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
                if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
                        return 1;
                if (attrlen) {
-                       gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+                       struct nlattr *gw_attr;
+
+                       gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
+                       gw = gw_attr ? nla_get_le16(gw_attr) : 0;
 
                        if (gw && gw != nh->nh_gw)
                                return 1;
@@ -483,7 +487,6 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned int h, s_h;
        unsigned int e = 0, s_e;
        struct dn_fib_table *tb;
-       struct hlist_node *node;
        int dumped = 0;
 
        if (!net_eq(net, &init_net))
@@ -498,7 +501,7 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
        for (h = s_h; h < DN_FIB_TABLE_HASHSZ; h++, s_h = 0) {
                e = 0;
-               hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist) {
+               hlist_for_each_entry(tb, &dn_fib_table_hash[h], hlist) {
                        if (e < s_e)
                                goto next;
                        if (dumped)
@@ -518,7 +521,8 @@ out:
        return skb->len;
 }
 
-static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
+static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
+                              struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
        struct dn_hash *table = (struct dn_hash *)tb->data;
        struct dn_fib_node *new_f, *f, **fp, **del_fp;
@@ -537,15 +541,14 @@ static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct
                return -ENOBUFS;
 
        dz_key_0(key);
-       if (rta->rta_dst) {
-               __le16 dst;
-               memcpy(&dst, rta->rta_dst, 2);
+       if (attrs[RTA_DST]) {
+               __le16 dst = nla_get_le16(attrs[RTA_DST]);
                if (dst & ~DZ_MASK(dz))
                        return -EINVAL;
                key = dz_key(dst, dz);
        }
 
-       if ((fi = dn_fib_create_info(r, rta, n, &err)) == NULL)
+       if ((fi = dn_fib_create_info(r, attrs, n, &err)) == NULL)
                return err;
 
        if (dz->dz_nent > (dz->dz_divisor << 2) &&
@@ -655,7 +658,8 @@ out:
 }
 
 
-static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
+static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
+                              struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
        struct dn_hash *table = (struct dn_hash*)tb->data;
        struct dn_fib_node **fp, **del_fp, *f;
@@ -672,9 +676,8 @@ static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct
                return -ESRCH;
 
        dz_key_0(key);
-       if (rta->rta_dst) {
-               __le16 dst;
-               memcpy(&dst, rta->rta_dst, 2);
+       if (attrs[RTA_DST]) {
+               __le16 dst = nla_get_le16(attrs[RTA_DST]);
                if (dst & ~DZ_MASK(dz))
                        return -EINVAL;
                key = dz_key(dst, dz);
@@ -704,7 +707,7 @@ static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct
                                (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
                                (!r->rtm_protocol ||
                                        fi->fib_protocol == r->rtm_protocol) &&
-                               dn_fib_nh_match(r, n, rta, fi) == 0)
+                               dn_fib_nh_match(r, n, attrs, fi) == 0)
                        del_fp = fp;
        }
 
@@ -828,7 +831,6 @@ out:
 struct dn_fib_table *dn_fib_get_table(u32 n, int create)
 {
        struct dn_fib_table *t;
-       struct hlist_node *node;
        unsigned int h;
 
        if (n < RT_TABLE_MIN)
@@ -839,7 +841,7 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
 
        h = n & (DN_FIB_TABLE_HASHSZ - 1);
        rcu_read_lock();
-       hlist_for_each_entry_rcu(t, node, &dn_fib_table_hash[h], hlist) {
+       hlist_for_each_entry_rcu(t, &dn_fib_table_hash[h], hlist) {
                if (t->n == n) {
                        rcu_read_unlock();
                        return t;
@@ -885,11 +887,10 @@ void dn_fib_flush(void)
 {
        int flushed = 0;
        struct dn_fib_table *tb;
-       struct hlist_node *node;
        unsigned int h;
 
        for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
-               hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist)
+               hlist_for_each_entry(tb, &dn_fib_table_hash[h], hlist)
                        flushed += tb->flush(tb);
        }
 
@@ -908,12 +909,12 @@ void __init dn_fib_table_init(void)
 void __exit dn_fib_table_cleanup(void)
 {
        struct dn_fib_table *t;
-       struct hlist_node *node, *next;
+       struct hlist_node *next;
        unsigned int h;
 
        write_lock(&dn_fib_tables_lock);
        for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
-               hlist_for_each_entry_safe(t, node, next, &dn_fib_table_hash[h],
+               hlist_for_each_entry_safe(t, next, &dn_fib_table_hash[h],
                                          hlist) {
                        hlist_del(&t->hlist);
                        kfree(t);