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

📄 in6.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct in6_multi_mship *imm;	/* stop DAD processing */	nd6_dad_stop(ifa);	/*	 * delete route to the destination of the address being purged.	 * The interface must be p2p or loopback in this case.	 */	if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {		int e;		if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))		    != 0) {			log(LOG_ERR, "in6_purgeaddr: failed to remove "			    "a route to the p2p destination: %s on %s, "			    "errno=%d\n",			    ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),			    e);			/* proceed anyway... */		}		else			ia->ia_flags &= ~IFA_ROUTE;	}	/* Remove ownaddr's loopback rtentry, if it exists. */	in6_ifremloop(&(ia->ia_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);	}	in6_unlink_ifa(ia, ifp);}intin6_update_ifa(ifp, ifra, ia)	struct ifnet *ifp;	struct in6_aliasreq *ifra;	struct in6_ifaddr *ia;{    int res;    int s = splnet();//    extern int irq_level;//    if (irq_level) {//        diag_printf("%s - called from IRQ!\n", __FUNCTION__);//    }    res = _in6_update_ifa(ifp, ifra, ia);    splx(s);    return res;}static voidin6_unlink_ifa(ia, ifp)	struct in6_ifaddr *ia;	struct ifnet *ifp;{	struct in6_ifaddr *oia;#ifdef __NetBSD__	int	s = splsoftnet();#else	int	s = splnet();#endif#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	struct ifaddr *ifa;#endif#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	if ((ifa = ifp->if_addrlist) == ia62ifa(ia))		ifp->if_addrlist = ifa->ifa_next;	else {		while (ifa->ifa_next &&		       (ifa->ifa_next != ia62ifa(ia)))			ifa = ifa->ifa_next;		if (ifa->ifa_next)			ifa->ifa_next = ia62ifa(ia)->ifa_next;		else {			/* search failed */			printf("Couldn't unlink in6_ifaddr from ifp\n");		}	}#else	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);        log_(LOG_ADDR) {            diag_printf("%s.%d - After removing %p into list %p\n",                         __FUNCTION__, __LINE__,                        &ia->ia_ifa, &ifp->if_addrlist);            _show_ifp(ifp);        }#endif#ifdef __NetBSD__	/* release a refcnt for the link from if_addrlist */	IFAFREE(&ia->ia_ifa);#endif	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 {			/* search failed */			printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");		}	}#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	if (oia->ia6_multiaddrs.lh_first != NULL) {#ifdef __NetBSD__		/*		 * XXX thorpej@netbsd.org -- if the interface is going		 * XXX away, don't save the multicast entries, delete them!		 */		if (oia->ia_ifa.ifa_ifp->if_output == if_nulloutput) {			struct in6_multi *in6m;			while ((in6m =			    LIST_FIRST(&oia->ia6_multiaddrs)) != NULL)				in6_delmulti(in6m);		} else			in6_savemkludge(oia);#else		in6_savemkludge(oia);#endif	}#endif#ifdef MEASURE_PERFORMANCE	in6h_delifa(oia);#endif	/*	 * When an autoconfigured address is being removed, release the	 * reference to the base prefix.  Also, since the release might	 * affect the status of other (detached) addresses, call	 * pfxlist_onlink_check().	 */	if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {		if (oia->ia6_ndpr == NULL) {			log(LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "			    "%p has no prefix\n", oia);		} else {			oia->ia6_ndpr->ndpr_refcnt--;			oia->ia6_flags &= ~IN6_IFF_AUTOCONF;			oia->ia6_ndpr = NULL;		}		pfxlist_onlink_check();	}	/*	 * release another refcnt for the link from in6_ifaddr.	 * Note that we should decrement the refcnt at least once for all *BSD.	 */	IFAFREE(&oia->ia_ifa);	splx(s);}voidin6_purgeif(ifp)	struct ifnet *ifp;{	struct ifaddr *ifa, *nifa;#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	for (ifa = ifp->if_addrlist; ifa; ifa = nifa)#else	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa)#endif	{#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)		nifa = ifa->ifa_next;#else		nifa = TAILQ_NEXT(ifa, ifa_list);#endif		if (ifa->ifa_addr->sa_family != AF_INET6)			continue;		in6_purgeaddr(ifa);	}#if !(defined(__bsdi__) && _BSDI_VERSION >= 199802)	in6_ifdetach(ifp);#endif}/* * SIOC[GAD]LIFADDR. *	SIOCGLIFADDR: get first address. (?) *	SIOCGLIFADDR with IFLR_PREFIX: *		get first address that matches the specified prefix. *	SIOCALIFADDR: add the specified address. *	SIOCALIFADDR with IFLR_PREFIX: *		add the specified prefix, filling hostid part from *		the first link-local address.  prefixlen must be <= 64. *	SIOCDLIFADDR: delete the specified address. *	SIOCDLIFADDR with IFLR_PREFIX: *		delete the first address that matches the specified prefix. * return values: *	EINVAL on invalid parameters *	EADDRNOTAVAIL on prefix match failed/specified address not found *	other values may be returned from in6_ioctl() * * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64. * this is to accomodate address naming scheme other than RFC2374, * in the future. * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374 * address encoding scheme. (see figure on page 8) */static int#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)in6_lifaddr_ioctl(so, cmd, data, ifp, p)	struct socket *so;	u_long cmd;	caddr_t	data;	struct ifnet *ifp;	struct proc *p;#elsein6_lifaddr_ioctl(so, cmd, data, ifp)	struct socket *so;	u_long cmd;	caddr_t	data;	struct ifnet *ifp;#endif{	struct if_laddrreq *iflr = (struct if_laddrreq *)data;	struct ifaddr *ifa;	struct sockaddr *sa;	int64_t zoneid;	/* sanity checks */	if (!data || !ifp) {		panic("invalid argument to in6_lifaddr_ioctl");		/* NOTREACHED */	}	switch (cmd) {	case SIOCGLIFADDR:		/* address must be specified on GET with IFLR_PREFIX */		if ((iflr->flags & IFLR_PREFIX) == 0)			break;		/* FALLTHROUGH */	case SIOCALIFADDR:	case SIOCDLIFADDR:		/* address must be specified on ADD and DELETE */		sa = (struct sockaddr *)&iflr->addr;		if (sa->sa_family != AF_INET6)			return EINVAL;		if (sa->sa_len != sizeof(struct sockaddr_in6))			return EINVAL;		/* XXX need improvement */		sa = (struct sockaddr *)&iflr->dstaddr;		if (sa->sa_family && sa->sa_family != AF_INET6)			return EINVAL;		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))			return EINVAL;		break;	default: /* shouldn't happen */#if 0		panic("invalid cmd to in6_lifaddr_ioctl");		/* NOTREACHED */#else		return EOPNOTSUPP;#endif	}	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)		return EINVAL;	switch (cmd) {	case SIOCALIFADDR:	    {		struct in6_aliasreq ifra;		struct in6_addr *hostid = NULL;		int prefixlen;		if ((iflr->flags & IFLR_PREFIX) != 0) {			struct sockaddr_in6 *sin6;			/*			 * hostid is to fill in the hostid part of the			 * address.  hostid points to the first link-local			 * address attached to the interface.			 */			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);			if (!ifa)				return EADDRNOTAVAIL;			hostid = IFA_IN6(ifa);		 	/* prefixlen must be <= 64. */			if (64 < iflr->prefixlen)				return EINVAL;			prefixlen = iflr->prefixlen;			/* hostid part must be zero. */			sin6 = (struct sockaddr_in6 *)&iflr->addr;			if (sin6->sin6_addr.s6_addr32[2] != 0			 || sin6->sin6_addr.s6_addr32[3] != 0) {				return EINVAL;			}		} else			prefixlen = iflr->prefixlen;		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */		bzero(&ifra, sizeof(ifra));		bcopy(iflr->iflr_name, ifra.ifra_name,			sizeof(ifra.ifra_name));		bcopy(&iflr->addr, &ifra.ifra_addr,			((struct sockaddr *)&iflr->addr)->sa_len);		if (hostid) {			/* fill in hostid part */			ifra.ifra_addr.sin6_addr.s6_addr32[2] =				hostid->s6_addr32[2];			ifra.ifra_addr.sin6_addr.s6_addr32[3] =				hostid->s6_addr32[3];		}		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,				((struct sockaddr *)&iflr->dstaddr)->sa_len);			if (hostid) {				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =					hostid->s6_addr32[2];				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =					hostid->s6_addr32[3];			}		}		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, p);#else		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp);#endif	    }	case SIOCGLIFADDR:	case SIOCDLIFADDR:	    {		struct in6_ifaddr *ia;		struct in6_addr mask, candidate, match;		struct sockaddr_in6 *sin6;		int cmp;		bzero(&mask, sizeof(mask));		if (iflr->flags & IFLR_PREFIX) {			/* lookup a prefix rather than address. */			in6_prefixlen2mask(&mask, iflr->prefixlen);			sin6 = (struct sockaddr_in6 *)&iflr->addr;			bcopy(&sin6->sin6_addr, &match, sizeof(match));			match.s6_addr32[0] &= mask.s6_addr32[0];			match.s6_addr32[1] &= mask.s6_addr32[1];			match.s6_addr32[2] &= mask.s6_addr32[2];			match.s6_addr32[3] &= mask.s6_addr32[3];			/* if you set extra bits, that's wrong */			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))				return EINVAL;			cmp = 1;		} else {			if (cmd == SIOCGLIFADDR) {				/* on getting an address, take the 1st match */				cmp = 0;	/* XXX */			} else {				/* on deleting an address, do exact match */				in6_prefixlen2mask(&mask, 128);				sin6 = (struct sockaddr_in6 *)&iflr->addr;				bcopy(&sin6->sin6_addr, &match, sizeof(match));				cmp = 1;			}		}#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->sa_family != AF_INET6)				continue;			if (!cmp)				break;			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));#ifndef SCOPEDROUTING			/*			 * XXX: this is adhoc, but is necessary to allow			 * a user to specify fe80::/64 (not /10) for a			 * link-local address.			 */			if (IN6_IS_ADDR_LINKLOCAL(&candidate))				candidate.s6_addr16[1] = 0;#endif			candidate.s6_addr32[0] &= mask.s6_addr32[0];			candidate.s6_addr32[1] &= mask.s6_addr32[1];			candidate.s6_addr32[2] &= mask.s6_addr32[2];			candidate.s6_addr32[3] &= mask.s6_addr32[3];			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))				break;		}		if (!ifa)			return EADDRNOTAVAIL;		ia = ifa2ia6(ifa);		if (cmd == SIOCGLIFADDR) {#ifndef SCOPEDROUTING			struct sockaddr_in6 *s6;#endif			/* fill in the if_laddrreq structure */			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);#ifndef SCOPEDROUTING		/* XXX see above */			s6 = (struct sockaddr_in6 *)&iflr->addr;			if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {				s6->sin6_addr.s6_addr16[1] = 0;				zoneid = in6_addr2zoneid(ifp, &s6->sin6_addr);				if (zoneid < 0) /* XXX: should not happen */					return(EINVAL);				s6->sin6_scope_id = zoneid;			}#endif			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,					ia->ia_dstaddr.sin6_len);#ifndef SCOPEDROUTING		/* XXX see above */				s6 = (struct sockaddr_in6 *)&iflr->dstaddr;				if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {					s6->sin6_addr.s6_addr16[1] = 0;					zoneid = in6_addr2zoneid(ifp,								 &s6->sin6_addr);					if (zoneid < 0) /* XXX */						return(EINVAL);					s6->sin6_scope_id = zoneid;				}#endif			} else				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));			iflr->prefixlen =				in6_mask2len(&ia->ia_prefixmask.sin6_addr,					     NULL);			iflr->flags = ia->ia6_flags;	/* XXX */			return 0;		} else {			struct in6_aliasreq ifra;			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */			bzero(&ifra, sizeof(ifra));			bcopy(iflr->iflr_name, ifra.ifra_name,				sizeof(ifra.ifra_name));			bcopy(&ia->ia_addr, &ifra.ifra_addr,				ia->ia_addr.sin6_len);			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,					ia->ia_dstaddr.sin6_len);			} else {				bzero(&ifra.ifra_dstaddr,				    sizeof(ifra.ifra_dstaddr));			}			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,				ia->ia_prefixmask.sin6_len);

⌨️ 快捷键说明

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