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

📄 ip_input.c

📁 完整的TCP/IP源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * set ip_mff if more fragments are expected,		 * convert offset of this to bytes.		 */		ip->ip_len -= hlen;		((struct ipasfrag *)ip)->ipf_mff &= ~1;		if (ip->ip_off & IP_MF)			((struct ipasfrag *)ip)->ipf_mff |= 1;		ip->ip_off <<= 3;		/*		 * If datagram marked as having more fragments		 * or if this is not the first fragment,		 * attempt reassembly; if it succeeds, proceed.		 */		if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {			ipstat.ips_fragments++;			if ((m = ipReAssemble (m, fp)) == NULL)				goto next;			ipstat.ips_reassembled++;		} else			if (fp)				ip_freef(fp);	} else		ip->ip_len -= hlen;#ifdef  FORWARD_BROADCASTS        if ((m->m_flags & M_BCAST) && (proxyBroadcastHook != NULL))            (* proxyBroadcastHook) (m, m->m_pkthdr.rcvif);#endif	/*	 * Switch out to protocol's input routine.	 */	ipstat.ips_delivered++;	(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);	goto next;bad:	m_freem(m);	goto next;}/********************************************************************************* ipReAssemble - reassemble ip fragments** This function reassembles the ip fragments and returns the pointer to the* mbuf chain if reassembly is complete orelse returns null.** RETURNS: pMbuf/NULL** SEE ALSO: ,** NOMANUAL*/LOCAL struct mbuf * ipReAssemble    (    FAST struct mbuf *	pMbuf,		/* pointer to mbuf chain fragment */    FAST struct ipq *	pIpFragQueue	/* pointer to ip fragment queue */    )    {    FAST struct mbuf ** 	pPtrMbuf; 	   /* pointer to ptr to mbuf */    FAST struct mbuf * 		pMbPktFrag = NULL; /* pointer to the packet */    FAST struct ip * 		pIpHdr;   	   /* pointer to ip header */    FAST struct ipasfrag *	pIpHdrFrag;	   /* ipfragment header */    FAST int		        len;     FAST struct mbuf *		pMbufTmp;	   /* pointer to mbuf */        pIpHdr = mtod (pMbuf, struct ip *);     pMbuf->m_nextpkt = NULL;     /*     * If first fragment to arrive, create a reassembly queue.     */    if (pIpFragQueue == 0)	{	if ((pMbufTmp = mBufClGet (M_DONTWAIT, MT_FTABLE, sizeof(struct ipq),				   TRUE)) == NULL)	    goto dropFrag;	pIpFragQueue = mtod(pMbufTmp, struct ipq *);	insque(pIpFragQueue, &ipq);	pIpFragQueue->ipq_ttl = ipfragttl;	/* configuration parameter */	pIpFragQueue->ipq_p = pIpHdr->ip_p;	pIpFragQueue->ipq_id = pIpHdr->ip_id;	pIpFragQueue->ipq_src = ((struct ip *)pIpHdr)->ip_src;	pIpFragQueue->ipq_dst = ((struct ip *)pIpHdr)->ip_dst;	pIpFragQueue->pMbufHdr   = pMbufTmp; 	/* back pointer to mbuf */	pIpFragQueue->pMbufPkt = pMbuf; 	/* first fragment received */	goto ipChkReAssembly; 	}    for (pPtrMbuf = &(pIpFragQueue->pMbufPkt); *pPtrMbuf != NULL;	 pPtrMbuf = &(*pPtrMbuf)->m_nextpkt)	{	pMbPktFrag = *pPtrMbuf; 	pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); 	if ((USHORT)pIpHdr->ip_off > (USHORT)pIpHdrFrag->ip_off)	    {	    if ((len = (signed int)((USHORT)pIpHdrFrag->ip_off +				    pIpHdrFrag->ip_len -				    (USHORT)pIpHdr->ip_off)) > 0)		{		if (len >= pIpHdr->ip_len)		    goto dropFrag;		/* drop the fragment */		pIpHdrFrag->ip_len -= len; 		m_adj(pMbPktFrag, -len); 	/* trim from the tail */		}	    if (pMbPktFrag->m_nextpkt == NULL)		{ 	/* this is the likely case most of the time */		pMbPktFrag->m_nextpkt = pMbuf; 	/* insert the fragment */		pMbuf->m_nextpkt = NULL;		break;		}	    }	else 		/* if pIpHdr->ip_off <= pIpHdrFrag->ip_off */	    {            /* if complete overlap */            while (((USHORT)pIpHdr->ip_off + pIpHdr->ip_len) >=                   ((USHORT)pIpHdrFrag->ip_off + pIpHdrFrag->ip_len))                {                *pPtrMbuf = (*pPtrMbuf)->m_nextpkt;                pMbPktFrag->m_nextpkt = NULL;                m_freem (pMbPktFrag);           /* drop the fragment */                pMbPktFrag = *pPtrMbuf;                if (pMbPktFrag == NULL)                    break;                pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *);                }            /* if partial overlap trim my data at the end*/            if ((pMbPktFrag != NULL) &&                ((len = (((USHORT)pIpHdr->ip_off + pIpHdr->ip_len) -                             pIpHdrFrag->ip_off)) > 0))                {                pIpHdr->ip_len -= len;                m_adj (pMbuf, -len);        	/* trim from the tail */                }	    pMbuf->m_nextpkt = pMbPktFrag; 	    *pPtrMbuf = pMbuf; 	/* insert the current fragment */	    	    break; 	    }	}    ipChkReAssembly:    len = 0;     for (pMbPktFrag = pIpFragQueue->pMbufPkt; pMbPktFrag != NULL;	 pMbPktFrag = pMbPktFrag->m_nextpkt)	{	pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); 	if ((USHORT)pIpHdrFrag->ip_off != len)	    return (NULL); 	len += pIpHdrFrag->ip_len; 	}        if (pIpHdrFrag->ipf_mff & 1)	/* last fragment's mff bit still set */	return (NULL);     /* reassemble and concatenate all fragments */    pMbuf = pIpFragQueue->pMbufPkt;     pMbufTmp = pMbuf->m_nextpkt;     pMbuf->m_nextpkt = NULL;     while (pMbufTmp != NULL)	{	pMbPktFrag = pMbufTmp; 	pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); 	pMbPktFrag->m_data += pIpHdrFrag->ip_hl << 2;	/* remove the header */	pMbPktFrag->m_len  -= pIpHdrFrag->ip_hl << 2;	pMbufTmp = pMbPktFrag->m_nextpkt; 	pMbPktFrag->m_nextpkt = NULL ; 	m_cat (pMbuf, pMbPktFrag); 	/* concatenate the fragment */	}    pIpHdrFrag = mtod(pMbuf, struct ipasfrag *);     pIpHdrFrag->ip_len = len; 		/* length of the ip packet */    pIpHdrFrag->ipf_mff &= ~1;    remque(pIpFragQueue);    (void) m_free (pIpFragQueue->pMbufHdr);     /* some debugging cruft by sklower, below, will go away soon */    if (pMbuf->m_flags & M_PKTHDR)	{ /* XXX this should be done elsewhere */	len = 0; 	for (pMbufTmp = pMbuf; pMbufTmp; pMbufTmp = pMbufTmp->m_next)	    len += pMbufTmp->m_len;	pMbuf->m_pkthdr.len = len;	}    return (pMbuf);			/* return the assembled packet */    dropFrag:    ipstat.ips_fragdropped++;    m_freem (pMbuf);			/* free the fragment */    return (NULL);    }/* * Free a fragment reassembly header and all * associated datagrams. */voidip_freef(fp)	struct ipq *fp;{	struct mbuf **  pPtrMbuf; 	struct mbuf *  pMbuf;		/* free all fragments */	pPtrMbuf = &(fp->pMbufPkt); 	while (*pPtrMbuf)	    {	    pMbuf = (*pPtrMbuf)->m_nextpkt; 	    m_freem (*pPtrMbuf); 	    *pPtrMbuf = pMbuf; 	    }	remque(fp);	(void) m_free(fp->pMbufHdr);}n_timeiptime(){	u_long t;	/* t is time in milliseconds (i hope) */	t = ((int) tickGet () * 1000) / sysClkRateGet ();	return (htonl(t));}/* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. */voidip_slowtimo(){	register struct ipq *fp;	int s = splnet();	fp = ipq.next;	if (fp == 0) {		splx(s);		return;	}	while (fp != &ipq) {		--fp->ipq_ttl;		fp = fp->next;		if (fp->prev->ipq_ttl == 0) {			ipstat.ips_fragtimeout++;			ip_freef(fp->prev);		}	}	splx(s);	return;}/* * Drain off all datagram fragments. */voidip_drain(){	while (ipq.next != &ipq) {		ipstat.ips_fragdropped++;		ip_freef(ipq.next);	}	return;}/* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, * or forwarding it if source-routed. * Returns 1 if packet has been forwarded/freed, * 0 if the packet should be processed further. */intip_dooptions(m)	struct mbuf *m;{	register struct ip *ip = mtod(m, struct ip *);	register u_char *cp;	register struct ip_timestamp *ipt;	register struct in_ifaddr *ia;	int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;	struct in_addr *sin, dst;	n_time ntime;	dst = ip->ip_dst;	cp = (u_char *)(ip + 1);	cnt = (ip->ip_hl << 2) - sizeof (struct ip);	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 <= 0 || optlen > cnt) {				code = &cp[IPOPT_OLEN] - (u_char *)ip;				goto bad;			}		}		switch (opt) {		default:			break;		/*		 * Source routing with record.		 * Find interface with current destination address.		 * If none on this machine then drop if strictly routed,		 * or do nothing if loosely routed.		 * Record interface address and bring up next address		 * component.  If strictly routed make sure next		 * address is on directly accessible net.		 */		case IPOPT_LSRR:		case IPOPT_SSRR:			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {				code = &cp[IPOPT_OFFSET] - (u_char *)ip;				goto bad;			}			ipaddr.sin_addr = ip->ip_dst;			TOS_SET (&ipaddr, ip->ip_tos);  /* tos routing */			ia = (struct in_ifaddr *)				ifa_ifwithaddr((struct sockaddr *)&ipaddr);			if (ia == 0) {				if (opt == IPOPT_SSRR) {					type = ICMP_UNREACH;					code = ICMP_UNREACH_SRCFAIL;					goto bad;				}				/*				 * Loose routing, and not at next destination				 * yet; nothing to do except forward.				 */				break;			}			off--;			/* 0 origin */			if (off > optlen - sizeof(struct in_addr)) {				/*				 * End of source route.  Should be for us.				 */				save_rte(cp, ip->ip_src);				break;			}			/*			 * locate outgoing interface			 */			bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,			    sizeof(ipaddr.sin_addr));			if (opt == IPOPT_SSRR) {#define	INA	struct in_ifaddr *#define	SA	struct sockaddr *			    if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)				ia = (INA)ifa_ifwithnet((SA)&ipaddr);			} else				ia = ip_rtaddr(ipaddr.sin_addr);			if (ia == 0) {				type = ICMP_UNREACH;				code = ICMP_UNREACH_SRCFAIL;				goto bad;			}			ip->ip_dst = ipaddr.sin_addr;			bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),			    (caddr_t)(cp + off), sizeof(struct in_addr));			cp[IPOPT_OFFSET] += sizeof(struct in_addr);			/*			 * Let ip_intr's mcast routing check handle mcast pkts			 */			forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));			break;		case IPOPT_RR:			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {				code = &cp[IPOPT_OFFSET] - (u_char *)ip;				goto bad;			}			/*			 * If no space remains, ignore.			 */			off--;			/* 0 origin */			if (off > optlen - sizeof(struct in_addr))				break;			bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,			    sizeof(ipaddr.sin_addr));			/*			 * locate outgoing interface; if we're the destination,			 * use the incoming interface (should be same).			 */			if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&			    (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {				type = ICMP_UNREACH;				code = ICMP_UNREACH_HOST;				goto bad;			}			bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),			    (caddr_t)(cp + off), sizeof(struct in_addr));			cp[IPOPT_OFFSET] += sizeof(struct in_addr);			break;		case IPOPT_TS:			code = cp - (u_char *)ip;			ipt = (struct ip_timestamp *)cp;			if (ipt->ipt_len < 5)				goto bad;			if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {				if (++ipt->ipt_oflw == 0)					goto bad;				break;			}			sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);			switch (ipt->ipt_flg) {			case IPOPT_TS_TSONLY:

⌨️ 快捷键说明

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