summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-02-07 06:05:42 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-02-07 06:05:42 +0000
commit449cfd223309afe74d6c4a8c341a74fbd9a011c2 (patch)
treefd95418bc047bda934829f1a130b50b96f224d30 /sys
parentad8ebcb6758d6b40520726074fd595ecb6ac70f4 (diff)
remove prefix information in the kernel when all matching in6_ifaddr are gone.
fix include file path.
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet6/in6_prefix.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/sys/netinet6/in6_prefix.c b/sys/netinet6/in6_prefix.c
index 16432409507..d6dcfc8fbf3 100644
--- a/sys/netinet6/in6_prefix.c
+++ b/sys/netinet6/in6_prefix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_prefix.c,v 1.3 2000/02/04 18:13:36 itojun Exp $ */
+/* $OpenBSD: in6_prefix.c,v 1.4 2000/02/07 06:05:41 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -79,7 +79,7 @@
#include <netinet/in.h>
#include <netinet/in_var.h>
-#include <netinet6/ip6.h>
+#include <netinet/ip6.h>
#include <netinet6/in6_prefix.h>
#include <netinet6/ip6_var.h>
@@ -87,10 +87,13 @@ struct rr_prhead rr_prefix;
#include <net/net_osdep.h>
+static void add_each_addr __P((struct socket *so, struct rr_prefix *rpp,
+ struct rp_addr *rap));
static int create_ra_entry __P((struct rp_addr **rapp));
static int add_each_prefix __P((struct socket *so, struct rr_prefix *rpp));
static void free_rp_entries __P((struct rr_prefix *rpp));
static int link_stray_ia6s __P((struct rr_prefix *rpp));
+static void rp_remove __P((struct rr_prefix *rpp));
/*
* Copy bits from src to tgt, from off bit for len bits.
@@ -393,6 +396,34 @@ assigne_ra_entry(struct rr_prefix *rpp, int iilen, struct in6_ifaddr *ia)
return 0;
}
+static int
+in6_prefix_add_llifid(int iilen, struct in6_ifaddr *ia)
+{
+ struct rr_prefix *rpp;
+ struct rp_addr *rap;
+ struct socket so;
+ int error, s;
+
+ if ((error = create_ra_entry(&rap)) != 0)
+ return(error);
+ /* copy interface id part */
+ bit_copy((caddr_t)&rap->ra_ifid, sizeof(rap->ra_ifid) << 3,
+ (caddr_t)IA6_IN6(ia), sizeof(*IA6_IN6(ia)) << 3,
+ 64, (sizeof(rap->ra_ifid) << 3) - 64);
+ /* XXX: init dummy so */
+ bzero(&so, sizeof(so));
+ /* insert into list */
+ for (rpp = LIST_FIRST(&rr_prefix); rpp; rpp = LIST_NEXT(rpp, rp_entry))
+ {
+ s = splnet();
+ LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
+ splx(s);
+ add_each_addr(&so, rpp, rap);
+ }
+ return 0;
+}
+
+
int
in6_prefix_add_ifid(int iilen, struct in6_ifaddr *ia)
{
@@ -401,6 +432,8 @@ in6_prefix_add_ifid(int iilen, struct in6_ifaddr *ia)
struct rp_addr *rap;
int error = 0;
+ if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia)))
+ return(in6_prefix_add_llifid(iilen, ia));
ifpr = in6_prefixwithifp(ia->ia_ifp, plen, IA6_IN6(ia));
if (ifpr == NULL) {
struct rr_prefix rp;
@@ -487,6 +520,8 @@ in6_prefix_remove_ifid(int iilen, struct in6_ifaddr *ia)
splx(s);
free(rap, M_RR_ADDR);
}
+ if (LIST_FIRST(&ifpr2rp(ia->ia6_ifpr)->rp_addrhead) == NULL)
+ rp_remove(ifpr2rp(ia->ia6_ifpr));
}
void
@@ -1032,11 +1067,20 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
free_rp_entries(&rp_tmp);
break;
}
- ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp);
- if (ifa != NULL) {
+ for (ifa = ifp->if_addrlist.tqh_first;
+ ifa;
+ ifa = ifa->ifa_list.tqe_next)
+ {
+ if (ifa->ifa_addr == NULL)
+ continue; /* just for safety */
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa)) == 0)
+ continue;
+
if ((error = create_ra_entry(&rap)) != 0) {
free_rp_entries(&rp_tmp);
- break;
+ goto bad;
}
/* copy interface id part */
bit_copy((caddr_t)&rap->ra_ifid,
@@ -1063,6 +1107,7 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
error = delete_each_prefix(rpp, ipr->ipr_origin);
break;
}
+ bad:
return error;
}