in6_ifattach.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,344 行 · 第 1/3 页

C
1,344
字号
				    ip6_sprintf(&mltaddr.sin6_addr), 				    error));			}		}	}}voidin6_nigroup_detach(name, namelen)	const char *name;	int namelen;{	struct ifnet *ifp;	struct sockaddr_in6 mltaddr;	struct in6_multi *in6m;	bzero(&mltaddr, sizeof(mltaddr));	mltaddr.sin6_family = AF_INET6;	mltaddr.sin6_len = sizeof(struct sockaddr_in6);	if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)		return;#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	for (ifp = ifnet; ifp; ifp = ifp->if_next)#else	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)#endif	{		mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);		IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);		if (in6m)			in6_delmulti(in6m);	}}#endif/* * XXX multiple loopback interface needs more care.  for instance, * nodelocal address needs to be configured onto only one of them. * XXX multiple link-local address case */voidin6_ifattach(ifp, altifp)	struct ifnet *ifp;	struct ifnet *altifp;	/* secondary EUI64 source */{	static size_t if_indexlim = 8;	struct in6_ifaddr *ia;	struct in6_addr in6;	/* some of the interfaces are inherently not IPv6 capable */	switch (ifp->if_type) {#ifdef IFT_BRIDGE	/* OpenBSD 2.8 */	case IFT_BRIDGE:		return;#endif#if defined(__OpenBSD__) || defined(__NetBSD__)	case IFT_PROPVIRTUAL:		if (strncmp("bridge", ifp->if_xname, sizeof("bridge")) == 0 &&		    '0' <= ifp->if_xname[sizeof("bridge")] &&		    ifp->if_xname[sizeof("bridge")] <= '9')			return;		break;#endif#ifdef IFT_PFLOG	case IFT_PFLOG:		return;#endif	}	/*	 * We have some arrays that should be indexed by if_index.	 * since if_index will grow dynamically, they should grow too.	 *	struct in6_ifstat **in6_ifstat	 *	struct icmp6_ifstat **icmp6_ifstat	 */	if (in6_ifstat == NULL || icmp6_ifstat == NULL ||	    if_index >= if_indexlim) {		size_t n;		caddr_t q;		size_t olim;		olim = if_indexlim;		while (if_index >= if_indexlim)			if_indexlim <<= 1;		/* grow in6_ifstat */		n = if_indexlim * sizeof(struct in6_ifstat *);		q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);		bzero(q, n);		if (in6_ifstat) {			bcopy((caddr_t)in6_ifstat, q,				olim * sizeof(struct in6_ifstat *));			free((caddr_t)in6_ifstat, M_IFADDR);		}		in6_ifstat = (struct in6_ifstat **)q;		in6_ifstatmax = if_indexlim;		/* grow icmp6_ifstat */		n = if_indexlim * sizeof(struct icmp6_ifstat *);		q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);		bzero(q, n);		if (icmp6_ifstat) {			bcopy((caddr_t)icmp6_ifstat, q,				olim * sizeof(struct icmp6_ifstat *));			free((caddr_t)icmp6_ifstat, M_IFADDR);		}		icmp6_ifstat = (struct icmp6_ifstat **)q;		icmp6_ifstatmax = if_indexlim;	}	/* initialize scope identifiers */	scope6_ifattach(ifp);	/* initialize NDP variables */	nd6_ifattach(ifp);#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	/* create a multicast kludge storage (if we have not had one) */	in6_createmkludge(ifp);#endif	/*	 * quirks based on interface type	 */	switch (ifp->if_type) {#ifdef IFT_STF	case IFT_STF:		/*		 * 6to4 interface is a very special kind of beast.		 * no multicast, no linklocal.  RFC2529 specifies how to make		 * linklocals for 6to4 interface, but there's no use and		 * it is rather harmful to have one.		 */		goto statinit;#endif	default:		break;	}	/*	 * usually, we require multicast capability to the interface	 */	if ((ifp->if_flags & IFF_MULTICAST) == 0) {		log(LOG_INFO, "in6_ifattach: "		    "%s is not multicast capable, IPv6 not enabled\n",		    if_name(ifp));		return;	}	/*	 * assign loopback address for loopback interface.	 * XXX multiple loopback interface case.	 */	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {		in6 = in6addr_loopback;		if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {			if (in6_ifattach_loopback(ifp) != 0)				return;		}	}	/*	 * assign a link-local address, if there's none. 	 */	if (ip6_auto_linklocal) {            int s = splnet();		ia = in6ifa_ifpforlinklocal(ifp, 0);		if (ia == NULL) {			if (in6_ifattach_linklocal(ifp, altifp) == 0) {				/* linklocal address assigned */			} else {				/* failed to assign linklocal address. bark? */			}		}                splx(s);	}#ifdef IFT_STF			/* XXX */statinit:	#endif	/* update dynamically. */	if (in6_maxmtu < ifp->if_mtu)		in6_maxmtu = ifp->if_mtu;	if (in6_ifstat[ifp->if_index] == NULL) {		in6_ifstat[ifp->if_index] = (struct in6_ifstat *)			malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);		bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));	}	if (icmp6_ifstat[ifp->if_index] == NULL) {		icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)			malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);		bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));	}}/* * 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. */#if !(defined(__bsdi__) && _BSDI_VERSION >= 199802)voidin6_ifdetach(ifp)	struct ifnet *ifp;{	struct in6_ifaddr *ia, *oia;	struct ifaddr *ifa, *next;#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	struct ifaddr *ifaprev = NULL;#endif	struct rtentry *rt;	short rtflags;	struct sockaddr_in6 sin6;#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)	struct in6_multi *in6m, *in6m_next;#endif	struct in6_multi_mship *imm;	/* remove neighbor management table */	nd6_purge(ifp);	/* nuke any of IPv6 addresses we have */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	for (ifa = ifp->if_addrlist; ifa; ifa = next)#else	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)#endif	{#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)		next = ifa->ifa_next;#else		next = ifa->ifa_list.tqe_next;#endif		if (ifa->ifa_addr->sa_family != AF_INET6)			continue;		in6_purgeaddr(ifa);	}	/* undo everything done by in6_ifattach(), just in case */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	for (ifa = ifp->if_addrlist; ifa; ifa = next)#else	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)#endif	{#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)		next = ifa->ifa_next;#else		next = ifa->ifa_list.tqe_next;#endif		if (ifa->ifa_addr->sa_family != AF_INET6		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)			ifaprev = ifa;#endif			continue;		}		ia = (struct in6_ifaddr *)ifa;		/*		 * leave from multicast groups we have joined for the interface		 */		while ((imm = ia->ia6_memberships.lh_first) != 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#ifdef __FreeBSD__				, 0UL#endif				))) {			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, (struct rtentry **)0);		}		/* remove from the linked list */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)		if (ifaprev)			ifaprev->ifa_next = ifa->ifa_next;		else			ifp->if_addrlist = ifa->ifa_next;#else		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);#endif		IFAFREE(&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);	}#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)	/* leave from all multicast groups joined */#if (defined(__FreeBSD__) && __FreeBSD__ >= 4)	in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);	in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);#endif	for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {		in6m_next = LIST_NEXT(in6m, in6m_entry);		if (in6m->in6m_ifp != ifp)			continue;		in6_delmulti(in6m);		in6m = NULL;	}#endif#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	/* cleanup multicast address kludge table, if there is any */	in6_purgemkludge(ifp);#endif	/*	 * 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);	/* 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);#ifndef __FreeBSD__	rt = rtalloc1((struct sockaddr *)&sin6, 0);#else	rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);#endif	if (rt && rt->rt_ifp == ifp) {		rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),			rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);		rtfree(rt);	}}#endifintin6_get_tmpifid(ifp, retbuf, baseid, generate)	struct ifnet *ifp;	u_int8_t *retbuf;	const u_int8_t *baseid;	int generate;{	u_int8_t nullbuf[8];	struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];	bzero(nullbuf, sizeof(nullbuf));	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {		/* we've never created a random ID.  Create a new one. */		generate = 1;	}	if (generate) {		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));		/* generate_tmp_ifid will update seedn and buf */		(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,					ndi->randomid);	}	bcopy(ndi->randomid, retbuf, 8);	if (generate && bcmp(retbuf, nullbuf, sizeof(nullbuf)) == 0) {		/* generate_tmp_ifid could not found a good ID. */		return(-1);	}	return(0);}voidin6_tmpaddrtimer(ignored_arg)	void *ignored_arg;{	int i;	struct nd_ifinfo *ndi;	u_int8_t nullbuf[8];#ifdef __NetBSD__	int s = splsoftnet();#else	int s = splnet();#endif#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)	callout_reset(&in6_tmpaddrtimer_ch,		      (ip6_temp_preferred_lifetime - ip6_desync_factor -		       ip6_temp_regen_advance) * hz,		      in6_tmpaddrtimer, NULL);#elif defined(__OpenBSD__)	timeout_set(&in6_tmpaddrtimer_ch, in6_tmpaddrtimer, NULL);	timeout_add(&in6_tmpaddrtimer_ch, 	    (ip6_temp_preferred_lifetime - ip6_desync_factor -	    ip6_temp_regen_advance) * hz);#else	timeout(in6_tmpaddrtimer, (caddr_t)0,		(ip6_temp_preferred_lifetime - ip6_desync_factor -		 ip6_temp_regen_advance) * hz);#endif	bzero(nullbuf, sizeof(nullbuf));	for (i = 1; i < if_index + 1; i++) {		ndi = &nd_ifinfo[i];		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {			/*			 * We've been generating a random ID on this interface.			 * Create a new one.			 */			(void)generate_tmp_ifid(ndi->randomseed0,						ndi->randomseed1,						ndi->randomid);		}	}	splx(s);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?