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

📄 ip_input.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
	(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, ifp);	goto next;bad:	m_freem(m);	goto next;}/* * 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), *mm;	register struct ipasfrag *q;	int hlen = ip->ip_hl << 2;	int i, next;	/*	 * Presence of header sizes in mbufs	 * would confuse code below.	 */	m->m_off += hlen;	m->m_len -= hlen;	/*	 * If first fragment to arrive, create a reassembly queue.	 */	if (fp == 0) {		KM_ALLOC(fp, struct ipq *, sizeof(struct ipq),KM_FTABLE, KM_NOWAIT);		if(fp == NULL)			goto dropfrag;		insque(fp, &ipq);		fp->ipq_ttl = IPFRAGTTL;		fp->ipq_p = ip->ip_p;		fp->ipq_id = ip->ip_id;		fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)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.	 */	/*	 * This is a cheap append if everything is all set 	 */	if(fp->ipq_prev->ip_off + fp->ipq_prev->ip_len == ip->ip_off) {		q = (struct ipasfrag *)fp;		goto insert;	}	for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = 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 != (struct ipasfrag *)fp) {		i = q->ipf_prev->ip_off + 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 = q->ipf_next;		m_freem(dtom(q->ipf_prev));		ip_deq(q->ipf_prev);	}insert:	/*	 * Stick new segment in its place;	 * check for complete reassembly.	 */	ip_enq(ip, q->ipf_prev);	next = 0;	for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {		if (q->ip_off != next) {			return (0);		}		next += q->ip_len;	}	if (q->ipf_prev->ipf_mff) {		return (0);	}	/*	 * Reassembly is complete; concatenate fragments.	 */	q = fp->ipq_next;	m = dtom(q);	mm = m->m_next;	m->m_next = 0;	m_cat(m, mm);	q = q->ipf_next;	while (q != (struct ipasfrag *)fp) {		mm = dtom(q);		q = q->ipf_next;		m_cat(m, mm);	}	/*	 * Create header for new ip packet by	 * modifying header of first packet;	 * dequeue and discard fragment reassembly header.	 * Make header visible.	 */	ip = fp->ipq_next;	ip->ip_len = next;	((struct ip *)ip)->ip_src = fp->ipq_src;	((struct ip *)ip)->ip_dst = fp->ipq_dst;	remque(fp);	KM_FREE(fp, KM_FTABLE);	m = dtom(ip);	m->m_len += (ip->ip_hl << 2);	m->m_off -= (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. *//* 12.9.88.us  Enter with lk_ipq set.  */ ip_freef(fp)	struct ipq *fp;{	register struct ipasfrag *q, *p;	if (smp_debug){		if (smp_owner(&lk_ipq) == 0)			panic("ip_freef not lock owner");	}	for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {		p = q->ipf_next;		ip_deq(q);		m_freem(dtom(q));	}	remque(fp);	KM_FREE(fp, KM_FTABLE);}/* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. *//* 12.9.88.us  Enter with lk_ipq set.  */ ip_enq(p, prev)	register struct ipasfrag *p, *prev;{	p->ipf_prev = prev;	p->ipf_next = prev->ipf_next;	prev->ipf_next->ipf_prev = p;	prev->ipf_next = p;}/* * To ip_enq as remque is to insque. *//* 12.9.88.us  Enter with lk_ipq set.  */ ip_deq(p)	register struct ipasfrag *p;{	p->ipf_prev->ipf_next = p->ipf_next;	p->ipf_next->ipf_prev = p->ipf_prev;}/* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. */ip_slowtimo(){	register struct ipq *fp;	int s = splnet();	/* 12.9.88.us.  Bug fix - panicing from a null referenced pointer	 * from inadequate locking on lk_ipq.  Note that all fixes on 	 * 12.9.88 are to fix this panic.  */	smp_lock(&lk_ipq, LK_RETRY);	fp = ipq.next;	if (fp == 0) {		smp_unlock(&lk_ipq);		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);		}	}	/* 12.8.88.us */	smp_unlock(&lk_ipq);	splx(s);}/* * Drain off all datagram fragments. */ip_drain(){	/* 12.8.88.us */	smp_lock(&lk_ipq, LK_RETRY);	while (ipq.next != &ipq) {		IPSTAT(ips_fragdropped++);		ip_freef(ipq.next);	}	/* 12.8.88.us */	smp_unlock(&lk_ipq);}extern struct in_ifaddr *ifptoia();struct in_ifaddr *ip_rtaddr();int icmp_badoptlen=0;		/* debug only: count of bad optlens */int icmp_badlsrroffset=0;	/* debug only: count of bad LSRR options *//* * Do option processing on a datagram, * possibly discarding it if bad options * are encountered. */ip_dooptions(ip, ifp)	register struct ip *ip;	struct ifnet *ifp;{	register u_char *cp;	int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB;	register struct ip_timestamp *ipt;	register struct in_ifaddr *ia;	struct in_addr *sin;	n_time ntime;	int s;	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;				icmp_badoptlen++;				m_freem(dtom(ip));				goto bad2;	/* don't attempt reply pkt */			}		}		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 on directly accessible net.		 */		case IPOPT_LSRR:		case IPOPT_SSRR:			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {				code = &cp[IPOPT_OFFSET] - (u_char *)ip;				icmp_badlsrroffset++;				m_freem(dtom(ip));				goto bad2; /* don't attempt reply pkt */			}#ifdef mips                        bcopy(&ip->ip_dst, &ipaddr.sin_addr,                                sizeof(ip->ip_dst));#endif mips#ifdef vax                        ipaddr.sin_addr = ip->ip_dst;#endif vax			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 &&			    in_iaonnetof(in_netof(ipaddr.sin_addr)) == 0) ||			    (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {				type = ICMP_UNREACH;				code = ICMP_UNREACH_SRCFAIL;				goto bad;			}#ifdef mips                        bcopy(&ipaddr.sin_addr, &ip->ip_dst,                                sizeof(ip->ip_dst));#endif mips#ifdef vax			ip->ip_dst = ipaddr.sin_addr;#endif vax			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_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 ((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) {

⌨️ 快捷键说明

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