summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-02-02 17:16:53 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-02-02 17:16:53 +0000
commitbd7ba2ee16046dabae7b31d1d7c34e7bfebe939d (patch)
tree0c7120f17c6ae301153d446900e618e6eda00297
parent6dbfa5790df49b345a7ac351f0efb65b9dad30ef (diff)
- improve in6_ifdetach to remove (1) multicast kludge list (2) route to
link-local allnode multicast (ff02:x::/32) - fix ifnet refcnt'ing in multicast kludge list management. - avoid dangling pointer in multicast kludge management. (angelos, try this version of in6_ifdetach() - it should be better)
-rw-r--r--sys/netinet6/in6.c32
-rw-r--r--sys/netinet6/in6_ifattach.c25
-rw-r--r--sys/netinet6/in6_var.h3
3 files changed, 56 insertions, 4 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 144bc1be623..7f3f526445d 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.c,v 1.9 2000/02/02 17:01:50 itojun Exp $ */
+/* $OpenBSD: in6.c,v 1.10 2000/02/02 17:16:52 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -1280,6 +1280,8 @@ in6_savemkludge(oia)
for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
next = in6m->in6m_entry.le_next;
+ IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
+ in6m->in6m_ia = NULL;
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
}
@@ -1310,6 +1312,8 @@ in6_restoremkludge(ia, ifp)
for (in6m = mk->mk_head.lh_first; in6m; in6m = next){
next = in6m->in6m_entry.le_next;
+ in6m->in6m_ia = ia;
+ ia->ia_ifa.ifa_refcnt++;
LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
in6m, in6m_entry);
}
@@ -1320,6 +1324,29 @@ in6_restoremkludge(ia, ifp)
}
}
+void
+in6_purgemkludge(ifp)
+ struct ifnet *ifp;
+{
+ struct multi6_kludge *mk;
+ struct in6_multi *in6m, *next;
+
+ for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
+ if (mk->mk_ifp != ifp)
+ continue;
+
+ for (in6m = mk->mk_head.lh_first; in6m; in6m = next) {
+ next = in6m->in6m_entry.le_next;
+ LIST_REMOVE(in6m, in6m_entry);
+ in6_delmulti(in6m);
+ in6m = NULL;
+ }
+ LIST_REMOVE(mk, mk_entry);
+ free(mk, M_IPMADDR);
+ break;
+ }
+}
+
/*
* Add an address to the list of IP6 multicast addresses for a
* given interface.
@@ -1421,7 +1448,8 @@ in6_delmulti(in6m)
* Unlink from list.
*/
LIST_REMOVE(in6m, in6m_entry);
- IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
+ if (in6m->in6m_ia)
+ IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
/*
* Notify the network driver to update its multicast
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 457e5ca197a..6e85d16d3d8 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_ifattach.c,v 1.3 1999/12/10 12:34:45 itojun Exp $ */
+/* $OpenBSD: in6_ifattach.c,v 1.4 2000/02/02 17:16:52 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -222,6 +222,10 @@ found:
}
}
+/*
+ * XXX multiple loopback interface needs more care. for instance,
+ * nodelocal address needs to be configured onto only one of them.
+ */
void
in6_ifattach(ifp, type, laddr, noloop)
struct ifnet *ifp;
@@ -609,6 +613,9 @@ in6_ifattach(ifp, type, laddr, noloop)
return;
}
+/*
+ * NOTE: in6_ifdetach() does not support loopback if at this moment.
+ */
void
in6_ifdetach(ifp)
struct ifnet *ifp;
@@ -617,6 +624,7 @@ in6_ifdetach(ifp)
struct ifaddr *ifa;
struct rtentry *rt;
short rtflags;
+ struct sockaddr_in6 sin6;
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
{
@@ -660,4 +668,19 @@ in6_ifdetach(ifp)
free(ia, M_IFADDR);
}
+
+ /* cleanup multicast address kludge table, if there is any */
+ in6_purgemkludge(ifp);
+
+ /* remove route to link-local allnodes multicast (ff02::1) */
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = in6addr_linklocal_allnodes;
+ sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
+ if ((rt = rtalloc1((struct sockaddr *)&sin6, 0)) != NULL) {
+ rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
+ rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
+ rtfree(rt);
+ }
}
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 650a82ec2fe..1b4720f9040 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_var.h,v 1.6 1999/12/10 10:04:28 angelos Exp $ */
+/* $OpenBSD: in6_var.h,v 1.7 2000/02/02 17:16:52 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -547,6 +547,7 @@ int in6_control __P((struct socket *,
void in6_savemkludge __P((struct in6_ifaddr *));
void in6_setmaxmtu __P((void));
void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *));
+void in6_purgemkludge __P((struct ifnet *));
struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *));
struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *,
struct in6_addr *));