plan 9 kernel history: overview | file list | diff list

1999/0309/ip/ip.c (diff list | history)

1997/0327/sys/src/9/ip/ip.c:104,1101997/0423/sys/src/9/ip/ip.c:104,114 (short | long)
1997/0327    
		goto raise; 
	} 
 
	m = Mediaroute(eh->dst, gate); 
1997/0423    
	if(isbmcast(eh->dst)){ 
		m = Mediaroute(eh->src, nil); 
		memmove(gate, eh->dst, Ipaddrlen); 
	} else 
		m = Mediaroute(eh->dst, gate); 
1997/0327    
	if(m == nil){ 
		netlog(Logip, "no interface %I\n", eh->dst); 
		goto raise; 
1997/0327/sys/src/9/ip/ip.c:222,2281997/0423/sys/src/9/ip/ip.c:226,232
1997/0327    
void (*ipextprotoiput)(Block*); 
 
void 
ipiput(Block *bp) 
1997/0423    
ipiput(Media *m, Block *bp) 
1997/0327    
{ 
	Iphdr *h; 
	Proto *p; 
1997/0327/sys/src/9/ip/ip.c:288,2941997/0423/sys/src/9/ip/ip.c:292,298
1997/0327    
 
	p = Fsrcvpcol(&fs, h->proto); 
	if(p != nil && p->rcv != nil) 
		(*p->rcv)(bp); 
1997/0423    
		(*p->rcv)(m, bp); 
1997/0327    
	else if(ipextprotoiput != nil) 
		ipextprotoiput(bp); 
	else 
1997/0423/sys/src/9/ip/ip.c:362,3691997/0504/sys/src/9/ip/ip.c:362,371 (short | long)
1997/0327    
		return bp; 
	} 
 
	if(bp->base+sizeof(Ipfrag) >= bp->rp) 
		panic("ipreassemble"); 
1997/0504    
	if(bp->base+sizeof(Ipfrag) >= bp->rp){ 
		bp = padblock(bp, sizeof(Ipfrag)); 
		bp->rp += sizeof(Ipfrag); 
	} 
1997/0327    
 
	BKFG(bp)->foff = offset<<3; 
	BKFG(bp)->flen = nhgets(ip->length)-IPHDR; 
1997/0504/sys/src/9/ip/ip.c:137,1431997/0522/sys/src/9/ip/ip.c:137,143 (short | long)
1997/0327    
	} 
 
	if(eh->frag[0] & (IP_DF>>8)){ 
		netlog(Logip, "%I: eh->frag[0] & (IP_DF>>8)", eh->dst); 
1997/0522    
		netlog(Logip, "%I: eh->frag[0] & (IP_DF>>8)\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
 
1997/0522/sys/src/9/ip/ip.c:37,431997/0529/sys/src/9/ip/ip.c:37,42 (short | long)
1997/0327    
 
struct Fragment 
{ 
	QLock; 
	Block*	blist; 
	Fragment* next; 
	Ipaddr 	src; 
1997/0522/sys/src/9/ip/ip.c:52,601997/0529/sys/src/9/ip/ip.c:51,59
1997/0327    
	ushort	flen; 
}; 
 
1997/0529    
QLock		fraglock; 
1997/0327    
Fragment*	flisthead; 
Fragment*	fragfree; 
QLock		fraglock; 
ulong		Id; 
int		iprouting;	/* true if we route like a gateway */ 
ulong		ipcsumerr; 
1997/0522/sys/src/9/ip/ip.c:70,761997/0529/sys/src/9/ip/ip.c:69,75
1997/0327    
 
ushort		ipcsum(byte*); 
Block*		ipreassemble(int, Block*, Iphdr*); 
void		ipfragfree(Fragment*, int); 
1997/0529    
void		ipfragfree(Fragment*); 
1997/0327    
Fragment*	ipfragallo(void); 
 
void 
1997/0522/sys/src/9/ip/ip.c:309,3161997/0529/sys/src/9/ip/ip.c:308,313
1997/0327    
	return n; 
} 
 
QLock iplock; 
                 
Block* 
ipreassemble(int offset, Block *bp, Iphdr *ip) 
{ 
1997/0522/sys/src/9/ip/ip.c:333,3521997/0529/sys/src/9/ip/ip.c:330,347
1997/0327    
		ip = (Iphdr *)(bp->rp); 
	} 
 
	qlock(&iplock); 
1997/0529    
	qlock(&fraglock); 
1997/0327    
 
	/* 
	 *  find a reassembly queue for this fragment 
	 */ 
	qlock(&fraglock); 
	for(f = flisthead; f; f = fnext){ 
		fnext = f->next;	/* because ipfragfree changes the list */ 
		if(f->src == src && f->dst == dst && f->id == id) 
			break; 
		if(f->age > msec && canqlock(f)) 
			ipfragfree(f, 0); 
1997/0529    
		if(f->age < msec) 
			ipfragfree(f); 
1997/0327    
	} 
	qunlock(&fraglock); 
 
	/* 
	 *  if this isn't a fragmented packet, accept it 
1997/0522/sys/src/9/ip/ip.c:354,3641997/0529/sys/src/9/ip/ip.c:349,357
1997/0327    
	 *  with it. 
	 */ 
	if(!ip->tos && (offset & ~(IP_MF|IP_DF)) == 0) { 
		if(f != nil) { 
			qlock(f); 
			ipfragfree(f, 1); 
		} 
		qunlock(&iplock); 
1997/0529    
		if(f != nil) 
			ipfragfree(f); 
		qunlock(&fraglock); 
1997/0327    
		return bp; 
	} 
 
1997/0522/sys/src/9/ip/ip.c:373,3791997/0529/sys/src/9/ip/ip.c:366,371
1997/0327    
	/* First fragment allocates a reassembly queue */ 
	if(f == nil) { 
		f = ipfragallo(); 
		qlock(f); 
		f->id = id; 
		f->src = src; 
		f->dst = dst; 
1997/0522/sys/src/9/ip/ip.c:380,3901997/0529/sys/src/9/ip/ip.c:372,380
1997/0327    
 
		f->blist = bp; 
 
		qunlock(f); 
		qunlock(&iplock); 
1997/0529    
		qunlock(&fraglock); 
1997/0327    
		return nil; 
	} 
	qlock(f); 
 
	/* 
	 *  find the new fragment's position in the queue 
1997/0522/sys/src/9/ip/ip.c:404,4111997/0529/sys/src/9/ip/ip.c:394,400
1997/0327    
		if(ovlap > 0) { 
			if(ovlap >= BKFG(bp)->flen) { 
				freeblist(bp); 
				qunlock(f); 
				qunlock(&iplock); 
1997/0529    
				qunlock(&fraglock); 
1997/0327    
				return nil; 
			} 
			BKFG(prev)->flen -= ovlap; 
1997/0522/sys/src/9/ip/ip.c:465,4881997/0529/sys/src/9/ip/ip.c:454,476
1997/0327    
 
			bl = f->blist; 
			f->blist = nil; 
			ipfragfree(f, 1); 
1997/0529    
			ipfragfree(f); 
1997/0327    
			ip = BLKIP(bl); 
			hnputs(ip->length, len); 
			qunlock(&iplock); 
1997/0529    
			qunlock(&fraglock); 
1997/0327    
			return bl;		 
		} 
		pktposn += BKFG(bl)->flen; 
	} 
	qunlock(f); 
	qunlock(&iplock); 
1997/0529    
	qunlock(&fraglock); 
1997/0327    
	return nil; 
} 
 
/* 
 * ipfragfree - Free a list of fragments, fragment list must be locked 
1997/0529    
 * ipfragfree - Free a list of fragments - assume hold fraglock 
1997/0327    
 */ 
void 
ipfragfree(Fragment *frag, int lockq) 
1997/0529    
ipfragfree(Fragment *frag) 
1997/0327    
{ 
	Fragment *fl, **l; 
 
1997/0522/sys/src/9/ip/ip.c:492,5021997/0529/sys/src/9/ip/ip.c:480,486
1997/0327    
	frag->src = 0; 
	frag->id = 0; 
	frag->blist = nil; 
	qunlock(frag); 
 
	if(lockq) 
		qlock(&fraglock); 
                 
	l = &flisthead; 
	for(fl = *l; fl; fl = fl->next) { 
		if(fl == frag) { 
1997/0522/sys/src/9/ip/ip.c:509,5201997/0529/sys/src/9/ip/ip.c:493,502
1997/0327    
	frag->next = fragfree; 
	fragfree = frag; 
 
	if(lockq) 
		qunlock(&fraglock); 
} 
 
/* 
 * ipfragallo - allocate a reassembly queue 
1997/0529    
 * ipfragallo - allocate a reassembly queue - assume hold fraglock 
1997/0327    
 */ 
Fragment * 
ipfragallo(void) 
1997/0522/sys/src/9/ip/ip.c:521,5331997/0529/sys/src/9/ip/ip.c:503,513
1997/0327    
{ 
	Fragment *f; 
 
	qlock(&fraglock); 
	while(fragfree == nil) { 
		for(f = flisthead; f; f = f->next) 
			if(canqlock(f)) { 
				ipfragfree(f, 0); 
				break; 
			} 
1997/0529    
		/* free last entry on fraglist */ 
		for(f = flisthead; f->next; f = f->next) 
			; 
		ipfragfree(f); 
1997/0327    
	} 
	f = fragfree; 
	fragfree = f->next; 
1997/0522/sys/src/9/ip/ip.c:535,5411997/0529/sys/src/9/ip/ip.c:515,520
1997/0327    
	flisthead = f; 
	f->age = msec + 30000; 
 
	qunlock(&fraglock); 
	return f; 
} 
 
1997/0529/sys/src/9/ip/ip.c:224,2291997/0806/sys/src/9/ip/ip.c:224,231 (short | long)
1997/0327    
 
void (*ipextprotoiput)(Block*); 
 
1997/0806    
//#define DBG(x)	if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog 
 
1997/0327    
void 
1997/0423    
ipiput(Media *m, Block *bp) 
1997/0327    
{ 
1997/0529/sys/src/9/ip/ip.c:232,2391997/0806/sys/src/9/ip/ip.c:234,241
1997/0327    
	ushort frag; 
	int notforme; 
 
/*	h = (Iphdr *)(bp->rp); 
	netlog(Logip, "ipiput %I %I len %d proto %d\n", h->src, h->dst, BLEN(bp), h->proto);*/ 
1997/0806    
//	h = (Iphdr *)(bp->rp); 
//	DBG(nhgetl(h->src))(Logipmsg, "ipiput %I %I len %d proto %d\n", h->src, h->dst, BLEN(bp), h->proto); 
1997/0327    
 
	/* Ensure we have enough data to process */ 
	if(BLEN(bp) < IPHDR) { 
1997/0806/sys/src/9/ip/ip.c:305,3111997/0808/sys/src/9/ip/ip.c:305,311 (short | long)
1997/0327    
{ 
	int n; 
 
	n = snprint(buf, len, "ip: csum %d inb %d outb %d inp %d outp %d\n", 
1997/0808    
	n = snprint(buf, len, "ip: csum %lud inb %lud outb %lud inp %lud outp %lud\n", 
1997/0327    
		ipcsumerr, ipin, ipout, ippin, ippout); 
	return n; 
} 
1997/0808/sys/src/9/ip/ip.c:105,1111997/0815/sys/src/9/ip/ip.c:105,111 (short | long)
1997/0327    
 
1997/0423    
	if(isbmcast(eh->dst)){ 
		m = Mediaroute(eh->src, nil); 
		memmove(gate, eh->dst, Ipaddrlen); 
1997/0815    
		memmove(gate, eh->dst, IPaddrlen); 
1997/0423    
	} else 
		m = Mediaroute(eh->dst, gate); 
1997/0327    
	if(m == nil){ 
1997/0815/sys/src/9/ip/ip.c:67,721997/0916/sys/src/9/ip/ip.c:67,78 (short | long)
1997/0327    
 */ 
#define BKFG(xp)	((Ipfrag*)((xp)->base)) 
 
1997/0916    
static struct Stats 
{ 
	ulong	noroute; 
	ulong	droppedfrag; 
} stats; 
 
1997/0327    
ushort		ipcsum(byte*); 
Block*		ipreassemble(int, Block*, Iphdr*); 
1997/0529    
void		ipfragfree(Fragment*); 
1997/0815/sys/src/9/ip/ip.c:109,1141997/0916/sys/src/9/ip/ip.c:115,121
1997/0423    
	} else 
		m = Mediaroute(eh->dst, gate); 
1997/0327    
	if(m == nil){ 
1997/0916    
		stats.noroute++; 
1997/0327    
		netlog(Logip, "no interface %I\n", eh->dst); 
		goto raise; 
	} 
1997/0815/sys/src/9/ip/ip.c:307,3121997/0916/sys/src/9/ip/ip.c:314,321
1997/0327    
 
1997/0808    
	n = snprint(buf, len, "ip: csum %lud inb %lud outb %lud inp %lud outp %lud\n", 
1997/0327    
		ipcsumerr, ipin, ipout, ippin, ippout); 
1997/0916    
	n += snprint(buf+n, len - n, "\tnoroute %lud droppedfrag %lud\n", 
		stats.noroute, stats.droppedfrag); 
1997/0327    
	return n; 
} 
 
1997/0815/sys/src/9/ip/ip.c:341,3481997/0916/sys/src/9/ip/ip.c:350,359
1997/0327    
		fnext = f->next;	/* because ipfragfree changes the list */ 
		if(f->src == src && f->dst == dst && f->id == id) 
			break; 
1997/0529    
		if(f->age < msec) 
1997/0916    
		if(f->age < msec){ 
			stats.droppedfrag++; 
1997/0529    
			ipfragfree(f); 
1997/0916    
		} 
1997/0327    
	} 
 
	/* 
1997/0916/sys/src/9/ip/ip.c:218,2241997/1104/sys/src/9/ip/ip.c:218,224 (short | long)
1997/0327    
{ 
	Fragment *fq, *eq; 
 
	fragfree = (Fragment*)malloc(sizeof(Fragment) * size); 
1997/1104    
	fragfree = malloc(sizeof(Fragment) * size); 
1997/0327    
	if(fragfree == nil) 
		panic("initfrag"); 
 
1997/1104/sys/src/9/ip/ip.c:18,241998/0217/sys/src/9/ip/ip.c:18,24 (short | long)
1997/0327    
	IP_HLEN		= 0x05,		/* Header length in characters */ 
	IP_DF		= 0x4000,	/* Don't fragment */ 
	IP_MF		= 0x2000,	/* More fragments */ 
	IP_MAX		= (32*1024),	/* Maximum Internet packet size */ 
1998/0217    
	IP_MAX		= (64*1024),	/* Maximum Internet packet size */ 
1997/0327    
}; 
 
struct Iphdr 
1998/0217/sys/src/9/ip/ip.c:18,381998/0306/sys/src/9/ip/ip.c:18,38 (short | long)
1997/0327    
	IP_HLEN		= 0x05,		/* Header length in characters */ 
	IP_DF		= 0x4000,	/* Don't fragment */ 
	IP_MF		= 0x2000,	/* More fragments */ 
1998/0217    
	IP_MAX		= (64*1024),	/* Maximum Internet packet size */ 
1998/0306    
	IP_MAX		= (32*1024),	/* Maximum Internet packet size */ 
1997/0327    
}; 
 
struct Iphdr 
{ 
	byte	vihl;		/* Version and header length */ 
	byte	tos;		/* Type of service */ 
	byte	length[2];	/* packet length */ 
	byte	id[2];		/* Identification */ 
	byte	frag[2];	/* Fragment information */ 
	byte	ttl;		/* Time to live */ 
	byte	proto;		/* Protocol */ 
	byte	cksum[2];	/* Header checksum */ 
	byte	src[4];		/* Ip source */ 
	byte	dst[4];		/* Ip destination */ 
1998/0306    
	uchar	vihl;		/* Version and header length */ 
	uchar	tos;		/* Type of service */ 
	uchar	length[2];	/* packet length */ 
	uchar	id[2];		/* Identification */ 
	uchar	frag[2];	/* Fragment information */ 
	uchar	ttl;		/* Time to live */ 
	uchar	proto;		/* Protocol */ 
	uchar	cksum[2];	/* Header checksum */ 
	uchar	src[4];		/* Ip source */ 
	uchar	dst[4];		/* Ip destination */ 
1997/0327    
}; 
 
struct Fragment 
1998/0217/sys/src/9/ip/ip.c:39,461998/0306/sys/src/9/ip/ip.c:39,46
1997/0327    
{ 
	Block*	blist; 
	Fragment* next; 
	Ipaddr 	src; 
	Ipaddr 	dst; 
1998/0306    
	ulong 	src; 
	ulong 	dst; 
1997/0327    
	ushort	id; 
	ulong 	age; 
}; 
1998/0217/sys/src/9/ip/ip.c:57,641998/0306/sys/src/9/ip/ip.c:57,64
1997/0327    
ulong		Id; 
int		iprouting;	/* true if we route like a gateway */ 
ulong		ipcsumerr; 
ulong		ipin, ippin;		/* bytes, packets in */ 
ulong		ipout, ippout;		/* bytes, packets out */ 
1998/0306    
ulong		ipin, ippin;		/* uchars, packets in */ 
ulong		ipout, ippout;		/* uchars, packets out */ 
1997/0327    
 
#define BLKIP(xp)	((Iphdr*)((xp)->rp)) 
/* 
1998/0217/sys/src/9/ip/ip.c:73,791998/0306/sys/src/9/ip/ip.c:73,79
1997/0916    
	ulong	droppedfrag; 
} stats; 
 
1997/0327    
ushort		ipcsum(byte*); 
1998/0306    
ushort		ipcsum(uchar*); 
1997/0327    
Block*		ipreassemble(int, Block*, Iphdr*); 
1997/0529    
void		ipfragfree(Fragment*); 
1997/0327    
Fragment*	ipfragallo(void); 
1998/0217/sys/src/9/ip/ip.c:81,971998/0306/sys/src/9/ip/ip.c:81,98
1997/0327    
void 
ipoput(Block *bp, int gating, int ttl) 
{ 
	Media *m; 
	byte gate[4]; 
1998/0306    
	Ipifc *ifc; 
	uchar *gate; 
1997/0327    
	ushort fragoff; 
	Block *xp, *nb; 
	Iphdr *eh, *feh; 
	int lid, len, seglen, chunk, dlen, blklen, offset, medialen; 
1998/0306    
	Route *r; 
1997/0327    
 
	/* Fill out the ip header */ 
	eh = (Iphdr *)(bp->rp); 
 
	/* Number of bytes in data and ip header to write */ 
1998/0306    
	/* Number of uchars in data and ip header to write */ 
1997/0327    
	len = blocklen(bp); 
	ipout += len; 
	ippout++; 
1998/0217/sys/src/9/ip/ip.c:104,1331998/0306/sys/src/9/ip/ip.c:105,134
1997/0327    
		if(chunk < len) 
			len = chunk; 
	} 
	if(len >= IP_MAX) { 
		netlog(Logip, "exceeded ip max size %I\n", eh->dst); 
1998/0306    
	if(len >= IP_MAX){ 
		netlog(Logip, "exceeded ip max size %V\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
 
1997/0423    
	if(isbmcast(eh->dst)){ 
		m = Mediaroute(eh->src, nil); 
1997/0815    
		memmove(gate, eh->dst, IPaddrlen); 
1997/0423    
	} else 
		m = Mediaroute(eh->dst, gate); 
1997/0327    
	if(m == nil){ 
1998/0306    
	r = v4lookup(eh->dst); 
	if(r == nil){ 
1997/0916    
		stats.noroute++; 
1997/0327    
		netlog(Logip, "no interface %I\n", eh->dst); 
1998/0306    
		netlog(Logip, "no interface %V\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
                 
1998/0306    
	if(r->type & (Rifc|Runi|Rbcast|Rmulti)) 
		gate = eh->dst; 
	else 
		gate = r->v4.gate; 
1997/0327    
	if(!gating){ 
		eh->vihl = IP_VER|IP_HLEN; 
		eh->tos = 0; 
		eh->ttl = ttl; 
	} 
1998/0306    
	ifc = r->ifc; 
1997/0327    
 
	/* If we dont need to fragment just send it */ 
	medialen = m->maxmtu-m->hsize; 
1998/0306    
	medialen = ifc->m->maxmtu - ifc->m->hsize; 
1997/0327    
	if(len <= medialen) { 
		if(!gating) 
			hnputs(eh->id, Id++); 
1998/0217/sys/src/9/ip/ip.c:138,1551998/0306/sys/src/9/ip/ip.c:139,157
1997/0327    
		eh->cksum[1] = 0; 
		hnputs(eh->cksum, ipcsum(&eh->vihl)); 
 
		Mediawrite(m, bp, gate); 
1998/0306    
/*print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate);*/ 
		ifc->m->bwrite(ifc, bp, V4, gate); 
1997/0327    
		return; 
	} 
 
	if(eh->frag[0] & (IP_DF>>8)){ 
1997/0522    
		netlog(Logip, "%I: eh->frag[0] & (IP_DF>>8)\n", eh->dst); 
1998/0306    
		netlog(Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
 
	seglen = (medialen - IPHDR) & ~7; 
	if(seglen < 8){ 
		netlog(Logip, "%I seglen < 8\n", eh->dst); 
1998/0306    
		netlog(Logip, "%V seglen < 8\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
 
1998/0217/sys/src/9/ip/ip.c:206,2121998/0306/sys/src/9/ip/ip.c:208,214
1997/0327    
		feh->cksum[0] = 0; 
		feh->cksum[1] = 0; 
		hnputs(feh->cksum, ipcsum(&feh->vihl)); 
		Mediawrite(m, nb, gate); 
1998/0306    
		ifc->m->bwrite(ifc, nb, V4, gate); 
1997/0327    
	} 
 
raise: 
1998/0217/sys/src/9/ip/ip.c:218,2241998/0306/sys/src/9/ip/ip.c:220,226
1997/0327    
{ 
	Fragment *fq, *eq; 
 
1997/1104    
	fragfree = malloc(sizeof(Fragment) * size); 
1998/0306    
	fragfree = (Fragment*)malloc(sizeof(Fragment) * size); 
1997/0327    
	if(fragfree == nil) 
		panic("initfrag"); 
 
1998/0217/sys/src/9/ip/ip.c:234,2451998/0306/sys/src/9/ip/ip.c:236,248
1997/0806    
//#define DBG(x)	if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog 
 
1997/0327    
void 
1997/0423    
ipiput(Media *m, Block *bp) 
1998/0306    
ipiput(uchar *ia, Block *bp) 
1997/0327    
{ 
	Iphdr *h; 
	Proto *p; 
	ushort frag; 
	int notforme; 
1998/0306    
	uchar v6dst[IPaddrlen]; 
1997/0327    
 
1997/0806    
//	h = (Iphdr *)(bp->rp); 
//	DBG(nhgetl(h->src))(Logipmsg, "ipiput %I %I len %d proto %d\n", h->src, h->dst, BLEN(bp), h->proto); 
1998/0217/sys/src/9/ip/ip.c:252,2651998/0306/sys/src/9/ip/ip.c:255,261
1997/0327    
	} 
	h = (Iphdr *)(bp->rp); 
 
	/* Look to see if its for me before we waste time checksumming it */ 
	notforme = Mediaforme(h->dst) == 0; 
	if(notforme && !iprouting) { 
		netlog(Logip, "ip: pkt not for me\n"); 
		freeblist(bp); 
		return; 
	} 
                 
1998/0306    
	/* dump anything that whose header doesn't checksum */ 
1997/0327    
	if(ipcsum(&h->vihl)) { 
		ipcsumerr++; 
		netlog(Logip, "ip: checksum error %I\n", h->src); 
1998/0217/sys/src/9/ip/ip.c:267,2721998/0306/sys/src/9/ip/ip.c:263,283
1997/0327    
		return; 
	} 
 
1998/0306    
	/* route */ 
	v4tov6(v6dst, h->dst); 
	notforme = ipforme(v6dst) == 0; 
	if(notforme) { 
		if(iprouting) { 
			/* gate */ 
			if(h->ttl <= 1) 
				freeblist(bp); 
			else 
				ipoput(bp, 1, h->ttl - 1); 
		} else 
			useriprouter(ia, bp); 
		return; 
	} 
 
1997/0327    
	/* Check header length and version */ 
	if(h->vihl != (IP_VER|IP_HLEN)) { 
		netlog(Logip, "ip: %I bad hivl %ux\n", h->src, h->vihl); 
1998/0217/sys/src/9/ip/ip.c:287,3061998/0306/sys/src/9/ip/ip.c:298,306
1997/0327    
	ipin += blocklen(bp); 
	ippin++; 
 
	if(iprouting) { 
		/* gate */ 
		if(notforme){ 
			if(h->ttl == 0) 
				freeblist(bp); 
			else 
				ipoput(bp, 1, h->ttl - 1); 
			return; 
		} 
	} 
                 
	p = Fsrcvpcol(&fs, h->proto); 
	if(p != nil && p->rcv != nil) 
1997/0423    
		(*p->rcv)(m, bp); 
1998/0306    
		(*p->rcv)(ia, bp); 
1997/0327    
	else if(ipextprotoiput != nil) 
		ipextprotoiput(bp); 
	else 
1998/0217/sys/src/9/ip/ip.c:325,3311998/0306/sys/src/9/ip/ip.c:325,331
1997/0327    
	int fend; 
	ushort id; 
	Fragment *f, *fnext; 
	Ipaddr src, dst; 
1998/0306    
	ulong src, dst; 
1997/0327    
	Block *bl, **l, *last, *prev; 
	int ovlap, len, fragsize, pktposn; 
 
1998/0217/sys/src/9/ip/ip.c:532,5381998/0306/sys/src/9/ip/ip.c:532,538
1997/0327    
} 
 
ushort 
ipcsum(byte *addr) 
1998/0306    
ipcsum(uchar *addr) 
1997/0327    
{ 
	int len; 
	ulong sum; 
1998/0306/sys/src/9/ip/ip.c:127,1321998/0307/sys/src/9/ip/ip.c:127,140 (short | long)
1997/0327    
	} 
1998/0306    
	ifc = r->ifc; 
1997/0327    
 
1998/0307    
	if(waserror()){ 
		runlock(ifc); 
		nexterror(); 
	} 
	rlock(ifc); 
	if(ifc->m == nil) 
		goto raise; 
 
1997/0327    
	/* If we dont need to fragment just send it */ 
1998/0306    
	medialen = ifc->m->maxmtu - ifc->m->hsize; 
1997/0327    
	if(len <= medialen) { 
1998/0306/sys/src/9/ip/ip.c:141,1461998/0307/sys/src/9/ip/ip.c:149,156
1997/0327    
 
1998/0306    
/*print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate);*/ 
		ifc->m->bwrite(ifc, bp, V4, gate); 
1998/0307    
		runlock(ifc); 
		poperror(); 
1997/0327    
		return; 
	} 
 
1998/0306/sys/src/9/ip/ip.c:203,2091998/0307/sys/src/9/ip/ip.c:213,219
1997/0327    
			chunk -= blklen; 
			if(xp->rp == xp->wp) 
				xp = xp->next; 
		}  
1998/0307    
		} 
1997/0327    
 
		feh->cksum[0] = 0; 
		feh->cksum[1] = 0; 
1998/0306/sys/src/9/ip/ip.c:212,2171998/0307/sys/src/9/ip/ip.c:222,229
1997/0327    
	} 
 
raise: 
1998/0307    
	runlock(ifc); 
	poperror(); 
1997/0327    
	freeblist(bp);	 
} 
 
1998/0307/sys/src/9/ip/ip.c:100,1061998/0308/sys/src/9/ip/ip.c:100,106 (short | long)
1997/0327    
		chunk = nhgets(eh->length); 
		if(chunk > len){ 
			netlog(Logip, "short gated packet\n"); 
			goto raise; 
1998/0308    
			goto free; 
1997/0327    
		} 
		if(chunk < len) 
			len = chunk; 
1998/0307/sys/src/9/ip/ip.c:107,1131998/0308/sys/src/9/ip/ip.c:107,113
1997/0327    
	} 
1998/0306    
	if(len >= IP_MAX){ 
		netlog(Logip, "exceeded ip max size %V\n", eh->dst); 
1997/0327    
		goto raise; 
1998/0308    
		goto free; 
1997/0327    
	} 
 
1998/0306    
	r = v4lookup(eh->dst); 
1998/0307/sys/src/9/ip/ip.c:114,1201998/0308/sys/src/9/ip/ip.c:114,120
1998/0306    
	if(r == nil){ 
1997/0916    
		stats.noroute++; 
1998/0306    
		netlog(Logip, "no interface %V\n", eh->dst); 
1997/0327    
		goto raise; 
1998/0308    
		goto free; 
1997/0327    
	} 
1998/0306    
	if(r->type & (Rifc|Runi|Rbcast|Rmulti)) 
		gate = eh->dst; 
1998/0307/sys/src/9/ip/ip.c:224,2291998/0308/sys/src/9/ip/ip.c:224,230
1997/0327    
raise: 
1998/0307    
	runlock(ifc); 
	poperror(); 
1998/0308    
free: 
1997/0327    
	freeblist(bp);	 
} 
 
1998/0308/sys/src/9/ip/ip.c:26,381998/0313/sys/src/9/ip/ip.c:26,38 (short | long)
1998/0306    
	uchar	vihl;		/* Version and header length */ 
	uchar	tos;		/* Type of service */ 
	uchar	length[2];	/* packet length */ 
	uchar	id[2];		/* Identification */ 
1998/0313    
	uchar	id[2];		/* ip->identification */ 
1998/0306    
	uchar	frag[2];	/* Fragment information */ 
	uchar	ttl;		/* Time to live */ 
	uchar	proto;		/* Protocol */ 
	uchar	cksum[2];	/* Header checksum */ 
	uchar	src[4];		/* Ip source */ 
	uchar	dst[4];		/* Ip destination */ 
1998/0313    
	uchar	src[4];		/* IP source */ 
	uchar	dst[4];		/* IP destination */ 
1997/0327    
}; 
 
struct Fragment 
1998/0308/sys/src/9/ip/ip.c:51,651998/0313/sys/src/9/ip/ip.c:51,95
1997/0327    
	ushort	flen; 
}; 
 
1997/0529    
QLock		fraglock; 
1997/0327    
Fragment*	flisthead; 
Fragment*	fragfree; 
ulong		Id; 
int		iprouting;	/* true if we route like a gateway */ 
ulong		ipcsumerr; 
1998/0306    
ulong		ipin, ippin;		/* uchars, packets in */ 
ulong		ipout, ippout;		/* uchars, packets out */ 
1998/0313    
/* MIB II counters */ 
typedef struct Ipstats Ipstats; 
struct Ipstats 
{ 
	ulong	ipForwarding; 
	ulong	ipDefaultTTL; 
	ulong	ipInReceives; 
	ulong	ipInHdrErrors; 
	ulong	ipInAddrErrors; 
	ulong	ipForwDatagrams; 
	ulong	ipInUnknownProtos; 
	ulong	ipInDiscards; 
	ulong	ipInDelivers; 
	ulong	ipOutRequests; 
	ulong	ipOutDiscards; 
	ulong	ipOutNoRoutes; 
	ulong	ipReasmTimeout; 
	ulong	ipReasmReqds; 
	ulong	ipReasmOKs; 
	ulong	ipReasmFails; 
	ulong	ipFragOKs; 
	ulong	ipFragFails; 
	ulong	ipFragCreates; 
}; 
1997/0327    
 
1998/0313    
/* an instance of IP */ 
struct IP 
{ 
	Ipstats		istats; 
 
	QLock		fraglock; 
	Fragment*	flisthead; 
	Fragment*	fragfree; 
 
	ulong		id; 
	int		iprouting;			/* true if we route like a gateway */ 
	void 		(*ipextprotoiput)(Block*); 
}; 
 
1997/0327    
#define BLKIP(xp)	((Iphdr*)((xp)->rp)) 
/* 
 * This sleazy macro relies on the media header size being 
1998/0308/sys/src/9/ip/ip.c:67,851998/0313/sys/src/9/ip/ip.c:97,119
1997/0327    
 */ 
#define BKFG(xp)	((Ipfrag*)((xp)->base)) 
 
1997/0916    
static struct Stats 
1998/0313    
ushort		ipcsum(uchar*); 
Block*		ipreassemble(IP*, int, Block*, Iphdr*); 
void		ipfragfree(IP*, Fragment*); 
Fragment*	ipfragallo(IP*); 
 
void 
ip_init(Fs *f) 
1997/0916    
{ 
	ulong	noroute; 
	ulong	droppedfrag; 
} stats; 
1998/0313    
	IP *ip; 
1997/0916    
 
1998/0306    
ushort		ipcsum(uchar*); 
1997/0327    
Block*		ipreassemble(int, Block*, Iphdr*); 
1997/0529    
void		ipfragfree(Fragment*); 
1997/0327    
Fragment*	ipfragallo(void); 
1998/0313    
	ip = smalloc(sizeof(IP)); 
	initfrag(ip, 100); 
	f->ip = ip; 
} 
1997/0327    
 
void 
ipoput(Block *bp, int gating, int ttl) 
1998/0313    
ipoput(Fs *f, Block *bp, int gating, int ttl) 
1997/0327    
{ 
1998/0306    
	Ipifc *ifc; 
	uchar *gate; 
1998/0308/sys/src/9/ip/ip.c:87,1051998/0313/sys/src/9/ip/ip.c:121,144
1997/0327    
	Block *xp, *nb; 
	Iphdr *eh, *feh; 
	int lid, len, seglen, chunk, dlen, blklen, offset, medialen; 
1998/0306    
	Route *r; 
1998/0313    
	Route *r, *sr; 
	IP *ip; 
1997/0327    
 
1998/0313    
	ip = f->ip; 
 
1997/0327    
	/* Fill out the ip header */ 
	eh = (Iphdr *)(bp->rp); 
 
1998/0313    
	ip->istats.ipOutRequests++; 
 
1998/0306    
	/* Number of uchars in data and ip header to write */ 
1997/0327    
	len = blocklen(bp); 
	ipout += len; 
	ippout++; 
1998/0313    
 
1997/0327    
	if(gating){ 
		chunk = nhgets(eh->length); 
		if(chunk > len){ 
			netlog(Logip, "short gated packet\n"); 
1998/0313    
			ip->istats.ipOutDiscards++; 
			netlog(f, Logip, "short gated packet\n"); 
1998/0308    
			goto free; 
1997/0327    
		} 
		if(chunk < len) 
1998/0308/sys/src/9/ip/ip.c:106,1311998/0313/sys/src/9/ip/ip.c:145,180
1997/0327    
			len = chunk; 
	} 
1998/0306    
	if(len >= IP_MAX){ 
		netlog(Logip, "exceeded ip max size %V\n", eh->dst); 
1998/0313    
		ip->istats.ipOutDiscards++; 
		netlog(f, Logip, "exceeded ip max size %V\n", eh->dst); 
1998/0308    
		goto free; 
1997/0327    
	} 
 
1998/0306    
	r = v4lookup(eh->dst); 
1998/0313    
	r = v4lookup(f, eh->dst); 
1998/0306    
	if(r == nil){ 
1997/0916    
		stats.noroute++; 
1998/0306    
		netlog(Logip, "no interface %V\n", eh->dst); 
1998/0313    
		ip->istats.ipOutNoRoutes++; 
		netlog(f, Logip, "no interface %V\n", eh->dst); 
1998/0308    
		goto free; 
1997/0327    
	} 
1998/0306    
	if(r->type & (Rifc|Runi|Rbcast|Rmulti)) 
1998/0313    
 
	ifc = r->ifc; 
	if(r->type & (Rifc|Runi)) 
1998/0306    
		gate = eh->dst; 
	else 
1998/0313    
	if(r->type & (Rbcast|Rmulti)) { 
		gate = eh->dst; 
		sr = v4lookup(f, eh->src); 
		if(sr != nil && (sr->type & Runi)) 
			ifc = sr->ifc; 
	} 
	else 
1998/0306    
		gate = r->v4.gate; 
1998/0313    
 
1997/0327    
	if(!gating){ 
		eh->vihl = IP_VER|IP_HLEN; 
		eh->tos = 0; 
		eh->ttl = ttl; 
	} 
1998/0306    
	ifc = r->ifc; 
1997/0327    
 
1998/0307    
	if(waserror()){ 
		runlock(ifc); 
1998/0308/sys/src/9/ip/ip.c:139,1451998/0313/sys/src/9/ip/ip.c:188,194
1998/0306    
	medialen = ifc->m->maxmtu - ifc->m->hsize; 
1997/0327    
	if(len <= medialen) { 
		if(!gating) 
			hnputs(eh->id, Id++); 
1998/0313    
			hnputs(eh->id, ip->id++); 
1997/0327    
		hnputs(eh->length, len); 
		eh->frag[0] = 0; 
		eh->frag[1] = 0; 
1998/0308/sys/src/9/ip/ip.c:147,1531998/0313/sys/src/9/ip/ip.c:196,202
1997/0327    
		eh->cksum[1] = 0; 
		hnputs(eh->cksum, ipcsum(&eh->vihl)); 
 
1998/0306    
/*print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate);*/ 
1998/0313    
/*		print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate); /**/ 
1998/0306    
		ifc->m->bwrite(ifc, bp, V4, gate); 
1998/0307    
		runlock(ifc); 
		poperror(); 
1998/0308/sys/src/9/ip/ip.c:155,1671998/0313/sys/src/9/ip/ip.c:204,218
1997/0327    
	} 
 
	if(eh->frag[0] & (IP_DF>>8)){ 
1998/0306    
		netlog(Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); 
1998/0313    
		ip->istats.ipOutDiscards++; 
		netlog(f, Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
 
	seglen = (medialen - IPHDR) & ~7; 
	if(seglen < 8){ 
1998/0306    
		netlog(Logip, "%V seglen < 8\n", eh->dst); 
1998/0313    
		ip->istats.ipOutDiscards++; 
		netlog(f, Logip, "%V seglen < 8\n", eh->dst); 
1997/0327    
		goto raise; 
	} 
 
1998/0308/sys/src/9/ip/ip.c:170,1761998/0313/sys/src/9/ip/ip.c:221,227
1997/0327    
	if(gating) 
		lid = nhgets(eh->id); 
	else 
		lid = Id++; 
1998/0313    
		lid = ip->id++; 
1997/0327    
 
	offset = IPHDR; 
	while(xp != nil && offset && offset >= BLEN(xp)) { 
1998/0308/sys/src/9/ip/ip.c:200,2071998/0313/sys/src/9/ip/ip.c:251,259
1997/0327    
		chunk = seglen; 
		while(chunk) { 
			if(!xp) { 
1998/0313    
				ip->istats.ipOutDiscards++; 
1997/0327    
				freeblist(nb); 
				netlog(Logip, "!xp: chunk %d\n", chunk); 
1998/0313    
				netlog(f, Logip, "!xp: chunk %d\n", chunk); 
1997/0327    
				goto raise; 
			} 
			blklen = chunk; 
1998/0308/sys/src/9/ip/ip.c:213,2261998/0313/sys/src/9/ip/ip.c:265,278
1997/0327    
			chunk -= blklen; 
			if(xp->rp == xp->wp) 
				xp = xp->next; 
1998/0307    
		} 
1998/0313    
		}  
1997/0327    
 
		feh->cksum[0] = 0; 
		feh->cksum[1] = 0; 
		hnputs(feh->cksum, ipcsum(&feh->vihl)); 
1998/0306    
		ifc->m->bwrite(ifc, nb, V4, gate); 
1998/0313    
		ip->istats.ipFragCreates++; 
1997/0327    
	} 
                 
raise: 
1998/0307    
	runlock(ifc); 
	poperror(); 
1998/0308/sys/src/9/ip/ip.c:229,2641998/0313/sys/src/9/ip/ip.c:281,320
1997/0327    
} 
 
void 
initfrag(int size) 
1998/0313    
initfrag(IP *ip, int size) 
1997/0327    
{ 
	Fragment *fq, *eq; 
 
1998/0306    
	fragfree = (Fragment*)malloc(sizeof(Fragment) * size); 
1997/0327    
	if(fragfree == nil) 
1998/0313    
	ip->fragfree = (Fragment*)malloc(sizeof(Fragment) * size); 
	if(ip->fragfree == nil) 
1997/0327    
		panic("initfrag"); 
 
	eq = &fragfree[size]; 
	for(fq = fragfree; fq < eq; fq++) 
1998/0313    
	eq = &ip->fragfree[size]; 
	for(fq = ip->fragfree; fq < eq; fq++) 
1997/0327    
		fq->next = fq+1; 
 
	fragfree[size-1].next = nil; 
1998/0313    
	ip->fragfree[size-1].next = nil; 
1997/0327    
} 
 
void (*ipextprotoiput)(Block*); 
1998/0313    
#define DBG(x)	if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog 
1997/0327    
 
1997/0806    
//#define DBG(x)	if((logmask & Logipmsg) && (iponly == 0 || x == iponly))netlog 
                 
1997/0327    
void 
1998/0306    
ipiput(uchar *ia, Block *bp) 
1998/0313    
ipiput(Fs *f, uchar *ia, Block *bp) 
1997/0327    
{ 
1998/0313    
	int hl; 
1997/0327    
	Iphdr *h; 
	Proto *p; 
	ushort frag; 
	int notforme; 
1998/0306    
	uchar v6dst[IPaddrlen]; 
1998/0313    
	uchar *dp, v6dst[IPaddrlen]; 
	IP *ip; 
1997/0327    
 
1998/0313    
	ip = f->ip; 
	ip->istats.ipInReceives++; 
 
1997/0806    
//	h = (Iphdr *)(bp->rp); 
//	DBG(nhgetl(h->src))(Logipmsg, "ipiput %I %I len %d proto %d\n", h->src, h->dst, BLEN(bp), h->proto); 
1998/0313    
//	DBG(nhgetl(h->src))(Logipmsg, "ipiput %V %V len %d proto %d\n", 
//				h->src, h->dst, BLEN(bp), h->proto); 
1997/0327    
 
	/* Ensure we have enough data to process */ 
	if(BLEN(bp) < IPHDR) { 
1998/0308/sys/src/9/ip/ip.c:270,3391998/0313/sys/src/9/ip/ip.c:326,420
1997/0327    
 
1998/0306    
	/* dump anything that whose header doesn't checksum */ 
1997/0327    
	if(ipcsum(&h->vihl)) { 
		ipcsumerr++; 
		netlog(Logip, "ip: checksum error %I\n", h->src); 
1998/0313    
		ip->istats.ipInHdrErrors++; 
		netlog(f, Logip, "ip: checksum error %I\n", h->src); 
1997/0327    
		freeblist(bp); 
		return; 
	} 
 
1998/0306    
	/* route */ 
	v4tov6(v6dst, h->dst); 
	notforme = ipforme(v6dst) == 0; 
1998/0313    
	notforme = ipforme(f, v6dst) == 0; 
 
	/* Check header length and version */ 
	if(h->vihl != (IP_VER|IP_HLEN)) { 
		hl = (h->vihl&0xF)<<2; 
		if((h->vihl&0xF0) != IP_VER || hl < (IP_HLEN<<2)) { 
			ip->istats.ipInHdrErrors++; 
			netlog(f, Logip, "ip: %V bad hivl %ux\n", h->src, h->vihl); 
			freeblist(bp); 
			return; 
		} 
		/* If this is not routed strip off the options */ 
		if(notforme == 0) { 
			dp = bp->rp + (hl - (IP_HLEN<<2)); 
			memmove(dp, h, IP_HLEN<<2); 
			bp->rp = dp; 
			h = (Iphdr *)(bp->rp); 
			h->vihl = (IP_VER|IP_HLEN); 
		} 
	} 
 
	/* route */ 
1998/0306    
	if(notforme) { 
		if(iprouting) { 
1998/0313    
		if(ip->iprouting) { 
1998/0306    
			/* gate */ 
			if(h->ttl <= 1) 
				freeblist(bp); 
			else 
				ipoput(bp, 1, h->ttl - 1); 
1998/0313    
			else { 
				ip->istats.ipForwDatagrams++; 
				ipoput(f, bp, 1, h->ttl - 1); 
			} 
1998/0306    
		} else 
			useriprouter(ia, bp); 
1998/0313    
			useriprouter(f, ia, bp); 
1998/0306    
		return; 
	} 
 
1997/0327    
	/* Check header length and version */ 
	if(h->vihl != (IP_VER|IP_HLEN)) { 
		netlog(Logip, "ip: %I bad hivl %ux\n", h->src, h->vihl); 
		freeblist(bp); 
		return; 
	} 
1998/0313    
 
 
1997/0327    
	frag = nhgets(h->frag); 
	if(frag) { 
		h->tos = 0; 
		if(frag & IP_MF) 
			h->tos = 1; 
		bp = ipreassemble(frag, bp, h); 
1998/0313    
		bp = ipreassemble(ip, frag, bp, h); 
1997/0327    
		if(bp == nil) 
			return; 
		h = (Iphdr *)(bp->rp); 
	} 
 
	ipin += blocklen(bp); 
	ippin++; 
                 
	p = Fsrcvpcol(&fs, h->proto); 
	if(p != nil && p->rcv != nil) 
1998/0306    
		(*p->rcv)(ia, bp); 
1997/0327    
	else if(ipextprotoiput != nil) 
		ipextprotoiput(bp); 
	else 
		freeblist(bp); 
1998/0313    
	p = Fsrcvpcol(f, h->proto); 
	if(p != nil && p->rcv != nil) { 
		ip->istats.ipInDelivers++; 
		(*p->rcv)(p, ia, bp); 
		return; 
	} 
	ip->istats.ipInDiscards++; 
	ip->istats.ipInUnknownProtos++; 
	freeblist(bp); 
1997/0327    
} 
 
int 
ipstats(char *buf, int len) 
1998/0313    
ipstats(Fs *f, char *buf, int len) 
1997/0327    
{ 
	int n; 
1998/0313    
	IP *ip; 
1997/0327    
 
1997/0808    
	n = snprint(buf, len, "ip: csum %lud inb %lud outb %lud inp %lud outp %lud\n", 
1997/0327    
		ipcsumerr, ipin, ipout, ippin, ippout); 
1997/0916    
	n += snprint(buf+n, len - n, "\tnoroute %lud droppedfrag %lud\n", 
		stats.noroute, stats.droppedfrag); 
1997/0327    
	return n; 
1998/0313    
	ip = f->ip; 
	return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d " 
				 "%d %d %d %d %d %d %d %d %d", 
		ip->istats.ipForwarding, ip->istats.ipDefaultTTL, 
		ip->istats.ipInReceives, ip->istats.ipInHdrErrors, 
		ip->istats.ipInAddrErrors, ip->istats.ipForwDatagrams, 
		ip->istats.ipInUnknownProtos, ip->istats.ipInDiscards, 
		ip->istats.ipInDelivers, ip->istats.ipOutRequests, 
		ip->istats.ipOutDiscards, ip->istats.ipOutNoRoutes, 
		ip->istats.ipReasmTimeout, ip->istats.ipReasmReqds, 
		ip->istats.ipReasmOKs, ip->istats.ipReasmFails, 
		ip->istats.ipFragOKs, ip->istats.ipFragFails, 
		ip->istats.ipFragCreates); 
1997/0327    
} 
 
Block* 
ipreassemble(int offset, Block *bp, Iphdr *ip) 
1998/0313    
ipreassemble(IP *ip, int offset, Block *bp, Iphdr *ih) 
1997/0327    
{ 
	int fend; 
	ushort id; 
1998/0308/sys/src/9/ip/ip.c:342,3501998/0313/sys/src/9/ip/ip.c:423,431
1997/0327    
	Block *bl, **l, *last, *prev; 
	int ovlap, len, fragsize, pktposn; 
 
	src = nhgetl(ip->src); 
	dst = nhgetl(ip->dst); 
	id = nhgets(ip->id); 
1998/0313    
	src = nhgetl(ih->src); 
	dst = nhgetl(ih->dst); 
	id = nhgets(ih->id); 
1997/0327    
 
	/* 
	 *  block lists are too hard, pullupblock into a single block 
1998/0308/sys/src/9/ip/ip.c:351,3711998/0313/sys/src/9/ip/ip.c:432,452
1997/0327    
	 */ 
	if(bp->next){ 
		bp = pullupblock(bp, blocklen(bp)); 
		ip = (Iphdr *)(bp->rp); 
1998/0313    
		ih = (Iphdr *)(bp->rp); 
1997/0327    
	} 
 
1997/0529    
	qlock(&fraglock); 
1998/0313    
	qlock(&ip->fraglock); 
1997/0327    
 
	/* 
	 *  find a reassembly queue for this fragment 
	 */ 
	for(f = flisthead; f; f = fnext){ 
1998/0313    
	for(f = ip->flisthead; f; f = fnext){ 
1997/0327    
		fnext = f->next;	/* because ipfragfree changes the list */ 
		if(f->src == src && f->dst == dst && f->id == id) 
			break; 
1997/0916    
		if(f->age < msec){ 
			stats.droppedfrag++; 
1997/0529    
			ipfragfree(f); 
1998/0313    
			ip->istats.ipReasmTimeout++; 
			ipfragfree(ip, f); 
1997/0916    
		} 
1997/0327    
	} 
 
1998/0308/sys/src/9/ip/ip.c:374,3831998/0313/sys/src/9/ip/ip.c:455,466
1997/0327    
	 *  and get rid of any fragments that might go 
	 *  with it. 
	 */ 
	if(!ip->tos && (offset & ~(IP_MF|IP_DF)) == 0) { 
1997/0529    
		if(f != nil) 
			ipfragfree(f); 
		qunlock(&fraglock); 
1998/0313    
	if(!ih->tos && (offset & ~(IP_MF|IP_DF)) == 0) { 
		if(f != nil) { 
			ipfragfree(ip, f); 
			ip->istats.ipReasmFails++; 
		} 
		qunlock(&ip->fraglock); 
1997/0327    
		return bp; 
	} 
 
1998/0308/sys/src/9/ip/ip.c:387,3971998/0313/sys/src/9/ip/ip.c:470,480
1997/0504    
	} 
1997/0327    
 
	BKFG(bp)->foff = offset<<3; 
	BKFG(bp)->flen = nhgets(ip->length)-IPHDR; 
1998/0313    
	BKFG(bp)->flen = nhgets(ih->length)-IPHDR; 
1997/0327    
 
	/* First fragment allocates a reassembly queue */ 
	if(f == nil) { 
		f = ipfragallo(); 
1998/0313    
		f = ipfragallo(ip); 
1997/0327    
		f->id = id; 
		f->src = src; 
		f->dst = dst; 
1998/0308/sys/src/9/ip/ip.c:398,4041998/0313/sys/src/9/ip/ip.c:481,488
1997/0327    
 
		f->blist = bp; 
 
1997/0529    
		qunlock(&fraglock); 
1998/0313    
		qunlock(&ip->fraglock); 
		ip->istats.ipReasmReqds++; 
1997/0327    
		return nil; 
	} 
 
1998/0308/sys/src/9/ip/ip.c:420,4261998/0313/sys/src/9/ip/ip.c:504,510
1997/0327    
		if(ovlap > 0) { 
			if(ovlap >= BKFG(bp)->flen) { 
				freeblist(bp); 
1997/0529    
				qunlock(&fraglock); 
1998/0313    
				qunlock(&ip->fraglock); 
1997/0327    
				return nil; 
			} 
			BKFG(prev)->flen -= ovlap; 
1998/0308/sys/src/9/ip/ip.c:443,4491998/0313/sys/src/9/ip/ip.c:527,533
1997/0327    
			if(ovlap < BKFG(*l)->flen) { 
				BKFG(*l)->flen -= ovlap; 
				BKFG(*l)->foff += ovlap; 
				/* move up ip hdrs */ 
1998/0313    
				/* move up ih hdrs */ 
1997/0327    
				memmove((*l)->rp + ovlap, (*l)->rp, IPHDR); 
				(*l)->rp += ovlap; 
				break; 
1998/0308/sys/src/9/ip/ip.c:480,4941998/0313/sys/src/9/ip/ip.c:564,579
1997/0327    
 
			bl = f->blist; 
			f->blist = nil; 
1997/0529    
			ipfragfree(f); 
1997/0327    
			ip = BLKIP(bl); 
			hnputs(ip->length, len); 
1997/0529    
			qunlock(&fraglock); 
1998/0313    
			ipfragfree(ip, f); 
			ih = BLKIP(bl); 
			hnputs(ih->length, len); 
			qunlock(&ip->fraglock); 
			ip->istats.ipReasmOKs++; 
1997/0327    
			return bl;		 
		} 
		pktposn += BKFG(bl)->flen; 
	} 
1997/0529    
	qunlock(&fraglock); 
1998/0313    
	qunlock(&ip->fraglock); 
1997/0327    
	return nil; 
} 
 
1998/0308/sys/src/9/ip/ip.c:496,5021998/0313/sys/src/9/ip/ip.c:581,587
1997/0529    
 * ipfragfree - Free a list of fragments - assume hold fraglock 
1997/0327    
 */ 
void 
1997/0529    
ipfragfree(Fragment *frag) 
1998/0313    
ipfragfree(IP *ip, Fragment *frag) 
1997/0327    
{ 
	Fragment *fl, **l; 
 
1998/0308/sys/src/9/ip/ip.c:507,5131998/0313/sys/src/9/ip/ip.c:592,598
1997/0327    
	frag->id = 0; 
	frag->blist = nil; 
 
	l = &flisthead; 
1998/0313    
	l = &ip->flisthead; 
1997/0327    
	for(fl = *l; fl; fl = fl->next) { 
		if(fl == frag) { 
			*l = frag->next; 
1998/0308/sys/src/9/ip/ip.c:516,5231998/0313/sys/src/9/ip/ip.c:601,608
1997/0327    
		l = &fl->next; 
	} 
 
	frag->next = fragfree; 
	fragfree = frag; 
1998/0313    
	frag->next = ip->fragfree; 
	ip->fragfree = frag; 
1997/0327    
 
} 
 
1998/0308/sys/src/9/ip/ip.c:525,5441998/0313/sys/src/9/ip/ip.c:610,629
1997/0529    
 * ipfragallo - allocate a reassembly queue - assume hold fraglock 
1997/0327    
 */ 
Fragment * 
ipfragallo(void) 
1998/0313    
ipfragallo(IP *ip) 
1997/0327    
{ 
	Fragment *f; 
 
	while(fragfree == nil) { 
1998/0313    
	while(ip->fragfree == nil) { 
1997/0529    
		/* free last entry on fraglist */ 
		for(f = flisthead; f->next; f = f->next) 
1998/0313    
		for(f = ip->flisthead; f->next; f = f->next) 
1997/0529    
			; 
		ipfragfree(f); 
1998/0313    
		ipfragfree(ip, f); 
1997/0327    
	} 
	f = fragfree; 
	fragfree = f->next; 
	f->next = flisthead; 
	flisthead = f; 
1998/0313    
	f = ip->fragfree; 
	ip->fragfree = f->next; 
	f->next = ip->flisthead; 
	ip->flisthead = f; 
1997/0327    
	f->age = msec + 30000; 
 
	return f; 
1998/0313/sys/src/9/ip/ip.c:113,1181998/0314/sys/src/9/ip/ip.c:113,124 (short | long)
1998/0313    
} 
1997/0327    
 
void 
1998/0314    
iprouting(Fs *f, int on) 
{ 
	f->ip->iprouting = on; 
} 
 
void 
1998/0313    
ipoput(Fs *f, Block *bp, int gating, int ttl) 
1997/0327    
{ 
1998/0306    
	Ipifc *ifc; 
1998/0314/sys/src/9/ip/ip.c:322,3301998/0326/sys/src/9/ip/ip.c:322,339 (short | long)
Pull up 64 bytes instead of just an IP header, to help other protocols.
rsc Fri Mar 4 12:44:25 2005
1998/0313    
//	DBG(nhgetl(h->src))(Logipmsg, "ipiput %V %V len %d proto %d\n", 
//				h->src, h->dst, BLEN(bp), h->proto); 
1997/0327    
 
	/* Ensure we have enough data to process */ 
	if(BLEN(bp) < IPHDR) { 
		bp = pullupblock(bp, IPHDR); 
1998/0326    
	/* 
	 *  Ensure we have allt he header info in the first 
	 *  block.  Make life easier for other protocols by 
	 *  collecting up to the first 64 bytes in the first block. 
	 */ 
	if(BLEN(bp) < 64) { 
		hl = blocklen(bp); 
		if(hl < IPHDR) 
			hl = IPHDR; 
		if(hl > 64) 
			hl = 64; 
		bp = pullupblock(bp, hl); 
1997/0327    
		if(bp == nil) 
			return; 
	} 
1998/0326/sys/src/9/ip/ip.c:323,3291998/0331/sys/src/9/ip/ip.c:323,329 (short | long)
Comment edit.
rsc Fri Mar 4 12:44:25 2005
1998/0313    
//				h->src, h->dst, BLEN(bp), h->proto); 
1997/0327    
 
1998/0326    
	/* 
	 *  Ensure we have allt he header info in the first 
1998/0331    
	 *  Ensure we have all the header info in the first 
1998/0326    
	 *  block.  Make life easier for other protocols by 
	 *  collecting up to the first 64 bytes in the first block. 
	 */ 
1998/0331/sys/src/9/ip/ip.c:182,1921998/0604/sys/src/9/ip/ip.c:182,192 (short | long)
1997/0327    
		eh->ttl = ttl; 
	} 
 
1998/0604    
	rlock(ifc); 
1998/0307    
	if(waserror()){ 
		runlock(ifc); 
		nexterror(); 
	} 
	rlock(ifc); 
	if(ifc->m == nil) 
		goto raise; 
 
1998/0604/sys/src/9/ip/ip.c:133,1391998/0630/sys/src/9/ip/ip.c:133,139 (short | long)
1998/0313    
	ip = f->ip; 
 
1997/0327    
	/* Fill out the ip header */ 
	eh = (Iphdr *)(bp->rp); 
1998/0630    
	eh = (Iphdr*)(bp->rp); 
1997/0327    
 
1998/0313    
	ip->istats.ipOutRequests++; 
 
1998/0604/sys/src/9/ip/ip.c:182,1921998/0630/sys/src/9/ip/ip.c:182,192
1997/0327    
		eh->ttl = ttl; 
	} 
 
1998/0604    
	rlock(ifc); 
1998/0307    
	if(waserror()){ 
		runlock(ifc); 
		nexterror(); 
	} 
1998/0630    
	rlock(ifc); 
1998/0307    
	if(ifc->m == nil) 
		goto raise; 
 
1998/0630/sys/src/9/ip/ip.c:116,1211998/0813/sys/src/9/ip/ip.c:116,125 (short | long)
1998/0314    
iprouting(Fs *f, int on) 
{ 
	f->ip->iprouting = on; 
1998/0813    
	if(f->ip->iprouting==0) 
		f->ip->istats.ipForwarding = 2; 
	else 
		f->ip->istats.ipForwarding = 1;	 
1998/0314    
} 
 
void 
1998/0630/sys/src/9/ip/ip.c:373,3811998/0813/sys/src/9/ip/ip.c:377,387
1998/0306    
	if(notforme) { 
1998/0313    
		if(ip->iprouting) { 
1998/0306    
			/* gate */ 
			if(h->ttl <= 1) 
1998/0813    
			if(h->ttl <= 1){ 
				ip->istats.ipInHdrErrors++; 
				icmpttlexceeded(f, ia, bp); 
1998/0306    
				freeblist(bp); 
1998/0313    
			else { 
1998/0813    
			} else { 
1998/0313    
				ip->istats.ipForwDatagrams++; 
				ipoput(f, bp, 1, h->ttl - 1); 
			} 
1998/0630/sys/src/9/ip/ip.c:414,4191998/0813/sys/src/9/ip/ip.c:420,426
1998/0313    
	IP *ip; 
1997/0327    
 
1998/0313    
	ip = f->ip; 
1998/0813    
	ip->istats.ipDefaultTTL = MAXTTL; 
1998/0313    
	return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d " 
				 "%d %d %d %d %d %d %d %d %d", 
		ip->istats.ipForwarding, ip->istats.ipDefaultTTL, 
1998/0813/sys/src/9/ip/ip.c:421,4281998/0825/sys/src/9/ip/ip.c:421,428 (short | long)
Bug fix: print format.
rsc Fri Mar 4 12:44:25 2005
1997/0327    
 
1998/0313    
	ip = f->ip; 
1998/0813    
	ip->istats.ipDefaultTTL = MAXTTL; 
1998/0313    
	return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d " 
				 "%d %d %d %d %d %d %d %d %d", 
1998/0825    
	return snprint(buf, len, "%lud %lud %lud %lud %lud %lud %lud %lud %lud %lud " 
				 "%lud %lud %lud %lud %lud %lud %lud %lud %lud", 
1998/0313    
		ip->istats.ipForwarding, ip->istats.ipDefaultTTL, 
		ip->istats.ipInReceives, ip->istats.ipInHdrErrors, 
		ip->istats.ipInAddrErrors, ip->istats.ipForwDatagrams, 
1998/0825/sys/src/9/ip/ip.c:346,3521998/1208/sys/src/9/ip/ip.c:346,352 (short | long)
1998/0306    
	/* dump anything that whose header doesn't checksum */ 
1997/0327    
	if(ipcsum(&h->vihl)) { 
1998/0313    
		ip->istats.ipInHdrErrors++; 
		netlog(f, Logip, "ip: checksum error %I\n", h->src); 
1998/1208    
		netlog(f, Logip, "ip: checksum error %V\n", h->src); 
1997/0327    
		freeblist(bp); 
		return; 
	} 
1998/1208/sys/src/9/ip/ip.c:318,3231998/1209/sys/src/9/ip/ip.c:318,324 (short | long)
1997/0327    
	int notforme; 
1998/0313    
	uchar *dp, v6dst[IPaddrlen]; 
	IP *ip; 
1998/1209    
	Route *r, *sr; 
1997/0327    
 
1998/0313    
	ip = f->ip; 
	ip->istats.ipInReceives++; 
1998/1208/sys/src/9/ip/ip.c:375,3921998/1209/sys/src/9/ip/ip.c:376,406
1998/0313    
 
	/* route */ 
1998/0306    
	if(notforme) { 
1998/0313    
		if(ip->iprouting) { 
1998/0306    
			/* gate */ 
1998/0813    
			if(h->ttl <= 1){ 
				ip->istats.ipInHdrErrors++; 
				icmpttlexceeded(f, ia, bp); 
1998/0306    
				freeblist(bp); 
1998/0813    
			} else { 
1998/0313    
				ip->istats.ipForwDatagrams++; 
				ipoput(f, bp, 1, h->ttl - 1); 
			} 
1998/0306    
		} else 
1998/1209    
		if(!ip->iprouting){ 
1998/0313    
			useriprouter(f, ia, bp); 
1998/1209    
			return; 
		} 
 
		/* don't forward to source's network */ 
		sr = v4lookup(f, h->src); 
		r = v4lookup(f, h->dst); 
		if(r == nil || sr == r){ 
			ip->istats.ipOutDiscards++; 
			freeblist(bp); 
			return; 
		} 
 
		/* don't forward if packet has timed out */ 
		if(h->ttl <= 1){ 
			ip->istats.ipInHdrErrors++; 
			icmpttlexceeded(f, ia, bp); 
			freeblist(bp); 
			return; 
		} 
 
		ip->istats.ipForwDatagrams++; 
		ipoput(f, bp, 1, h->ttl - 1); 
 
1998/0306    
		return; 
	} 
 
1998/1209/sys/src/9/ip/ip.c:85,911999/0302/sys/src/9/ip/ip.c:85,91 (short | long)
1998/0313    
	Fragment*	flisthead; 
	Fragment*	fragfree; 
 
	ulong		id; 
1999/0302    
	Ref		id; 
1998/0313    
	int		iprouting;			/* true if we route like a gateway */ 
	void 		(*ipextprotoiput)(Block*); 
}; 
1998/1209/sys/src/9/ip/ip.c:186,1961999/0302/sys/src/9/ip/ip.c:186,197
1997/0327    
		eh->ttl = ttl; 
	} 
 
1999/0302    
	if(!canrlock(ifc)) 
		goto free; 
1998/0307    
	if(waserror()){ 
		runlock(ifc); 
		nexterror(); 
	} 
1998/0630    
	rlock(ifc); 
1998/0307    
	if(ifc->m == nil) 
		goto raise; 
 
1998/1209/sys/src/9/ip/ip.c:198,2041999/0302/sys/src/9/ip/ip.c:199,205
1998/0306    
	medialen = ifc->m->maxmtu - ifc->m->hsize; 
1997/0327    
	if(len <= medialen) { 
		if(!gating) 
1998/0313    
			hnputs(eh->id, ip->id++); 
1999/0302    
			hnputs(eh->id, incref(&ip->id)); 
1997/0327    
		hnputs(eh->length, len); 
		eh->frag[0] = 0; 
		eh->frag[1] = 0; 
1998/1209/sys/src/9/ip/ip.c:231,2371999/0302/sys/src/9/ip/ip.c:232,238
1997/0327    
	if(gating) 
		lid = nhgets(eh->id); 
	else 
1998/0313    
		lid = ip->id++; 
1999/0302    
		lid = incref(&ip->id); 
1997/0327    
 
	offset = IPHDR; 
	while(xp != nil && offset && offset >= BLEN(xp)) { 
1999/0302/sys/src/9/ip/ip.c:183,1901999/0309/sys/src/9/ip/ip.c:183,190 (short | long)
1997/0327    
	if(!gating){ 
		eh->vihl = IP_VER|IP_HLEN; 
		eh->tos = 0; 
		eh->ttl = ttl; 
	} 
1999/0309    
	eh->ttl = ttl; 
1997/0327    
 
1999/0302    
	if(!canrlock(ifc)) 
		goto free; 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)