Commit 58d7d8f9b20ee6f883532b952f246e4289fe06eb

Authored by Thomas Graf
Committed by David S. Miller
1 parent 9b924dbd5e

decnet: Parse netlink attributes on our own

decnet is the only subsystem left that is relying on the global
netlink attribute buffer rta_buf. It's horrible design and we
want to get rid of it.

This converts all of decnet to do implicit attribute parsing. It
also gets rid of the error prone struct dn_kern_rta.

Yes, the fib_magic() stuff is not pretty.

It's compiled tested but I need someone with appropriate hardware
to test the patch since I don't have access to it.

Cc: linux-decnet-user@lists.sourceforge.net
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 4 changed files with 160 additions and 148 deletions Side-by-side Diff

include/net/dn_fib.h
1 1 #ifndef _NET_DN_FIB_H
2 2 #define _NET_DN_FIB_H
3 3  
4   -/* WARNING: The ordering of these elements must match ordering
5   - * of RTA_* rtnetlink attribute numbers.
6   - */
7   -struct dn_kern_rta {
8   - void *rta_dst;
9   - void *rta_src;
10   - int *rta_iif;
11   - int *rta_oif;
12   - void *rta_gw;
13   - u32 *rta_priority;
14   - void *rta_prefsrc;
15   - struct rtattr *rta_mx;
16   - struct rtattr *rta_mp;
17   - unsigned char *rta_protoinfo;
18   - u32 *rta_flow;
19   - struct rta_cacheinfo *rta_ci;
20   - struct rta_session *rta_sess;
21   -};
  4 +#include <linux/netlink.h>
22 5  
  6 +extern const struct nla_policy rtm_dn_policy[];
  7 +
23 8 struct dn_fib_res {
24 9 struct fib_rule *r;
25 10 struct dn_fib_info *fi;
26 11  
... ... @@ -93,10 +78,10 @@
93 78 u32 n;
94 79  
95 80 int (*insert)(struct dn_fib_table *t, struct rtmsg *r,
96   - struct dn_kern_rta *rta, struct nlmsghdr *n,
  81 + struct nlattr *attrs[], struct nlmsghdr *n,
97 82 struct netlink_skb_parms *req);
98 83 int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
99   - struct dn_kern_rta *rta, struct nlmsghdr *n,
  84 + struct nlattr *attrs[], struct nlmsghdr *n,
100 85 struct netlink_skb_parms *req);
101 86 int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
102 87 struct dn_fib_res *res);
103 88  
... ... @@ -116,13 +101,12 @@
116 101 extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd,
117 102 unsigned long arg);
118 103 extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
119   - struct dn_kern_rta *rta,
  104 + struct nlattr *attrs[],
120 105 const struct nlmsghdr *nlh, int *errp);
121 106 extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
122 107 const struct flowidn *fld,
123 108 struct dn_fib_res *res);
124 109 extern void dn_fib_release_info(struct dn_fib_info *fi);
125   -extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
126 110 extern void dn_fib_flush(void);
127 111 extern void dn_fib_select_multipath(const struct flowidn *fld,
128 112 struct dn_fib_res *res);
... ... @@ -145,23 +145,11 @@
145 145 return NULL;
146 146 }
147 147  
148   -__le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type)
  148 +static int dn_fib_count_nhs(const struct nlattr *attr)
149 149 {
150   - while(RTA_OK(attr,attrlen)) {
151   - if (attr->rta_type == type)
152   - return *(__le16*)RTA_DATA(attr);
153   - attr = RTA_NEXT(attr, attrlen);
154   - }
  150 + struct rtnexthop *nhp = nla_data(attr);
  151 + int nhs = 0, nhlen = nla_len(attr);
155 152  
156   - return 0;
157   -}
158   -
159   -static int dn_fib_count_nhs(struct rtattr *rta)
160   -{
161   - int nhs = 0;
162   - struct rtnexthop *nhp = RTA_DATA(rta);
163   - int nhlen = RTA_PAYLOAD(rta);
164   -
165 153 while(nhlen >= (int)sizeof(struct rtnexthop)) {
166 154 if ((nhlen -= nhp->rtnh_len) < 0)
167 155 return 0;
168 156  
... ... @@ -172,10 +160,11 @@
172 160 return nhs;
173 161 }
174 162  
175   -static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct rtattr *rta, const struct rtmsg *r)
  163 +static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr,
  164 + const struct rtmsg *r)
176 165 {
177   - struct rtnexthop *nhp = RTA_DATA(rta);
178   - int nhlen = RTA_PAYLOAD(rta);
  166 + struct rtnexthop *nhp = nla_data(attr);
  167 + int nhlen = nla_len(attr);
179 168  
180 169 change_nexthops(fi) {
181 170 int attrlen = nhlen - sizeof(struct rtnexthop);
... ... @@ -187,7 +176,10 @@
187 176 nh->nh_weight = nhp->rtnh_hops + 1;
188 177  
189 178 if (attrlen) {
190   - nh->nh_gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
  179 + struct nlattr *gw_attr;
  180 +
  181 + gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
  182 + nh->nh_gw = gw_attr ? nla_get_le16(gw_attr) : 0;
191 183 }
192 184 nhp = RTNH_NEXT(nhp);
193 185 } endfor_nexthops(fi);
... ... @@ -268,7 +260,8 @@
268 260 }
269 261  
270 262  
271   -struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta *rta, const struct nlmsghdr *nlh, int *errp)
  263 +struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct nlattr *attrs[],
  264 + const struct nlmsghdr *nlh, int *errp)
272 265 {
273 266 int err;
274 267 struct dn_fib_info *fi = NULL;
... ... @@ -281,11 +274,9 @@
281 274 if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
282 275 goto err_inval;
283 276  
284   - if (rta->rta_mp) {
285   - nhs = dn_fib_count_nhs(rta->rta_mp);
286   - if (nhs == 0)
287   - goto err_inval;
288   - }
  277 + if (attrs[RTA_MULTIPATH] &&
  278 + (nhs = dn_fib_count_nhs(attrs[RTA_MULTIPATH])) == 0)
  279 + goto err_inval;
289 280  
290 281 fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL);
291 282 err = -ENOBUFS;
292 283  
293 284  
294 285  
295 286  
296 287  
297 288  
298 289  
299 290  
300 291  
301 292  
302 293  
303 294  
304 295  
... ... @@ -295,53 +286,65 @@
295 286 fi->fib_protocol = r->rtm_protocol;
296 287 fi->fib_nhs = nhs;
297 288 fi->fib_flags = r->rtm_flags;
298   - if (rta->rta_priority)
299   - fi->fib_priority = *rta->rta_priority;
300   - if (rta->rta_mx) {
301   - int attrlen = RTA_PAYLOAD(rta->rta_mx);
302   - struct rtattr *attr = RTA_DATA(rta->rta_mx);
303 289  
304   - while(RTA_OK(attr, attrlen)) {
305   - unsigned int flavour = attr->rta_type;
  290 + if (attrs[RTA_PRIORITY])
  291 + fi->fib_priority = nla_get_u32(attrs[RTA_PRIORITY]);
306 292  
307   - if (flavour) {
308   - if (flavour > RTAX_MAX)
  293 + if (attrs[RTA_METRICS]) {
  294 + struct nlattr *attr;
  295 + int rem;
  296 +
  297 + nla_for_each_nested(attr, attrs[RTA_METRICS], rem) {
  298 + int type = nla_type(attr);
  299 +
  300 + if (type) {
  301 + if (type > RTAX_MAX || nla_len(attr) < 4)
309 302 goto err_inval;
310   - fi->fib_metrics[flavour-1] = *(unsigned int *)RTA_DATA(attr);
  303 +
  304 + fi->fib_metrics[type-1] = nla_get_u32(attr);
311 305 }
312   - attr = RTA_NEXT(attr, attrlen);
313 306 }
314 307 }
315   - if (rta->rta_prefsrc)
316   - memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 2);
317 308  
318   - if (rta->rta_mp) {
319   - if ((err = dn_fib_get_nhs(fi, rta->rta_mp, r)) != 0)
  309 + if (attrs[RTA_PREFSRC])
  310 + fi->fib_prefsrc = nla_get_le16(attrs[RTA_PREFSRC]);
  311 +
  312 + if (attrs[RTA_MULTIPATH]) {
  313 + if ((err = dn_fib_get_nhs(fi, attrs[RTA_MULTIPATH], r)) != 0)
320 314 goto failure;
321   - if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif)
  315 +
  316 + if (attrs[RTA_OIF] &&
  317 + fi->fib_nh->nh_oif != nla_get_u32(attrs[RTA_OIF]))
322 318 goto err_inval;
323   - if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 2))
  319 +
  320 + if (attrs[RTA_GATEWAY] &&
  321 + fi->fib_nh->nh_gw != nla_get_le16(attrs[RTA_GATEWAY]))
324 322 goto err_inval;
325 323 } else {
326 324 struct dn_fib_nh *nh = fi->fib_nh;
327   - if (rta->rta_oif)
328   - nh->nh_oif = *rta->rta_oif;
329   - if (rta->rta_gw)
330   - memcpy(&nh->nh_gw, rta->rta_gw, 2);
  325 +
  326 + if (attrs[RTA_OIF])
  327 + nh->nh_oif = nla_get_u32(attrs[RTA_OIF]);
  328 +
  329 + if (attrs[RTA_GATEWAY])
  330 + nh->nh_gw = nla_get_le16(attrs[RTA_GATEWAY]);
  331 +
331 332 nh->nh_flags = r->rtm_flags;
332 333 nh->nh_weight = 1;
333 334 }
334 335  
335 336 if (r->rtm_type == RTN_NAT) {
336   - if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
  337 + if (!attrs[RTA_GATEWAY] || nhs != 1 || attrs[RTA_OIF])
337 338 goto err_inval;
338   - memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 2);
  339 +
  340 + fi->fib_nh->nh_gw = nla_get_le16(attrs[RTA_GATEWAY]);
339 341 goto link_it;
340 342 }
341 343  
342 344 if (dn_fib_props[r->rtm_type].error) {
343   - if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
  345 + if (attrs[RTA_GATEWAY] || attrs[RTA_OIF] || attrs[RTA_MULTIPATH])
344 346 goto err_inval;
  347 +
345 348 goto link_it;
346 349 }
347 350  
... ... @@ -367,8 +370,8 @@
367 370 }
368 371  
369 372 if (fi->fib_prefsrc) {
370   - if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
371   - memcmp(&fi->fib_prefsrc, rta->rta_dst, 2))
  373 + if (r->rtm_type != RTN_LOCAL || !attrs[RTA_DST] ||
  374 + fi->fib_prefsrc != nla_get_le16(attrs[RTA_DST]))
372 375 if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
373 376 goto err_inval;
374 377 }
375 378  
376 379  
377 380  
... ... @@ -486,30 +489,25 @@
486 489 spin_unlock_bh(&dn_fib_multipath_lock);
487 490 }
488 491  
  492 +const struct nla_policy rtm_dn_policy[RTA_MAX + 1] = {
  493 + [RTA_DST] = { .type = NLA_U16 },
  494 + [RTA_SRC] = { .type = NLA_U16 },
  495 + [RTA_IIF] = { .type = NLA_U32 },
  496 + [RTA_OIF] = { .type = NLA_U32 },
  497 + [RTA_GATEWAY] = { .type = NLA_U16 },
  498 + [RTA_PRIORITY] = { .type = NLA_U32 },
  499 + [RTA_PREFSRC] = { .type = NLA_U16 },
  500 + [RTA_METRICS] = { .type = NLA_NESTED },
  501 + [RTA_MULTIPATH] = { .type = NLA_NESTED },
  502 + [RTA_TABLE] = { .type = NLA_U32 },
  503 + [RTA_MARK] = { .type = NLA_U32 },
  504 +};
489 505  
490   -static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
  506 +static inline u32 rtm_get_table(struct nlattr *attrs[], u8 table)
491 507 {
492   - int i;
  508 + if (attrs[RTA_TABLE])
  509 + table = nla_get_u32(attrs[RTA_TABLE]);
493 510  
494   - for(i = 1; i <= RTA_MAX; i++) {
495   - struct rtattr *attr = rta[i-1];
496   - if (attr) {
497   - if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
498   - return -EINVAL;
499   - if (i != RTA_MULTIPATH && i != RTA_METRICS &&
500   - i != RTA_TABLE)
501   - rta[i-1] = (struct rtattr *)RTA_DATA(attr);
502   - }
503   - }
504   -
505   - return 0;
506   -}
507   -
508   -static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
509   -{
510   - if (rta[RTA_TABLE - 1])
511   - table = nla_get_u32((struct nlattr *) rta[RTA_TABLE - 1]);
512   -
513 511 return table;
514 512 }
515 513  
... ... @@ -517,8 +515,9 @@
517 515 {
518 516 struct net *net = sock_net(skb->sk);
519 517 struct dn_fib_table *tb;
520   - struct rtattr **rta = arg;
521   - struct rtmsg *r = NLMSG_DATA(nlh);
  518 + struct rtmsg *r = nlmsg_data(nlh);
  519 + struct nlattr *attrs[RTA_MAX+1];
  520 + int err;
522 521  
523 522 if (!capable(CAP_NET_ADMIN))
524 523 return -EPERM;
525 524  
526 525  
527 526  
... ... @@ -526,22 +525,24 @@
526 525 if (!net_eq(net, &init_net))
527 526 return -EINVAL;
528 527  
529   - if (dn_fib_check_attr(r, rta))
530   - return -EINVAL;
  528 + err = nlmsg_parse(nlh, sizeof(*r), attrs, RTA_MAX, rtm_dn_policy);
  529 + if (err < 0)
  530 + return err;
531 531  
532   - tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
533   - if (tb)
534   - return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
  532 + tb = dn_fib_get_table(rtm_get_table(attrs, r->rtm_table), 0);
  533 + if (!tb)
  534 + return -ESRCH;
535 535  
536   - return -ESRCH;
  536 + return tb->delete(tb, r, attrs, nlh, &NETLINK_CB(skb));
537 537 }
538 538  
539 539 static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
540 540 {
541 541 struct net *net = sock_net(skb->sk);
542 542 struct dn_fib_table *tb;
543   - struct rtattr **rta = arg;
544   - struct rtmsg *r = NLMSG_DATA(nlh);
  543 + struct rtmsg *r = nlmsg_data(nlh);
  544 + struct nlattr *attrs[RTA_MAX+1];
  545 + int err;
545 546  
546 547 if (!capable(CAP_NET_ADMIN))
547 548 return -EPERM;
548 549  
549 550  
... ... @@ -549,14 +550,15 @@
549 550 if (!net_eq(net, &init_net))
550 551 return -EINVAL;
551 552  
552   - if (dn_fib_check_attr(r, rta))
553   - return -EINVAL;
  553 + err = nlmsg_parse(nlh, sizeof(*r), attrs, RTA_MAX, rtm_dn_policy);
  554 + if (err < 0)
  555 + return err;
554 556  
555   - tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
556   - if (tb)
557   - return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
  557 + tb = dn_fib_get_table(rtm_get_table(attrs, r->rtm_table), 1);
  558 + if (!tb)
  559 + return -ENOBUFS;
558 560  
559   - return -ENOBUFS;
  561 + return tb->insert(tb, r, attrs, nlh, &NETLINK_CB(skb));
560 562 }
561 563  
562 564 static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
563 565  
... ... @@ -566,10 +568,31 @@
566 568 struct nlmsghdr nlh;
567 569 struct rtmsg rtm;
568 570 } req;
569   - struct dn_kern_rta rta;
  571 + struct {
  572 + struct nlattr hdr;
  573 + __le16 dst;
  574 + } dst_attr = {
  575 + .dst = dst,
  576 + };
  577 + struct {
  578 + struct nlattr hdr;
  579 + __le16 prefsrc;
  580 + } prefsrc_attr = {
  581 + .prefsrc = ifa->ifa_local,
  582 + };
  583 + struct {
  584 + struct nlattr hdr;
  585 + u32 oif;
  586 + } oif_attr = {
  587 + .oif = ifa->ifa_dev->dev->ifindex,
  588 + };
  589 + struct nlattr *attrs[RTA_MAX+1] = {
  590 + [RTA_DST] = (struct nlattr *) &dst_attr,
  591 + [RTA_PREFSRC] = (struct nlattr * ) &prefsrc_attr,
  592 + [RTA_OIF] = (struct nlattr *) &oif_attr,
  593 + };
570 594  
571 595 memset(&req.rtm, 0, sizeof(req.rtm));
572   - memset(&rta, 0, sizeof(rta));
573 596  
574 597 if (type == RTN_UNICAST)
575 598 tb = dn_fib_get_table(RT_MIN_TABLE, 1);
576 599  
577 600  
... ... @@ -591,14 +614,10 @@
591 614 req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
592 615 req.rtm.rtm_type = type;
593 616  
594   - rta.rta_dst = &dst;
595   - rta.rta_prefsrc = &ifa->ifa_local;
596   - rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
597   -
598 617 if (cmd == RTM_NEWROUTE)
599   - tb->insert(tb, &req.rtm, &rta, &req.nlh, NULL);
  618 + tb->insert(tb, &req.rtm, attrs, &req.nlh, NULL);
600 619 else
601   - tb->delete(tb, &req.rtm, &rta, &req.nlh, NULL);
  620 + tb->delete(tb, &req.rtm, attrs, &req.nlh, NULL);
602 621 }
603 622  
604 623 static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa)
net/decnet/dn_route.c
... ... @@ -1619,17 +1619,21 @@
1619 1619 static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
1620 1620 {
1621 1621 struct net *net = sock_net(in_skb->sk);
1622   - struct rtattr **rta = arg;
1623 1622 struct rtmsg *rtm = nlmsg_data(nlh);
1624 1623 struct dn_route *rt = NULL;
1625 1624 struct dn_skb_cb *cb;
1626 1625 int err;
1627 1626 struct sk_buff *skb;
1628 1627 struct flowidn fld;
  1628 + struct nlattr *tb[RTA_MAX+1];
1629 1629  
1630 1630 if (!net_eq(net, &init_net))
1631 1631 return -EINVAL;
1632 1632  
  1633 + err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_dn_policy);
  1634 + if (err < 0)
  1635 + return err;
  1636 +
1633 1637 memset(&fld, 0, sizeof(fld));
1634 1638 fld.flowidn_proto = DNPROTO_NSP;
1635 1639  
1636 1640  
... ... @@ -1639,13 +1643,15 @@
1639 1643 skb_reset_mac_header(skb);
1640 1644 cb = DN_SKB_CB(skb);
1641 1645  
1642   - if (rta[RTA_SRC-1])
1643   - memcpy(&fld.saddr, RTA_DATA(rta[RTA_SRC-1]), 2);
1644   - if (rta[RTA_DST-1])
1645   - memcpy(&fld.daddr, RTA_DATA(rta[RTA_DST-1]), 2);
1646   - if (rta[RTA_IIF-1])
1647   - memcpy(&fld.flowidn_iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
  1646 + if (tb[RTA_SRC])
  1647 + fld.saddr = nla_get_le16(tb[RTA_SRC]);
1648 1648  
  1649 + if (tb[RTA_DST])
  1650 + fld.daddr = nla_get_le16(tb[RTA_DST]);
  1651 +
  1652 + if (tb[RTA_IIF])
  1653 + fld.flowidn_iif = nla_get_u32(tb[RTA_IIF]);
  1654 +
1649 1655 if (fld.flowidn_iif) {
1650 1656 struct net_device *dev;
1651 1657 if ((dev = dev_get_by_index(&init_net, fld.flowidn_iif)) == NULL) {
... ... @@ -1669,10 +1675,9 @@
1669 1675 if (!err && -rt->dst.error)
1670 1676 err = rt->dst.error;
1671 1677 } else {
1672   - int oif = 0;
1673   - if (rta[RTA_OIF - 1])
1674   - memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
1675   - fld.flowidn_oif = oif;
  1678 + if (tb[RTA_OIF])
  1679 + fld.flowidn_oif = nla_get_u32(tb[RTA_OIF]);
  1680 +
1676 1681 err = dn_route_output_key((struct dst_entry **)&rt, &fld, 0);
1677 1682 }
1678 1683  
net/decnet/dn_table.c
... ... @@ -224,26 +224,27 @@
224 224 }
225 225  
226 226  
227   -static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern_rta *rta, struct dn_fib_info *fi)
  227 +static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct nlattr *attrs[], struct dn_fib_info *fi)
228 228 {
229 229 struct rtnexthop *nhp;
230 230 int nhlen;
231 231  
232   - if (rta->rta_priority && *rta->rta_priority != fi->fib_priority)
  232 + if (attrs[RTA_PRIORITY] &&
  233 + nla_get_u32(attrs[RTA_PRIORITY]) != fi->fib_priority)
233 234 return 1;
234 235  
235   - if (rta->rta_oif || rta->rta_gw) {
236   - if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
237   - (!rta->rta_gw || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 2) == 0))
  236 + if (attrs[RTA_OIF] || attrs[RTA_GATEWAY]) {
  237 + if ((!attrs[RTA_OIF] || nla_get_u32(attrs[RTA_OIF]) == fi->fib_nh->nh_oif) &&
  238 + (!attrs[RTA_GATEWAY] || nla_get_le16(attrs[RTA_GATEWAY]) != fi->fib_nh->nh_gw))
238 239 return 0;
239 240 return 1;
240 241 }
241 242  
242   - if (rta->rta_mp == NULL)
  243 + if (!attrs[RTA_MULTIPATH])
243 244 return 0;
244 245  
245   - nhp = RTA_DATA(rta->rta_mp);
246   - nhlen = RTA_PAYLOAD(rta->rta_mp);
  246 + nhp = nla_data(attrs[RTA_MULTIPATH]);
  247 + nhlen = nla_len(attrs[RTA_MULTIPATH]);
247 248  
248 249 for_nexthops(fi) {
249 250 int attrlen = nhlen - sizeof(struct rtnexthop);
250 251  
... ... @@ -254,8 +255,11 @@
254 255 if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
255 256 return 1;
256 257 if (attrlen) {
257   - gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
  258 + struct nlattr *gw_attr;
258 259  
  260 + gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
  261 + gw = gw_attr ? nla_get_le16(gw_attr) : 0;
  262 +
259 263 if (gw && gw != nh->nh_gw)
260 264 return 1;
261 265 }
... ... @@ -517,7 +521,8 @@
517 521 return skb->len;
518 522 }
519 523  
520   -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)
  524 +static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
  525 + struct nlmsghdr *n, struct netlink_skb_parms *req)
521 526 {
522 527 struct dn_hash *table = (struct dn_hash *)tb->data;
523 528 struct dn_fib_node *new_f, *f, **fp, **del_fp;
524 529  
... ... @@ -536,15 +541,14 @@
536 541 return -ENOBUFS;
537 542  
538 543 dz_key_0(key);
539   - if (rta->rta_dst) {
540   - __le16 dst;
541   - memcpy(&dst, rta->rta_dst, 2);
  544 + if (attrs[RTA_DST]) {
  545 + __le16 dst = nla_get_le16(attrs[RTA_DST]);
542 546 if (dst & ~DZ_MASK(dz))
543 547 return -EINVAL;
544 548 key = dz_key(dst, dz);
545 549 }
546 550  
547   - if ((fi = dn_fib_create_info(r, rta, n, &err)) == NULL)
  551 + if ((fi = dn_fib_create_info(r, attrs, n, &err)) == NULL)
548 552 return err;
549 553  
550 554 if (dz->dz_nent > (dz->dz_divisor << 2) &&
... ... @@ -654,7 +658,8 @@
654 658 }
655 659  
656 660  
657   -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)
  661 +static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
  662 + struct nlmsghdr *n, struct netlink_skb_parms *req)
658 663 {
659 664 struct dn_hash *table = (struct dn_hash*)tb->data;
660 665 struct dn_fib_node **fp, **del_fp, *f;
... ... @@ -671,9 +676,8 @@
671 676 return -ESRCH;
672 677  
673 678 dz_key_0(key);
674   - if (rta->rta_dst) {
675   - __le16 dst;
676   - memcpy(&dst, rta->rta_dst, 2);
  679 + if (attrs[RTA_DST]) {
  680 + __le16 dst = nla_get_le16(attrs[RTA_DST]);
677 681 if (dst & ~DZ_MASK(dz))
678 682 return -EINVAL;
679 683 key = dz_key(dst, dz);
... ... @@ -703,7 +707,7 @@
703 707 (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
704 708 (!r->rtm_protocol ||
705 709 fi->fib_protocol == r->rtm_protocol) &&
706   - dn_fib_nh_match(r, n, rta, fi) == 0)
  710 + dn_fib_nh_match(r, n, attrs, fi) == 0)
707 711 del_fp = fp;
708 712 }
709 713