⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 in6.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			ifra.ifra_flags = ia->ia6_flags;#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,				ifp, p);#else			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,				ifp);#endif		}	    }	}	return EOPNOTSUPP;	/* just for safety */}/* * Initialize an interface's intetnet6 address * and routing table entry. */static intin6_ifinit(ifp, ia, sin6, newhost)	struct ifnet *ifp;	struct in6_ifaddr *ia;	struct sockaddr_in6 *sin6;	int newhost;{	int	error = 0, plen, ifacount = 0;	int	s = splimp();	struct ifaddr *ifa;	/*	 * Give the interface a chance to initialize	 * if this is its first address,	 * and to validate the address if necessary.	 */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)#elif defined(__FreeBSD__) && __FreeBSD__ >= 4	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)#else	for (ifa = ifp->if_addrlist.tqh_first; ifa;	     ifa = ifa->ifa_list.tqe_next)#endif	{		if (ifa->ifa_addr == NULL)			continue;	/* just for safety */		if (ifa->ifa_addr->sa_family != AF_INET6)			continue;		ifacount++;	}	ia->ia_addr = *sin6;	if (ifacount <= 1 && ifp->if_ioctl &&	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {		splx(s);		return(error);	}	splx(s);	ia->ia_ifa.ifa_metric = ifp->if_metric;	/* we could do in(6)_socktrim here, but just omit it at this moment. */	/*	 * Special case:	 * If the destination address is specified for a point-to-point	 * interface, install a route to the destination as an interface	 * direct route.	 */	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */	if (plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) {		if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,				    RTF_UP | RTF_HOST)) != 0)			return(error);		ia->ia_flags |= IFA_ROUTE;	}	if (plen < 128) {		/*		 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().		 */		ia->ia_ifa.ifa_flags |= RTF_CLONING;	}	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */	if (newhost) {		/* set the rtrequest function to create llinfo */		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;		in6_ifaddloop(&(ia->ia_ifa));	}#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	if (ifp->if_flags & IFF_MULTICAST)		in6_restoremkludge(ia, ifp);#endif	return(error);}#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)/* * Multicast address kludge: * If there were any multicast addresses attached to this interface address, * either move them to another address on this interface, or save them until * such time as this interface is reconfigured for IPv6. */voidin6_savemkludge(oia)	struct in6_ifaddr *oia;{	struct in6_ifaddr *ia;	struct in6_multi *in6m, *next;	IFP_TO_IA6(oia->ia_ifp, ia);	if (ia) {	/* there is another address */		for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){			next = in6m->in6m_entry.le_next;			IFAFREE(&in6m->in6m_ia->ia_ifa);			IFAREF(&ia->ia_ifa);			in6m->in6m_ia = ia;			LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);		}	} else {	/* last address on this if deleted, save */		struct multi6_kludge *mk;		for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {			if (mk->mk_ifp == oia->ia_ifp)				break;		}		if (mk == NULL) /* this should not happen! */			panic("in6_savemkludge: no kludge space");		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);		}	}}/* * Continuation of multicast address hack: * If there was a multicast group list previously saved for this interface, * then we re-attach it to the first address configured on the i/f. */voidin6_restoremkludge(ia, ifp)	struct in6_ifaddr *ia;	struct ifnet *ifp;{	struct multi6_kludge *mk;	for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {		if (mk->mk_ifp == ifp) {			struct in6_multi *in6m, *next;			for (in6m = mk->mk_head.lh_first; in6m; in6m = next) {				next = in6m->in6m_entry.le_next;				in6m->in6m_ia = ia;				IFAREF(&ia->ia_ifa);				LIST_INSERT_HEAD(&ia->ia6_multiaddrs,						 in6m, in6m_entry);			}			LIST_INIT(&mk->mk_head);			break;		}	}}/* * Allocate space for the kludge at interface initialization time. * Formerly, we dynamically allocated the space in in6_savemkludge() with * malloc(M_WAITOK).  However, it was wrong since the function could be called * under an interrupt context (software timer on address lifetime expiration). * Also, we cannot just give up allocating the strucutre, since the group * membership structure is very complex and we need to keep it anyway. * Of course, this function MUST NOT be called under an interrupt context. * Specifically, it is expected to be called only from in6_ifattach(), though * it is a global function. */voidin6_createmkludge(ifp)	struct ifnet *ifp;{	struct multi6_kludge *mk;	for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {		/* If we've already had one, do not allocate. */		if (mk->mk_ifp == ifp)			return;	}	mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK);	bzero(mk, sizeof(*mk));	LIST_INIT(&mk->mk_head);	mk->mk_ifp = ifp;	LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);}voidin6_purgemkludge(ifp)	struct ifnet *ifp;{	struct multi6_kludge *mk;	struct in6_multi *in6m;	for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {		if (mk->mk_ifp != ifp)			continue;		/* leave from all multicast groups joined */		while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL)			in6_delmulti(in6m);		LIST_REMOVE(mk, mk_entry);		free(mk, M_IPMADDR);		break;	}}/* * Add an address to the list of IP6 multicast addresses for a * given interface. */struct	in6_multi *in6_addmulti(maddr6, ifp, errorp)	struct in6_addr *maddr6;	struct ifnet *ifp;	int *errorp;{	struct	in6_ifaddr *ia;	struct	in6_ifreq ifr;	struct	in6_multi *in6m;#ifdef __NetBSD__	int	s = splsoftnet();#else	int	s = splnet();#endif	*errorp = 0;	/*	 * See if address already in list.	 */	IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);	if (in6m != NULL) {		/*		 * Found it; just increment the refrence count.		 */		in6m->in6m_refcount++;	} else {		/*		 * New address; allocate a new multicast record		 * and link it into the interface's multicast list.		 */		in6m = (struct in6_multi *)			malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);		if (in6m == NULL) {			splx(s);			*errorp = ENOBUFS;			return(NULL);		}		in6m->in6m_addr = *maddr6;		in6m->in6m_ifp = ifp;		in6m->in6m_refcount = 1;		IFP_TO_IA6(ifp, ia);		if (ia == NULL) {			free(in6m, M_IPMADDR);			splx(s);			*errorp = EADDRNOTAVAIL; /* appropriate? */			return(NULL);		}		in6m->in6m_ia = ia;		IFAREF(&ia->ia_ifa); /* gain a reference */		LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);		/*		 * Ask the network driver to update its multicast reception		 * filter appropriately for the new address.		 */		bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));		ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);		ifr.ifr_addr.sin6_family = AF_INET6;		ifr.ifr_addr.sin6_addr = *maddr6;		if (ifp->if_ioctl == NULL)			*errorp = ENXIO; /* XXX: appropriate? */		else			*errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,						    (caddr_t)&ifr);		if (*errorp) {			LIST_REMOVE(in6m, in6m_entry);			free(in6m, M_IPMADDR);			IFAFREE(&ia->ia_ifa);			splx(s);			return(NULL);		}		/*		 * Let MLD6 know that we have joined a new IP6 multicast		 * group.		 */		mld6_start_listening(in6m);	}	splx(s);	return(in6m);}/* * Delete a multicast address record. */voidin6_delmulti(in6m)	struct in6_multi *in6m;{	struct	in6_ifreq ifr;#ifdef __NetBSD__	int	s = splsoftnet();#else	int	s = splnet();#endif	if (--in6m->in6m_refcount == 0) {		/*		 * No remaining claims to this record; let MLD6 know		 * that we are leaving the multicast group.		 */		mld6_stop_listening(in6m);		/*		 * Unlink from list.		 */		LIST_REMOVE(in6m, in6m_entry);		if (in6m->in6m_ia) {			IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */		}		/*		 * Notify the network driver to update its multicast		 * reception filter.		 */		bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));		ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);		ifr.ifr_addr.sin6_family = AF_INET6;		ifr.ifr_addr.sin6_addr = in6m->in6m_addr;		(*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,					    SIOCDELMULTI, (caddr_t)&ifr);		free(in6m, M_IPMADDR);	}	splx(s);}#else /* not FreeBSD3 *//* * Add an address to the list of IP6 multicast addresses for a * given interface. */struct	in6_multi *in6_addmulti(maddr6, ifp, errorp)	struct in6_addr *maddr6;	struct ifnet *ifp;	int *errorp;{	struct	in6_multi *in6m;	struct sockaddr_in6 sin6;	struct ifmultiaddr *ifma;	int	s = splnet();	*errorp = 0;	/*	 * Call generic routine to add membership or increment	 * refcount.  It wants addresses in the form of a sockaddr,	 * so we build one here (being careful to zero the unused bytes).	 */	bzero(&sin6, sizeof sin6);	sin6.sin6_family = AF_INET6;	sin6.sin6_len = sizeof sin6;	sin6.sin6_addr = *maddr6;	*errorp = if_addmulti(ifp, (struct sockaddr *)&sin6, &ifma);	if (*errorp) {		splx(s);		return 0;	}	/*	 * If ifma->ifma_protospec is null, then if_addmulti() created	 * a new record.  Otherwise, we are done.	 */	if (ifma->ifma_protospec != 0)		return ifma->ifma_protospec;	/* XXX - if_addmulti uses M_WAITOK.  Can this really be called	   at interrupt time?  If so, need to fix if_addmulti. XXX */	in6m = (struct in6_multi *)malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);	if (in6m == NULL) {		splx(s);		return (NULL);	}	bzero(in6m, sizeof *in6m);	in6m->in6m_addr = *maddr6;	in6m->in6m_ifp = ifp;	in6m->in6m_ifma = ifma;	ifma->ifma_protospec = in6m;	LIST_INSERT_HEAD(&in6_multihead, in6m, in6m_entry);	/*	 * Let MLD6 know that we have joined a new IP6 multicast	 * group.	 */	mld6_start_listening(in6m);	splx(s);	return(in6m);}/* * Delete a multicast address record. */voidin6_delmulti(in6m)	struct in6_multi *in6m;{	struct ifmultiaddr *ifma = in6m->in6m_ifma;	int	s = splnet();	if (ifma->ifma_refcount == 1) {		/*		 * No remaining claims to this record; let MLD6 know		 * that we are leaving the multicast group.		 */		mld6_stop_listening(in6m);		ifma->ifma_protospec = 0;		LIST_REMOVE(in6m, in6m_entry);		free(in6m, M_IPMADDR);	}	/* XXX - should be separate API for when we have an ifma? */	if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);	splx(s);}#endif /* not FreeBSD3 */struct in6_multi_mship *in6_joingroup(ifp, addr, errorp)	struct ifnet *ifp;	struct in6_addr *addr;	int *errorp;{	struct in6_multi_mship *imm;	imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);	if (!imm) {		*errorp = ENOBUFS;		return NULL;	}	imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);	if (!imm->i6mm_maddr) {		/* *errorp is alrady set */		free(imm, M_IPMADDR);		return NULL;	}	return imm;}intin6_leavegroup(imm)	struct in6_multi_mship *imm;{	if (imm->i6mm_maddr)		in6_delmulti(imm->i6mm_maddr);	free(imm,  M_IPMADDR);	return 0;}/* * Find an IPv6 interface link-local address specific to an interface. */struct in6_ifaddr *in6ifa_ifpforlinklocal(ifp, ignoreflags)	struct ifnet *ifp;	int ignoreflags;

⌨️ 快捷键说明

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