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

📄 in.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
 *	SIOCGLIFADDR with IFLR_PREFIX: *		get first address that matches the specified prefix. *	SIOCALIFADDR: add the specified address. *	SIOCALIFADDR with IFLR_PREFIX: *		EINVAL since we can't deduce hostid part of the address. *	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 in_ioctl() */static intin_lifaddr_ioctl(so, cmd, data, ifp)	struct socket *so;	u_long cmd;	caddr_t	data;	struct ifnet *ifp;{	struct if_laddrreq *iflr = (struct if_laddrreq *)data;	struct ifaddr *ifa;	struct sockaddr *sa;	/* sanity checks */	if (!data || !ifp) {		panic("invalid argument to in_lifaddr_ioctl");		/*NOTRECHED*/	}	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_INET)			return EINVAL;		if (sa->sa_len != sizeof(struct sockaddr_in))			return EINVAL;		/* XXX need improvement */		sa = (struct sockaddr *)&iflr->dstaddr;		if (sa->sa_family		 && sa->sa_family != AF_INET)			return EINVAL;		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))			return EINVAL;		break;	default: /*shouldn't happen*/#if 0		panic("invalid cmd to in_lifaddr_ioctl");		/*NOTREACHED*/#else		return EOPNOTSUPP;#endif	}	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)		return EINVAL;	switch (cmd) {	case SIOCALIFADDR:	    {		struct in_aliasreq ifra;		if (iflr->flags & IFLR_PREFIX)			return EINVAL;		/* copy args to in_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 (((struct sockaddr *)&iflr->dstaddr)->sa_family) {	/*XXX*/			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,				((struct sockaddr *)&iflr->dstaddr)->sa_len);		}		ifra.ifra_mask.sin_family = AF_INET;		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);		return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);	    }	case SIOCGLIFADDR:	case SIOCDLIFADDR:	    {		struct in_ifaddr *ia;		struct in_addr mask, candidate, match;		struct sockaddr_in *sin;		int cmp;		bzero(&mask, sizeof(mask));		if (iflr->flags & IFLR_PREFIX) {			/* lookup a prefix rather than address. */			in_len2mask(&mask, iflr->prefixlen);			sin = (struct sockaddr_in *)&iflr->addr;			match.s_addr = sin->sin_addr.s_addr;			match.s_addr &= mask.s_addr;			/* if you set extra bits, that's wrong */			if (match.s_addr != sin->sin_addr.s_addr)				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 */				in_len2mask(&mask, 32);				sin = (struct sockaddr_in *)&iflr->addr;				match.s_addr = sin->sin_addr.s_addr;				cmp = 1;			}		}		for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) {			if (ifa->ifa_addr->sa_family != AF_INET6)				continue;			if (!cmp)				break;			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;			candidate.s_addr &= mask.s_addr;			if (candidate.s_addr == match.s_addr)				break;		}		if (!ifa)			return EADDRNOTAVAIL;		ia = (struct in_ifaddr *)ifa;		if (cmd == SIOCGLIFADDR) {			/* fill in the if_laddrreq structure */			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,					ia->ia_dstaddr.sin_len);			} else				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));			iflr->prefixlen =				in_mask2len(&ia->ia_sockmask.sin_addr);			iflr->flags = 0;	/*XXX*/			return 0;		} else {			struct in_aliasreq ifra;			/* fill in_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.sin_len);			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,					ia->ia_dstaddr.sin_len);			}			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,				ia->ia_sockmask.sin_len);			return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);		}	    }	}	return EOPNOTSUPP;	/*just for safety*/}/* * Delete any existing route for an interface. */voidin_ifscrub(ifp, ia)	register struct ifnet *ifp;	register struct in_ifaddr *ia;{	if ((ia->ia_flags & IFA_ROUTE) == 0)		return;	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);	else		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);	ia->ia_flags &= ~IFA_ROUTE;}/* * Initialize an interface's internet address * and routing table entry. */intin_ifinit(ifp, ia, sin, scrub)	register struct ifnet *ifp;	register struct in_ifaddr *ia;	struct sockaddr_in *sin;	int scrub;{	register u_int32_t i = sin->sin_addr.s_addr;	struct sockaddr_in oldaddr;	int s = splimp(), flags = RTF_UP, error;	oldaddr = ia->ia_addr;	ia->ia_addr = *sin;	/*	 * Give the interface a chance to initialize	 * if this is its first address,	 * and to validate the address if necessary.	 */	if (ifp->if_ioctl &&	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {		splx(s);		ia->ia_addr = oldaddr;		return (error);	}	splx(s);	if (scrub) {		ia->ia_ifa.ifa_addr = sintosa(&oldaddr);		in_ifscrub(ifp, ia);		ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);	}	if (IN_CLASSA(i))		ia->ia_netmask = IN_CLASSA_NET;	else if (IN_CLASSB(i))		ia->ia_netmask = IN_CLASSB_NET;	else		ia->ia_netmask = IN_CLASSC_NET;	/*	 * The subnet mask usually includes at least the standard network part,	 * but may may be smaller in the case of supernetting.	 * If it is set, we believe it.	 */	if (ia->ia_subnetmask == 0) {		ia->ia_subnetmask = ia->ia_netmask;		ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;	} else		ia->ia_netmask &= ia->ia_subnetmask;	ia->ia_net = i & ia->ia_netmask;	ia->ia_subnet = i & ia->ia_subnetmask;	in_socktrim(&ia->ia_sockmask);	/*	 * Add route for the network.	 */	ia->ia_ifa.ifa_metric = ifp->if_metric;	if (ifp->if_flags & IFF_BROADCAST) {		ia->ia_broadaddr.sin_addr.s_addr =			ia->ia_subnet | ~ia->ia_subnetmask;		ia->ia_netbroadcast.s_addr =			ia->ia_net | ~ia->ia_netmask;	} else if (ifp->if_flags & IFF_LOOPBACK) {		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;		flags |= RTF_HOST;	} else if (ifp->if_flags & IFF_POINTOPOINT) {		if (ia->ia_dstaddr.sin_family != AF_INET)			return (0);		flags |= RTF_HOST;	}	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)		ia->ia_flags |= IFA_ROUTE;	/*	 * If the interface supports multicast, join the "all hosts"	 * multicast group on that interface.	 */	if (ifp->if_flags & IFF_MULTICAST) {		struct in_addr addr;		addr.s_addr = INADDR_ALLHOSTS_GROUP;		in_addmulti(&addr, ifp);	}	return (error);}/* * Return 1 if the address might be a local broadcast address. */intin_broadcast(in, ifp)	struct in_addr in;	struct ifnet *ifp;{	struct ifnet *ifn, *if_first, *if_target;	register struct ifaddr *ifa;	if (in.s_addr == INADDR_BROADCAST ||	    in.s_addr == INADDR_ANY)		return 1;	if (ifp && ((ifp->if_flags & IFF_BROADCAST) == 0))		return 0;	if (ifp == NULL)	{	  	if_first = ifnet.tqh_first;		if_target = 0;	}	else	{		if_first = ifp;		if_target = ifp->if_list.tqe_next;	}#define ia (ifatoia(ifa))	/*	 * Look through the list of addresses for a match	 * with a broadcast address.	 * If ifp is NULL, check against all the interfaces.	 */        for (ifn = if_first; ifn != if_target; ifn = ifn->if_list.tqe_next)	  for (ifa = ifn->if_addrlist.tqh_first; ifa;	       ifa = ifa->ifa_list.tqe_next)	      if (!ifp)	      {		  if (ifa->ifa_addr->sa_family == AF_INET &&		      ((ia->ia_subnetmask != 0xffffffff &&		      (((ifn->if_flags & IFF_BROADCAST) &&			in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) ||			 in.s_addr == ia->ia_subnet)) ||		       /*			* Check for old-style (host 0) broadcast.			*/		       (in.s_addr == ia->ia_netbroadcast.s_addr ||			in.s_addr == ia->ia_net)))		              return 1;	      }	      else		  if (ifa->ifa_addr->sa_family == AF_INET &&		      (((ifn->if_flags & IFF_BROADCAST) &&		      in.s_addr == ia->ia_broadaddr.sin_addr.s_addr) ||		       in.s_addr == ia->ia_netbroadcast.s_addr ||		       /*			* Check for old-style (host 0) broadcast.			*/		       in.s_addr == ia->ia_subnet ||		       in.s_addr == ia->ia_net))		              return 1;	return (0);#undef ia}/* * Add an address to the list of IP multicast addresses for a given interface. */struct in_multi *in_addmulti(ap, ifp)	register struct in_addr *ap;	register struct ifnet *ifp;{	register struct in_multi *inm;	struct ifreq ifr;	struct in_ifaddr *ia;	int s = splsoftnet();	/*	 * See if address already in list.	 */	IN_LOOKUP_MULTI(*ap, ifp, inm);	if (inm != NULL) {		/*		 * Found it; just increment the reference count.		 */		++inm->inm_refcount;	} else {		/*		 * New address; allocate a new multicast record		 * and link it into the interface's multicast list.		 */		inm = (struct in_multi *)malloc(sizeof(*inm),		    M_IPMADDR, M_NOWAIT);		if (inm == NULL) {			splx(s);			return (NULL);		}		inm->inm_addr = *ap;		inm->inm_ifp = ifp;		inm->inm_refcount = 1;		IFP_TO_IA(ifp, ia);		if (ia == NULL) {			free(inm, M_IPMADDR);			splx(s);			return (NULL);		}		inm->inm_ia = ia;		LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);		/*		 * Ask the network driver to update its multicast reception		 * filter appropriately for the new address.		 */		satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);		satosin(&ifr.ifr_addr)->sin_family = AF_INET;		satosin(&ifr.ifr_addr)->sin_addr = *ap;		if ((ifp->if_ioctl == NULL) ||		    (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {			LIST_REMOVE(inm, inm_list);			free(inm, M_IPMADDR);			splx(s);			return (NULL);		}		/*		 * Let IGMP know that we have joined a new IP multicast group.		 */		igmp_joingroup(inm);	}	splx(s);	return (inm);}/* * Delete a multicast address record. */voidin_delmulti(inm)	register struct in_multi *inm;{	struct ifreq ifr;	int s = splsoftnet();	if (--inm->inm_refcount == 0) {		/*		 * No remaining claims to this record; let IGMP know that		 * we are leaving the multicast group.		 */		igmp_leavegroup(inm);		/*		 * Unlink from list.		 */		LIST_REMOVE(inm, inm_list);		/*		 * Notify the network driver to update its multicast reception		 * filter.		 */		satosin(&ifr.ifr_addr)->sin_family = AF_INET;		satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;		(*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,							     (caddr_t)&ifr);		free(inm, M_IPMADDR);	}	splx(s);}#endif

⌨️ 快捷键说明

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