Commit 58d7d8f9b20ee6f883532b952f246e4289fe06eb
Committed by
David S. Miller
1 parent
9b924dbd5e
Exists in
master
and in
20 other branches
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); |
net/decnet/dn_fib.c
... | ... | @@ -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 |