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

📄 ip.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "all.h"#include "../ip/ip.h"#define	DEBUG	if(1||cons.flags&Fip)printtypedef	struct	Rock	Rock;typedef	struct	Frag	Frag;struct	Frag{	int	start;	int	end;};struct	Rock{	uchar	src[Pasize];	uchar	dst[Pasize];	int	id;		/* src,dst,id are address of the rock */	Msgbuf*	mb;		/* reassembly. if 0, the rock is empty */	Timet	age;		/* timeout to throw away */	int	last;		/* set to data size when last frag arrives */	int	nfrag;	Frag	frag[Nfrag];};staticstruct{	Lock;	Rock	rock[Nrock];} ip;voidipreceive(Enpkt *ep, int l, Ifc *ifc){	Ippkt *p;	Msgbuf *mb;	Rock *r, *or;	Frag *f;	int len, id, frag, off, loff, i, n;	Ippkt pkt;	Timet t;	p = (Ippkt*)ep;	if(l < Ensize+Ipsize) {		ifc->sumerr++;		print("ip: en too small\n");		return;	}	if(l > LARGEBUF) {		ifc->sumerr++;		print("ip: en too large\n");		return;	}	memmove(&pkt, p, Ensize+Ipsize);	/* copy pkt to 'real' memory */	if(pkt.vihl != (IP_VER|IP_HLEN))		return;	if(!ipforme(pkt.dst, ifc))		return;	if(ipcsum(&pkt.vihl)) {		ifc->sumerr++;		print("ip: checksum error (from %I)\n", pkt.src);		return;	}	frag = nhgets(pkt.frag);	len = nhgets(pkt.length) - Ipsize;	id = nhgets(pkt.id);	/*	 * total ip msg fits into one frag	 */	if((frag & ~IP_DF) == 0) {		mb = mballoc(l, 0, Mbip3);		memmove(mb->data, &pkt, Ensize+Ipsize);		memmove(mb->data + (Ensize+Ipsize),			(uchar*)p + (Ensize+Ipsize), l-(Ensize+Ipsize));		goto send;	}	/*	 * throw away old rocks.	 */	t = toytime();	lock(&ip);	r = ip.rock;	for(i=0; i<Nrock; i++,r++)		if(r->mb && t >= r->age) {			mbfree(r->mb);			r->mb = 0;		}	/*	 * reassembly of fragments	 * look up rock by src, dst, id.	 */	or = 0;	r = ip.rock;	for(i=0; i<Nrock; i++,r++) {		if(r->mb == 0) {			if(or == 0)				or = r;			continue;		}		if(id == r->id)		if(memcmp(r->src, pkt.src, Pasize) == 0)		if(memcmp(r->dst, pkt.dst, Pasize) == 0)			goto found;	}	r = or;	if(r == 0) {		/* no available rocks */		r = ip.rock;		for(i=0; i<Nrock; i++,r++)			if(r->mb) {				mbfree(r->mb);				r->mb = 0;			}		r = ip.rock;	}	r->id = id;	r->mb = mballoc(LARGEBUF, 0, Mbip2);	memmove(r->src, pkt.src, Pasize);	memmove(r->dst, pkt.dst, Pasize);	r->nfrag = 0;	r->last = 0;found:	mb = r->mb;	r->age = t + SECOND(30);	off = (frag & ~(IP_DF|IP_MF)) << 3;	if(len+off+Ensize+Ipsize > mb->count) {		/* ip pkt too big */		mbfree(mb);		r->mb = 0;		goto uout;	}	if(!(frag & IP_MF))		r->last = off+len;		/* found the end */	memmove(mb->data+(Ensize+Ipsize)+off,		(uchar*)p + (Ensize+Ipsize), len);	/*	 * frag algorithm:	 * first entry is easy	 */	n = r->nfrag;	if(n == 0) {		r->frag[0].start = off;		r->frag[0].end = off+len;		r->nfrag = 1;		goto span;	}	/*	 * two in a row is easy	 */	if(r->frag[n-1].end == off) {		r->frag[n-1].end += len;		goto span;	}	/*	 * add this frag	 */	if(n >= Nfrag) {		/* too many frags */		mbfree(mb);		r->mb = 0;		goto uout;	}	r->frag[n].start = off;	r->frag[n].end = off+len;	n++;	r->nfrag = n;span:	/*	 * see if we span the whole list	 * can be O(n**2), but usually much smaller	 */	if(r->last == 0)		goto uout;	off = 0;spanloop:	loff = off;	f = r->frag;	for(i=0; i<n; i++,f++)		if(off >= f->start && off < f->end)			off = f->end;	if(loff == off)		goto uout;	if(off < r->last)		goto spanloop;	memmove(mb->data, &pkt, Ensize+Ipsize);	p = (Ippkt*)mb->data;	hnputs(p->length, r->last+Ipsize);	l = r->last + (Ensize+Ipsize);	mb->count = l;	r->mb = 0;	unlock(&ip);send:	switch(pkt.proto) {	default:		mbfree(mb);		break;	case Ilproto:		ilrecv(mb, ifc);		break;	case Udpproto:		udprecv(mb, ifc);		break;	case Icmpproto:		icmprecv(mb, ifc);		break;	case Igmpproto:		igmprecv(mb, ifc);		break;	case Tcpproto:		tcprecv(mb, ifc);		break;	}	return;uout:	unlock(&ip);}

⌨️ 快捷键说明

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