Exemple #1
0
void
in6_pcbpurgeif0(struct inpcbtable *table, struct ifnet *ifp)
{
	struct in6pcb *in6p, *nin6p;
	struct ip6_moptions *im6o;
	struct in6_multi_mship *imm, *nimm;

	for (in6p = (struct in6pcb *)CIRCLEQ_FIRST(&table->inpt_queue);
	    in6p != (void *)&table->inpt_queue;
	    in6p = nin6p) {
		nin6p = (struct in6pcb *)CIRCLEQ_NEXT(in6p, in6p_queue);
		if (in6p->in6p_af != AF_INET6)
			continue;

		im6o = in6p->in6p_moptions;
		if (im6o) {
			/*
			 * Unselect the outgoing interface if it is being
			 * detached.
			 */
			if (im6o->im6o_multicast_ifp == ifp)
				im6o->im6o_multicast_ifp = NULL;

			/*
			 * Drop multicast group membership if we joined
			 * through the interface being detached.
			 * XXX controversial - is it really legal for kernel
			 * to force this?
			 */
			for (imm = im6o->im6o_memberships.lh_first;
			     imm != NULL; imm = nimm) {
				nimm = imm->i6mm_chain.le_next;
				if (imm->i6mm_maddr->in6m_ifp == ifp) {
					LIST_REMOVE(imm, i6mm_chain);
					in6_leavegroup(imm);
				}
			}
		}
	}
}
Exemple #2
0
/*
 * NOTE: in6_ifdetach() does not support loopback if at this moment.
 * We don't need this function in bsdi, because interfaces are never removed
 * from the ifnet list in bsdi.
 */
void
in6_ifdetach(struct ifnet *ifp)
{
	struct in6_ifaddr *ia, *oia;
	struct ifaddr *ifa, *next;
	struct rtentry *rt;
	short rtflags;
	struct in6_multi_mship *imm;

	/* remove ip6_mrouter stuff */
	ip6_mrouter_detach(ifp);

	/* remove neighbor management table */
	nd6_purge(ifp);

	/* XXX this code is duplicated in in6_purgeif() --dyoung */
	/* nuke any of IPv6 addresses we have */
	if_purgeaddrs(ifp, AF_INET6, in6_purgeaddr);

	/* XXX isn't this code is redundant, given the above? --dyoung */
	/* XXX doesn't this code replicate code in in6_purgeaddr() ? --dyoung */
	/* undo everything done by in6_ifattach(), just in case */
	for (ifa = IFADDR_FIRST(ifp); ifa != NULL; ifa = next) {
		next = IFADDR_NEXT(ifa);

		if (ifa->ifa_addr->sa_family != AF_INET6
		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
			continue;
		}

		ia = (struct in6_ifaddr *)ifa;

		/*
		 * leave from multicast groups we have joined for the interface
		 */
		while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
			LIST_REMOVE(imm, i6mm_chain);
			in6_leavegroup(imm);
		}

		/* remove from the routing table */
		if ((ia->ia_flags & IFA_ROUTE) &&
		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
			rtflags = rt->rt_flags;
			rtfree(rt);
			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
			    (struct sockaddr *)&ia->ia_addr,
			    (struct sockaddr *)&ia->ia_prefixmask,
			    rtflags, NULL);
		}

		/* remove from the linked list */
		ifa_remove(ifp, &ia->ia_ifa);

		/* also remove from the IPv6 address chain(itojun&jinmei) */
		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 {
				nd6log((LOG_ERR,
				    "%s: didn't unlink in6ifaddr from list\n",
				    if_name(ifp)));
			}
		}

		ifafree(&oia->ia_ifa);
	}

	/* cleanup multicast address kludge table, if there is any */
	in6_purgemkludge(ifp);

	/*
	 * remove neighbor management table.  we call it twice just to make
	 * sure we nuke everything.  maybe we need just one call.
	 * XXX: since the first call did not release addresses, some prefixes
	 * might remain.  We should call nd6_purge() again to release the
	 * prefixes after removing all addresses above.
	 * (Or can we just delay calling nd6_purge until at this point?)
	 */
	nd6_purge(ifp);
}