Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thomas Graf and committed by
David S. Miller
58d7d8f9 9b924dbd

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