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

📄 ip_output.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			break;		}		break;	}	return (error);}/* * Set up IP options in pcb for insertion in output packets. * Store in mbuf with pointer in pcbopt, adding pseudo-option * with destination address if source routed. */int#ifdef notyetip_pcbopts(optname, pcbopt, m)	int optname;#elseip_pcbopts(pcbopt, m)#endif	struct mbuf **pcbopt;	register struct mbuf *m;{	register int cnt, optlen;	register u_char *cp;	u_char opt;	/* turn off any old options */	if (*pcbopt)		(void)m_free(*pcbopt);	*pcbopt = 0;	if (m == (struct mbuf *)0 || m->m_len == 0) {		/*		 * Only turning off any previous options.		 */		if (m)			(void)m_free(m);		return (0);	}#ifndef	vax	if (m->m_len % sizeof(long))		goto bad;#endif	/*	 * IP first-hop destination address will be stored before	 * actual options; move other options back	 * and clear it when none present.	 */#if 0 /*XXX changed for default cluster support vinai*/	if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])		goto bad;#else	if (m->m_data + m->m_len + sizeof(struct in_addr) >= 	    (m->m_extBuf + m->m_extSize))		goto bad;#endif	cnt = m->m_len;	m->m_len += sizeof(struct in_addr);	cp = mtod(m, u_char *) + sizeof(struct in_addr);	ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);	bzero(mtod(m, caddr_t), sizeof(struct in_addr));	for (; cnt > 0; cnt -= optlen, cp += optlen) {		opt = cp[IPOPT_OPTVAL];		if (opt == IPOPT_EOL)			break;		if (opt == IPOPT_NOP)			optlen = 1;		else {			optlen = cp[IPOPT_OLEN];			if (optlen <= IPOPT_OLEN || optlen > cnt)				goto bad;		}		switch (opt) {		default:			break;		case IPOPT_LSRR:		case IPOPT_SSRR:			/*			 * user process specifies route as:			 *	->A->B->C->D			 * D must be our final destination (but we can't			 * check that since we may not have connected yet).			 * A is first hop destination, which doesn't appear in			 * actual IP option, but is stored before the options.			 */			if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))				goto bad;			m->m_len -= sizeof(struct in_addr);			cnt -= sizeof(struct in_addr);			optlen -= sizeof(struct in_addr);			cp[IPOPT_OLEN] = optlen;			/*			 * Move first hop before start of options.			 */			bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),			    sizeof(struct in_addr));			/*			 * Then copy rest of options back			 * to close up the deleted entry.			 */			ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +			    sizeof(struct in_addr)),			    (caddr_t)&cp[IPOPT_OFFSET+1],			    (unsigned)cnt + sizeof(struct in_addr));			break;		}	}	if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))		goto bad;	*pcbopt = m;	return (0);bad:	(void)m_free(m);	return (EINVAL);}/* * Set the IP multicast options in response to user setsockopt(). */static int ip_setmoptions    (    int			optname,    struct inpcb * 	pInPcb,    struct mbuf *	m    ){	register int error = 0;	u_char loop;	struct in_addr addr;	register struct ip_mreq *mreq;	register struct ifnet *ifp;        register struct ip_moptions ** imop = &pInPcb->inp_moptions;	register struct ip_moptions *imo = *imop;	struct route ro;	register struct sockaddr_in *dst;        struct in_multi * 	pInMulti;        M_BLK_ID 		pInmMblk = NULL;        M_BLK **		ppMblk;	if (imo == NULL) {		/*		 * No multicast option buffer attached to the pcb;		 * allocate one and initialize to default values.		 */		MALLOC(imo,struct ip_moptions *, sizeof (*imo),		       MT_IPMOPTS, M_WAIT);		if (imo == NULL)			return (ENOBUFS);		*imop = imo;		imo->imo_multicast_ifp = NULL;		imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;		imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;		imo->imo_num_memberships = 0;                imo->pInmMblk = NULL; 	}	switch (optname) {	case IP_MULTICAST_IF:		/*		 * Select the interface for outgoing multicast packets.		 */		if (m == NULL || m->m_len != sizeof(struct in_addr)) {			error = EINVAL;			break;		}		addr = *(mtod(m, struct in_addr *));		/*		 * INADDR_ANY is used to remove a previous selection.		 * When no interface is selected, a default one is		 * chosen every time a multicast packet is sent.		 */		if (addr.s_addr == INADDR_ANY) {			imo->imo_multicast_ifp = NULL;			break;		}		/*		 * The selected interface is identified by its local		 * IP address.  Find the interface and confirm that		 * it supports multicasting.		 */		INADDR_TO_IFP(addr, ifp);		if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {			error = EADDRNOTAVAIL;			break;		}		imo->imo_multicast_ifp = ifp;		break;	case IP_MULTICAST_TTL:		/*		 * Set the IP time-to-live for outgoing multicast packets.		 */		if (m == NULL || m->m_len != 1) {			error = EINVAL;			break;		}		imo->imo_multicast_ttl = *(mtod(m, u_char *));		break;	case IP_MULTICAST_LOOP:		/*		 * Set the loopback flag for outgoing multicast packets.		 * Must be zero or one.		 */		if (m == NULL || m->m_len != 1 ||		   (loop = *(mtod(m, u_char *))) > 1) {			error = EINVAL;			break;		}		imo->imo_multicast_loop = loop;		break;	case IP_ADD_MEMBERSHIP:		/*		 * Add a multicast group membership.		 * Group must be a valid IP multicast address.		 */		if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {			error = EINVAL;			break;		}		mreq = mtod(m, struct ip_mreq *);		if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {			error = EINVAL;			break;		}		/*		 * If no interface address was provided, use the interface of		 * the route to the given multicast address.		 */		if (mreq->imr_interface.s_addr == INADDR_ANY) {			ro.ro_rt = NULL;			dst = (struct sockaddr_in *)&ro.ro_dst;			dst->sin_len = sizeof(*dst);			dst->sin_family = AF_INET;			dst->sin_addr = mreq->imr_multiaddr;			rtalloc(&ro);			if (ro.ro_rt == NULL) {				error = EADDRNOTAVAIL;				break;			}			ifp = ro.ro_rt->rt_ifp;			rtfree(ro.ro_rt);		}		else {			INADDR_TO_IFP(mreq->imr_interface, ifp);		}		/*		 * See if we found an interface, and confirm that it		 * supports multicast.		 */		if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {			error = EADDRNOTAVAIL;			break;		}                ppMblk = &imo->pInmMblk;                while (*ppMblk)                    {                    pInMulti = mtod (*ppMblk, struct in_multi*);                    if ((pInMulti->inm_ifp == ifp) &&                        (pInMulti->inm_addr.s_addr ==                         mreq->imr_multiaddr.s_addr))                        break;		/* jump out of the while loop */                    ppMblk = &(*ppMblk)->mBlkHdr.mNext;                    }                if (*ppMblk == NULL)                    {                    if ((pInmMblk = in_addmulti (&mreq->imr_multiaddr,                                                 ifp, pInPcb)) == NULL)                        {			error = ENOBUFS;                        break;                        }                    *ppMblk = pInmMblk;		/* add to the list */                    ++imo->imo_num_memberships;                    }                else                    error = EADDRINUSE;                break;	case IP_DROP_MEMBERSHIP:		/*		 * Drop a multicast group membership.		 * Group must be a valid IP multicast address.		 */		if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {			error = EINVAL;			break;		}		mreq = mtod(m, struct ip_mreq *);		if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {			error = EINVAL;			break;		}		/*		 * If an interface address was specified, get a pointer		 * to its ifnet structure.		 */		if (mreq->imr_interface.s_addr == INADDR_ANY)			ifp = NULL;		else {			INADDR_TO_IFP(mreq->imr_interface, ifp);			if (ifp == NULL) {				error = EADDRNOTAVAIL;				break;			}		}                {                ppMblk = &imo->pInmMblk;                while (*ppMblk)                    {                    pInMulti = mtod (*ppMblk, struct in_multi*);                    if ((ifp == NULL || pInMulti->inm_ifp == ifp) &&                        (pInMulti->inm_addr.s_addr ==                         mreq->imr_multiaddr.s_addr))                        {                        pInmMblk = *ppMblk;                        /* delete from the list */                        *ppMblk = (*ppMblk)->mBlkHdr.mNext;                         break;		/* jump out of the while loop */                        }                    ppMblk = &(*ppMblk)->mBlkHdr.mNext;                    }                if (pInmMblk == NULL)                    {                    error = EADDRNOTAVAIL;                    break;                    }                		/*		 * Give up the multicast address record to which the		 * membership points.		 */		in_delmulti (pInmMblk, pInPcb);		--imo->imo_num_memberships;                		break;                }	default:		error = EOPNOTSUPP;		break;	}	/*	 * If all options have default values, no need to keep the mbuf.	 */	if (imo->imo_multicast_ifp == NULL &&	    imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&	    imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&	    imo->imo_num_memberships == 0) {		 FREE(*imop, MT_IPMOPTS);		*imop = NULL;	}	return (error);}/* * Return the IP multicast options in response to user getsockopt(). */intip_getmoptions(optname, imo, mp)	int optname;	register struct ip_moptions *imo;	register struct mbuf **mp;{	u_char *ttl;	u_char *loop;	struct in_addr *addr;	struct in_ifaddr *ia;	*mp = mBufClGet(M_WAIT, MT_SOOPTS, CL_SIZE_128, TRUE);	if (*mp == NULL)	    return (ENOBUFS);	    	switch (optname) {	case IP_MULTICAST_IF:		addr = mtod(*mp, struct in_addr *);		(*mp)->m_len = sizeof(struct in_addr);		if (imo == NULL || imo->imo_multicast_ifp == NULL)			addr->s_addr = INADDR_ANY;		else {			IFP_TO_IA(imo->imo_multicast_ifp, ia);			addr->s_addr = (ia == NULL) ? INADDR_ANY					: IA_SIN(ia)->sin_addr.s_addr;		}		return (0);	case IP_MULTICAST_TTL:		ttl = mtod(*mp, u_char *);		(*mp)->m_len = 1;		*ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL				     : imo->imo_multicast_ttl;		return (0);	case IP_MULTICAST_LOOP:		loop = mtod(*mp, u_char *);		(*mp)->m_len = 1;		*loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP				      : imo->imo_multicast_loop;		return (0);	default:		return (EOPNOTSUPP);	}}/* * Discard the IP multicast options. */voidip_freemoptions(imo, pInPcb)	register struct ip_moptions *imo;	struct inpcb * 	pInPcb;        {        M_BLK_ID	pInmMblk;        M_BLK_ID	pInmMblkNext;	if (imo != NULL) {                pInmMblk = imo->pInmMblk;                pInmMblkNext = imo->pInmMblk;        	while ((pInmMblk = pInmMblkNext) != NULL)                    {                    pInmMblkNext = pInmMblk->mBlkHdr.mNext;                     in_delmulti (pInmMblk, pInPcb);                    }		FREE(imo, MT_IPMOPTS);	}}/* * Routine called from ip_output() to loop back a copy of an IP multicast * packet to the input queue of a specified interface.  Note that this * calls the output routine of the loopback "driver", but with an interface * pointer that might NOT be &loif -- easier than replicating that code here. */voidip_mloopback(ifp, m, dst, rt)	struct ifnet *ifp;	register struct mbuf *m;	register struct sockaddr_in *dst;	struct rtentry *rt;{	register struct ip *ip;	struct mbuf *copym;        struct mbuf * pMbuf;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */    WV_NET_EVENT_0 (NET_AUX_EVENT, WV_NET_INFO, 12, 7,                    WV_NETEVENT_IPMLOOP_START, WV_NET_RECV)#endif  /* INCLUDE_WVNET */#endif	copym = m_copy(m, 0, M_COPYALL);	if (copym != NULL) {		/*		 * We don't bother to fragment if the IP length is greater		 * than the interface's MTU.  Can this possibly matter?		 */		ip = mtod(copym, struct ip *);                /*                 * This copying of ip header is done because the same                 * ip header is shared by looutput and the code under the                 * the label sendit: in ip_output. so a fresh mbuf has to be                 * linked to the data.                 */                if ((pMbuf = mBufClGet (M_DONTWAIT, MT_DATA, sizeof(struct ip),                                   TRUE)) == NULL)                    {                    m_freem (copym);                     return;                    }                /* copy the ip header */                bcopy ((char *)ip , (char *)(mtod(pMbuf, char *)),                       sizeof(struct ip));                pMbuf->m_len   = sizeof (struct ip);                 pMbuf->m_flags = copym->m_flags;	/* copy the flags */                pMbuf->m_pkthdr = copym->m_pkthdr;	/* copy the pkt hdr */                pMbuf->m_next = copym;                                copym->m_flags &= ~M_PKTHDR;                copym->m_len -= sizeof(struct ip);                copym->m_data += sizeof(struct ip);		ip = mtod(pMbuf, struct ip *);                copym = pMbuf; 		ip->ip_len = htons((u_short)ip->ip_len);		ip->ip_off = htons((u_short)ip->ip_off);                ip->ip_sum = 0;                if (_ipCfgFlags & IP_DO_CHECKSUM_SND)                    ip->ip_sum = in_cksum(copym, ip->ip_hl << 2);		(void) looutput(ifp, copym, (struct sockaddr *)dst, rt);	}}

⌨️ 快捷键说明

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