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 ---