1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
--- 16 unchanged lines hidden (view full) ---
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/netinet6/nd6_rtr.c 241686 2012-10-18 13:57:24Z andre $");
34
35#include "opt_inet.h"
36#include "opt_inet6.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/mbuf.h>
--- 426 unchanged lines hidden (view full) ---
468 ifa_free(ifa);
469}
470
471static void
472defrouter_addreq(struct nd_defrouter *new)
473{
474 struct sockaddr_in6 def, mask, gate;
475 struct rtentry *newrt = NULL;
476 int error;
477
478 bzero(&def, sizeof(def));
479 bzero(&mask, sizeof(mask));
480 bzero(&gate, sizeof(gate));
481
482 def.sin6_len = mask.sin6_len = gate.sin6_len =
483 sizeof(struct sockaddr_in6);
484 def.sin6_family = gate.sin6_family = AF_INET6;
485 gate.sin6_addr = new->rtaddr;
486
487 error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&def,
488 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
489 RTF_GATEWAY, &newrt, RT_DEFAULT_FIB);
490 if (newrt) {
491 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
492 RTFREE(newrt);
493 }
494 if (error == 0)
495 new->installed = 1;
496 return;
497}
498
499struct nd_defrouter *
500defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp)
501{
502 struct nd_defrouter *dr;
503
--- 112 unchanged lines hidden (view full) ---
616 * At this moment, we do not try to install more than one default router,
617 * even when the multipath routing is available, because we're not sure about
618 * the benefits for stub hosts comparing to the risk of making the code
619 * complicated and the possibility of introducing bugs.
620 */
621void
622defrouter_select(void)
623{
624 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
625 struct llentry *ln = NULL;
626
627 /*
628 * Let's handle easy case (3) first:
629 * If default router list is empty, there's nothing to be done.
630 */
631 if (TAILQ_EMPTY(&V_nd_defrouter))
632 return;
633
634 /*
635 * Search for a (probably) reachable router from the list.
636 * We just pick up the first reachable one (if any), assuming that
637 * the ordering rule of the list described in defrtrlist_update().
638 */
639 TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
640 IF_AFDATA_LOCK(dr->ifp);
--- 47 unchanged lines hidden (view full) ---
688 * Note that the selected router is never NULL here.
689 */
690 if (installed_dr != selected_dr) {
691 if (installed_dr)
692 defrouter_delreq(installed_dr);
693 defrouter_addreq(selected_dr);
694 }
695
696 return;
697}
698
699/*
700 * for default router selection
701 * regards router-preference field as a 2-bit signed integer
702 */
703static int
--- 18 unchanged lines hidden (view full) ---
722 }
723 /* NOTREACHED */
724}
725
726static struct nd_defrouter *
727defrtrlist_update(struct nd_defrouter *new)
728{
729 struct nd_defrouter *dr, *n;
730
731 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
732 /* entry exists */
733 if (new->rtlifetime == 0) {
734 defrtrlist_del(dr);
735 dr = NULL;
736 } else {
737 int oldpref = rtpref(dr);
738
739 /* override */
740 dr->flags = new->flags; /* xxx flag check */
741 dr->rtlifetime = new->rtlifetime;
742 dr->expire = new->expire;
743
744 /*
745 * If the preference does not change, there's no need
746 * to sort the entries. Also make sure the selected
747 * router is still installed in the kernel.
748 */
749 if (dr->installed && rtpref(new) == oldpref)
750 return (dr);
751
752 /*
753 * preferred router may be changed, so relocate
754 * this router.
755 * XXX: calling TAILQ_REMOVE directly is a bad manner.
756 * However, since defrtrlist_del() has many side
757 * effects, we intentionally do so here.
758 * defrouter_select() below will handle routing
759 * changes later.
760 */
761 TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry);
762 n = dr;
763 goto insert;
764 }
765 return (dr);
766 }
767
768 /* entry does not exist */
769 if (new->rtlifetime == 0)
770 return (NULL);
771
772 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
773 if (n == NULL)
774 return (NULL);
775 bzero(n, sizeof(*n));
776 *n = *new;
777
778insert:
779 /*
780 * Insert the new router in the Default Router List;
781 * The Default Router List should be in the descending order
782 * of router-preferece. Routers with the same preference are
--- 7 unchanged lines hidden (view full) ---
790 }
791 if (dr)
792 TAILQ_INSERT_BEFORE(dr, n, dr_entry);
793 else
794 TAILQ_INSERT_TAIL(&V_nd_defrouter, n, dr_entry);
795
796 defrouter_select();
797
798 return (n);
799}
800
801static struct nd_pfxrouter *
802pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
803{
804 struct nd_pfxrouter *search;
805
--- 46 unchanged lines hidden (view full) ---
852}
853
854int
855nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
856 struct nd_prefix **newp)
857{
858 struct nd_prefix *new = NULL;
859 int error = 0;
860 int i;
861 char ip6buf[INET6_ADDRSTRLEN];
862
863 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
864 if (new == NULL)
865 return(ENOMEM);
866 bzero(new, sizeof(*new));
867 new->ndpr_ifp = pr->ndpr_ifp;
868 new->ndpr_prefix = pr->ndpr_prefix;
--- 12 unchanged lines hidden (view full) ---
881 /* initialization */
882 LIST_INIT(&new->ndpr_advrtrs);
883 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
884 /* make prefix in the canonical form */
885 for (i = 0; i < 4; i++)
886 new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
887 new->ndpr_mask.s6_addr32[i];
888
889 /* link ndpr_entry to nd_prefix list */
890 LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry);
891
892 /* ND_OPT_PI_FLAG_ONLINK processing */
893 if (new->ndpr_raf_onlink) {
894 int e;
895
896 if ((e = nd6_prefix_onlink(new)) != 0) {
897 nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
898 "the prefix %s/%d on-link on %s (errno=%d)\n",
--- 8 unchanged lines hidden (view full) ---
907
908 return 0;
909}
910
911void
912prelist_remove(struct nd_prefix *pr)
913{
914 struct nd_pfxrouter *pfr, *next;
915 int e;
916 char ip6buf[INET6_ADDRSTRLEN];
917
918 /* make sure to invalidate the prefix until it is really freed. */
919 pr->ndpr_vltime = 0;
920 pr->ndpr_pltime = 0;
921
922 /*
923 * Though these flags are now meaningless, we'd rather keep the value
--- 8 unchanged lines hidden (view full) ---
932 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
933 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
934 /* what should we do? */
935 }
936
937 if (pr->ndpr_refcnt > 0)
938 return; /* notice here? */
939
940 /* unlink ndpr_entry from nd_prefix list */
941 LIST_REMOVE(pr, ndpr_entry);
942
943 /* free list of routers that adversed the prefix */
944 LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) {
945 free(pfr, M_IP6NDP);
946 }
947 free(pr, M_IP6NDP);
948
949 pfxlist_onlink_check();
950}
951
952/*
953 * dr - may be NULL
954 */
955
956static int
957prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
958 struct mbuf *m, int mcast)
959{
960 struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL;
961 struct ifaddr *ifa;
962 struct ifnet *ifp = new->ndpr_ifp;
963 struct nd_prefix *pr;
964 int error = 0;
965 int newprefix = 0;
966 int auth;
967 struct in6_addrlifetime lt6_tmp;
968 char ip6buf[INET6_ADDRSTRLEN];
969
970 auth = 0;
971 if (m) {
--- 308 unchanged lines hidden (view full) ---
1280 pfxlist_onlink_check();
1281 } else {
1282 /* just set an error. do not bark here. */
1283 error = EADDRNOTAVAIL; /* XXX: might be unused. */
1284 }
1285 }
1286
1287 end:
1288 return error;
1289}
1290
1291/*
1292 * A supplement function used in the on-link detection below;
1293 * detect if a given prefix has a (probably) reachable advertising router.
1294 * XXX: lengthy function name...
1295 */
--- 786 unchanged lines hidden (view full) ---
2082 * XXX: this function causes search through all entries of routing table, so
2083 * it shouldn't be called when acting as a router.
2084 */
2085void
2086rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
2087{
2088 struct radix_node_head *rnh;
2089 u_int fibnum;
2090
2091 /* We'll care only link-local addresses */
2092 if (!IN6_IS_ADDR_LINKLOCAL(gateway))
2093 return;
2094
2095 /* XXX Do we really need to walk any but the default FIB? */
2096 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
2097 rnh = rt_tables_get_rnh(fibnum, AF_INET6);
2098 if (rnh == NULL)
2099 continue;
2100
2101 RADIX_NODE_HEAD_LOCK(rnh);
2102 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
2103 RADIX_NODE_HEAD_UNLOCK(rnh);
2104 }
2105}
2106
2107static int
2108rt6_deleteroute(struct radix_node *rn, void *arg)
2109{
2110#define SIN6(s) ((struct sockaddr_in6 *)s)
2111 struct rtentry *rt = (struct rtentry *)rn;
2112 struct in6_addr *gate = (struct in6_addr *)arg;
--- 55 unchanged lines hidden ---
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
--- 16 unchanged lines hidden (view full) ---
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/netinet6/nd6_rtr.c 241686 2012-10-18 13:57:24Z andre $");
34
35#include "opt_inet.h"
36#include "opt_inet6.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/mbuf.h>
--- 426 unchanged lines hidden (view full) ---
468 ifa_free(ifa);
469}
470
471static void
472defrouter_addreq(struct nd_defrouter *new)
473{
474 struct sockaddr_in6 def, mask, gate;
475 struct rtentry *newrt = NULL;
476 int error;
477
478 bzero(&def, sizeof(def));
479 bzero(&mask, sizeof(mask));
480 bzero(&gate, sizeof(gate));
481
482 def.sin6_len = mask.sin6_len = gate.sin6_len =
483 sizeof(struct sockaddr_in6);
484 def.sin6_family = gate.sin6_family = AF_INET6;
485 gate.sin6_addr = new->rtaddr;
486
487 error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&def,
488 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
489 RTF_GATEWAY, &newrt, RT_DEFAULT_FIB);
490 if (newrt) {
491 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
492 RTFREE(newrt);
493 }
494 if (error == 0)
495 new->installed = 1;
496 return;
497}
498
499struct nd_defrouter *
500defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp)
501{
502 struct nd_defrouter *dr;
503
--- 112 unchanged lines hidden (view full) ---
616 * At this moment, we do not try to install more than one default router,
617 * even when the multipath routing is available, because we're not sure about
618 * the benefits for stub hosts comparing to the risk of making the code
619 * complicated and the possibility of introducing bugs.
620 */
621void
622defrouter_select(void)
623{
624 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
625 struct llentry *ln = NULL;
626
627 /*
628 * Let's handle easy case (3) first:
629 * If default router list is empty, there's nothing to be done.
630 */
631 if (TAILQ_EMPTY(&V_nd_defrouter))
632 return;
633
634 /*
635 * Search for a (probably) reachable router from the list.
636 * We just pick up the first reachable one (if any), assuming that
637 * the ordering rule of the list described in defrtrlist_update().
638 */
639 TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
640 IF_AFDATA_LOCK(dr->ifp);
--- 47 unchanged lines hidden (view full) ---
688 * Note that the selected router is never NULL here.
689 */
690 if (installed_dr != selected_dr) {
691 if (installed_dr)
692 defrouter_delreq(installed_dr);
693 defrouter_addreq(selected_dr);
694 }
695
696 return;
697}
698
699/*
700 * for default router selection
701 * regards router-preference field as a 2-bit signed integer
702 */
703static int
--- 18 unchanged lines hidden (view full) ---
722 }
723 /* NOTREACHED */
724}
725
726static struct nd_defrouter *
727defrtrlist_update(struct nd_defrouter *new)
728{
729 struct nd_defrouter *dr, *n;
730
731 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
732 /* entry exists */
733 if (new->rtlifetime == 0) {
734 defrtrlist_del(dr);
735 dr = NULL;
736 } else {
737 int oldpref = rtpref(dr);
738
739 /* override */
740 dr->flags = new->flags; /* xxx flag check */
741 dr->rtlifetime = new->rtlifetime;
742 dr->expire = new->expire;
743
744 /*
745 * If the preference does not change, there's no need
746 * to sort the entries. Also make sure the selected
747 * router is still installed in the kernel.
748 */
749 if (dr->installed && rtpref(new) == oldpref)
750 return (dr);
751
752 /*
753 * preferred router may be changed, so relocate
754 * this router.
755 * XXX: calling TAILQ_REMOVE directly is a bad manner.
756 * However, since defrtrlist_del() has many side
757 * effects, we intentionally do so here.
758 * defrouter_select() below will handle routing
759 * changes later.
760 */
761 TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry);
762 n = dr;
763 goto insert;
764 }
765 return (dr);
766 }
767
768 /* entry does not exist */
769 if (new->rtlifetime == 0)
770 return (NULL);
771
772 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
773 if (n == NULL)
774 return (NULL);
775 bzero(n, sizeof(*n));
776 *n = *new;
777
778insert:
779 /*
780 * Insert the new router in the Default Router List;
781 * The Default Router List should be in the descending order
782 * of router-preferece. Routers with the same preference are
--- 7 unchanged lines hidden (view full) ---
790 }
791 if (dr)
792 TAILQ_INSERT_BEFORE(dr, n, dr_entry);
793 else
794 TAILQ_INSERT_TAIL(&V_nd_defrouter, n, dr_entry);
795
796 defrouter_select();
797
798 return (n);
799}
800
801static struct nd_pfxrouter *
802pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
803{
804 struct nd_pfxrouter *search;
805
--- 46 unchanged lines hidden (view full) ---
852}
853
854int
855nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
856 struct nd_prefix **newp)
857{
858 struct nd_prefix *new = NULL;
859 int error = 0;
860 int i;
861 char ip6buf[INET6_ADDRSTRLEN];
862
863 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
864 if (new == NULL)
865 return(ENOMEM);
866 bzero(new, sizeof(*new));
867 new->ndpr_ifp = pr->ndpr_ifp;
868 new->ndpr_prefix = pr->ndpr_prefix;
--- 12 unchanged lines hidden (view full) ---
881 /* initialization */
882 LIST_INIT(&new->ndpr_advrtrs);
883 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
884 /* make prefix in the canonical form */
885 for (i = 0; i < 4; i++)
886 new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
887 new->ndpr_mask.s6_addr32[i];
888
889 /* link ndpr_entry to nd_prefix list */
890 LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry);
891
892 /* ND_OPT_PI_FLAG_ONLINK processing */
893 if (new->ndpr_raf_onlink) {
894 int e;
895
896 if ((e = nd6_prefix_onlink(new)) != 0) {
897 nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
898 "the prefix %s/%d on-link on %s (errno=%d)\n",
--- 8 unchanged lines hidden (view full) ---
907
908 return 0;
909}
910
911void
912prelist_remove(struct nd_prefix *pr)
913{
914 struct nd_pfxrouter *pfr, *next;
915 int e;
916 char ip6buf[INET6_ADDRSTRLEN];
917
918 /* make sure to invalidate the prefix until it is really freed. */
919 pr->ndpr_vltime = 0;
920 pr->ndpr_pltime = 0;
921
922 /*
923 * Though these flags are now meaningless, we'd rather keep the value
--- 8 unchanged lines hidden (view full) ---
932 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
933 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
934 /* what should we do? */
935 }
936
937 if (pr->ndpr_refcnt > 0)
938 return; /* notice here? */
939
940 /* unlink ndpr_entry from nd_prefix list */
941 LIST_REMOVE(pr, ndpr_entry);
942
943 /* free list of routers that adversed the prefix */
944 LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) {
945 free(pfr, M_IP6NDP);
946 }
947 free(pr, M_IP6NDP);
948
949 pfxlist_onlink_check();
950}
951
952/*
953 * dr - may be NULL
954 */
955
956static int
957prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
958 struct mbuf *m, int mcast)
959{
960 struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL;
961 struct ifaddr *ifa;
962 struct ifnet *ifp = new->ndpr_ifp;
963 struct nd_prefix *pr;
964 int error = 0;
965 int newprefix = 0;
966 int auth;
967 struct in6_addrlifetime lt6_tmp;
968 char ip6buf[INET6_ADDRSTRLEN];
969
970 auth = 0;
971 if (m) {
--- 308 unchanged lines hidden (view full) ---
1280 pfxlist_onlink_check();
1281 } else {
1282 /* just set an error. do not bark here. */
1283 error = EADDRNOTAVAIL; /* XXX: might be unused. */
1284 }
1285 }
1286
1287 end:
1288 return error;
1289}
1290
1291/*
1292 * A supplement function used in the on-link detection below;
1293 * detect if a given prefix has a (probably) reachable advertising router.
1294 * XXX: lengthy function name...
1295 */
--- 786 unchanged lines hidden (view full) ---
2082 * XXX: this function causes search through all entries of routing table, so
2083 * it shouldn't be called when acting as a router.
2084 */
2085void
2086rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
2087{
2088 struct radix_node_head *rnh;
2089 u_int fibnum;
2090
2091 /* We'll care only link-local addresses */
2092 if (!IN6_IS_ADDR_LINKLOCAL(gateway))
2093 return;
2094
2095 /* XXX Do we really need to walk any but the default FIB? */
2096 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
2097 rnh = rt_tables_get_rnh(fibnum, AF_INET6);
2098 if (rnh == NULL)
2099 continue;
2100
2101 RADIX_NODE_HEAD_LOCK(rnh);
2102 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
2103 RADIX_NODE_HEAD_UNLOCK(rnh);
2104 }
2105}
2106
2107static int
2108rt6_deleteroute(struct radix_node *rn, void *arg)
2109{
2110#define SIN6(s) ((struct sockaddr_in6 *)s)
2111 struct rtentry *rt = (struct rtentry *)rn;
2112 struct in6_addr *gate = (struct in6_addr *)arg;
--- 55 unchanged lines hidden ---