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

2000/0404/port/devbridge.c (diff list | history)

2000/0331/sys/src/9/port/devbridge.c:135,1402000/0404/sys/src/9/port/devbridge.c:135,143 (short | long | prev | next)
1999/0826    
enum { 
	IP_VER		= 0x40,		/* Using IP version 4 */ 
	IP_HLEN		= 0x05,		/* Header length in characters */ 
2000/0404    
	IP_DF		= 0x4000,	/* Don't fragment */ 
	IP_MF		= 0x2000,	/* More fragments */ 
	IP_MAX		= (32*1024),	/* Maximum Internet packet size */ 
1999/0826    
	IP_TCPPROTO = 6, 
1999/0827    
	EOLOPT		= 0, 
	NOOPOPT		= 1, 
2000/0331/sys/src/9/port/devbridge.c:141,1462000/0404/sys/src/9/port/devbridge.c:144,150
1999/0826    
	MSSOPT		= 2, 
	MSS_LENGTH	= 4,		/* Mean segment size */ 
1999/0827    
	SYN		= 0x02,		/* Pkt. is synchronise */ 
2000/0404    
	IPHDR		= 20,		/* sizeof(Iphdr) */ 
1999/0826    
}; 
 
struct Iphdr 
2000/0331/sys/src/9/port/devbridge.c:187,1922000/0404/sys/src/9/port/devbridge.c:191,197
2000/0331    
static void etherwrite(Port *port, Block *bp); 
1999/0316    
 
extern ulong	parseip(uchar*, char*); 
2000/0404    
extern ushort	ipcsum(uchar *addr); 
1999/0316    
 
static void 
bridgeinit(void) 
2000/0331/sys/src/9/port/devbridge.c:326,3342000/0404/sys/src/9/port/devbridge.c:331,339
1999/0316    
			} 
1999/0731    
			ingood = port->in-port->inmulti-port->inunknown; 
			outgood = port->out-port->outmulti-port->outunknown; 
			i += snprint(buf+i, sizeof(buf)-i, "in=%d(%d:%d:%d) out=%d(%d:%d:%d)\n", 
2000/0404    
			i += snprint(buf+i, sizeof(buf)-i, "in=%d(%d:%d:%d) out=%d(%d:%d:%d:%d)\n", 
1999/0731    
				port->in, ingood, port->inmulti, port->inunknown, 
				port->out, outgood, port->outmulti, port->outunknown); 
2000/0404    
				port->out, outgood, port->outmulti, port->outunknown, port->outfrag); 
1999/0316    
			USED(i); 
		} 
		n = readstr(off, a, n, buf); 
2000/0331/sys/src/9/port/devbridge.c:887,8932000/0404/sys/src/9/port/devbridge.c:892,898
1999/0826    
		return; 
1999/0827    
	iphdr = (Iphdr*)(epkt->data); 
1999/0826    
	n -= ETHERHDRSIZE; 
	if(n < sizeof(Iphdr)) 
2000/0404    
	if(n < IPHDR) 
1999/0826    
		return; 
 
	// check it is ok IP packet 
2000/0331/sys/src/9/port/devbridge.c:1032,10422000/0404/sys/src/9/port/devbridge.c:1037,1156
1999/0316    
	pexit("hangup", 1); 
2000/0331    
} 
 
2000/0404    
static int 
fragment(Etherpkt *epkt, int n) 
{ 
	Iphdr *iphdr; 
 
	if(n <= TunnelMtu) 
		return 0; 
 
	// check it is an ip packet 
	if(nhgets(epkt->type) != 0x800) 
		return 0; 
	iphdr = (Iphdr*)(epkt->data); 
	n -= ETHERHDRSIZE; 
	if(n < IPHDR) 
		return 0; 
 
	// check it is ok IP packet - I don't handle IP options for the momment 
	if(iphdr->vihl != (IP_VER|IP_HLEN)) 
		return 0; 
 
	// check for don't fragment 
	if(iphdr->frag[0] & (IP_DF>>8)) 
		return 0; 
 
	// check for short block 
	if(nhgets(iphdr->length) > n) 
		return 0; 
 
	return 1; 
} 
 
 
2000/0331    
static void 
etherwrite(Port *port, Block *bp) 
{ 
2000/0404    
	Iphdr *eh, *feh; 
	Etherpkt *epkt; 
	int n, lid, len, seglen, chunk, dlen, blklen, offset, mf; 
	Block *xp, *nb; 
	ushort fragoff, frag; 
 
2000/0331    
	port->out++; 
	devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0); 
2000/0404    
	epkt = (Etherpkt*)bp->rp; 
	n = blocklen(bp); 
	if(port->type != Ttun || !fragment(epkt, n)) { 
		devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0); 
		return; 
	} 
	port->outfrag++; 
	if(waserror()){ 
		freeblist(bp);	 
		nexterror(); 
	} 
 
	seglen = (TunnelMtu - ETHERHDRSIZE - IPHDR) & ~7; 
	eh = (Iphdr*)(epkt->data); 
	len = nhgets(eh->length); 
	frag = nhgets(eh->frag); 
	mf = frag & IP_MF; 
	frag <<= 3; 
	dlen = len - IPHDR; 
	xp = bp; 
	lid = nhgets(eh->id); 
	offset = ETHERHDRSIZE+IPHDR; 
	while(xp != nil && offset && offset >= BLEN(xp)) { 
		offset -= BLEN(xp); 
		xp = xp->next; 
	} 
	xp->rp += offset; 
	 
if(0) print("seglen=%d, dlen=%d, mf=%x, frag=%d\n", seglen, dlen, mf, frag); 
	for(fragoff = 0; fragoff < dlen; fragoff += seglen) { 
		nb = allocb(ETHERHDRSIZE+IPHDR+seglen); 
		 
		feh = (Iphdr*)(nb->wp+ETHERHDRSIZE); 
 
		memmove(nb->wp, epkt, ETHERHDRSIZE+IPHDR); 
		nb->wp += ETHERHDRSIZE+IPHDR; 
 
		if((fragoff + seglen) >= dlen) { 
			seglen = dlen - fragoff; 
			hnputs(feh->frag, (frag+fragoff)>>3 | mf); 
		} 
		else	 
			hnputs(feh->frag, (frag+fragoff>>3) | IP_MF); 
 
		hnputs(feh->length, seglen + IPHDR); 
		hnputs(feh->id, lid); 
 
		/* Copy up the data area */ 
		chunk = seglen; 
		while(chunk) { 
			blklen = chunk; 
			if(BLEN(xp) < chunk) 
				blklen = BLEN(xp); 
			memmove(nb->wp, xp->rp, blklen); 
			nb->wp += blklen; 
			xp->rp += blklen; 
			chunk -= blklen; 
			if(xp->rp == xp->wp) 
				xp = xp->next; 
		}  
 
		feh->cksum[0] = 0; 
		feh->cksum[1] = 0; 
		hnputs(feh->cksum, ipcsum(&feh->vihl)); 
	 
		// don't generate small packets 
		if(BLEN(nb) < ETHERMINTU) 
			nb->wp = nb->rp + ETHERMINTU; 
		devtab[port->data[1]->type]->bwrite(port->data[1], nb, 0); 
	} 
	poperror(); 
	freeblist(bp);	 
1999/0316    
} 
 
// hold b lock 


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