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

📄 ip_input.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986, 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)ip_input.c	8.2 (Berkeley) 1/4/94 * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp *//* * Changes and additions relating to SLiRP are * Copyright (c) 1995 Danny Gasparovski. *  * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */#include <slirp.h>#include "ip_icmp.h"int ip_defttl;struct ipstat ipstat;struct ipq ipq;/* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */voidip_init(){	ipq.next = ipq.prev = (ipqp_32)&ipq;	ip_id = tt.tv_sec & 0xffff;	udp_init();	tcp_init();	ip_defttl = IPDEFTTL;}/* * Ip input routine.  Checksum and byte swap header.  If fragmented * try to reassemble.  Process options.  Pass to next level. */voidip_input(m)	struct mbuf *m;{	register struct ip *ip;	int hlen;		DEBUG_CALL("ip_input");	DEBUG_ARG("m = %lx", (long)m);	DEBUG_ARG("m_len = %d", m->m_len);	ipstat.ips_total++;		if (m->m_len < sizeof (struct ip)) {		ipstat.ips_toosmall++;		return;	}		ip = mtod(m, struct ip *);		if (ip->ip_v != IPVERSION) {		ipstat.ips_badvers++;		goto bad;	}	hlen = ip->ip_hl << 2;	if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */	  ipstat.ips_badhlen++;                     /* or packet too short */	  goto bad;	}        /* keep ip header intact for ICMP reply	 * ip->ip_sum = cksum(m, hlen); 	 * if (ip->ip_sum) { 	 */	if(cksum(m,hlen)) {	  ipstat.ips_badsum++;	  goto bad;	}	/*	 * Convert fields to host representation.	 */	NTOHS(ip->ip_len);	if (ip->ip_len < hlen) {		ipstat.ips_badlen++;		goto bad;	}	NTOHS(ip->ip_id);	NTOHS(ip->ip_off);	/*	 * Check that the amount of data in the buffers	 * is as at least much as the IP header would have us expect.	 * Trim mbufs if longer than we expect.	 * Drop packet if shorter than we expect.	 */	if (m->m_len < ip->ip_len) {		ipstat.ips_tooshort++;		goto bad;	}	/* Should drop packet if mbuf too long? hmmm... */	if (m->m_len > ip->ip_len)	   m_adj(m, ip->ip_len - m->m_len);	/* check ip_ttl for a correct ICMP reply */	if(ip->ip_ttl==0 || ip->ip_ttl==1) {	  icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");	  goto bad;	}	/*	 * Process options and, if not destined for us,	 * ship it on.  ip_dooptions returns 1 when an	 * error was detected (causing an icmp message	 * to be sent and the original packet to be freed).	 *//* We do no IP options *//*	if (hlen > sizeof (struct ip) && ip_dooptions(m)) *		goto next; */	/*	 * If offset or IP_MF are set, must reassemble.	 * Otherwise, nothing need be done.	 * (We could look in the reassembly queue to see	 * if the packet was previously fragmented,	 * but it's not worth the time; just let them time out.)	 * 	 * XXX This should fail, don't fragment yet	 */	if (ip->ip_off &~ IP_DF) {	  register struct ipq *fp;		/*		 * Look for queue of fragments		 * of this datagram.		 */		for (fp = (struct ipq *) ipq.next; fp != &ipq;		     fp = (struct ipq *) fp->next)		  if (ip->ip_id == fp->ipq_id &&		      ip->ip_src.s_addr == fp->ipq_src.s_addr &&		      ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&		      ip->ip_p == fp->ipq_p)		    goto found;		fp = 0;	found:		/*		 * Adjust ip_len to not reflect header,		 * set ip_mff if more fragments are expected,		 * convert offset of this to bytes.		 */		ip->ip_len -= hlen;		if (ip->ip_off & IP_MF)		  ((struct ipasfrag *)ip)->ipf_mff |= 1;		else 		  ((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++;			ip = ip_reass((struct ipasfrag *)ip, fp);			if (ip == 0)				return;			ipstat.ips_reassembled++;			m = dtom(ip);		} else			if (fp)		   	   ip_freef(fp);	} else		ip->ip_len -= hlen;	/*	 * Switch out to protocol's input routine.	 */	ipstat.ips_delivered++;	switch (ip->ip_p) {	 case IPPROTO_TCP:		tcp_input(m, hlen, (struct socket *)NULL);		break;	 case IPPROTO_UDP:		udp_input(m, hlen);		break;	 case IPPROTO_ICMP:		icmp_input(m, hlen);		break;	 default:		ipstat.ips_noproto++;		m_free(m);	}	return;bad:	m_freem(m);	return;}/* * Take incoming datagram fragment and try to * reassemble it into whole datagram.  If a chain for * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */struct ip *ip_reass(ip, fp)	register struct ipasfrag *ip;	register struct ipq *fp;{	register struct mbuf *m = dtom(ip);	register struct ipasfrag *q;	int hlen = ip->ip_hl << 2;	int i, next;		DEBUG_CALL("ip_reass");	DEBUG_ARG("ip = %lx", (long)ip);	DEBUG_ARG("fp = %lx", (long)fp);	DEBUG_ARG("m = %lx", (long)m);	/*	 * Presence of header sizes in mbufs	 * would confuse code below.         * Fragment m_data is concatenated.	 */	m->m_data += hlen;	m->m_len -= hlen;	/*	 * If first fragment to arrive, create a reassembly queue.	 */	if (fp == 0) {	  struct mbuf *t;	  if ((t = m_get()) == NULL) goto dropfrag;	  fp = mtod(t, struct ipq *);	  insque_32(fp, &ipq);	  fp->ipq_ttl = IPFRAGTTL;	  fp->ipq_p = ip->ip_p;	  fp->ipq_id = ip->ip_id;	  fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;	  fp->ipq_src = ((struct ip *)ip)->ip_src;	  fp->ipq_dst = ((struct ip *)ip)->ip_dst;	  q = (struct ipasfrag *)fp;	  goto insert;	}		/*	 * Find a segment which begins after this one does.	 */	for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;	    q = (struct ipasfrag *)q->ipf_next)		if (q->ip_off > ip->ip_off)			break;	/*	 * If there is a preceding segment, it may provide some of	 * our data already.  If so, drop the data from the incoming	 * segment.  If it provides all of our data, drop us.	 */	if (q->ipf_prev != (ipasfragp_32)fp) {		i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +		  ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;		if (i > 0) {			if (i >= ip->ip_len)				goto dropfrag;			m_adj(dtom(ip), i);			ip->ip_off += i;			ip->ip_len -= i;		}	}	/*	 * While we overlap succeeding segments trim them or,	 * if they are completely covered, dequeue them.	 */	while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {		i = (ip->ip_off + ip->ip_len) - q->ip_off;		if (i < q->ip_len) {			q->ip_len -= i;			q->ip_off += i;			m_adj(dtom(q), i);			break;		}		q = (struct ipasfrag *) q->ipf_next;		m_freem(dtom((struct ipasfrag *) q->ipf_prev));		ip_deq((struct ipasfrag *) q->ipf_prev);	}insert:	/*	 * Stick new segment in its place;	 * check for complete reassembly.	 */	ip_enq(ip, (struct ipasfrag *) q->ipf_prev);	next = 0;	for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;	     q = (struct ipasfrag *) q->ipf_next) {		if (q->ip_off != next)			return (0);		next += q->ip_len;	}	if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)		return (0);	/*	 * Reassembly is complete; concatenate fragments.	 */	q = (struct ipasfrag *) fp->ipq_next;	m = dtom(q);	q = (struct ipasfrag *) q->ipf_next;	while (q != (struct ipasfrag *)fp) {	  struct mbuf *t;	  t = dtom(q);	  q = (struct ipasfrag *) q->ipf_next;	  m_cat(m, t);	}

⌨️ 快捷键说明

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