route.c (5d0bbeeb144f631150881712607345c532e38e7e) | route.c (c71099acce933455123ee505cc75964610a209ad) |
---|---|
1/* 2 * Linux INET6 implementation 3 * FIB front-end. 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $ --- 126 unchanged lines hidden (view full) --- 135 .path = (struct dst_entry*)&ip6_null_entry, 136 } 137 }, 138 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 139 .rt6i_metric = ~(u32) 0, 140 .rt6i_ref = ATOMIC_INIT(1), 141}; 142 | 1/* 2 * Linux INET6 implementation 3 * FIB front-end. 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $ --- 126 unchanged lines hidden (view full) --- 135 .path = (struct dst_entry*)&ip6_null_entry, 136 } 137 }, 138 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 139 .rt6i_metric = ~(u32) 0, 140 .rt6i_ref = ATOMIC_INIT(1), 141}; 142 |
143struct fib6_node ip6_routing_table = { 144 .leaf = &ip6_null_entry, 145 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, 146}; 147 148/* Protects all the ip6 fib */ 149 150DEFINE_RWLOCK(rt6_lock); 151 152 | |
153/* allocate dst with ip6_dst_ops */ 154static __inline__ struct rt6_info *ip6_dst_alloc(void) 155{ 156 return (struct rt6_info *)dst_alloc(&ip6_dst_ops); 157} 158 159static void ip6_dst_destroy(struct dst_entry *dst) 160{ --- 22 unchanged lines hidden (view full) --- 183} 184 185static __inline__ int rt6_check_expired(const struct rt6_info *rt) 186{ 187 return (rt->rt6i_flags & RTF_EXPIRES && 188 time_after(jiffies, rt->rt6i_expires)); 189} 190 | 143/* allocate dst with ip6_dst_ops */ 144static __inline__ struct rt6_info *ip6_dst_alloc(void) 145{ 146 return (struct rt6_info *)dst_alloc(&ip6_dst_ops); 147} 148 149static void ip6_dst_destroy(struct dst_entry *dst) 150{ --- 22 unchanged lines hidden (view full) --- 173} 174 175static __inline__ int rt6_check_expired(const struct rt6_info *rt) 176{ 177 return (rt->rt6i_flags & RTF_EXPIRES && 178 time_after(jiffies, rt->rt6i_expires)); 179} 180 |
181static inline int rt6_need_strict(struct in6_addr *daddr) 182{ 183 return (ipv6_addr_type(daddr) & 184 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); 185} 186 |
|
191/* | 187/* |
192 * Route lookup. Any rt6_lock is implied. | 188 * Route lookup. Any table->tb6_lock is implied. |
193 */ 194 195static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, 196 int oif, 197 int strict) 198{ 199 struct rt6_info *local = NULL; 200 struct rt6_info *sprt; --- 235 unchanged lines hidden (view full) --- 436 rt->rt6i_flags |= RTF_EXPIRES; 437 } 438 dst_release(&rt->u.dst); 439 } 440 return 0; 441} 442#endif 443 | 189 */ 190 191static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, 192 int oif, 193 int strict) 194{ 195 struct rt6_info *local = NULL; 196 struct rt6_info *sprt; --- 235 unchanged lines hidden (view full) --- 432 rt->rt6i_flags |= RTF_EXPIRES; 433 } 434 dst_release(&rt->u.dst); 435 } 436 return 0; 437} 438#endif 439 |
444struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, 445 int oif, int strict) | 440#define BACKTRACK() \ 441if (rt == &ip6_null_entry && flags & RT6_F_STRICT) { \ 442 while ((fn = fn->parent) != NULL) { \ 443 if (fn->fn_flags & RTN_TL_ROOT) { \ 444 dst_hold(&rt->u.dst); \ 445 goto out; \ 446 } \ 447 if (fn->fn_flags & RTN_RTINFO) \ 448 goto restart; \ 449 } \ 450} 451 452static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, 453 struct flowi *fl, int flags) |
446{ 447 struct fib6_node *fn; 448 struct rt6_info *rt; 449 | 454{ 455 struct fib6_node *fn; 456 struct rt6_info *rt; 457 |
450 read_lock_bh(&rt6_lock); 451 fn = fib6_lookup(&ip6_routing_table, daddr, saddr); 452 rt = rt6_device_match(fn->leaf, oif, strict); | 458 read_lock_bh(&table->tb6_lock); 459 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); 460restart: 461 rt = fn->leaf; 462 rt = rt6_device_match(rt, fl->oif, flags & RT6_F_STRICT); 463 BACKTRACK(); |
453 dst_hold(&rt->u.dst); | 464 dst_hold(&rt->u.dst); |
454 rt->u.dst.__use++; 455 read_unlock_bh(&rt6_lock); | 465out: 466 read_unlock_bh(&table->tb6_lock); |
456 457 rt->u.dst.lastuse = jiffies; | 467 468 rt->u.dst.lastuse = jiffies; |
458 if (rt->u.dst.error == 0) 459 return rt; 460 dst_release(&rt->u.dst); | 469 rt->u.dst.__use++; 470 471 return rt; 472 473} 474 475struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, 476 int oif, int strict) 477{ 478 struct flowi fl = { 479 .oif = oif, 480 .nl_u = { 481 .ip6_u = { 482 .daddr = *daddr, 483 /* TODO: saddr */ 484 }, 485 }, 486 }; 487 struct dst_entry *dst; 488 int flags = strict ? RT6_F_STRICT : 0; 489 490 dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); 491 if (dst->error == 0) 492 return (struct rt6_info *) dst; 493 494 dst_release(dst); 495 |
461 return NULL; 462} 463 | 496 return NULL; 497} 498 |
464/* ip6_ins_rt is called with FREE rt6_lock. | 499/* ip6_ins_rt is called with FREE table->tb6_lock. |
465 It takes new route entry, the addition fails by any reason the 466 route is freed. In any case, if caller does not hold it, it may 467 be destroyed. 468 */ 469 470int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, 471 void *_rtattr, struct netlink_skb_parms *req) 472{ 473 int err; | 500 It takes new route entry, the addition fails by any reason the 501 route is freed. In any case, if caller does not hold it, it may 502 be destroyed. 503 */ 504 505int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, 506 void *_rtattr, struct netlink_skb_parms *req) 507{ 508 int err; |
509 struct fib6_table *table; |
|
474 | 510 |
475 write_lock_bh(&rt6_lock); 476 err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req); 477 write_unlock_bh(&rt6_lock); | 511 table = rt->rt6i_table; 512 write_lock_bh(&table->tb6_lock); 513 err = fib6_add(&table->tb6_root, rt, nlh, _rtattr, req); 514 write_unlock_bh(&table->tb6_lock); |
478 479 return err; 480} 481 482static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr, 483 struct in6_addr *saddr) 484{ 485 struct rt6_info *rt; --- 41 unchanged lines hidden (view full) --- 527 if (rt->rt6i_flags & RTF_REJECT) 528 rt->u.dst.error = ort->u.dst.error; 529 rt->u.dst.flags |= DST_HOST; 530 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); 531 } 532 return rt; 533} 534 | 515 516 return err; 517} 518 519static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr, 520 struct in6_addr *saddr) 521{ 522 struct rt6_info *rt; --- 41 unchanged lines hidden (view full) --- 564 if (rt->rt6i_flags & RTF_REJECT) 565 rt->u.dst.error = ort->u.dst.error; 566 rt->u.dst.flags |= DST_HOST; 567 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); 568 } 569 return rt; 570} 571 |
535#define BACKTRACK() \ 536if (rt == &ip6_null_entry) { \ 537 while ((fn = fn->parent) != NULL) { \ 538 if (fn->fn_flags & RTN_ROOT) { \ 539 goto out; \ 540 } \ 541 if (fn->fn_flags & RTN_RTINFO) \ 542 goto restart; \ 543 } \ 544} 545 546 547void ip6_route_input(struct sk_buff *skb) | 572struct rt6_info *ip6_pol_route_input(struct fib6_table *table, struct flowi *fl, 573 int flags) |
548{ 549 struct fib6_node *fn; 550 struct rt6_info *rt, *nrt; | 574{ 575 struct fib6_node *fn; 576 struct rt6_info *rt, *nrt; |
551 int strict; | 577 int strict = 0; |
552 int attempts = 3; 553 int err; 554 int reachable = RT6_SELECT_F_REACHABLE; 555 | 578 int attempts = 3; 579 int err; 580 int reachable = RT6_SELECT_F_REACHABLE; 581 |
556 strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; | 582 if (flags & RT6_F_STRICT) 583 strict = RT6_SELECT_F_IFACE; |
557 558relookup: | 584 585relookup: |
559 read_lock_bh(&rt6_lock); | 586 read_lock_bh(&table->tb6_lock); |
560 561restart_2: | 587 588restart_2: |
562 fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr, 563 &skb->nh.ipv6h->saddr); | 589 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
564 565restart: | 590 591restart: |
566 rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | reachable); | 592 rt = rt6_select(&fn->leaf, fl->iif, strict | reachable); |
567 BACKTRACK(); 568 if (rt == &ip6_null_entry || 569 rt->rt6i_flags & RTF_CACHE) 570 goto out; 571 572 dst_hold(&rt->u.dst); | 593 BACKTRACK(); 594 if (rt == &ip6_null_entry || 595 rt->rt6i_flags & RTF_CACHE) 596 goto out; 597 598 dst_hold(&rt->u.dst); |
573 read_unlock_bh(&rt6_lock); | 599 read_unlock_bh(&table->tb6_lock); |
574 575 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 600 601 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
576 nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr); | 602 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); |
577 else { 578#if CLONE_OFFLINK_ROUTE | 603 else { 604#if CLONE_OFFLINK_ROUTE |
579 nrt = rt6_alloc_clone(rt, &skb->nh.ipv6h->daddr); | 605 nrt = rt6_alloc_clone(rt, &fl->fl6_dst); |
580#else 581 goto out2; 582#endif 583 } 584 585 dst_release(&rt->u.dst); 586 rt = nrt ? : &ip6_null_entry; 587 588 dst_hold(&rt->u.dst); 589 if (nrt) { | 606#else 607 goto out2; 608#endif 609 } 610 611 dst_release(&rt->u.dst); 612 rt = nrt ? : &ip6_null_entry; 613 614 dst_hold(&rt->u.dst); 615 if (nrt) { |
590 err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb)); | 616 err = ip6_ins_rt(nrt, NULL, NULL, NULL); |
591 if (!err) 592 goto out2; 593 } 594 595 if (--attempts <= 0) 596 goto out2; 597 598 /* | 617 if (!err) 618 goto out2; 619 } 620 621 if (--attempts <= 0) 622 goto out2; 623 624 /* |
599 * Race condition! In the gap, when rt6_lock was | 625 * Race condition! In the gap, when table->tb6_lock was |
600 * released someone could insert this route. Relookup. 601 */ 602 dst_release(&rt->u.dst); 603 goto relookup; 604 605out: 606 if (reachable) { 607 reachable = 0; 608 goto restart_2; 609 } 610 dst_hold(&rt->u.dst); | 626 * released someone could insert this route. Relookup. 627 */ 628 dst_release(&rt->u.dst); 629 goto relookup; 630 631out: 632 if (reachable) { 633 reachable = 0; 634 goto restart_2; 635 } 636 dst_hold(&rt->u.dst); |
611 read_unlock_bh(&rt6_lock); | 637 read_unlock_bh(&table->tb6_lock); |
612out2: 613 rt->u.dst.lastuse = jiffies; 614 rt->u.dst.__use++; | 638out2: 639 rt->u.dst.lastuse = jiffies; 640 rt->u.dst.__use++; |
615 skb->dst = (struct dst_entry *) rt; 616 return; | 641 642 return rt; |
617} 618 | 643} 644 |
619struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | 645void ip6_route_input(struct sk_buff *skb) |
620{ | 646{ |
647 struct ipv6hdr *iph = skb->nh.ipv6h; 648 struct flowi fl = { 649 .iif = skb->dev->ifindex, 650 .nl_u = { 651 .ip6_u = { 652 .daddr = iph->daddr, 653 .saddr = iph->saddr, 654 .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK, 655 }, 656 }, 657 .proto = iph->nexthdr, 658 }; 659 int flags = 0; 660 661 if (rt6_need_strict(&iph->daddr)) 662 flags |= RT6_F_STRICT; 663 664 skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); 665} 666 667static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, 668 struct flowi *fl, int flags) 669{ |
|
621 struct fib6_node *fn; 622 struct rt6_info *rt, *nrt; | 670 struct fib6_node *fn; 671 struct rt6_info *rt, *nrt; |
623 int strict; | 672 int strict = 0; |
624 int attempts = 3; 625 int err; 626 int reachable = RT6_SELECT_F_REACHABLE; 627 | 673 int attempts = 3; 674 int err; 675 int reachable = RT6_SELECT_F_REACHABLE; 676 |
628 strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; | 677 if (flags & RT6_F_STRICT) 678 strict = RT6_SELECT_F_IFACE; |
629 630relookup: | 679 680relookup: |
631 read_lock_bh(&rt6_lock); | 681 read_lock_bh(&table->tb6_lock); |
632 633restart_2: | 682 683restart_2: |
634 fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src); | 684 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
635 636restart: 637 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); 638 BACKTRACK(); 639 if (rt == &ip6_null_entry || 640 rt->rt6i_flags & RTF_CACHE) 641 goto out; 642 643 dst_hold(&rt->u.dst); | 685 686restart: 687 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); 688 BACKTRACK(); 689 if (rt == &ip6_null_entry || 690 rt->rt6i_flags & RTF_CACHE) 691 goto out; 692 693 dst_hold(&rt->u.dst); |
644 read_unlock_bh(&rt6_lock); | 694 read_unlock_bh(&table->tb6_lock); |
645 646 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 647 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); 648 else { 649#if CLONE_OFFLINK_ROUTE 650 nrt = rt6_alloc_clone(rt, &fl->fl6_dst); 651#else 652 goto out2; --- 9 unchanged lines hidden (view full) --- 662 if (!err) 663 goto out2; 664 } 665 666 if (--attempts <= 0) 667 goto out2; 668 669 /* | 695 696 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 697 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); 698 else { 699#if CLONE_OFFLINK_ROUTE 700 nrt = rt6_alloc_clone(rt, &fl->fl6_dst); 701#else 702 goto out2; --- 9 unchanged lines hidden (view full) --- 712 if (!err) 713 goto out2; 714 } 715 716 if (--attempts <= 0) 717 goto out2; 718 719 /* |
670 * Race condition! In the gap, when rt6_lock was | 720 * Race condition! In the gap, when table->tb6_lock was |
671 * released someone could insert this route. Relookup. 672 */ 673 dst_release(&rt->u.dst); 674 goto relookup; 675 676out: 677 if (reachable) { 678 reachable = 0; 679 goto restart_2; 680 } 681 dst_hold(&rt->u.dst); | 721 * released someone could insert this route. Relookup. 722 */ 723 dst_release(&rt->u.dst); 724 goto relookup; 725 726out: 727 if (reachable) { 728 reachable = 0; 729 goto restart_2; 730 } 731 dst_hold(&rt->u.dst); |
682 read_unlock_bh(&rt6_lock); | 732 read_unlock_bh(&table->tb6_lock); |
683out2: 684 rt->u.dst.lastuse = jiffies; 685 rt->u.dst.__use++; | 733out2: 734 rt->u.dst.lastuse = jiffies; 735 rt->u.dst.__use++; |
686 return &rt->u.dst; | 736 return rt; |
687} 688 | 737} 738 |
739struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) 740{ 741 int flags = 0; |
|
689 | 742 |
743 if (rt6_need_strict(&fl->fl6_dst)) 744 flags |= RT6_F_STRICT; 745 746 return fib6_rule_lookup(fl, flags, ip6_pol_route_output); 747} 748 749 |
|
690/* 691 * Destination cache support functions 692 */ 693 694static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) 695{ 696 struct rt6_info *rt; 697 --- 203 unchanged lines hidden (view full) --- 901 return hoplimit; 902} 903 904/* 905 * 906 */ 907 908int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, | 750/* 751 * Destination cache support functions 752 */ 753 754static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) 755{ 756 struct rt6_info *rt; 757 --- 203 unchanged lines hidden (view full) --- 961 return hoplimit; 962} 963 964/* 965 * 966 */ 967 968int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, |
909 void *_rtattr, struct netlink_skb_parms *req) | 969 void *_rtattr, struct netlink_skb_parms *req, 970 u32 table_id) |
910{ 911 int err; 912 struct rtmsg *r; 913 struct rtattr **rta; 914 struct rt6_info *rt = NULL; 915 struct net_device *dev = NULL; 916 struct inet6_dev *idev = NULL; | 971{ 972 int err; 973 struct rtmsg *r; 974 struct rtattr **rta; 975 struct rt6_info *rt = NULL; 976 struct net_device *dev = NULL; 977 struct inet6_dev *idev = NULL; |
978 struct fib6_table *table; |
|
917 int addr_type; 918 919 rta = (struct rtattr **) _rtattr; 920 921 if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128) 922 return -EINVAL; 923#ifndef CONFIG_IPV6_SUBTREES 924 if (rtmsg->rtmsg_src_len) --- 7 unchanged lines hidden (view full) --- 932 idev = in6_dev_get(dev); 933 if (!idev) 934 goto out; 935 } 936 937 if (rtmsg->rtmsg_metric == 0) 938 rtmsg->rtmsg_metric = IP6_RT_PRIO_USER; 939 | 979 int addr_type; 980 981 rta = (struct rtattr **) _rtattr; 982 983 if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128) 984 return -EINVAL; 985#ifndef CONFIG_IPV6_SUBTREES 986 if (rtmsg->rtmsg_src_len) --- 7 unchanged lines hidden (view full) --- 994 idev = in6_dev_get(dev); 995 if (!idev) 996 goto out; 997 } 998 999 if (rtmsg->rtmsg_metric == 0) 1000 rtmsg->rtmsg_metric = IP6_RT_PRIO_USER; 1001 |
1002 table = fib6_new_table(table_id); 1003 if (table == NULL) { 1004 err = -ENOBUFS; 1005 goto out; 1006 } 1007 |
|
940 rt = ip6_dst_alloc(); 941 942 if (rt == NULL) { 943 err = -ENOMEM; 944 goto out; 945 } 946 947 rt->u.dst.obsolete = -1; --- 140 unchanged lines hidden (view full) --- 1088 if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0) 1089 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; 1090 if (!rt->u.dst.metrics[RTAX_MTU-1]) 1091 rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); 1092 if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) 1093 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); 1094 rt->u.dst.dev = dev; 1095 rt->rt6i_idev = idev; | 1008 rt = ip6_dst_alloc(); 1009 1010 if (rt == NULL) { 1011 err = -ENOMEM; 1012 goto out; 1013 } 1014 1015 rt->u.dst.obsolete = -1; --- 140 unchanged lines hidden (view full) --- 1156 if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0) 1157 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; 1158 if (!rt->u.dst.metrics[RTAX_MTU-1]) 1159 rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); 1160 if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) 1161 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); 1162 rt->u.dst.dev = dev; 1163 rt->rt6i_idev = idev; |
1164 rt->rt6i_table = table; |
|
1096 return ip6_ins_rt(rt, nlh, _rtattr, req); 1097 1098out: 1099 if (dev) 1100 dev_put(dev); 1101 if (idev) 1102 in6_dev_put(idev); 1103 if (rt) 1104 dst_free((struct dst_entry *) rt); 1105 return err; 1106} 1107 1108int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) 1109{ 1110 int err; | 1165 return ip6_ins_rt(rt, nlh, _rtattr, req); 1166 1167out: 1168 if (dev) 1169 dev_put(dev); 1170 if (idev) 1171 in6_dev_put(idev); 1172 if (rt) 1173 dst_free((struct dst_entry *) rt); 1174 return err; 1175} 1176 1177int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) 1178{ 1179 int err; |
1180 struct fib6_table *table; |
|
1111 | 1181 |
1112 write_lock_bh(&rt6_lock); | 1182 table = rt->rt6i_table; 1183 write_lock_bh(&table->tb6_lock); |
1113 1114 err = fib6_del(rt, nlh, _rtattr, req); 1115 dst_release(&rt->u.dst); 1116 | 1184 1185 err = fib6_del(rt, nlh, _rtattr, req); 1186 dst_release(&rt->u.dst); 1187 |
1117 write_unlock_bh(&rt6_lock); | 1188 write_unlock_bh(&table->tb6_lock); |
1118 1119 return err; 1120} 1121 | 1189 1190 return err; 1191} 1192 |
1122static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) | 1193static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, 1194 void *_rtattr, struct netlink_skb_parms *req, 1195 u32 table_id) |
1123{ | 1196{ |
1197 struct fib6_table *table; |
|
1124 struct fib6_node *fn; 1125 struct rt6_info *rt; 1126 int err = -ESRCH; 1127 | 1198 struct fib6_node *fn; 1199 struct rt6_info *rt; 1200 int err = -ESRCH; 1201 |
1128 read_lock_bh(&rt6_lock); | 1202 table = fib6_get_table(table_id); 1203 if (table == NULL) 1204 return err; |
1129 | 1205 |
1130 fn = fib6_locate(&ip6_routing_table, | 1206 read_lock_bh(&table->tb6_lock); 1207 1208 fn = fib6_locate(&table->tb6_root, |
1131 &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len, 1132 &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len); 1133 1134 if (fn) { 1135 for (rt = fn->leaf; rt; rt = rt->u.next) { 1136 if (rtmsg->rtmsg_ifindex && 1137 (rt->rt6i_dev == NULL || 1138 rt->rt6i_dev->ifindex != rtmsg->rtmsg_ifindex)) 1139 continue; 1140 if (rtmsg->rtmsg_flags&RTF_GATEWAY && 1141 !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway)) 1142 continue; 1143 if (rtmsg->rtmsg_metric && 1144 rtmsg->rtmsg_metric != rt->rt6i_metric) 1145 continue; 1146 dst_hold(&rt->u.dst); | 1209 &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len, 1210 &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len); 1211 1212 if (fn) { 1213 for (rt = fn->leaf; rt; rt = rt->u.next) { 1214 if (rtmsg->rtmsg_ifindex && 1215 (rt->rt6i_dev == NULL || 1216 rt->rt6i_dev->ifindex != rtmsg->rtmsg_ifindex)) 1217 continue; 1218 if (rtmsg->rtmsg_flags&RTF_GATEWAY && 1219 !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway)) 1220 continue; 1221 if (rtmsg->rtmsg_metric && 1222 rtmsg->rtmsg_metric != rt->rt6i_metric) 1223 continue; 1224 dst_hold(&rt->u.dst); |
1147 read_unlock_bh(&rt6_lock); | 1225 read_unlock_bh(&table->tb6_lock); |
1148 1149 return ip6_del_rt(rt, nlh, _rtattr, req); 1150 } 1151 } | 1226 1227 return ip6_del_rt(rt, nlh, _rtattr, req); 1228 } 1229 } |
1152 read_unlock_bh(&rt6_lock); | 1230 read_unlock_bh(&table->tb6_lock); |
1153 1154 return err; 1155} 1156 1157/* 1158 * Handle redirects 1159 */ 1160void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, 1161 struct neighbour *neigh, u8 *lladdr, int on_link) 1162{ 1163 struct rt6_info *rt, *nrt = NULL; | 1231 1232 return err; 1233} 1234 1235/* 1236 * Handle redirects 1237 */ 1238void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, 1239 struct neighbour *neigh, u8 *lladdr, int on_link) 1240{ 1241 struct rt6_info *rt, *nrt = NULL; |
1164 int strict; | |
1165 struct fib6_node *fn; | 1242 struct fib6_node *fn; |
1243 struct fib6_table *table; |
|
1166 struct netevent_redirect netevent; 1167 | 1244 struct netevent_redirect netevent; 1245 |
1246 /* TODO: Very lazy, might need to check all tables */ 1247 table = fib6_get_table(RT6_TABLE_MAIN); 1248 if (table == NULL) 1249 return; 1250 |
|
1168 /* 1169 * Get the "current" route for this destination and 1170 * check if the redirect has come from approriate router. 1171 * 1172 * RFC 2461 specifies that redirects should only be 1173 * accepted if they come from the nexthop to the target. 1174 * Due to the way the routes are chosen, this notion 1175 * is a bit fuzzy and one might need to check all possible 1176 * routes. 1177 */ | 1251 /* 1252 * Get the "current" route for this destination and 1253 * check if the redirect has come from approriate router. 1254 * 1255 * RFC 2461 specifies that redirects should only be 1256 * accepted if they come from the nexthop to the target. 1257 * Due to the way the routes are chosen, this notion 1258 * is a bit fuzzy and one might need to check all possible 1259 * routes. 1260 */ |
1178 strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL); | |
1179 | 1261 |
1180 read_lock_bh(&rt6_lock); 1181 fn = fib6_lookup(&ip6_routing_table, dest, NULL); | 1262 read_lock_bh(&table->tb6_lock); 1263 fn = fib6_lookup(&table->tb6_root, dest, NULL); |
1182restart: 1183 for (rt = fn->leaf; rt; rt = rt->u.next) { 1184 /* 1185 * Current route is on-link; redirect is always invalid. 1186 * 1187 * Seems, previous statement is not true. It could 1188 * be node, which looks for us as on-link (f.e. proxy ndisc) 1189 * But then router serving it might decide, that we should --- 6 unchanged lines hidden (view full) --- 1196 if (neigh->dev != rt->rt6i_dev) 1197 continue; 1198 if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) 1199 continue; 1200 break; 1201 } 1202 if (rt) 1203 dst_hold(&rt->u.dst); | 1264restart: 1265 for (rt = fn->leaf; rt; rt = rt->u.next) { 1266 /* 1267 * Current route is on-link; redirect is always invalid. 1268 * 1269 * Seems, previous statement is not true. It could 1270 * be node, which looks for us as on-link (f.e. proxy ndisc) 1271 * But then router serving it might decide, that we should --- 6 unchanged lines hidden (view full) --- 1278 if (neigh->dev != rt->rt6i_dev) 1279 continue; 1280 if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) 1281 continue; 1282 break; 1283 } 1284 if (rt) 1285 dst_hold(&rt->u.dst); |
1204 else if (strict) { | 1286 else if (rt6_need_strict(dest)) { |
1205 while ((fn = fn->parent) != NULL) { 1206 if (fn->fn_flags & RTN_ROOT) 1207 break; 1208 if (fn->fn_flags & RTN_RTINFO) 1209 goto restart; 1210 } 1211 } | 1287 while ((fn = fn->parent) != NULL) { 1288 if (fn->fn_flags & RTN_ROOT) 1289 break; 1290 if (fn->fn_flags & RTN_RTINFO) 1291 goto restart; 1292 } 1293 } |
1212 read_unlock_bh(&rt6_lock); | 1294 read_unlock_bh(&table->tb6_lock); |
1213 1214 if (!rt) { 1215 if (net_ratelimit()) 1216 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " 1217 "for redirect target\n"); 1218 return; 1219 } 1220 --- 158 unchanged lines hidden (view full) --- 1379 ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); 1380 rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; 1381 rt->rt6i_metric = 0; 1382 1383 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); 1384#ifdef CONFIG_IPV6_SUBTREES 1385 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); 1386#endif | 1295 1296 if (!rt) { 1297 if (net_ratelimit()) 1298 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " 1299 "for redirect target\n"); 1300 return; 1301 } 1302 --- 158 unchanged lines hidden (view full) --- 1461 ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); 1462 rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; 1463 rt->rt6i_metric = 0; 1464 1465 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); 1466#ifdef CONFIG_IPV6_SUBTREES 1467 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); 1468#endif |
1469 rt->rt6i_table = ort->rt6i_table; |
|
1387 } 1388 return rt; 1389} 1390 1391#ifdef CONFIG_IPV6_ROUTE_INFO 1392static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, 1393 struct in6_addr *gwaddr, int ifindex) 1394{ 1395 struct fib6_node *fn; 1396 struct rt6_info *rt = NULL; | 1470 } 1471 return rt; 1472} 1473 1474#ifdef CONFIG_IPV6_ROUTE_INFO 1475static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, 1476 struct in6_addr *gwaddr, int ifindex) 1477{ 1478 struct fib6_node *fn; 1479 struct rt6_info *rt = NULL; |
1480 struct fib6_table *table; |
|
1397 | 1481 |
1398 write_lock_bh(&rt6_lock); 1399 fn = fib6_locate(&ip6_routing_table, prefix ,prefixlen, NULL, 0); | 1482 table = fib6_get_table(RT6_TABLE_INFO); 1483 if (table == NULL) 1484 return NULL; 1485 1486 write_lock_bh(&table->tb6_lock); 1487 fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0); |
1400 if (!fn) 1401 goto out; 1402 1403 for (rt = fn->leaf; rt; rt = rt->u.next) { 1404 if (rt->rt6i_dev->ifindex != ifindex) 1405 continue; 1406 if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) 1407 continue; 1408 if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) 1409 continue; 1410 dst_hold(&rt->u.dst); 1411 break; 1412 } 1413out: | 1488 if (!fn) 1489 goto out; 1490 1491 for (rt = fn->leaf; rt; rt = rt->u.next) { 1492 if (rt->rt6i_dev->ifindex != ifindex) 1493 continue; 1494 if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) 1495 continue; 1496 if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) 1497 continue; 1498 dst_hold(&rt->u.dst); 1499 break; 1500 } 1501out: |
1414 write_unlock_bh(&rt6_lock); | 1502 write_unlock_bh(&table->tb6_lock); |
1415 return rt; 1416} 1417 1418static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, 1419 struct in6_addr *gwaddr, int ifindex, 1420 unsigned pref) 1421{ 1422 struct in6_rtmsg rtmsg; --- 5 unchanged lines hidden (view full) --- 1428 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); 1429 rtmsg.rtmsg_metric = 1024; 1430 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref); 1431 /* We should treat it as a default route if prefix length is 0. */ 1432 if (!prefixlen) 1433 rtmsg.rtmsg_flags |= RTF_DEFAULT; 1434 rtmsg.rtmsg_ifindex = ifindex; 1435 | 1503 return rt; 1504} 1505 1506static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, 1507 struct in6_addr *gwaddr, int ifindex, 1508 unsigned pref) 1509{ 1510 struct in6_rtmsg rtmsg; --- 5 unchanged lines hidden (view full) --- 1516 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); 1517 rtmsg.rtmsg_metric = 1024; 1518 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref); 1519 /* We should treat it as a default route if prefix length is 0. */ 1520 if (!prefixlen) 1521 rtmsg.rtmsg_flags |= RTF_DEFAULT; 1522 rtmsg.rtmsg_ifindex = ifindex; 1523 |
1436 ip6_route_add(&rtmsg, NULL, NULL, NULL); | 1524 ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_INFO); |
1437 1438 return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); 1439} 1440#endif 1441 1442struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) 1443{ 1444 struct rt6_info *rt; | 1525 1526 return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); 1527} 1528#endif 1529 1530struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) 1531{ 1532 struct rt6_info *rt; |
1445 struct fib6_node *fn; | 1533 struct fib6_table *table; |
1446 | 1534 |
1447 fn = &ip6_routing_table; | 1535 table = fib6_get_table(RT6_TABLE_DFLT); 1536 if (table == NULL) 1537 return NULL; |
1448 | 1538 |
1449 write_lock_bh(&rt6_lock); 1450 for (rt = fn->leaf; rt; rt=rt->u.next) { | 1539 write_lock_bh(&table->tb6_lock); 1540 for (rt = table->tb6_root.leaf; rt; rt=rt->u.next) { |
1451 if (dev == rt->rt6i_dev && 1452 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && 1453 ipv6_addr_equal(&rt->rt6i_gateway, addr)) 1454 break; 1455 } 1456 if (rt) 1457 dst_hold(&rt->u.dst); | 1541 if (dev == rt->rt6i_dev && 1542 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && 1543 ipv6_addr_equal(&rt->rt6i_gateway, addr)) 1544 break; 1545 } 1546 if (rt) 1547 dst_hold(&rt->u.dst); |
1458 write_unlock_bh(&rt6_lock); | 1548 write_unlock_bh(&table->tb6_lock); |
1459 return rt; 1460} 1461 1462struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, 1463 struct net_device *dev, 1464 unsigned int pref) 1465{ 1466 struct in6_rtmsg rtmsg; 1467 1468 memset(&rtmsg, 0, sizeof(struct in6_rtmsg)); 1469 rtmsg.rtmsg_type = RTMSG_NEWROUTE; 1470 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); 1471 rtmsg.rtmsg_metric = 1024; 1472 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES | 1473 RTF_PREF(pref); 1474 1475 rtmsg.rtmsg_ifindex = dev->ifindex; 1476 | 1549 return rt; 1550} 1551 1552struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, 1553 struct net_device *dev, 1554 unsigned int pref) 1555{ 1556 struct in6_rtmsg rtmsg; 1557 1558 memset(&rtmsg, 0, sizeof(struct in6_rtmsg)); 1559 rtmsg.rtmsg_type = RTMSG_NEWROUTE; 1560 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); 1561 rtmsg.rtmsg_metric = 1024; 1562 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES | 1563 RTF_PREF(pref); 1564 1565 rtmsg.rtmsg_ifindex = dev->ifindex; 1566 |
1477 ip6_route_add(&rtmsg, NULL, NULL, NULL); | 1567 ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_DFLT); |
1478 return rt6_get_dflt_router(gwaddr, dev); 1479} 1480 1481void rt6_purge_dflt_routers(void) 1482{ 1483 struct rt6_info *rt; | 1568 return rt6_get_dflt_router(gwaddr, dev); 1569} 1570 1571void rt6_purge_dflt_routers(void) 1572{ 1573 struct rt6_info *rt; |
1574 struct fib6_table *table; |
|
1484 | 1575 |
1576 /* NOTE: Keep consistent with rt6_get_dflt_router */ 1577 table = fib6_get_table(RT6_TABLE_DFLT); 1578 if (table == NULL) 1579 return; 1580 |
|
1485restart: | 1581restart: |
1486 read_lock_bh(&rt6_lock); 1487 for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) { | 1582 read_lock_bh(&table->tb6_lock); 1583 for (rt = table->tb6_root.leaf; rt; rt = rt->u.next) { |
1488 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { 1489 dst_hold(&rt->u.dst); | 1584 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { 1585 dst_hold(&rt->u.dst); |
1490 1491 read_unlock_bh(&rt6_lock); 1492 | 1586 read_unlock_bh(&table->tb6_lock); |
1493 ip6_del_rt(rt, NULL, NULL, NULL); | 1587 ip6_del_rt(rt, NULL, NULL, NULL); |
1494 | |
1495 goto restart; 1496 } 1497 } | 1588 goto restart; 1589 } 1590 } |
1498 read_unlock_bh(&rt6_lock); | 1591 read_unlock_bh(&table->tb6_lock); |
1499} 1500 1501int ipv6_route_ioctl(unsigned int cmd, void __user *arg) 1502{ 1503 struct in6_rtmsg rtmsg; 1504 int err; 1505 1506 switch(cmd) { --- 4 unchanged lines hidden (view full) --- 1511 err = copy_from_user(&rtmsg, arg, 1512 sizeof(struct in6_rtmsg)); 1513 if (err) 1514 return -EFAULT; 1515 1516 rtnl_lock(); 1517 switch (cmd) { 1518 case SIOCADDRT: | 1592} 1593 1594int ipv6_route_ioctl(unsigned int cmd, void __user *arg) 1595{ 1596 struct in6_rtmsg rtmsg; 1597 int err; 1598 1599 switch(cmd) { --- 4 unchanged lines hidden (view full) --- 1604 err = copy_from_user(&rtmsg, arg, 1605 sizeof(struct in6_rtmsg)); 1606 if (err) 1607 return -EFAULT; 1608 1609 rtnl_lock(); 1610 switch (cmd) { 1611 case SIOCADDRT: |
1519 err = ip6_route_add(&rtmsg, NULL, NULL, NULL); | 1612 err = ip6_route_add(&rtmsg, NULL, NULL, NULL, 1613 RT6_TABLE_MAIN); |
1520 break; 1521 case SIOCDELRT: | 1614 break; 1615 case SIOCDELRT: |
1522 err = ip6_route_del(&rtmsg, NULL, NULL, NULL); | 1616 err = ip6_route_del(&rtmsg, NULL, NULL, NULL, 1617 RT6_TABLE_MAIN); |
1523 break; 1524 default: 1525 err = -EINVAL; 1526 } 1527 rtnl_unlock(); 1528 1529 return err; 1530 }; --- 57 unchanged lines hidden (view full) --- 1588 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); 1589 if (rt->rt6i_nexthop == NULL) { 1590 dst_free((struct dst_entry *) rt); 1591 return ERR_PTR(-ENOMEM); 1592 } 1593 1594 ipv6_addr_copy(&rt->rt6i_dst.addr, addr); 1595 rt->rt6i_dst.plen = 128; | 1618 break; 1619 default: 1620 err = -EINVAL; 1621 } 1622 rtnl_unlock(); 1623 1624 return err; 1625 }; --- 57 unchanged lines hidden (view full) --- 1683 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); 1684 if (rt->rt6i_nexthop == NULL) { 1685 dst_free((struct dst_entry *) rt); 1686 return ERR_PTR(-ENOMEM); 1687 } 1688 1689 ipv6_addr_copy(&rt->rt6i_dst.addr, addr); 1690 rt->rt6i_dst.plen = 128; |
1691 rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL); |
|
1596 1597 atomic_set(&rt->u.dst.__refcnt, 1); 1598 1599 return rt; 1600} 1601 1602static int fib6_ifdown(struct rt6_info *rt, void *arg) 1603{ 1604 if (((void*)rt->rt6i_dev == arg || arg == NULL) && 1605 rt != &ip6_null_entry) { 1606 RT6_TRACE("deleted by ifdown %p\n", rt); 1607 return -1; 1608 } 1609 return 0; 1610} 1611 1612void rt6_ifdown(struct net_device *dev) 1613{ | 1692 1693 atomic_set(&rt->u.dst.__refcnt, 1); 1694 1695 return rt; 1696} 1697 1698static int fib6_ifdown(struct rt6_info *rt, void *arg) 1699{ 1700 if (((void*)rt->rt6i_dev == arg || arg == NULL) && 1701 rt != &ip6_null_entry) { 1702 RT6_TRACE("deleted by ifdown %p\n", rt); 1703 return -1; 1704 } 1705 return 0; 1706} 1707 1708void rt6_ifdown(struct net_device *dev) 1709{ |
1614 write_lock_bh(&rt6_lock); 1615 fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev); 1616 write_unlock_bh(&rt6_lock); | 1710 fib6_clean_all(fib6_ifdown, 0, dev); |
1617} 1618 1619struct rt6_mtu_change_arg 1620{ 1621 struct net_device *dev; 1622 unsigned mtu; 1623}; 1624 --- 33 unchanged lines hidden (view full) --- 1658 dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) 1659 rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; 1660 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu); 1661 return 0; 1662} 1663 1664void rt6_mtu_change(struct net_device *dev, unsigned mtu) 1665{ | 1711} 1712 1713struct rt6_mtu_change_arg 1714{ 1715 struct net_device *dev; 1716 unsigned mtu; 1717}; 1718 --- 33 unchanged lines hidden (view full) --- 1752 dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) 1753 rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; 1754 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu); 1755 return 0; 1756} 1757 1758void rt6_mtu_change(struct net_device *dev, unsigned mtu) 1759{ |
1666 struct rt6_mtu_change_arg arg; | 1760 struct rt6_mtu_change_arg arg = { 1761 .dev = dev, 1762 .mtu = mtu, 1763 }; |
1667 | 1764 |
1668 arg.dev = dev; 1669 arg.mtu = mtu; 1670 read_lock_bh(&rt6_lock); 1671 fib6_clean_tree(&ip6_routing_table, rt6_mtu_change_route, 0, &arg); 1672 read_unlock_bh(&rt6_lock); | 1765 fib6_clean_all(rt6_mtu_change_route, 0, &arg); |
1673} 1674 1675static int inet6_rtm_to_rtmsg(struct rtmsg *r, struct rtattr **rta, 1676 struct in6_rtmsg *rtmsg) 1677{ 1678 memset(rtmsg, 0, sizeof(*rtmsg)); 1679 1680 rtmsg->rtmsg_dst_len = r->rtm_dst_len; --- 33 unchanged lines hidden (view full) --- 1714 1715int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1716{ 1717 struct rtmsg *r = NLMSG_DATA(nlh); 1718 struct in6_rtmsg rtmsg; 1719 1720 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1721 return -EINVAL; | 1766} 1767 1768static int inet6_rtm_to_rtmsg(struct rtmsg *r, struct rtattr **rta, 1769 struct in6_rtmsg *rtmsg) 1770{ 1771 memset(rtmsg, 0, sizeof(*rtmsg)); 1772 1773 rtmsg->rtmsg_dst_len = r->rtm_dst_len; --- 33 unchanged lines hidden (view full) --- 1807 1808int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1809{ 1810 struct rtmsg *r = NLMSG_DATA(nlh); 1811 struct in6_rtmsg rtmsg; 1812 1813 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1814 return -EINVAL; |
1722 return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb)); | 1815 return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb), r->rtm_table); |
1723} 1724 1725int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1726{ 1727 struct rtmsg *r = NLMSG_DATA(nlh); 1728 struct in6_rtmsg rtmsg; 1729 1730 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1731 return -EINVAL; | 1816} 1817 1818int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1819{ 1820 struct rtmsg *r = NLMSG_DATA(nlh); 1821 struct in6_rtmsg rtmsg; 1822 1823 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1824 return -EINVAL; |
1732 return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb)); | 1825 return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb), r->rtm_table); |
1733} 1734 1735struct rt6_rtnl_dump_arg 1736{ 1737 struct sk_buff *skb; 1738 struct netlink_callback *cb; 1739}; 1740 --- 15 unchanged lines hidden (view full) --- 1756 } 1757 1758 nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); 1759 rtm = NLMSG_DATA(nlh); 1760 rtm->rtm_family = AF_INET6; 1761 rtm->rtm_dst_len = rt->rt6i_dst.plen; 1762 rtm->rtm_src_len = rt->rt6i_src.plen; 1763 rtm->rtm_tos = 0; | 1826} 1827 1828struct rt6_rtnl_dump_arg 1829{ 1830 struct sk_buff *skb; 1831 struct netlink_callback *cb; 1832}; 1833 --- 15 unchanged lines hidden (view full) --- 1849 } 1850 1851 nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); 1852 rtm = NLMSG_DATA(nlh); 1853 rtm->rtm_family = AF_INET6; 1854 rtm->rtm_dst_len = rt->rt6i_dst.plen; 1855 rtm->rtm_src_len = rt->rt6i_src.plen; 1856 rtm->rtm_tos = 0; |
1857 if (rt->rt6i_table) 1858 rtm->rtm_table = rt->rt6i_table->tb6_id; 1859 else 1860 rtm->rtm_table = RT6_TABLE_UNSPEC; |
|
1764 rtm->rtm_table = RT_TABLE_MAIN; 1765 if (rt->rt6i_flags&RTF_REJECT) 1766 rtm->rtm_type = RTN_UNREACHABLE; 1767 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) 1768 rtm->rtm_type = RTN_LOCAL; 1769 else 1770 rtm->rtm_type = RTN_UNICAST; 1771 rtm->rtm_flags = 0; --- 91 unchanged lines hidden (view full) --- 1863} 1864 1865static void fib6_dump_end(struct netlink_callback *cb) 1866{ 1867 struct fib6_walker_t *w = (void*)cb->args[0]; 1868 1869 if (w) { 1870 cb->args[0] = 0; | 1861 rtm->rtm_table = RT_TABLE_MAIN; 1862 if (rt->rt6i_flags&RTF_REJECT) 1863 rtm->rtm_type = RTN_UNREACHABLE; 1864 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) 1865 rtm->rtm_type = RTN_LOCAL; 1866 else 1867 rtm->rtm_type = RTN_UNICAST; 1868 rtm->rtm_flags = 0; --- 91 unchanged lines hidden (view full) --- 1960} 1961 1962static void fib6_dump_end(struct netlink_callback *cb) 1963{ 1964 struct fib6_walker_t *w = (void*)cb->args[0]; 1965 1966 if (w) { 1967 cb->args[0] = 0; |
1871 fib6_walker_unlink(w); | |
1872 kfree(w); 1873 } 1874 cb->done = (void*)cb->args[1]; 1875 cb->args[1] = 0; 1876} 1877 1878static int fib6_dump_done(struct netlink_callback *cb) 1879{ 1880 fib6_dump_end(cb); 1881 return cb->done ? cb->done(cb) : 0; 1882} 1883 1884int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) 1885{ | 1968 kfree(w); 1969 } 1970 cb->done = (void*)cb->args[1]; 1971 cb->args[1] = 0; 1972} 1973 1974static int fib6_dump_done(struct netlink_callback *cb) 1975{ 1976 fib6_dump_end(cb); 1977 return cb->done ? cb->done(cb) : 0; 1978} 1979 1980int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) 1981{ |
1982 struct fib6_table *table; |
|
1886 struct rt6_rtnl_dump_arg arg; 1887 struct fib6_walker_t *w; | 1983 struct rt6_rtnl_dump_arg arg; 1984 struct fib6_walker_t *w; |
1888 int res; | 1985 int i, res = 0; |
1889 1890 arg.skb = skb; 1891 arg.cb = cb; 1892 | 1986 1987 arg.skb = skb; 1988 arg.cb = cb; 1989 |
1990 /* 1991 * cb->args[0] = pointer to walker structure 1992 * cb->args[1] = saved cb->done() pointer 1993 * cb->args[2] = current table being dumped 1994 */ 1995 |
|
1893 w = (void*)cb->args[0]; 1894 if (w == NULL) { 1895 /* New dump: 1896 * 1897 * 1. hook callback destructor. 1898 */ 1899 cb->args[1] = (long)cb->done; 1900 cb->done = fib6_dump_done; 1901 1902 /* 1903 * 2. allocate and initialize walker. 1904 */ 1905 w = kzalloc(sizeof(*w), GFP_ATOMIC); 1906 if (w == NULL) 1907 return -ENOMEM; | 1996 w = (void*)cb->args[0]; 1997 if (w == NULL) { 1998 /* New dump: 1999 * 2000 * 1. hook callback destructor. 2001 */ 2002 cb->args[1] = (long)cb->done; 2003 cb->done = fib6_dump_done; 2004 2005 /* 2006 * 2. allocate and initialize walker. 2007 */ 2008 w = kzalloc(sizeof(*w), GFP_ATOMIC); 2009 if (w == NULL) 2010 return -ENOMEM; |
1908 RT6_TRACE("dump<%p", w); 1909 w->root = &ip6_routing_table; | |
1910 w->func = fib6_dump_node; 1911 w->args = &arg; 1912 cb->args[0] = (long)w; | 2011 w->func = fib6_dump_node; 2012 w->args = &arg; 2013 cb->args[0] = (long)w; |
1913 read_lock_bh(&rt6_lock); 1914 res = fib6_walk(w); 1915 read_unlock_bh(&rt6_lock); | 2014 cb->args[2] = FIB6_TABLE_MIN; |
1916 } else { 1917 w->args = &arg; | 2015 } else { 2016 w->args = &arg; |
1918 read_lock_bh(&rt6_lock); 1919 res = fib6_walk_continue(w); 1920 read_unlock_bh(&rt6_lock); | 2017 i = cb->args[2]; 2018 if (i > FIB6_TABLE_MAX) 2019 goto end; 2020 2021 table = fib6_get_table(i); 2022 if (table != NULL) { 2023 read_lock_bh(&table->tb6_lock); 2024 w->root = &table->tb6_root; 2025 res = fib6_walk_continue(w); 2026 read_unlock_bh(&table->tb6_lock); 2027 if (res != 0) { 2028 if (res < 0) 2029 fib6_walker_unlink(w); 2030 goto end; 2031 } 2032 } 2033 2034 fib6_walker_unlink(w); 2035 cb->args[2] = ++i; |
1921 } | 2036 } |
1922#if RT6_DEBUG >= 3 1923 if (res <= 0 && skb->len == 0) 1924 RT6_TRACE("%p>dump end\n", w); 1925#endif | 2037 2038 for (i = cb->args[2]; i <= FIB6_TABLE_MAX; i++) { 2039 table = fib6_get_table(i); 2040 if (table == NULL) 2041 continue; 2042 2043 read_lock_bh(&table->tb6_lock); 2044 w->root = &table->tb6_root; 2045 res = fib6_walk(w); 2046 read_unlock_bh(&table->tb6_lock); 2047 if (res) 2048 break; 2049 } 2050end: 2051 cb->args[2] = i; 2052 |
1926 res = res < 0 ? res : skb->len; 1927 /* res < 0 is an error. (really, impossible) 1928 res == 0 means that dump is complete, but skb still can contain data. 1929 res > 0 dump is not complete, but frame is full. 1930 */ 1931 /* Destroy walker, if dump of this table is complete. */ 1932 if (res <= 0) 1933 fib6_dump_end(cb); --- 163 unchanged lines hidden (view full) --- 2097 rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), 2098 rt->u.dst.__use, rt->rt6i_flags, 2099 rt->rt6i_dev ? rt->rt6i_dev->name : ""); 2100 return 0; 2101} 2102 2103static int rt6_proc_info(char *buffer, char **start, off_t offset, int length) 2104{ | 2053 res = res < 0 ? res : skb->len; 2054 /* res < 0 is an error. (really, impossible) 2055 res == 0 means that dump is complete, but skb still can contain data. 2056 res > 0 dump is not complete, but frame is full. 2057 */ 2058 /* Destroy walker, if dump of this table is complete. */ 2059 if (res <= 0) 2060 fib6_dump_end(cb); --- 163 unchanged lines hidden (view full) --- 2224 rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), 2225 rt->u.dst.__use, rt->rt6i_flags, 2226 rt->rt6i_dev ? rt->rt6i_dev->name : ""); 2227 return 0; 2228} 2229 2230static int rt6_proc_info(char *buffer, char **start, off_t offset, int length) 2231{ |
2105 struct rt6_proc_arg arg; 2106 arg.buffer = buffer; 2107 arg.offset = offset; 2108 arg.length = length; 2109 arg.skip = 0; 2110 arg.len = 0; | 2232 struct rt6_proc_arg arg = { 2233 .buffer = buffer, 2234 .offset = offset, 2235 .length = length, 2236 }; |
2111 | 2237 |
2112 read_lock_bh(&rt6_lock); 2113 fib6_clean_tree(&ip6_routing_table, rt6_info_route, 0, &arg); 2114 read_unlock_bh(&rt6_lock); | 2238 fib6_clean_all(rt6_info_route, 0, &arg); |
2115 2116 *start = buffer; 2117 if (offset) 2118 *start += offset % RT6_INFO_LEN; 2119 2120 arg.len -= offset % RT6_INFO_LEN; 2121 2122 if (arg.len > length) --- 179 unchanged lines hidden --- | 2239 2240 *start = buffer; 2241 if (offset) 2242 *start += offset % RT6_INFO_LEN; 2243 2244 arg.len -= offset % RT6_INFO_LEN; 2245 2246 if (arg.len > length) --- 179 unchanged lines hidden --- |