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

2000/0913/ip/ethermedium.c (diff list | history)

1998/0306/sys/src/9/ip/ethermedium.c:45,501998/0307/sys/src/9/ip/ethermedium.c:45,51 (short | long)
1998/0306    
	nil,			/* flushroute */ 
	nil,			/* joinmulti */ 
	nil,			/* leavemulti */ 
1998/0307    
	0,			/* don't unbind on last close */ 
1998/0306    
}; 
 
typedef struct	Etherrock Etherrock; 
1998/0306/sys/src/9/ip/ethermedium.c:205,2111998/0307/sys/src/9/ip/ethermedium.c:206,212
1998/0306    
} 
 
/* 
 *  called by ipoput with a single block to write 
1998/0307    
 *  called by ipoput with a single block to write with ifc rlock'd 
1998/0306    
 */ 
static void 
etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) 
1998/0306/sys/src/9/ip/ethermedium.c:215,2311998/0307/sys/src/9/ip/ethermedium.c:216,221
1998/0306    
	uchar mac[6]; 
	Etherrock *er = ifc->arg; 
 
	if(waserror()) { 
		print("etherbwrite failed\n"); 
		ipifccheckout(ifc); 
		return; 
	} 
	if(ipifccheckin(ifc, ðermedium) < 0){ 
		freeb(bp); 
		poperror(); 
		return; 
	} 
                 
	/* get mac address of destination */ 
	a = arpget(bp, version, ðermedium, ip, mac); 
	if(a){ 
1998/0306/sys/src/9/ip/ethermedium.c:233,2391998/0307/sys/src/9/ip/ethermedium.c:223,229
1998/0306    
		bp = multicastarp(a, mac); 
		if(bp == nil){ 
			sendarp(ifc, a); 
			goto out; 
1998/0307    
			return; 
1998/0306    
		} 
	} 
 
1998/0306/sys/src/9/ip/ethermedium.c:261,2701998/0307/sys/src/9/ip/ethermedium.c:251,256
1998/0306    
 
	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0); 
	ifc->out++; 
                 
out: 
	ipifccheckout(ifc); 
	poperror(); 
} 
 
/* 
1998/0306/sys/src/9/ip/ethermedium.c:276,2911998/0307/sys/src/9/ip/ethermedium.c:262,281
1998/0306    
	Ipifc *ifc; 
	Block *bp; 
	Etherrock *er; 
1998/0307    
	int locked = 0; 
1998/0306    
 
	ifc = a; 
	er = ifc->arg; 
	er->readp = up;	/* hide identity under a rock for unbind */ 
	if(waserror()){ 
1998/0307    
		if(locked) 
			runlock(ifc); 
1998/0306    
		er->readp = 0; 
		pexit("hangup", 1); 
	} 
	for(;;){ 
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); 
1998/0307    
		rlock(ifc);	locked = 1;	USED(locked); 
1998/0306    
		ifc->in++; 
		bp->rp += ifc->m->hsize; 
		if(ifc->lifc == nil) 
1998/0306/sys/src/9/ip/ethermedium.c:292,2971998/0307/sys/src/9/ip/ethermedium.c:282,289
1998/0306    
			freeb(bp); 
		else 
			ipiput(ifc->lifc->local, bp); 
1998/0307    
		runlock(ifc);	locked = 0;	USED(locked); 
 
1998/0306    
	} 
} 
 
1998/0307/sys/src/9/ip/ethermedium.c:22,281998/0313/sys/src/9/ip/ethermedium.c:22,28 (short | long)
1998/0306    
static void	etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); 
static void	etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia); 
static void	etherremmulti(Ipifc *ifc, uchar *a, uchar *ia); 
static Block*	multicastarp(Arpent *a, uchar *mac); 
1998/0313    
static Block*	multicastarp(Fs *f, Arpent *a, uchar *mac); 
1998/0306    
static void	sendarp(Ipifc *ifc, Arpent *a); 
static int	multicastea(uchar *ea, uchar *ip); 
static void	recvarpproc(Ipifc *ifc); 
1998/0307/sys/src/9/ip/ethermedium.c:51,561998/0313/sys/src/9/ip/ethermedium.c:51,57
1998/0306    
typedef struct	Etherrock Etherrock; 
struct Etherrock 
{ 
1998/0313    
	Fs	*f;		/* file system we belong to */ 
1998/0306    
	Proc	*arpp;		/* arp process */ 
	Proc	*readp;		/* reading process */ 
	Chan	*mchan;		/* Data channel */ 
1998/0307/sys/src/9/ip/ethermedium.c:128,1351998/0313/sys/src/9/ip/ethermedium.c:129,136
1998/0306    
	fd = kdial(addr, nil, dir, &cfd); 
	if(fd < 0) 
		error("dial 0x800 failed"); 
	mchan = fdtochan(fd, ORDWR, 0, 1); 
	cchan = fdtochan(cfd, ORDWR, 0, 1); 
1998/0313    
	mchan = commonfdtochan(fd, ORDWR, 0, 1); 
	cchan = commonfdtochan(cfd, ORDWR, 0, 1); 
1998/0306    
	kclose(fd); 
	kclose(cfd); 
 
1998/0307/sys/src/9/ip/ethermedium.c:162,1681998/0313/sys/src/9/ip/ethermedium.c:163,169
1998/0306    
	fd = kdial(addr, nil, nil, nil); 
	if(fd < 0) 
		error("dial 0x806 failed"); 
	achan = fdtochan(fd, ORDWR, 0, 1); 
1998/0313    
	achan = commonfdtochan(fd, ORDWR, 0, 1); 
1998/0306    
	kclose(fd); 
 
	er = smalloc(sizeof(*er)); 
1998/0307/sys/src/9/ip/ethermedium.c:169,1741998/0313/sys/src/9/ip/ethermedium.c:170,176
1998/0306    
	er->mchan = mchan; 
	er->cchan = cchan; 
	er->achan = achan; 
1998/0313    
	er->f = ifc->conv->p->f; 
1998/0306    
	ifc->arg = er; 
 
	free(buf); 
1998/0307/sys/src/9/ip/ethermedium.c:217,2261998/0313/sys/src/9/ip/ethermedium.c:219,228
1998/0306    
	Etherrock *er = ifc->arg; 
 
	/* get mac address of destination */ 
	a = arpget(bp, version, ðermedium, ip, mac); 
1998/0313    
	a = arpget(er->f->arp, bp, version, ðermedium, ip, mac); 
1998/0306    
	if(a){ 
		/* check for broadcast or multicast */ 
		bp = multicastarp(a, mac); 
1998/0313    
		bp = multicastarp(er->f, a, mac); 
1998/0306    
		if(bp == nil){ 
			sendarp(ifc, a); 
1998/0307    
			return; 
1998/0307/sys/src/9/ip/ethermedium.c:281,2871998/0313/sys/src/9/ip/ethermedium.c:283,289
1998/0306    
		if(ifc->lifc == nil) 
			freeb(bp); 
		else 
			ipiput(ifc->lifc->local, bp); 
1998/0313    
			ipiput(er->f, ifc->lifc->local, bp); 
1998/0307    
		runlock(ifc);	locked = 0;	USED(locked); 
 
1998/0306    
	} 
1998/0307/sys/src/9/ip/ethermedium.c:325,3311998/0313/sys/src/9/ip/ethermedium.c:327,333
1998/0306    
 
	/* don't do anything if it's been less than a second since the last */ 
	if(msec - a->time < 1000){ 
		arprelease(a); 
1998/0313    
		arprelease(er->f->arp, a); 
1998/0306    
		return; 
	} 
 
1998/0307/sys/src/9/ip/ethermedium.c:339,3451998/0313/sys/src/9/ip/ethermedium.c:341,347
1998/0306    
 
	/* try to keep it around for a second more */ 
	a->time = msec; 
	arprelease(a); 
1998/0313    
	arprelease(er->f->arp, a); 
1998/0306    
 
	n = sizeof(Etherarp); 
	if(n < a->type->minmtu) 
1998/0307/sys/src/9/ip/ethermedium.c:387,3931998/0313/sys/src/9/ip/ethermedium.c:389,395
1998/0306    
		break; 
 
	case ARPREPLY: 
		arpenter(ifc, V4, e->spa, e->sha, ðermedium, 0); 
1998/0313    
		arpenter(er->f->arp, ifc, V4, e->spa, e->sha, ðermedium, 0); 
1998/0306    
		break; 
 
	case ARPREQUEST: 
1998/0307/sys/src/9/ip/ethermedium.c:408,4191998/0313/sys/src/9/ip/ethermedium.c:410,421
1998/0306    
		} 
 
		/* refresh what we know about sender */ 
		arpenter(ifc, V4, e->spa, e->sha, ðermedium, 1); 
1998/0313    
		arpenter(er->f->arp, ifc, V4, e->spa, e->sha, ðermedium, 1); 
1998/0306    
 
		/* answer only requests for our address or systems we're proxying for */ 
		v4tov6(ip, e->tpa); 
		if(!iplocalonifc(ifc, ip)) 
		if(ipproxyifc(ifc, ip) == 0) 
1998/0313    
		if(ipproxyifc(er->f, ifc, ip) == 0) 
1998/0306    
			break; 
 
/* print("arp: rem %I %E (for %I)\n", e->spa, e->sha, e->tpa); /**/ 
1998/0307/sys/src/9/ip/ethermedium.c:490,5041998/0313/sys/src/9/ip/ethermedium.c:492,506
1998/0306    
 *  addresses 
 */ 
static Block* 
multicastarp(Arpent *a, uchar *mac) 
1998/0313    
multicastarp(Fs *f, Arpent *a, uchar *mac) 
1998/0306    
{ 
	/* is it broadcast? */ 
	switch(ipforme(a->ip)){ 
1998/0313    
	switch(ipforme(f, a->ip)){ 
1998/0306    
	case Runi: 
		return nil; 
	case Rbcast: 
		memset(mac, 0xff, 6); 
		return arpresolve(a, ðermedium, mac); 
1998/0313    
		return arpresolve(f->arp, a, ðermedium, mac); 
1998/0306    
	default: 
		break; 
	} 
1998/0307/sys/src/9/ip/ethermedium.c:507,5131998/0313/sys/src/9/ip/ethermedium.c:509,515
1998/0306    
	switch(multicastea(mac, a->ip)){ 
	case V4: 
	case V6: 
		return arpresolve(a, ðermedium, mac); 
1998/0313    
		return arpresolve(f->arp, a, ðermedium, mac); 
1998/0306    
	} 
 
	/* let arp take care of it */ 
1998/0313/sys/src/9/ip/ethermedium.c:515,5171998/0423/sys/src/9/ip/ethermedium.c:515,523 (short | long)
Register with addipmedium.
rsc Fri Mar 4 12:44:25 2005
1998/0306    
	/* let arp take care of it */ 
	return nil; 
} 
1998/0423    
 
void 
ethermediumlink(void) 
{ 
	addipmedium(ðermedium); 
} 
1998/0423/sys/src/9/ip/ethermedium.c:45,501998/0630/sys/src/9/ip/ethermedium.c:45,51 (short | long)
1998/0306    
	nil,			/* flushroute */ 
	nil,			/* joinmulti */ 
	nil,			/* leavemulti */ 
1998/0630    
	arpenter,		/* ares */ 
1998/0307    
	0,			/* don't unbind on last close */ 
1998/0306    
}; 
 
1998/0423/sys/src/9/ip/ethermedium.c:389,3951998/0630/sys/src/9/ip/ethermedium.c:390,396
1998/0306    
		break; 
 
	case ARPREPLY: 
1998/0313    
		arpenter(er->f->arp, ifc, V4, e->spa, e->sha, ðermedium, 0); 
1998/0630    
		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0); 
1998/0306    
		break; 
 
	case ARPREQUEST: 
1998/0423/sys/src/9/ip/ethermedium.c:410,4161998/0630/sys/src/9/ip/ethermedium.c:411,417
1998/0306    
		} 
 
		/* refresh what we know about sender */ 
1998/0313    
		arpenter(er->f->arp, ifc, V4, e->spa, e->sha, ðermedium, 1); 
1998/0630    
		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1); 
1998/0306    
 
		/* answer only requests for our address or systems we're proxying for */ 
		v4tov6(ip, e->tpa); 
1998/0630/sys/src/9/ip/ethermedium.c:286,2921998/0808/sys/src/9/ip/ethermedium.c:286,291 (short | long)
Remove blank line.
rsc Fri Mar 4 12:44:25 2005
1998/0306    
		else 
1998/0313    
			ipiput(er->f, ifc->lifc->local, bp); 
1998/0307    
		runlock(ifc);	locked = 0;	USED(locked); 
                 
1998/0306    
	} 
} 
 
1998/0808/sys/src/9/ip/ethermedium.c:265,2841999/0302/sys/src/9/ip/ethermedium.c:265,288 (short | long)
1998/0306    
	Ipifc *ifc; 
	Block *bp; 
	Etherrock *er; 
1998/0307    
	int locked = 0; 
1998/0306    
 
	ifc = a; 
	er = ifc->arg; 
	er->readp = up;	/* hide identity under a rock for unbind */ 
	if(waserror()){ 
1998/0307    
		if(locked) 
			runlock(ifc); 
1998/0306    
		er->readp = 0; 
		pexit("hangup", 1); 
	} 
	for(;;){ 
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); 
1998/0307    
		rlock(ifc);	locked = 1;	USED(locked); 
1999/0302    
		if(!canrlock(ifc)){ 
			freeb(bp); 
			continue; 
		} 
		if(waserror()){ 
			runlock(ifc); 
			nexterror(); 
		} 
1998/0306    
		ifc->in++; 
		bp->rp += ifc->m->hsize; 
		if(ifc->lifc == nil) 
1998/0808/sys/src/9/ip/ethermedium.c:285,2911999/0302/sys/src/9/ip/ethermedium.c:289,296
1998/0306    
			freeb(bp); 
		else 
1998/0313    
			ipiput(er->f, ifc->lifc->local, bp); 
1998/0307    
		runlock(ifc);	locked = 0;	USED(locked); 
1999/0302    
		runlock(ifc); 
		poperror(); 
1998/0306    
	} 
} 
 
1999/0302/sys/src/9/ip/ethermedium.c:25,311999/0320/sys/src/9/ip/ethermedium.c:25,31 (short | long)
1998/0313    
static Block*	multicastarp(Fs *f, Arpent *a, uchar *mac); 
1998/0306    
static void	sendarp(Ipifc *ifc, Arpent *a); 
static int	multicastea(uchar *ea, uchar *ip); 
static void	recvarpproc(Ipifc *ifc); 
1999/0320    
static void	recvarpproc(void*); 
1998/0306    
 
Medium ethermedium = 
{ 
1999/0302/sys/src/9/ip/ethermedium.c:453,4601999/0320/sys/src/9/ip/ethermedium.c:453,461
1998/0306    
} 
 
static void 
recvarpproc(Ipifc *ifc) 
1999/0320    
recvarpproc(void *v) 
1998/0306    
{ 
1999/0320    
	Ipifc *ifc = v; 
1998/0306    
	Etherrock *er = ifc->arg; 
 
	er->arpp = up; 
1999/0320/sys/src/9/ip/ethermedium.c:24,521999/0731/sys/src/9/ip/ethermedium.c:24,47 (short | long)
1998/0306    
static void	etherremmulti(Ipifc *ifc, uchar *a, uchar *ia); 
1998/0313    
static Block*	multicastarp(Fs *f, Arpent *a, uchar *mac); 
1998/0306    
static void	sendarp(Ipifc *ifc, Arpent *a); 
1999/0731    
static void	sendgarp(Ipifc *ifc, uchar*); 
1998/0306    
static int	multicastea(uchar *ea, uchar *ip); 
1999/0320    
static void	recvarpproc(void*); 
1998/0306    
 
Medium ethermedium = 
{ 
	"ether", 
	14, 
	60, 
	1514, 
	6, 
	etherbind, 
	etherunbind, 
	etherbwrite, 
	etheraddmulti, 
	etherremmulti, 
	nil,			/* pktin */ 
	nil,			/* addroute */ 
	nil,			/* remroute */ 
	nil,			/* flushroute */ 
	nil,			/* joinmulti */ 
	nil,			/* leavemulti */ 
1998/0630    
	arpenter,		/* ares */ 
1998/0307    
	0,			/* don't unbind on last close */ 
1999/0731    
.name=		"ether", 
.hsize=		14, 
.minmtu=	60, 
.maxmtu=	1514, 
.maclen=	6, 
.bind=		etherbind, 
.unbind=	etherunbind, 
.bwrite=	etherbwrite, 
.addmulti=	etheraddmulti, 
.remmulti=	etherremmulti, 
.ares=		arpenter, 
.areg=		sendgarp, 
1998/0306    
}; 
 
typedef struct	Etherrock Etherrock; 
1999/0320/sys/src/9/ip/ethermedium.c:373,3791999/0731/sys/src/9/ip/ethermedium.c:368,414
1998/0306    
		print("arp: send: %r\n"); 
} 
 
1999/0731    
/* 
 *  send a gratuitous arp to refresh arp caches 
 */ 
1998/0306    
static void 
1999/0731    
sendgarp(Ipifc *ifc, uchar *ip) 
{ 
	int n; 
	Block *bp; 
	Etherarp *e; 
	Etherrock *er = ifc->arg; 
 
	/* don't arp for our initial non address */ 
	if(ipcmp(ip, IPnoaddr) == 0) 
		return; 
 
	n = sizeof(Etherarp); 
	if(n < ethermedium.minmtu) 
		n = ethermedium.minmtu; 
	bp = allocb(n); 
	memset(bp->rp, 0, n); 
	e = (Etherarp*)bp->rp; 
	memmove(e->tpa, ip+IPv4off, sizeof(e->tpa)); 
	memmove(e->spa, ip+IPv4off, sizeof(e->spa)); 
	memmove(e->sha, ifc->mac, sizeof(e->sha)); 
	memset(e->d, 0xff, sizeof(e->d));		/* ethernet broadcast */ 
	memmove(e->s, ifc->mac, sizeof(e->s)); 
 
	hnputs(e->type, ETARP); 
	hnputs(e->hrd, 1); 
	hnputs(e->pro, ETIP); 
	e->hln = sizeof(e->sha); 
	e->pln = sizeof(e->spa); 
	hnputs(e->op, ARPREQUEST); 
	bp->wp += n; 
 
	n = devtab[er->achan->type]->bwrite(er->achan, bp, 0); 
	if(n < 0) 
		print("garp: send: %r\n"); 
} 
 
static void 
1998/0306    
recvarp(Ipifc *ifc) 
{ 
	int n; 
1999/0320/sys/src/9/ip/ethermedium.c:404,4101999/0731/sys/src/9/ip/ethermedium.c:439,445
1998/0306    
 
		/* check for someone that think's they're me */ 
		v4tov6(ip, e->spa); 
		if(iplocalonifc(ifc, ip)){ 
1999/0731    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
1998/0306    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0) 
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
		} else { 
1999/0320/sys/src/9/ip/ethermedium.c:420,4261999/0731/sys/src/9/ip/ethermedium.c:455,461
1998/0306    
		/* answer only requests for our address or systems we're proxying for */ 
		v4tov6(ip, e->tpa); 
		if(!iplocalonifc(ifc, ip)) 
1998/0313    
		if(ipproxyifc(er->f, ifc, ip) == 0) 
1999/0731    
		if(!ipproxyifc(er->f, ifc, ip)) 
1998/0306    
			break; 
 
/* print("arp: rem %I %E (for %I)\n", e->spa, e->sha, e->tpa); /**/ 
1999/0731/sys/src/9/ip/ethermedium.c:22,282000/0913/sys/src/9/ip/ethermedium.c:22,28 (short | long)
1998/0306    
static void	etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); 
static void	etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia); 
static void	etherremmulti(Ipifc *ifc, uchar *a, uchar *ia); 
1998/0313    
static Block*	multicastarp(Fs *f, Arpent *a, uchar *mac); 
2000/0913    
static Block*	multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac); 
1998/0306    
static void	sendarp(Ipifc *ifc, Arpent *a); 
1999/0731    
static void	sendgarp(Ipifc *ifc, uchar*); 
1998/0306    
static int	multicastea(uchar *ea, uchar *ip); 
1999/0731/sys/src/9/ip/ethermedium.c:215,2242000/0913/sys/src/9/ip/ethermedium.c:215,224
1998/0306    
	Etherrock *er = ifc->arg; 
 
	/* get mac address of destination */ 
1998/0313    
	a = arpget(er->f->arp, bp, version, ðermedium, ip, mac); 
2000/0913    
	a = arpget(er->f->arp, bp, version, ifc->m, ip, mac); 
1998/0306    
	if(a){ 
		/* check for broadcast or multicast */ 
1998/0313    
		bp = multicastarp(er->f, a, mac); 
2000/0913    
		bp = multicastarp(er->f, a, ifc->m, mac); 
1998/0306    
		if(bp == nil){ 
			sendarp(ifc, a); 
1998/0307    
			return; 
1999/0731/sys/src/9/ip/ethermedium.c:384,3912000/0913/sys/src/9/ip/ethermedium.c:384,391
1999/0731    
		return; 
 
	n = sizeof(Etherarp); 
	if(n < ethermedium.minmtu) 
		n = ethermedium.minmtu; 
2000/0913    
	if(n < ifc->m->minmtu) 
		n = ifc->m->minmtu; 
1999/0731    
	bp = allocb(n); 
	memset(bp->rp, 0, n); 
	e = (Etherarp*)bp->rp; 
1999/0731/sys/src/9/ip/ethermedium.c:533,5392000/0913/sys/src/9/ip/ethermedium.c:533,539
1998/0306    
 *  addresses 
 */ 
static Block* 
1998/0313    
multicastarp(Fs *f, Arpent *a, uchar *mac) 
2000/0913    
multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac) 
1998/0306    
{ 
	/* is it broadcast? */ 
1998/0313    
	switch(ipforme(f, a->ip)){ 
1999/0731/sys/src/9/ip/ethermedium.c:541,5472000/0913/sys/src/9/ip/ethermedium.c:541,547
1998/0306    
		return nil; 
	case Rbcast: 
		memset(mac, 0xff, 6); 
1998/0313    
		return arpresolve(f->arp, a, ðermedium, mac); 
2000/0913    
		return arpresolve(f->arp, a, medium, mac); 
1998/0306    
	default: 
		break; 
	} 
1999/0731/sys/src/9/ip/ethermedium.c:550,5562000/0913/sys/src/9/ip/ethermedium.c:550,556
1998/0306    
	switch(multicastea(mac, a->ip)){ 
	case V4: 
	case V6: 
1998/0313    
		return arpresolve(f->arp, a, ðermedium, mac); 
2000/0913    
		return arpresolve(f->arp, a, medium, mac); 
1998/0306    
	} 
 
	/* let arp take care of it */ 
2000/0913/sys/src/9/ip/ethermedium.c:44,492000/0922/sys/src/9/ip/ethermedium.c:44,65 (short | long)
1999/0731    
.areg=		sendgarp, 
1998/0306    
}; 
 
2000/0922    
Medium gbemedium = 
{ 
.name=		"gbe", 
.hsize=		14, 
.minmtu=	60, 
.maxmtu=	9014, 
.maclen=	6, 
.bind=		etherbind, 
.unbind=	etherunbind, 
.bwrite=	etherbwrite, 
.addmulti=	etheraddmulti, 
.remmulti=	etherremmulti, 
.ares=		arpenter, 
.areg=		sendgarp, 
}; 
 
1998/0306    
typedef struct	Etherrock Etherrock; 
struct Etherrock 
{ 
2000/0913/sys/src/9/ip/ethermedium.c:561,5642000/0922/sys/src/9/ip/ethermedium.c:577,581
1998/0423    
ethermediumlink(void) 
{ 
	addipmedium(ðermedium); 
2000/0922    
	addipmedium(&gbemedium); 
1998/0423    
} 
2000/0922/sys/src/9/ip/ethermedium.c:6,122000/1111/sys/src/9/ip/ethermedium.c:6,11 (short | long)
1998/0306    
#include "../port/error.h" 
 
#include "ip.h" 
#include "kernel.h" 
 
typedef struct Etherhdr Etherhdr; 
struct Etherhdr 
2000/0922/sys/src/9/ip/ethermedium.c:110,1162000/1111/sys/src/9/ip/ethermedium.c:109,115
1998/0306    
	char addr[2*NAMELEN]; 
	char dir[2*NAMELEN]; 
	char *buf; 
	int fd, cfd, n; 
2000/1111    
	int n; 
1998/0306    
	char *ptr; 
	Etherrock *er; 
 
2000/0922/sys/src/9/ip/ethermedium.c:138,1642000/1111/sys/src/9/ip/ethermedium.c:137,152
1998/0306    
	 *  this device. 
	 */ 
	snprint(addr, sizeof(addr), "%s!0x800", argv[2]); 
	fd = kdial(addr, nil, dir, &cfd); 
	if(fd < 0) 
		error("dial 0x800 failed"); 
1998/0313    
	mchan = commonfdtochan(fd, ORDWR, 0, 1); 
	cchan = commonfdtochan(cfd, ORDWR, 0, 1); 
1998/0306    
	kclose(fd); 
	kclose(cfd); 
2000/1111    
	mchan = chandial(addr, nil, dir, &cchan); 
1998/0306    
 
	/* 
	 *  get mac address 
	 */ 
	snprint(addr, sizeof(addr), "%s/stats", dir); 
	fd = kopen(addr, OREAD); 
	if(fd < 0) 
		error("can't read ether stats"); 
                 
	buf = smalloc(512); 
	n = kread(fd, buf, 511); 
	kclose(fd); 
	if(n <= 0) 
		error(Eio); 
2000/1111    
	achan = namec(addr, Aopen, OREAD, 0); 
	n = devtab[achan->type]->read(achan, buf, 511, 0); 
	cclose(achan); 
1998/0306    
	buf[n] = 0; 
 
	ptr = strstr(buf, "addr: "); 
2000/0922/sys/src/9/ip/ethermedium.c:172,1822000/1111/sys/src/9/ip/ethermedium.c:160,166
1998/0306    
 	 *  open arp conversation 
	 */ 
	snprint(addr, sizeof(addr), "%s!0x806", argv[2]); 
	fd = kdial(addr, nil, nil, nil); 
	if(fd < 0) 
		error("dial 0x806 failed"); 
1998/0313    
	achan = commonfdtochan(fd, ORDWR, 0, 1); 
1998/0306    
	kclose(fd); 
2000/1111    
	achan = chandial(addr, nil, nil, nil); 
1998/0306    
 
	er = smalloc(sizeof(*er)); 
	er->mchan = mchan; 
2000/1111/sys/src/9/ip/ethermedium.c:106,1132001/0527/sys/src/9/ip/ethermedium.c:106,113 (short | long)
1998/0306    
etherbind(Ipifc *ifc, int argc, char **argv) 
{ 
	Chan *mchan, *cchan, *achan; 
	char addr[2*NAMELEN]; 
	char dir[2*NAMELEN]; 
2001/0527    
	char addr[Maxpath]; 
	char dir[Maxpath]; 
1998/0306    
	char *buf; 
2000/1111    
	int n; 
1998/0306    
	char *ptr; 
2001/0527/sys/src/9/ip/ethermedium.c:283,2892001/0623/sys/src/9/ip/ethermedium.c:283,289 (short | long)
1998/0306    
		if(ifc->lifc == nil) 
			freeb(bp); 
		else 
1998/0313    
			ipiput(er->f, ifc->lifc->local, bp); 
2001/0623    
			ipiput(er->f, ifc, bp); 
1999/0302    
		runlock(ifc); 
		poperror(); 
1998/0306    
	} 
2001/0623/sys/src/9/ip/ethermedium.c:429,4342002/0108/sys/src/9/ip/ethermedium.c:429,440 (short | long)
1998/0306    
		break; 
 
	case ARPREPLY: 
2002/0108    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
				break; 
			} 
		} 
1998/0630    
		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0); 
1998/0306    
		break; 
 
2001/0623/sys/src/9/ip/ethermedium.c:440,4472002/0108/sys/src/9/ip/ethermedium.c:446,455
1998/0306    
		/* check for someone that think's they're me */ 
		v4tov6(ip, e->spa); 
1999/0731    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
1998/0306    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0) 
2002/0108    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
1998/0306    
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
2002/0108    
				break; 
			} 
1998/0306    
		} else { 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){ 
				print("arp: %V also has ether addr %E\n", e->spa, e->sha); 
2002/0108/sys/src/9/ip/ethermedium.c:431,4372002/0223/sys/src/9/ip/ethermedium.c:431,438 (short | long)
1998/0306    
	case ARPREPLY: 
2002/0108    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
2002/0223    
				print("arprep: 0x%E/0x%E also has ip addr %V\n", 
					e->s, e->sha, e->spa); 
2002/0108    
				break; 
			} 
		} 
2002/0108/sys/src/9/ip/ethermedium.c:447,4532002/0223/sys/src/9/ip/ethermedium.c:448,455
1998/0306    
		v4tov6(ip, e->spa); 
1999/0731    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
2002/0108    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
1998/0306    
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
2002/0223    
				print("arpreq: 0x%E/0x%E also has ip addr %V\n", 
					e->s, e->sha, e->spa); 
2002/0108    
				break; 
			} 
1998/0306    
		} else { 
2002/0223/sys/src/9/ip/ethermedium.c:6,112002/0507/sys/src/9/ip/ethermedium.c:6,12 (short | long)
1998/0306    
#include "../port/error.h" 
 
#include "ip.h" 
2002/0507    
#include "ipv6.h" 
1998/0306    
 
typedef struct Etherhdr Etherhdr; 
struct Etherhdr 
2002/0223/sys/src/9/ip/ethermedium.c:15,212002/0507/sys/src/9/ip/ethermedium.c:16,23
1998/0306    
	uchar	t[2]; 
}; 
 
static void	etherread(void *a); 
2002/0507    
static void	etherread4(void *a); 
static void	etherread6(void *a); 
1998/0306    
static void	etherbind(Ipifc *ifc, int argc, char **argv); 
static void	etherunbind(Ipifc *ifc); 
static void	etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip); 
2002/0223/sys/src/9/ip/ethermedium.c:26,312002/0507/sys/src/9/ip/ethermedium.c:28,35
1999/0731    
static void	sendgarp(Ipifc *ifc, uchar*); 
1998/0306    
static int	multicastea(uchar *ea, uchar *ip); 
1999/0320    
static void	recvarpproc(void*); 
2002/0507    
static void	resolveaddr6(Ipifc *ifc, Arpent *a); 
static void	etherpref2addr(uchar *pref, uchar *ea); 
1998/0306    
 
Medium ethermedium = 
{ 
2002/0223/sys/src/9/ip/ethermedium.c:41,462002/0507/sys/src/9/ip/ethermedium.c:45,51
1999/0731    
.remmulti=	etherremmulti, 
.ares=		arpenter, 
.areg=		sendgarp, 
2002/0507    
.pref2addr=	etherpref2addr, 
1998/0306    
}; 
 
2000/0922    
Medium gbemedium = 
2002/0223/sys/src/9/ip/ethermedium.c:57,622002/0507/sys/src/9/ip/ethermedium.c:62,68
2000/0922    
.remmulti=	etherremmulti, 
.ares=		arpenter, 
.areg=		sendgarp, 
2002/0507    
.pref2addr=	etherpref2addr, 
2000/0922    
}; 
 
1998/0306    
typedef struct	Etherrock Etherrock; 
2002/0223/sys/src/9/ip/ethermedium.c:64,732002/0507/sys/src/9/ip/ethermedium.c:70,82
1998/0306    
{ 
1998/0313    
	Fs	*f;		/* file system we belong to */ 
1998/0306    
	Proc	*arpp;		/* arp process */ 
	Proc	*readp;		/* reading process */ 
	Chan	*mchan;		/* Data channel */ 
2002/0507    
	Proc	*read4p;	/* reading process (v4)*/ 
	Proc	*read6p;	/* reading process (v6)*/ 
	Chan	*mchan4;	/* Data channel for v4 */ 
1998/0306    
	Chan	*achan;		/* Arp channel */ 
	Chan	*cchan;		/* Control channel */ 
2002/0507    
	Chan	*cchan4;	/* Control channel for v4 */ 
	Chan	*mchan6;	/* Data channel for v6 */ 
	Chan	*cchan6;	/* Control channel for v6 */ 
1998/0306    
}; 
 
/* 
2002/0223/sys/src/9/ip/ethermedium.c:76,852002/0507/sys/src/9/ip/ethermedium.c:85,96
1998/0306    
enum 
{ 
	ETARP		= 0x0806, 
	ETIP		= 0x0800, 
2002/0507    
	ETIP4		= 0x0800, 
	ETIP6		= 0x86DD, 
1998/0306    
	ARPREQUEST	= 1, 
	ARPREPLY	= 2, 
}; 
2002/0507    
 
1998/0306    
typedef struct Etherarp Etherarp; 
struct Etherarp 
{ 
2002/0223/sys/src/9/ip/ethermedium.c:97,1032002/0507/sys/src/9/ip/ethermedium.c:108,113
1998/0306    
	uchar	tpa[4]; 
}; 
 
                 
/* 
 *  called to bind an IP ifc to an ethernet device 
 *  called with ifc wlock'd 
2002/0223/sys/src/9/ip/ethermedium.c:105,1132002/0507/sys/src/9/ip/ethermedium.c:115,123
1998/0306    
static void 
etherbind(Ipifc *ifc, int argc, char **argv) 
{ 
	Chan *mchan, *cchan, *achan; 
2001/0527    
	char addr[Maxpath]; 
	char dir[Maxpath]; 
2002/0507    
	Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6; 
	char addr[Maxpath];	//char addr[2*KNAMELEN]; 
	char dir[Maxpath];	//char dir[2*KNAMELEN]; 
1998/0306    
	char *buf; 
2000/1111    
	int n; 
1998/0306    
	char *ptr; 
2002/0223/sys/src/9/ip/ethermedium.c:116,1302002/0507/sys/src/9/ip/ethermedium.c:126,144
1998/0306    
	if(argc < 2) 
		error(Ebadarg); 
 
	mchan = cchan = achan = nil; 
2002/0507    
	mchan4 = cchan4 = achan = mchan6 = cchan6 = nil; 
1998/0306    
	buf = nil; 
	if(waserror()){ 
		if(mchan != nil) 
			cclose(mchan); 
		if(cchan != nil) 
			cclose(cchan); 
2002/0507    
		if(mchan4 != nil) 
			cclose(mchan4); 
		if(cchan4 != nil) 
			cclose(cchan4); 
1998/0306    
		if(achan != nil) 
			cclose(achan); 
2002/0507    
		if(mchan6 != nil) 
			cclose(mchan6); 
		if(cchan6 != nil) 
			cclose(cchan6); 
1998/0306    
		if(buf != nil) 
			free(buf); 
		nexterror();  
2002/0223/sys/src/9/ip/ethermedium.c:137,1432002/0507/sys/src/9/ip/ethermedium.c:151,157
1998/0306    
	 *  this device. 
	 */ 
	snprint(addr, sizeof(addr), "%s!0x800", argv[2]); 
2000/1111    
	mchan = chandial(addr, nil, dir, &cchan); 
2002/0507    
	mchan4 = chandial(addr, nil, dir, &cchan4); 
1998/0306    
 
	/* 
	 *  get mac address 
2002/0223/sys/src/9/ip/ethermedium.c:162,1712002/0507/sys/src/9/ip/ethermedium.c:176,196
1998/0306    
	snprint(addr, sizeof(addr), "%s!0x806", argv[2]); 
2000/1111    
	achan = chandial(addr, nil, nil, nil); 
1998/0306    
 
2002/0507    
	/* 
	 *  open ip conversation 
	 * 
	 *  the dial will fail if the type is already open on 
	 *  this device. 
	 */ 
	snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]); 
	mchan6 = chandial(addr, nil, dir, &cchan6); 
 
1998/0306    
	er = smalloc(sizeof(*er)); 
	er->mchan = mchan; 
	er->cchan = cchan; 
2002/0507    
	er->mchan4 = mchan4; 
	er->cchan4 = cchan4; 
1998/0306    
	er->achan = achan; 
2002/0507    
	er->mchan6 = mchan6; 
	er->cchan6 = cchan6; 
1998/0313    
	er->f = ifc->conv->p->f; 
1998/0306    
	ifc->arg = er; 
 
2002/0223/sys/src/9/ip/ethermedium.c:172,1792002/0507/sys/src/9/ip/ethermedium.c:197,205
1998/0306    
	free(buf); 
	poperror(); 
 
	kproc("etherread", etherread, ifc); 
2002/0507    
	kproc("etherread4", etherread4, ifc); 
1998/0306    
	kproc("recvarpproc", recvarpproc, ifc); 
2002/0507    
	kproc("etherread6", etherread6, ifc); 
1998/0306    
} 
 
/* 
2002/0223/sys/src/9/ip/ethermedium.c:184,2042002/0507/sys/src/9/ip/ethermedium.c:210,236
1998/0306    
{ 
	Etherrock *er = ifc->arg; 
 
	if(er->readp) 
		postnote(er->readp, 1, "unbind", 0); 
2002/0507    
	if(er->read4p) 
		postnote(er->read4p, 1, "unbind", 0); 
	if(er->read6p) 
		postnote(er->read6p, 1, "unbind", 0); 
1998/0306    
	if(er->arpp) 
		postnote(er->arpp, 1, "unbind", 0); 
 
	/* wait for readers to die */ 
	while(er->arpp != 0 || er->readp != 0) 
2002/0507    
	while(er->arpp != 0 || er->read4p != 0 || er->read6p != 0) 
1998/0306    
		tsleep(&up->sleep, return0, 0, 300); 
 
	if(er->mchan != nil) 
		cclose(er->mchan); 
2002/0507    
	if(er->mchan4 != nil) 
		cclose(er->mchan4); 
1998/0306    
	if(er->achan != nil) 
		cclose(er->achan); 
	if(er->cchan != nil) 
		cclose(er->cchan); 
2002/0507    
	if(er->cchan4 != nil) 
		cclose(er->cchan4); 
	if(er->mchan6 != nil) 
		cclose(er->mchan6); 
	if(er->cchan6 != nil) 
		cclose(er->cchan6); 
1998/0306    
 
	free(er); 
} 
2002/0223/sys/src/9/ip/ethermedium.c:215,2262002/0507/sys/src/9/ip/ethermedium.c:247,261
1998/0306    
	Etherrock *er = ifc->arg; 
 
	/* get mac address of destination */ 
2000/0913    
	a = arpget(er->f->arp, bp, version, ifc->m, ip, mac); 
2002/0507    
	a = arpget(er->f->arp, bp, version, ifc, ip, mac); 
1998/0306    
	if(a){ 
		/* check for broadcast or multicast */ 
2000/0913    
		bp = multicastarp(er->f, a, ifc->m, mac); 
1998/0306    
		if(bp == nil){ 
			sendarp(ifc, a); 
2002/0507    
		if(bp==nil){ 
			if(version == V4)  
				sendarp(ifc, a); 
			else  
				resolveaddr6(ifc, a); 
1998/0307    
			return; 
1998/0306    
		} 
	} 
2002/0223/sys/src/9/ip/ethermedium.c:236,2612002/0507/sys/src/9/ip/ethermedium.c:271,298
1998/0306    
	/* copy in mac addresses and ether type */ 
	memmove(eh->s, ifc->mac, sizeof(eh->s)); 
	memmove(eh->d, mac, sizeof(eh->d)); 
	switch(version){ 
2002/0507    
 
 	switch(version){ 
1998/0306    
	case V4: 
		eh->t[0] = 0x08; 
		eh->t[1] = 0x00; 
2002/0507    
		devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0); 
1998/0306    
		break; 
	case V6: 
		eh->t[0] = 0x86; 
		eh->t[1] = 0xDD; 
2002/0507    
		devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0); 
1998/0306    
		break; 
	} 
                 
	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0); 
	ifc->out++; 
} 
 
2002/0507    
 
1998/0306    
/* 
 *  process to read from the ethernet 
 */ 
static void 
etherread(void *a) 
2002/0507    
etherread4(void *a) 
1998/0306    
{ 
	Ipifc *ifc; 
	Block *bp; 
2002/0223/sys/src/9/ip/ethermedium.c:263,2752002/0507/sys/src/9/ip/ethermedium.c:300,312
1998/0306    
 
	ifc = a; 
	er = ifc->arg; 
	er->readp = up;	/* hide identity under a rock for unbind */ 
2002/0507    
	er->read4p = up;	/* hide identity under a rock for unbind */ 
1998/0306    
	if(waserror()){ 
		er->readp = 0; 
2002/0507    
		er->read4p = 0; 
1998/0306    
		pexit("hangup", 1); 
	} 
	for(;;){ 
		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); 
2002/0507    
		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxmtu, 0); 
1999/0302    
		if(!canrlock(ifc)){ 
			freeb(bp); 
			continue; 
2002/0223/sys/src/9/ip/ethermedium.c:283,3042002/0507/sys/src/9/ip/ethermedium.c:320,384
1998/0306    
		if(ifc->lifc == nil) 
			freeb(bp); 
		else 
2001/0623    
			ipiput(er->f, ifc, bp); 
2002/0507    
			ipiput4(er->f, ifc, bp); 
1999/0302    
		runlock(ifc); 
		poperror(); 
1998/0306    
	} 
} 
 
2002/0507    
 
/* 
 *  process to read from the ethernet, IPv6 
 */ 
1998/0306    
static void 
2002/0507    
etherread6(void *a) 
{ 
	Ipifc *ifc; 
	Block *bp; 
	Etherrock *er; 
 
	ifc = a; 
	er = ifc->arg; 
	er->read6p = up;	/* hide identity under a rock for unbind */ 
	if(waserror()){ 
		er->read6p = 0; 
		pexit("hangup", 1); 
	} 
	for(;;){ 
		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxmtu, 0); 
		if(!canrlock(ifc)){ 
			freeb(bp); 
			continue; 
		} 
		if(waserror()){ 
			runlock(ifc); 
			nexterror(); 
		} 
		ifc->in++; 
		bp->rp += ifc->m->hsize; 
		if(ifc->lifc == nil) 
			freeb(bp); 
		else 
			ipiput6(er->f, ifc, bp); 
		runlock(ifc); 
		poperror(); 
	} 
} 
 
static void 
1998/0306    
etheraddmulti(Ipifc *ifc, uchar *a, uchar *) 
{ 
	uchar mac[6]; 
	char buf[64]; 
	Etherrock *er = ifc->arg; 
2002/0507    
	int type; 
1998/0306    
 
	multicastea(mac, a); 
2002/0507    
	type = multicastea(mac, a); 
1998/0306    
	sprint(buf, "addmulti %E", mac); 
	devtab[er->cchan->type]->write(er->cchan, buf, strlen(buf), 0); 
2002/0507    
	if(type == V4)  
		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0); 
	else if(type == V6)  
		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0); 
1998/0306    
} 
 
static void 
2002/0223/sys/src/9/ip/ethermedium.c:307,3162002/0507/sys/src/9/ip/ethermedium.c:387,400
1998/0306    
	uchar mac[6]; 
	char buf[64]; 
	Etherrock *er = ifc->arg; 
2002/0507    
	int type; 
1998/0306    
 
	multicastea(mac, a); 
2002/0507    
	type = multicastea(mac, a); 
1998/0306    
	sprint(buf, "remmulti %E", mac); 
	devtab[er->cchan->type]->write(er->cchan, buf, strlen(buf), 0); 
2002/0507    
	if(type == V4)  
		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0); 
	else if(type == V6)  
		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0); 
1998/0306    
} 
 
/* 
2002/0223/sys/src/9/ip/ethermedium.c:357,3632002/0507/sys/src/9/ip/ethermedium.c:441,447
1998/0306    
 
	hnputs(e->type, ETARP); 
	hnputs(e->hrd, 1); 
	hnputs(e->pro, ETIP); 
2002/0507    
	hnputs(e->pro, ETIP4); 
1998/0306    
	e->hln = sizeof(e->sha); 
	e->pln = sizeof(e->spa); 
	hnputs(e->op, ARPREQUEST); 
2002/0223/sys/src/9/ip/ethermedium.c:368,3732002/0507/sys/src/9/ip/ethermedium.c:452,494
1998/0306    
		print("arp: send: %r\n"); 
} 
 
2002/0507    
static void 
resolveaddr6(Ipifc *ifc, Arpent *a) 
{ 
	int sflag; 
	Block *bp; 
	Etherrock *er = ifc->arg; 
	uchar ipsrc[IPaddrlen]; 
 
	/* don't do anything if it's been less than a second since the last */ 
	if(msec - a->time < ReTransTimer){ 
		arprelease(er->f->arp, a); 
		return; 
	} 
 
	/* remove all but the last message */ 
	while((bp = a->hold) != nil){ 
		if(bp == a->last) 
			break; 
		a->hold = bp->list; 
		freeblist(bp); 
	} 
 
	/* try to keep it around for a second more */ 
	a->time = msec; 
	a->rxtat = msec + ReTransTimer; 
	if(a->rxtsrem <= 0) { 
		arprelease(er->f->arp, a); 
		return; 
	} 
 
	a->rxtsrem--; 
	arprelease(er->f->arp, a); 
 
	if(sflag = ipv6anylocal(ifc, ipsrc))  
		icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac); 
} 
 
1999/0731    
/* 
 *  send a gratuitous arp to refresh arp caches 
 */ 
2002/0223/sys/src/9/ip/ethermedium.c:397,4032002/0507/sys/src/9/ip/ethermedium.c:518,524
1999/0731    
 
	hnputs(e->type, ETARP); 
	hnputs(e->hrd, 1); 
	hnputs(e->pro, ETIP); 
2002/0507    
	hnputs(e->pro, ETIP4); 
1999/0731    
	e->hln = sizeof(e->sha); 
	e->pln = sizeof(e->spa); 
	hnputs(e->op, ARPREQUEST); 
2002/0223/sys/src/9/ip/ethermedium.c:429,4412002/0507/sys/src/9/ip/ethermedium.c:550,555
1998/0306    
		break; 
 
	case ARPREPLY: 
2002/0108    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
2002/0223    
				print("arprep: 0x%E/0x%E also has ip addr %V\n", 
					e->s, e->sha, e->spa); 
2002/0108    
				break; 
			} 
		} 
1998/0630    
		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0); 
1998/0306    
		break; 
 
2002/0223/sys/src/9/ip/ethermedium.c:447,4572002/0507/sys/src/9/ip/ethermedium.c:561,568
1998/0306    
		/* check for someone that think's they're me */ 
		v4tov6(ip, e->spa); 
1999/0731    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
2002/0108    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
2002/0223    
				print("arpreq: 0x%E/0x%E also has ip addr %V\n", 
					e->s, e->sha, e->spa); 
2002/0108    
				break; 
			} 
2002/0507    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0) 
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
1998/0306    
		} else { 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){ 
				print("arp: %V also has ether addr %E\n", e->spa, e->sha); 
2002/0223/sys/src/9/ip/ethermedium.c:468,4752002/0507/sys/src/9/ip/ethermedium.c:579,584
1999/0731    
		if(!ipproxyifc(er->f, ifc, ip)) 
1998/0306    
			break; 
 
/* print("arp: rem %I %E (for %I)\n", e->spa, e->sha, e->tpa); /**/ 
                 
		n = sizeof(Etherarp); 
		if(n < ifc->minmtu) 
			n = ifc->minmtu; 
2002/0223/sys/src/9/ip/ethermedium.c:478,4842002/0507/sys/src/9/ip/ethermedium.c:587,593
1998/0306    
		memset(r, 0, sizeof(Etherarp)); 
		hnputs(r->type, ETARP); 
		hnputs(r->hrd, 1); 
		hnputs(r->pro, ETIP); 
2002/0507    
		hnputs(r->pro, ETIP4); 
1998/0306    
		r->hln = sizeof(r->sha); 
		r->pln = sizeof(r->spa); 
		hnputs(r->op, ARPREPLY); 
2002/0223/sys/src/9/ip/ethermedium.c:526,5392002/0507/sys/src/9/ip/ethermedium.c:635,648
1998/0306    
		ea[4] = ip[14]; 
		ea[5] = ip[15]; 
		break; 
	case V6: 
		ea[0] = 0x33; 
		ea[1] = 0x33; 
		ea[2] = ip[12]; 
2002/0507    
 	case V6: 
 		ea[0] = 0x33; 
 		ea[1] = 0x33; 
 		ea[2] = ip[12]; 
1998/0306    
		ea[3] = ip[13]; 
		ea[4] = ip[14]; 
		ea[5] = ip[15]; 
		break; 
2002/0507    
 		ea[4] = ip[14]; 
 		ea[5] = ip[15]; 
 		break; 
1998/0306    
	} 
	return x; 
} 
2002/0223/sys/src/9/ip/ethermedium.c:572,5752002/0507/sys/src/9/ip/ethermedium.c:681,698
1998/0423    
{ 
	addipmedium(ðermedium); 
2000/0922    
	addipmedium(&gbemedium); 
2002/0507    
} 
 
 
static void  
etherpref2addr(uchar *pref, uchar *ea) 
{ 
	pref[8]  = ea[0] | 0x2; 
	pref[9]  = ea[1]; 
	pref[10] = ea[2]; 
	pref[11] = 0xFF; 
	pref[12] = 0xFE; 
	pref[13] = ea[3]; 
	pref[14] = ea[4]; 
	pref[15] = ea[5]; 
1998/0423    
} 
2002/0507/sys/src/9/ip/ethermedium.c:550,5552002/0514/sys/src/9/ip/ethermedium.c:550,565 (short | long)
1998/0306    
		break; 
 
	case ARPREPLY: 
2002/0514    
		/* check for machine using my ip address */ 
		v4tov6(ip, e->spa); 
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
				print("arprep: 0x%E/0x%E also has ip addr %V\n", 
					e->s, e->sha, e->spa); 
				break; 
			} 
		} 
 
1998/0630    
		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0); 
1998/0306    
		break; 
 
2002/0507/sys/src/9/ip/ethermedium.c:558,5712002/0514/sys/src/9/ip/ethermedium.c:568,581
1998/0306    
		if(ifc->lifc == 0) 
			break; 
 
		/* check for someone that think's they're me */ 
2002/0514    
		/* check for machine using my ip or ether address */ 
1998/0306    
		v4tov6(ip, e->spa); 
1999/0731    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
2002/0507    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0) 
				print("arp: 0x%E also has ip addr %V\n", e->sha, e->spa); 
2002/0514    
				print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa); 
1998/0306    
		} else { 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){ 
				print("arp: %V also has ether addr %E\n", e->spa, e->sha); 
2002/0514    
				print("arpreq: %V also has ether addr %E\n", e->spa, e->sha); 
1998/0306    
				break; 
			} 
		} 
2002/0514/sys/src/9/ip/ethermedium.c:252,2612002/0601/sys/src/9/ip/ethermedium.c:252,267 (short | long)
1998/0306    
		/* check for broadcast or multicast */ 
2000/0913    
		bp = multicastarp(er->f, a, ifc->m, mac); 
2002/0507    
		if(bp==nil){ 
			if(version == V4)  
2002/0601    
			switch(version){ 
			case V4: 
2002/0507    
				sendarp(ifc, a); 
			else  
2002/0601    
				break; 
			case V6:  
2002/0507    
				resolveaddr6(ifc, a); 
2002/0601    
				break; 
			default: 
				panic("etherbwrite: version %d", version); 
			} 
1998/0307    
			return; 
1998/0306    
		} 
	} 
2002/0514/sys/src/9/ip/ethermedium.c:283,2882002/0601/sys/src/9/ip/ethermedium.c:289,296
1998/0306    
		eh->t[1] = 0xDD; 
2002/0507    
		devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0); 
1998/0306    
		break; 
2002/0601    
	default: 
		panic("etherbwrite2: version %d", version); 
1998/0306    
	} 
	ifc->out++; 
} 
2002/0514/sys/src/9/ip/ethermedium.c:371,3842002/0601/sys/src/9/ip/ethermedium.c:379,398
1998/0306    
	uchar mac[6]; 
	char buf[64]; 
	Etherrock *er = ifc->arg; 
2002/0507    
	int type; 
2002/0601    
	int version; 
1998/0306    
 
2002/0507    
	type = multicastea(mac, a); 
2002/0601    
	version = multicastea(mac, a); 
1998/0306    
	sprint(buf, "addmulti %E", mac); 
2002/0507    
	if(type == V4)  
2002/0601    
	switch(version){ 
	case V4: 
2002/0507    
		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0); 
	else if(type == V6)  
2002/0601    
		break; 
	case V6: 
2002/0507    
		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0); 
2002/0601    
		break; 
	default: 
		panic("etheraddmulti: version %d", version); 
	} 
1998/0306    
} 
 
static void 
2002/0514/sys/src/9/ip/ethermedium.c:387,4002002/0601/sys/src/9/ip/ethermedium.c:401,420
1998/0306    
	uchar mac[6]; 
	char buf[64]; 
	Etherrock *er = ifc->arg; 
2002/0507    
	int type; 
2002/0601    
	int version; 
1998/0306    
 
2002/0507    
	type = multicastea(mac, a); 
2002/0601    
	version = multicastea(mac, a); 
1998/0306    
	sprint(buf, "remmulti %E", mac); 
2002/0507    
	if(type == V4)  
2002/0601    
	switch(version){ 
	case V4: 
2002/0507    
		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0); 
	else if(type == V6)  
2002/0601    
		break; 
	case V6: 
2002/0507    
		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0); 
2002/0601    
		break; 
	default: 
		panic("etherremmulti: version %d", version); 
	} 
1998/0306    
} 
 
/* 
2002/0514/sys/src/9/ip/ethermedium.c:659,6652002/0601/sys/src/9/ip/ethermedium.c:679,686
1998/0306    
 
/* 
 *  fill in an arp entry for broadcast or multicast 
 *  addresses 
2002/0601    
 *  addresses.  Return the first queued packet for the 
 *  IP address. 
1998/0306    
 */ 
static Block* 
2000/0913    
multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac) 
2002/0601/sys/src/9/ip/ethermedium.c:115,1212002/0704/sys/src/9/ip/ethermedium.c:115,121 (short | long)
1998/0306    
static void 
etherbind(Ipifc *ifc, int argc, char **argv) 
{ 
2002/0507    
	Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6; 
2002/0704    
	Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan; 
2002/0507    
	char addr[Maxpath];	//char addr[2*KNAMELEN]; 
	char dir[Maxpath];	//char dir[2*KNAMELEN]; 
1998/0306    
	char *buf; 
2002/0601/sys/src/9/ip/ethermedium.c:158,1662002/0704/sys/src/9/ip/ethermedium.c:158,171
1998/0306    
	 */ 
	snprint(addr, sizeof(addr), "%s/stats", dir); 
	buf = smalloc(512); 
2000/1111    
	achan = namec(addr, Aopen, OREAD, 0); 
	n = devtab[achan->type]->read(achan, buf, 511, 0); 
	cclose(achan); 
2002/0704    
	schan = namec(addr, Aopen, OREAD, 0); 
	if(waserror()){ 
		cclose(schan); 
		nexterror(); 
	} 
	n = devtab[schan->type]->read(schan, buf, 511, 0); 
	cclose(schan); 
	poperror(); 
1998/0306    
	buf[n] = 0; 
 
	ptr = strstr(buf, "addr: "); 
2002/0704/sys/src/9/ip/ethermedium.c:435,4412002/0710/sys/src/9/ip/ethermedium.c:435,441 (short | long)
1998/0306    
	Etherrock *er = ifc->arg; 
 
	/* don't do anything if it's been less than a second since the last */ 
	if(msec - a->time < 1000){ 
2002/0710    
	if(NOW - a->time < 1000){ 
1998/0313    
		arprelease(er->f->arp, a); 
1998/0306    
		return; 
	} 
2002/0704/sys/src/9/ip/ethermedium.c:449,4552002/0710/sys/src/9/ip/ethermedium.c:449,455
1998/0306    
	} 
 
	/* try to keep it around for a second more */ 
	a->time = msec; 
2002/0710    
	a->time = NOW; 
1998/0313    
	arprelease(er->f->arp, a); 
1998/0306    
 
	n = sizeof(Etherarp); 
2002/0704/sys/src/9/ip/ethermedium.c:486,4922002/0710/sys/src/9/ip/ethermedium.c:486,492
2002/0507    
	uchar ipsrc[IPaddrlen]; 
 
	/* don't do anything if it's been less than a second since the last */ 
	if(msec - a->time < ReTransTimer){ 
2002/0710    
	if(NOW - a->time < ReTransTimer){ 
2002/0507    
		arprelease(er->f->arp, a); 
		return; 
	} 
2002/0704/sys/src/9/ip/ethermedium.c:500,5072002/0710/sys/src/9/ip/ethermedium.c:500,507
2002/0507    
	} 
 
	/* try to keep it around for a second more */ 
	a->time = msec; 
	a->rxtat = msec + ReTransTimer; 
2002/0710    
	a->time = NOW; 
	a->rxtat = NOW + ReTransTimer; 
2002/0507    
	if(a->rxtsrem <= 0) { 
		arprelease(er->f->arp, a); 
		return; 
2002/0710/sys/src/9/ip/ethermedium.c:108,1132002/0712/sys/src/9/ip/ethermedium.c:108,115 (short | long)
1998/0306    
	uchar	tpa[4]; 
}; 
 
2002/0712    
static char *nbmsg = "nonblocking"; 
 
1998/0306    
/* 
 *  called to bind an IP ifc to an ethernet device 
 *  called with ifc wlock'd 
2002/0710/sys/src/9/ip/ethermedium.c:145,1512002/0712/sys/src/9/ip/ethermedium.c:147,153
1998/0306    
	} 
 
	/* 
	 *  open ip conversation 
2002/0712    
	 *  open ip converstation 
1998/0306    
	 * 
	 *  the dial will fail if the type is already open on 
	 *  this device. 
2002/0710/sys/src/9/ip/ethermedium.c:154,1592002/0712/sys/src/9/ip/ethermedium.c:156,166
2002/0507    
	mchan4 = chandial(addr, nil, dir, &cchan4); 
1998/0306    
 
	/* 
2002/0712    
	 *  make it non-blocking 
	 */ 
	devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0); 
 
	/* 
1998/0306    
	 *  get mac address 
	 */ 
	snprint(addr, sizeof(addr), "%s/stats", dir); 
2002/0710/sys/src/9/ip/ethermedium.c:189,1942002/0712/sys/src/9/ip/ethermedium.c:196,206
2002/0507    
	 */ 
	snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]); 
	mchan6 = chandial(addr, nil, dir, &cchan6); 
2002/0712    
 
	/* 
	 *  make it non-blocking 
	 */ 
	devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0); 
2002/0507    
 
1998/0306    
	er = smalloc(sizeof(*er)); 
2002/0507    
	er->mchan4 = mchan4; 
2002/0712/sys/src/9/ip/ethermedium.c:573,5782002/0920/sys/src/9/ip/ethermedium.c:573,579 (short | long)
1998/0306    
	Block *ebp, *rbp; 
	Etherarp *e, *r; 
	uchar ip[IPaddrlen]; 
2002/0920    
	static uchar eprinted[4]; 
1998/0306    
	Etherrock *er = ifc->arg; 
 
	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxmtu, 0); 
2002/0712/sys/src/9/ip/ethermedium.c:608,6152002/0920/sys/src/9/ip/ethermedium.c:609,621
2002/0514    
		/* check for machine using my ip or ether address */ 
1998/0306    
		v4tov6(ip, e->spa); 
1999/0731    
		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){ 
2002/0507    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0) 
2002/0514    
				print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa); 
2002/0920    
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ 
				if (memcmp(eprinted, e->spa, sizeof(e->spa))){ 
					/* print only once */ 
					print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa); 
					memmove(eprinted, e->spa, sizeof(e->spa)); 
				} 
			} 
1998/0306    
		} else { 
			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){ 
2002/0514    
				print("arpreq: %V also has ether addr %E\n", e->spa, e->sha); 
2002/0920/sys/src/9/ip/ethermedium.c:35,422003/0209/sys/src/9/ip/ethermedium.c:35,42 (short | long)
1998/0306    
{ 
1999/0731    
.name=		"ether", 
.hsize=		14, 
.minmtu=	60, 
.maxmtu=	1514, 
2003/0209    
.mintu=		60, 
.maxtu=		1514, 
1999/0731    
.maclen=	6, 
.bind=		etherbind, 
.unbind=	etherunbind, 
2002/0920/sys/src/9/ip/ethermedium.c:52,592003/0209/sys/src/9/ip/ethermedium.c:52,59
2000/0922    
{ 
.name=		"gbe", 
.hsize=		14, 
.minmtu=	60, 
.maxmtu=	9014, 
2003/0209    
.mintu=		60, 
.maxtu=		9014, 
2000/0922    
.maclen=	6, 
.bind=		etherbind, 
.unbind=	etherunbind, 
2002/0920/sys/src/9/ip/ethermedium.c:161,1672003/0209/sys/src/9/ip/ethermedium.c:161,167
2002/0712    
	devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0); 
 
	/* 
1998/0306    
	 *  get mac address 
2003/0209    
	 *  get mac address and speed 
1998/0306    
	 */ 
	snprint(addr, sizeof(addr), "%s/stats", dir); 
	buf = smalloc(512); 
2002/0920/sys/src/9/ip/ethermedium.c:179,1872003/0209/sys/src/9/ip/ethermedium.c:179,193
1998/0306    
	if(!ptr) 
		error(Eio); 
	ptr += 6; 
                 
	parsemac(ifc->mac, ptr, 6); 
 
2003/0209    
	ptr = strstr(buf, "mbps: "); 
	if(ptr){ 
		ptr += 6; 
		ifc->mbps = atoi(ptr); 
	} else 
		ifc->mbps = 100; 
 
1998/0306    
	/* 
 	 *  open arp conversation 
	 */ 
2002/0920/sys/src/9/ip/ethermedium.c:287,2942003/0209/sys/src/9/ip/ethermedium.c:293,300
1998/0306    
	bp = padblock(bp, ifc->m->hsize); 
	if(bp->next) 
		bp = concatblock(bp); 
	if(BLEN(bp) < ifc->minmtu) 
		bp = adjustblock(bp, ifc->minmtu); 
2003/0209    
	if(BLEN(bp) < ifc->mintu) 
		bp = adjustblock(bp, ifc->mintu); 
1998/0306    
	eh = (Etherhdr*)bp->rp; 
 
	/* copy in mac addresses and ether type */ 
2002/0920/sys/src/9/ip/ethermedium.c:331,3372003/0209/sys/src/9/ip/ethermedium.c:337,343
1998/0306    
		pexit("hangup", 1); 
	} 
	for(;;){ 
2002/0507    
		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxmtu, 0); 
2003/0209    
		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0); 
1999/0302    
		if(!canrlock(ifc)){ 
			freeb(bp); 
			continue; 
2002/0920/sys/src/9/ip/ethermedium.c:370,3762003/0209/sys/src/9/ip/ethermedium.c:376,382
2002/0507    
		pexit("hangup", 1); 
	} 
	for(;;){ 
		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxmtu, 0); 
2003/0209    
		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0); 
2002/0507    
		if(!canrlock(ifc)){ 
			freeb(bp); 
			continue; 
2002/0920/sys/src/9/ip/ethermedium.c:465,4722003/0209/sys/src/9/ip/ethermedium.c:471,478
1998/0313    
	arprelease(er->f->arp, a); 
1998/0306    
 
	n = sizeof(Etherarp); 
	if(n < a->type->minmtu) 
		n = a->type->minmtu; 
2003/0209    
	if(n < a->type->mintu) 
		n = a->type->mintu; 
1998/0306    
	bp = allocb(n); 
	memset(bp->rp, 0, n); 
	e = (Etherarp*)bp->rp; 
2002/0920/sys/src/9/ip/ethermedium.c:542,5492003/0209/sys/src/9/ip/ethermedium.c:548,555
1999/0731    
		return; 
 
	n = sizeof(Etherarp); 
2000/0913    
	if(n < ifc->m->minmtu) 
		n = ifc->m->minmtu; 
2003/0209    
	if(n < ifc->m->mintu) 
		n = ifc->m->mintu; 
1999/0731    
	bp = allocb(n); 
	memset(bp->rp, 0, n); 
	e = (Etherarp*)bp->rp; 
2002/0920/sys/src/9/ip/ethermedium.c:576,5822003/0209/sys/src/9/ip/ethermedium.c:582,588
2002/0920    
	static uchar eprinted[4]; 
1998/0306    
	Etherrock *er = ifc->arg; 
 
	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxmtu, 0); 
2003/0209    
	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0); 
1998/0306    
	if(ebp == nil) { 
		print("arp: rcv: %r\n"); 
		return; 
2002/0920/sys/src/9/ip/ethermedium.c:633,6402003/0209/sys/src/9/ip/ethermedium.c:639,646
1998/0306    
			break; 
 
		n = sizeof(Etherarp); 
		if(n < ifc->minmtu) 
			n = ifc->minmtu; 
2003/0209    
		if(n < ifc->mintu) 
			n = ifc->mintu; 
1998/0306    
		rbp = allocb(n); 
		r = (Etherarp*)rbp->rp; 
		memset(r, 0, sizeof(Etherarp)); 
2003/0209/sys/src/9/ip/ethermedium.c:453,4592003/0310/sys/src/9/ip/ethermedium.c:453,459 (short | long)
1998/0306    
	Etherrock *er = ifc->arg; 
 
	/* don't do anything if it's been less than a second since the last */ 
2002/0710    
	if(NOW - a->time < 1000){ 
2003/0310    
	if(NOW - a->ctime < 1000){ 
1998/0313    
		arprelease(er->f->arp, a); 
1998/0306    
		return; 
	} 
2003/0209/sys/src/9/ip/ethermedium.c:467,4732003/0310/sys/src/9/ip/ethermedium.c:467,473
1998/0306    
	} 
 
	/* try to keep it around for a second more */ 
2002/0710    
	a->time = NOW; 
2003/0310    
	a->ctime = NOW; 
1998/0313    
	arprelease(er->f->arp, a); 
1998/0306    
 
	n = sizeof(Etherarp); 
2003/0209/sys/src/9/ip/ethermedium.c:504,5102003/0310/sys/src/9/ip/ethermedium.c:504,510
2002/0507    
	uchar ipsrc[IPaddrlen]; 
 
	/* don't do anything if it's been less than a second since the last */ 
2002/0710    
	if(NOW - a->time < ReTransTimer){ 
2003/0310    
	if(NOW - a->ctime < ReTransTimer){ 
2002/0507    
		arprelease(er->f->arp, a); 
		return; 
	} 
2003/0209/sys/src/9/ip/ethermedium.c:518,5252003/0310/sys/src/9/ip/ethermedium.c:518,525
2002/0507    
	} 
 
	/* try to keep it around for a second more */ 
2002/0710    
	a->time = NOW; 
	a->rxtat = NOW + ReTransTimer; 
2003/0310    
	a->ctime = NOW; 
	a->rtime = NOW + ReTransTimer; 
2002/0507    
	if(a->rxtsrem <= 0) { 
		arprelease(er->f->arp, a); 
		return; 


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