diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-02-02 17:16:53 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-02-02 17:16:53 +0000 |
commit | bd7ba2ee16046dabae7b31d1d7c34e7bfebe939d (patch) | |
tree | 0c7120f17c6ae301153d446900e618e6eda00297 | |
parent | 6dbfa5790df49b345a7ac351f0efb65b9dad30ef (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.c | 32 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 25 | ||||
-rw-r--r-- | sys/netinet6/in6_var.h | 3 |
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 *)); |