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

📄 ip_input.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * Create header for new ip packet by	 * modifying header of first packet;	 * dequeue and discard fragment reassembly header.	 * Make header visible.	 */	ip = (struct ipasfrag *) fp->ipq_next;	/*	 * If the fragments concatenated to an mbuf that's	 * bigger than the total size of the fragment, then and	 * m_ext buffer was alloced. But fp->ipq_next points to	 * the old buffer (in the mbuf), so we must point ip	 * into the new buffer.	 */	if (m->m_flags & M_EXT) {	  int delta;	  delta = (char *)ip - m->m_dat;	  ip = (struct ipasfrag *)(m->m_ext + delta);	}	/* DEBUG_ARG("ip = %lx", (long)ip); 	 * ip=(struct ipasfrag *)m->m_data; */	ip->ip_len = next;	ip->ipf_mff &= ~1;	((struct ip *)ip)->ip_src = fp->ipq_src;	((struct ip *)ip)->ip_dst = fp->ipq_dst;	remque_32(fp);	(void) m_free(dtom(fp));	m = dtom(ip);	m->m_len += (ip->ip_hl << 2);	m->m_data -= (ip->ip_hl << 2);	return ((struct ip *)ip);dropfrag:	ipstat.ips_fragdropped++;	m_freem(m);	return (0);}/* * Free a fragment reassembly header and all * associated datagrams. */voidip_freef(fp)	struct ipq *fp;{	register struct ipasfrag *q, *p;	for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;	    q = p) {		p = (struct ipasfrag *) q->ipf_next;		ip_deq(q);		m_freem(dtom(q));	}	remque_32(fp);	(void) m_free(dtom(fp));}/* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */voidip_enq(p, prev)	register struct ipasfrag *p, *prev;{	DEBUG_CALL("ip_enq");	DEBUG_ARG("prev = %lx", (long)prev);	p->ipf_prev = (ipasfragp_32) prev;	p->ipf_next = prev->ipf_next;	((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;	prev->ipf_next = (ipasfragp_32) p;}/* * To ip_enq as remque is to insque. */voidip_deq(p)	register struct ipasfrag *p;{	((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;	((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;}/* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. */voidip_slowtimo(){	register struct ipq *fp;		DEBUG_CALL("ip_slowtimo");		fp = (struct ipq *) ipq.next;	if (fp == 0)	   return;	while (fp != &ipq) {		--fp->ipq_ttl;		fp = (struct ipq *) fp->next;		if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {			ipstat.ips_fragtimeout++;			ip_freef((struct ipq *) fp->prev);		}	}}/* * 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. */#ifdef notdefintip_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; */	int opt, optlen, cnt, off, code, type, forward = 0;	struct in_addr *sin, dst;typedef u_int32_t n_time;	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;			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 (int32_t)) {				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:				break;			case IPOPT_TS_TSANDADDR:				if (ipt->ipt_ptr + sizeof(n_time) +				    sizeof(struct in_addr) > ipt->ipt_len)					goto bad;				ipaddr.sin_addr = dst;				ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,							    m->m_pkthdr.rcvif);				if (ia == 0)					continue;				bcopy((caddr_t)&IA_SIN(ia)->sin_addr,				    (caddr_t)sin, sizeof(struct in_addr));				ipt->ipt_ptr += sizeof(struct in_addr);				break;			case IPOPT_TS_PRESPEC:				if (ipt->ipt_ptr + sizeof(n_time) +				    sizeof(struct in_addr) > ipt->ipt_len)					goto bad;				bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,				    sizeof(struct in_addr));				if (ifa_ifwithaddr((SA)&ipaddr) == 0)					continue;				ipt->ipt_ptr += sizeof(struct in_addr);				break;			default:				goto bad;			}			ntime = iptime();			bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,			    sizeof(n_time));			ipt->ipt_ptr += sizeof(n_time);		}	}	if (forward) {		ip_forward(m, 1);		return (1);	}		}	}	return (0);bad:	/* ip->ip_len -= ip->ip_hl << 2;   XXX icmp_error adds in hdr length *//* Not yet */ 	icmp_error(m, type, code, 0, 0);	ipstat.ips_badoptions++;	return (1);}#endif /* notdef *//* * Strip out IP options, at higher * level protocol in the kernel. * Second argument is buffer to which options * will be moved, and return value is their length. * (XXX) should be deleted; last arg currently ignored. */voidip_stripoptions(m, mopt)	register struct mbuf *m;	struct mbuf *mopt;{	register int i;	struct ip *ip = mtod(m, struct ip *);	register caddr_t opts;	int olen;	olen = (ip->ip_hl<<2) - sizeof (struct ip);	opts = (caddr_t)(ip + 1);	i = m->m_len - (sizeof (struct ip) + olen);	memcpy(opts, opts  + olen, (unsigned)i);	m->m_len -= olen;		ip->ip_hl = sizeof(struct ip) >> 2;}

⌨️ 快捷键说明

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