summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet6/in6.c116
-rw-r--r--sys/netinet6/in6_ifattach.c16
-rw-r--r--sys/netinet6/in6_prefix.c77
-rw-r--r--sys/netinet6/in6_prefix.h5
-rw-r--r--sys/netinet6/in6_var.h4
-rw-r--r--sys/netinet6/nd6.c99
-rw-r--r--sys/netinet6/nd6.h3
7 files changed, 210 insertions, 110 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 319ced98ec6..90247dbbb76 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.c,v 1.11 2000/02/02 17:53:52 itojun Exp $ */
+/* $OpenBSD: in6.c,v 1.12 2000/02/04 18:13:35 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -739,6 +739,7 @@ in6_control(so, cmd, data, ifp, p)
if ((ifp->if_flags & IFF_POINTOPOINT) &&
(ifra->ifra_dstaddr.sin6_family == AF_INET6)) {
in6_ifscrub(ifp, ia);
+ oldaddr = ia->ia_dstaddr;
ia->ia_dstaddr = ifra->ifra_dstaddr;
/* link-local index check: should be a separate function? */
if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
@@ -846,59 +847,7 @@ in6_control(so, cmd, data, ifp, p)
return(error);
case SIOCDIFADDR_IN6:
- in6_ifscrub(ifp, ia);
-
- if (ifp->if_flags & IFF_MULTICAST) {
- /*
- * delete solicited multicast addr for deleting host id
- */
- struct in6_multi *in6m;
- struct in6_addr llsol;
- bzero(&llsol, sizeof(struct in6_addr));
- llsol.s6_addr16[0] = htons(0xff02);
- llsol.s6_addr16[1] = htons(ifp->if_index);
- llsol.s6_addr32[1] = 0;
- llsol.s6_addr32[2] = htonl(1);
- llsol.s6_addr32[3] =
- ia->ia_addr.sin6_addr.s6_addr32[3];
- llsol.s6_addr8[12] = 0xff;
-
- IN6_LOOKUP_MULTI(llsol, ifp, in6m);
- if (in6m)
- in6_delmulti(in6m);
- }
- /* Leave dstaddr's solicited multicast if necessary. */
- if (nd6_proxyall)
- in6_ifremproxy(ia);
-
- TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
- oia = ia;
- if (oia == (ia = in6_ifaddr))
- in6_ifaddr = ia->ia_next;
- else {
- while (ia->ia_next && (ia->ia_next != oia))
- ia = ia->ia_next;
- if (ia->ia_next)
- ia->ia_next = oia->ia_next;
- else
- printf("Didn't unlink in6_ifaddr from list\n");
- }
- {
- int iilen;
-
- iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
- in6_mask2len(&oia->ia_prefixmask.sin6_addr);
- in6_prefix_remove_ifid(iilen, oia);
- }
-
- if (oia->ia6_multiaddrs.lh_first == NULL) {
- IFAFREE(&oia->ia_ifa);
- break;
- }
- else
- in6_savemkludge(oia);
-
- IFAFREE((&oia->ia_ifa));
+ in6_purgeaddr(&ia->ia_ifa, ifp);
break;
default:
@@ -909,6 +858,65 @@ in6_control(so, cmd, data, ifp, p)
return(0);
}
+void
+in6_purgeaddr(ifa, ifp)
+ struct ifaddr *ifa;
+ struct ifnet *ifp;
+{
+ struct in6_ifaddr *oia, *ia = (void *) ifa;
+
+ in6_ifscrub(ifp, ia);
+
+ if (ifp->if_flags & IFF_MULTICAST) {
+ /*
+ * delete solicited multicast addr for deleting host id
+ */
+ struct in6_multi *in6m;
+ struct in6_addr llsol;
+ bzero(&llsol, sizeof(struct in6_addr));
+ llsol.s6_addr16[0] = htons(0xff02);
+ llsol.s6_addr16[1] = htons(ifp->if_index);
+ llsol.s6_addr32[1] = 0;
+ llsol.s6_addr32[2] = htonl(1);
+ llsol.s6_addr32[3] =
+ ia->ia_addr.sin6_addr.s6_addr32[3];
+ llsol.s6_addr8[12] = 0xff;
+
+ IN6_LOOKUP_MULTI(llsol, ifp, in6m);
+ if (in6m)
+ in6_delmulti(in6m);
+ }
+ /* Leave dstaddr's solicited multicast if necessary. */
+ if (nd6_proxyall)
+ in6_ifremproxy(ia);
+
+ TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
+ IFAFREE(&ia->ia_ifa);
+
+ oia = ia;
+ if (oia == (ia = in6_ifaddr))
+ in6_ifaddr = ia->ia_next;
+ else {
+ while (ia->ia_next && (ia->ia_next != oia))
+ ia = ia->ia_next;
+ if (ia->ia_next)
+ ia->ia_next = oia->ia_next;
+ else
+ printf("Didn't unlink in6_ifaddr from list\n");
+ }
+ {
+ int iilen;
+
+ iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
+ in6_mask2len(&oia->ia_prefixmask.sin6_addr);
+ in6_prefix_remove_ifid(iilen, oia);
+ }
+ if (oia->ia6_multiaddrs.lh_first != NULL)
+ in6_savemkludge(oia);
+
+ IFAFREE(&oia->ia_ifa);
+}
+
/*
* SIOC[GAD]LIFADDR.
* SIOCGLIFADDR: get first address. (???)
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 6e85d16d3d8..9ed1318d7b0 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_ifattach.c,v 1.4 2000/02/02 17:16:52 itojun Exp $ */
+/* $OpenBSD: in6_ifattach.c,v 1.5 2000/02/04 18:13:36 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -625,6 +625,13 @@ in6_ifdetach(ifp)
struct rtentry *rt;
short rtflags;
struct sockaddr_in6 sin6;
+ struct in6_multi *in6m;
+
+ /* nuke prefix list. this may try to remove some of ifaddrs as well */
+ in6_purgeprefix(ifp);
+
+ /* remove neighbor management table */
+ nd6_purge(ifp);
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
{
@@ -635,6 +642,10 @@ in6_ifdetach(ifp)
ia = (struct in6_ifaddr *)ifa;
+ /* leave from all multicast groups joined */
+ while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL)
+ in6_delmulti(in6m);
+
/* remove from the routing table */
if ((ia->ia_flags & IFA_ROUTE)
&& (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
@@ -672,6 +683,9 @@ in6_ifdetach(ifp)
/* cleanup multicast address kludge table, if there is any */
in6_purgemkludge(ifp);
+ /* remove neighbor management table */
+ nd6_purge(ifp);
+
/* remove route to link-local allnodes multicast (ff02::1) */
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
diff --git a/sys/netinet6/in6_prefix.c b/sys/netinet6/in6_prefix.c
index 3ccd022f746..16432409507 100644
--- a/sys/netinet6/in6_prefix.c
+++ b/sys/netinet6/in6_prefix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_prefix.c,v 1.2 1999/12/10 10:04:28 angelos Exp $ */
+/* $OpenBSD: in6_prefix.c,v 1.3 2000/02/04 18:13:36 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -205,7 +205,7 @@ search_matched_prefix(struct ifnet *ifp, struct in6_prefixreq *ipr)
}
if (ifpr != NULL)
log(LOG_ERR, "in6_prefix.c: search_matched_prefix: addr %s"
- "has no pointer to prefix %s", ip6_sprintf(IFA_IN6(ifa)),
+ "has no pointer to prefix %s\n", ip6_sprintf(IFA_IN6(ifa)),
ip6_sprintf(IFPR_IN6(ifpr)));
return ifpr2rp(ifpr);
}
@@ -263,7 +263,7 @@ mark_matched_prefixes(u_long cmd, struct ifnet *ifp, struct in6_rrenumreq *irr)
} else
log(LOG_WARNING, "in6_prefix.c: mark_matched_prefixes:"
"no back pointer to ifprefix for %s. "
- "ND autoconfigured addr?",
+ "ND autoconfigured addr?\n",
ip6_sprintf(IFA_IN6(ifa)));
}
return matched;
@@ -458,7 +458,7 @@ in6_prefix_add_ifid(int iilen, struct in6_ifaddr *ia)
else if (rap->ra_addr != ia) {
/* There may be some inconsistencies between addrs. */
log(LOG_ERR, "ip6_prefix.c: addr %s/%d matched prefix"
- "has already another ia %p(%s) on its ifid list",
+ "has already another ia %p(%s) on its ifid list\n",
ip6_sprintf(IA6_IN6(ia)), plen,
rap->ra_addr,
ip6_sprintf(IA6_IN6(rap->ra_addr)));
@@ -489,6 +489,22 @@ in6_prefix_remove_ifid(int iilen, struct in6_ifaddr *ia)
}
}
+void
+in6_purgeprefix(ifp)
+ struct ifnet *ifp;
+{
+ struct ifprefix *ifpr, *nextifpr;
+
+ /* delete prefixes before ifnet goes away */
+ for (ifpr = ifp->if_prefixlist; ifpr; ifpr = nextifpr) {
+ nextifpr = ifpr->ifpr_next;
+ if (ifpr->ifpr_prefix->sa_family != AF_INET6 ||
+ ifpr->ifpr_type != IN6_PREFIX_RR)
+ continue;
+ (void)delete_each_prefix(ifpr2rp(ifpr), PR_ORIG_KERNEL);
+ }
+}
+
static void
add_each_addr(struct socket *so, struct rr_prefix *rpp, struct rp_addr *rap)
{
@@ -539,7 +555,7 @@ add_each_addr(struct socket *so, struct rr_prefix *rpp, struct rp_addr *rap)
* log it and return.
*/
log(LOG_ERR, "in6_prefix.c: add_each_addr: addition of an addr"
- "%s/%d failed because there is already another addr %s/%d",
+ "%s/%d failed because there is already another addr %s/%d\n",
ip6_sprintf(&ifra.ifra_addr.sin6_addr), rpp->rp_plen,
ip6_sprintf(IA6_IN6(ia6)),
in6_mask2len(&ia6->ia_prefixmask.sin6_addr));
@@ -548,10 +564,11 @@ add_each_addr(struct socket *so, struct rr_prefix *rpp, struct rp_addr *rap)
/* propagate ANYCAST flag if it is set for ancestor addr */
if (rap->ra_flags.anycast != 0)
ifra.ifra_flags |= IN6_IFF_ANYCAST;
- error = in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, rpp->rp_ifp, curproc);
+ error = in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, rpp->rp_ifp
+ , curproc);
if (error != 0)
log(LOG_ERR, "in6_prefix.c: add_each_addr: addition of an addr"
- "%s/%d failed because in6_control failed for error %d",
+ "%s/%d failed because in6_control failed for error %d\n",
ip6_sprintf(&ifra.ifra_addr.sin6_addr), rpp->rp_plen,
error);
return;
@@ -628,7 +645,7 @@ rrpr_update(struct socket *so, struct rr_prefix *new)
M_NOWAIT);
if (rpp == NULL) {
log(LOG_ERR, "in6_prefix.c: rrpr_update:%d"
- ": ENOBUFS for rr_prefix", __LINE__);
+ ": ENOBUFS for rr_prefix\n", __LINE__);
return(ENOBUFS);
}
/* initilization */
@@ -728,7 +745,7 @@ create_ra_entry(struct rp_addr **rapp)
M_NOWAIT);
if (*rapp == NULL) {
log(LOG_ERR, "in6_prefix.c: init_newprefix:%d: ENOBUFS"
- "for rp_addr", __LINE__);
+ "for rp_addr\n", __LINE__);
return ENOBUFS;
}
bzero(*rapp, sizeof(*(*rapp)));
@@ -845,9 +862,8 @@ unprefer_prefix(struct rr_prefix *rpp)
}
int
-delete_each_prefix(struct socket *so, struct rr_prefix *rpp, u_char origin)
+delete_each_prefix(struct rr_prefix *rpp, u_char origin)
{
- struct in6_aliasreq ifra;
int error = 0;
if (rpp->rp_origin > origin)
@@ -869,22 +885,7 @@ delete_each_prefix(struct socket *so, struct rr_prefix *rpp, u_char origin)
}
rap->ra_addr->ia6_ifpr = NULL;
- bzero(&ifra, sizeof(ifra));
- strncpy(ifra.ifra_name, if_name(rpp->rp_ifp),
- sizeof(ifra.ifra_name));
- ifra.ifra_addr = rap->ra_addr->ia_addr;
- ifra.ifra_dstaddr = rap->ra_addr->ia_dstaddr;
- ifra.ifra_prefixmask = rap->ra_addr->ia_prefixmask;
-
- error = in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
- rpp->rp_ifp, curproc);
- if (error != 0)
- log(LOG_ERR, "in6_prefix.c: delete_each_prefix:"
- "deletion of an addr %s/%d failed because"
- "in6_control failed for error %d",
- ip6_sprintf(&ifra.ifra_addr.sin6_addr),
- rpp->rp_plen, error);
-
+ in6_purgeaddr(&rap->ra_addr->ia_ifa, rpp->rp_ifp);
free(rap, M_RR_ADDR);
}
rp_remove(rpp);
@@ -893,7 +894,7 @@ delete_each_prefix(struct socket *so, struct rr_prefix *rpp, u_char origin)
}
static void
-delete_prefixes(struct socket *so, struct ifnet *ifp, u_char origin)
+delete_prefixes(struct ifnet *ifp, u_char origin)
{
struct ifprefix *ifpr, *nextifpr;
@@ -904,7 +905,7 @@ delete_prefixes(struct socket *so, struct ifnet *ifp, u_char origin)
ifpr->ifpr_type != IN6_PREFIX_RR)
continue;
if (ifpr2rp(ifpr)->rp_statef_delmark)
- (void)delete_each_prefix(so, ifpr2rp(ifpr), origin);
+ (void)delete_each_prefix(ifpr2rp(ifpr), origin);
}
}
@@ -931,7 +932,7 @@ link_stray_ia6s(struct rr_prefix *rpp)
rpp->rp_plen))
log(LOG_ERR, "in6_prefix.c: link_stray_ia6s:"
"addr %s/%d already linked to a prefix"
- "and it matches also %s/%d",
+ "and it matches also %s/%d\n",
ip6_sprintf(IFA_IN6(ifa)), orpp->rp_plen,
ip6_sprintf(RP_IN6(rpp)),
rpp->rp_plen);
@@ -946,6 +947,7 @@ link_stray_ia6s(struct rr_prefix *rpp)
return 0;
}
+/* XXX assumes that permission is already checked by the caller */
int
in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
struct ifnet *ifp)
@@ -974,7 +976,7 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
if (irr->irr_pltime > irr->irr_vltime) {
log(LOG_NOTICE,
"in6_prefix_ioctl: preferred lifetime"
- "(%ld) is greater than valid lifetime(%ld)",
+ "(%ld) is greater than valid lifetime(%ld)\n",
(u_long)irr->irr_pltime, (u_long)irr->irr_vltime);
error = EINVAL;
break;
@@ -985,7 +987,7 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
!= 0)
goto failed;
if (cmd != SIOCAIFPREFIX_IN6)
- delete_prefixes(so, ifp, irr->irr_origin);
+ delete_prefixes(ifp, irr->irr_origin);
} else
return (EADDRNOTAVAIL);
failed:
@@ -1009,7 +1011,7 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
if (ipr->ipr_pltime > ipr->ipr_vltime) {
log(LOG_NOTICE,
"in6_prefix_ioctl: preferred lifetime"
- "(%ld) is greater than valid lifetime(%ld)",
+ "(%ld) is greater than valid lifetime(%ld)\n",
(u_long)ipr->ipr_pltime, (u_long)ipr->ipr_vltime);
error = EINVAL;
break;
@@ -1058,7 +1060,7 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
if (rpp == NULL || ifp != rpp->rp_ifp)
return (EADDRNOTAVAIL);
- error = delete_each_prefix(so, rpp, ipr->ipr_origin);
+ error = delete_each_prefix(rpp, ipr->ipr_origin);
break;
}
return error;
@@ -1079,14 +1081,9 @@ in6_rr_timer(void *ignored_arg)
while (rpp) {
if (rpp->rp_expire && rpp->rp_expire < time_second) {
struct rr_prefix *next_rpp;
- struct socket so;
-
- /* XXX: init dummy so */
- bzero(&so, sizeof(so));
- so.so_state |= SS_PRIV;
next_rpp = LIST_NEXT(rpp, rp_entry);
- delete_each_prefix(&so, rpp, PR_ORIG_KERNEL);
+ delete_each_prefix(rpp, PR_ORIG_KERNEL);
rpp = next_rpp;
continue;
}
diff --git a/sys/netinet6/in6_prefix.h b/sys/netinet6/in6_prefix.h
index d8f0484b488..f6856a61aa9 100644
--- a/sys/netinet6/in6_prefix.h
+++ b/sys/netinet6/in6_prefix.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_prefix.h,v 1.1 1999/12/08 06:50:21 itojun Exp $ */
+/* $OpenBSD: in6_prefix.h,v 1.2 2000/02/04 18:13:36 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998 and 1999 WIDE Project.
@@ -84,5 +84,4 @@ LIST_HEAD(rr_prhead, rr_prefix);
extern struct rr_prhead rr_prefix;
void in6_rr_timer __P((void *));
-int delete_each_prefix __P((struct socket *so, struct rr_prefix *rpp,
- u_char origin));
+int delete_each_prefix __P((struct rr_prefix *rpp, u_char origin));
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 1b4720f9040..3002c2c5e6a 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_var.h,v 1.7 2000/02/02 17:16:52 itojun Exp $ */
+/* $OpenBSD: in6_var.h,v 1.8 2000/02/04 18:13:36 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -544,6 +544,7 @@ extern int in6_mask2len __P((struct in6_addr *));
extern void in6_len2mask __P((struct in6_addr *, int));
int in6_control __P((struct socket *,
u_long, caddr_t, struct ifnet *, struct proc *));
+void in6_purgeaddr __P((struct ifaddr *, struct ifnet *));
void in6_savemkludge __P((struct in6_ifaddr *));
void in6_setmaxmtu __P((void));
void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *));
@@ -560,6 +561,7 @@ int in6_prefix_ioctl __P((struct socket *so, u_long cmd, caddr_t data,
struct ifnet *ifp));
int in6_prefix_add_ifid __P((int iilen, struct in6_ifaddr *ia));
void in6_prefix_remove_ifid __P((int iilen, struct in6_ifaddr *ia));
+void in6_purgeprefix __P((struct ifnet *));
#endif /* _KERNEL */
#endif /* _NETINET6_IN6_VAR_H_ */
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 9e11a477cd1..3555c8dd905 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.c,v 1.4 2000/01/08 05:49:41 angelos Exp $ */
+/* $OpenBSD: nd6.c,v 1.5 2000/02/04 18:13:36 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -529,6 +529,94 @@ nd6_timer(ignored_arg)
splx(s);
}
+/*
+ * Nuke neighbor cache/prefix/default router management table, right before
+ * ifp goes away.
+ */
+void
+nd6_purge(ifp)
+ struct ifnet *ifp;
+{
+ struct llinfo_nd6 *ln, *nln;
+ struct nd_defrouter *dr, *ndr, drany;
+ struct nd_prefix *pr, *npr;
+
+ /* Nuke default router list entries toward ifp */
+ if ((dr = nd_defrouter.lh_first) != NULL) {
+ /*
+ * The first entry of the list may be stored in
+ * the routing table, so we'll delete it later.
+ */
+ for (dr = dr->dr_next; dr; dr = ndr) {
+ ndr = dr->dr_next;
+ if (dr->ifp == ifp)
+ defrtrlist_del(dr);
+ }
+ dr = nd_defrouter.lh_first;
+ if (dr->ifp == ifp)
+ defrtrlist_del(dr);
+ }
+
+ /* Nuke prefix list entries toward ifp */
+ for (pr = nd_prefix.lh_first; pr; pr = npr) {
+ npr = pr->ndpr_next;
+ if (pr->ndpr_ifp == ifp) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
+ in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
+ prelist_remove(pr);
+ }
+ }
+
+ /* refresh default router list */
+ bzero(&drany, sizeof(drany));
+ defrouter_delreq(&drany, 0);
+
+ /*
+ * Nuke neighbor cache entries for the ifp.
+ * Note that rt->rt_ifp may not be the same as ifp,
+ * due to KAME goto ours hack. See RTM_RESOLVE case in
+ * nd6_rtrequest(), and ip6_input().
+ */
+ ln = llinfo_nd6.ln_next;
+ while (ln && ln != &llinfo_nd6) {
+ struct rtentry *rt;
+ struct sockaddr_dl *sdl;
+
+ nln = ln->ln_next;
+ rt = ln->ln_rt;
+ if (rt && rt->rt_gateway &&
+ rt->rt_gateway->sa_family == AF_LINK) {
+ sdl = (struct sockaddr_dl *)rt->rt_gateway;
+ if (sdl->sdl_index == ifp->if_index)
+ nd6_free(rt);
+ }
+ ln = nln;
+ }
+
+ /*
+ * Neighbor cache entry for interface route will be retained
+ * with ND6_LLINFO_WAITDELETE state, by nd6_free(). Nuke it.
+ */
+ ln = llinfo_nd6.ln_next;
+ while (ln && ln != &llinfo_nd6) {
+ struct rtentry *rt;
+ struct sockaddr_dl *sdl;
+
+ nln = ln->ln_next;
+ rt = ln->ln_rt;
+ if (rt && rt->rt_gateway &&
+ rt->rt_gateway->sa_family == AF_LINK) {
+ sdl = (struct sockaddr_dl *)rt->rt_gateway;
+ if (sdl->sdl_index == ifp->if_index) {
+ rtrequest(RTM_DELETE, rt_key(rt),
+ (struct sockaddr *)0, rt_mask(rt), 0,
+ (struct rtentry **)0);
+ }
+ }
+ ln = nln;
+ }
+}
+
struct rtentry *
nd6_lookup(addr6, create, ifp)
struct in6_addr *addr6;
@@ -952,14 +1040,10 @@ nd6_rtrequest(req, rt, sa)
ln->ln_expire = time_second;
}
rt->rt_flags |= RTF_LLINFO;
-#if 0
- insque(ln, &llinfo_nd6);
-#else
ln->ln_next = llinfo_nd6.ln_next;
llinfo_nd6.ln_next = ln;
ln->ln_prev = &llinfo_nd6;
ln->ln_next->ln_prev = ln;
-#endif
/*
* check if rt_key(rt) is one of my address assigned
@@ -998,13 +1082,9 @@ nd6_rtrequest(req, rt, sa)
if (!ln)
break;
nd6_inuse--;
-#if 0
- remque(ln);
-#else
ln->ln_next->ln_prev = ln->ln_prev;
ln->ln_prev->ln_next = ln->ln_next;
ln->ln_prev = NULL;
-#endif
rt->rt_llinfo = 0;
rt->rt_flags &= ~RTF_LLINFO;
if (ln->ln_hold)
@@ -1482,7 +1562,6 @@ nd6_slowtimo(ignored_arg)
void *ignored_arg;
{
int s = splnet();
-
register int i;
register struct nd_ifinfo *nd6if;
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index fcc70b0054d..0a89dd38108 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.h,v 1.2 2000/01/08 04:49:22 deraadt Exp $ */
+/* $OpenBSD: nd6.h,v 1.3 2000/02/04 18:13:36 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -255,6 +255,7 @@ int nd6_options __P((union nd_opts *));
struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
void nd6_setmtu __P((struct ifnet *));
void nd6_timer __P((void *));
+void nd6_purge __P((struct ifnet *));
void nd6_free __P((struct rtentry *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *));
int nd6_resolve __P((struct ifnet *, struct rtentry *,