xref: /plan9/sys/src/cmd/ip/rarpd.c (revision da51d93a95fd527106ceeb0537961de9ab01e9ec)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ip.h>
53e12c5d1SDavid du Colombier #include <ndb.h>
6219b2ee8SDavid du Colombier #include "arp.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier typedef struct Rarp	Rarp;
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier struct Rarp
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	uchar	edst[6];
133e12c5d1SDavid du Colombier 	uchar	esrc[6];
143e12c5d1SDavid du Colombier 	uchar	type[2];
153e12c5d1SDavid du Colombier 	uchar	hrd[2];
163e12c5d1SDavid du Colombier 	uchar	pro[2];
173e12c5d1SDavid du Colombier 	uchar	hln;
183e12c5d1SDavid du Colombier 	uchar	pln;
193e12c5d1SDavid du Colombier 	uchar	op[2];
203e12c5d1SDavid du Colombier 	uchar	sha[6];
213e12c5d1SDavid du Colombier 	uchar	spa[4];
223e12c5d1SDavid du Colombier 	uchar	tha[6];
233e12c5d1SDavid du Colombier 	uchar	tpa[4];
243e12c5d1SDavid du Colombier };
253e12c5d1SDavid du Colombier 
263ff48bf5SDavid du Colombier uchar	myip[IPaddrlen];
273e12c5d1SDavid du Colombier uchar	myether[6];
283e12c5d1SDavid du Colombier char	rlog[] = "ipboot";
297dd7cddfSDavid du Colombier char	*device = "ether0";
303e12c5d1SDavid du Colombier int	debug;
313e12c5d1SDavid du Colombier Ndb	*db;
323e12c5d1SDavid du Colombier 
33*da51d93aSDavid du Colombier char*	lookup(char*, char*, char*, char*, int);
347dd7cddfSDavid du Colombier 
353e12c5d1SDavid du Colombier void
error(char * s)363e12c5d1SDavid du Colombier error(char *s)
373e12c5d1SDavid du Colombier {
383e12c5d1SDavid du Colombier 	syslog(1, rlog, "error %s: %r", s);
393e12c5d1SDavid du Colombier 	exits(s);
403e12c5d1SDavid du Colombier }
413e12c5d1SDavid du Colombier 
429a747e4fSDavid du Colombier char net[32];
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier void
usage(void)457dd7cddfSDavid du Colombier usage(void)
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier 	fprint(2, "usage: %s [-e device] [-x netmtpt] [-f ndb-file] [-d]\n", argv0);
487dd7cddfSDavid du Colombier 	exits("usage");
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier 
513e12c5d1SDavid du Colombier void
main(int argc,char * argv[])523e12c5d1SDavid du Colombier main(int argc, char *argv[])
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier 	int edata, ectl;
553e12c5d1SDavid du Colombier 	uchar buf[2048];
563e12c5d1SDavid du Colombier 	long n;
573e12c5d1SDavid du Colombier 	Rarp *rp;
58*da51d93aSDavid du Colombier 	char ebuf[16];
59*da51d93aSDavid du Colombier 	char ipbuf[64];
609a747e4fSDavid du Colombier 	char file[128];
613e12c5d1SDavid du Colombier 	int arp;
627dd7cddfSDavid du Colombier 	char *p, *ndbfile;
633e12c5d1SDavid du Colombier 
647dd7cddfSDavid du Colombier 	ndbfile = nil;
657dd7cddfSDavid du Colombier 	setnetmtpt(net, sizeof(net), nil);
663e12c5d1SDavid du Colombier 	ARGBEGIN{
673e12c5d1SDavid du Colombier 	case 'e':
687dd7cddfSDavid du Colombier 		p = ARGF();
697dd7cddfSDavid du Colombier 		if(p == nil)
707dd7cddfSDavid du Colombier 			usage();
717dd7cddfSDavid du Colombier 		device = p;
723e12c5d1SDavid du Colombier 		break;
733e12c5d1SDavid du Colombier 	case 'd':
743e12c5d1SDavid du Colombier 		debug = 1;
753e12c5d1SDavid du Colombier 		break;
767dd7cddfSDavid du Colombier 	case 'f':
777dd7cddfSDavid du Colombier 		p = ARGF();
787dd7cddfSDavid du Colombier 		if(p == nil)
797dd7cddfSDavid du Colombier 			usage();
807dd7cddfSDavid du Colombier 		ndbfile = p;
817dd7cddfSDavid du Colombier 		break;
827dd7cddfSDavid du Colombier 	case 'x':
837dd7cddfSDavid du Colombier 		p = ARGF();
847dd7cddfSDavid du Colombier 		if(p == nil)
857dd7cddfSDavid du Colombier 			usage();
867dd7cddfSDavid du Colombier 		setnetmtpt(net, sizeof(net), p);
877dd7cddfSDavid du Colombier 		break;
883e12c5d1SDavid du Colombier 	}ARGEND
893e12c5d1SDavid du Colombier 	USED(argc, argv);
903e12c5d1SDavid du Colombier 
919a747e4fSDavid du Colombier 	fmtinstall('E', eipfmt);
929a747e4fSDavid du Colombier 	fmtinstall('I', eipfmt);
933ff48bf5SDavid du Colombier 	fmtinstall('V', eipfmt);
943e12c5d1SDavid du Colombier 
957dd7cddfSDavid du Colombier 	db = ndbopen(ndbfile);
963e12c5d1SDavid du Colombier 	if(db == 0)
973e12c5d1SDavid du Colombier 		error("can't open the database");
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	edata = dial(netmkaddr("0x8035", device, 0), 0, 0, &ectl);
1003e12c5d1SDavid du Colombier 	if(edata < 0)
1013e12c5d1SDavid du Colombier 		error("can't open ethernet");
1023e12c5d1SDavid du Colombier 
1039a747e4fSDavid du Colombier 	if(myipaddr(myip, net) < 0)
1043e12c5d1SDavid du Colombier 		error("can't get my ip address");
1057dd7cddfSDavid du Colombier 	sprint(ebuf, "%s/%s", net, device);
1063e12c5d1SDavid du Colombier 	if(myetheraddr(myether, ebuf) < 0)
1073e12c5d1SDavid du Colombier 		error("can't get my ether address");
1083e12c5d1SDavid du Colombier 
1097dd7cddfSDavid du Colombier 	snprint(file, sizeof(file), "%s/arp", net);
1107dd7cddfSDavid du Colombier 	if((arp = open(file, ORDWR)) < 0)
1117dd7cddfSDavid du Colombier 		fprint(2, "rarpd: can't open %s\n", file);
1123e12c5d1SDavid du Colombier 
1133e12c5d1SDavid du Colombier 	switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
1143e12c5d1SDavid du Colombier 	case -1:
1153e12c5d1SDavid du Colombier 		error("fork");
1163e12c5d1SDavid du Colombier 	case 0:
1173e12c5d1SDavid du Colombier 		break;
1183e12c5d1SDavid du Colombier 	default:
1193e12c5d1SDavid du Colombier 		exits(0);
1203e12c5d1SDavid du Colombier 	}
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 	for(;;){
1233e12c5d1SDavid du Colombier 		n = read(edata, buf, sizeof(buf));
1243e12c5d1SDavid du Colombier 		if(n <= 0)
1253e12c5d1SDavid du Colombier 			error("reading");
1263e12c5d1SDavid du Colombier 		if(n < sizeof(Rarp)){
1277dd7cddfSDavid du Colombier 			syslog(debug, rlog, "bad packet size %ld", n);
1283e12c5d1SDavid du Colombier 			continue;
1293e12c5d1SDavid du Colombier 		}
1303e12c5d1SDavid du Colombier 		rp = (Rarp*)buf;
1313e12c5d1SDavid du Colombier 		if(rp->op[0]!=0 && rp->op[1]!=3){
1323e12c5d1SDavid du Colombier 			syslog(debug, rlog, "bad op %d %d %E",
1333e12c5d1SDavid du Colombier 				rp->op[1], rp->op[0], rp->esrc);
1343e12c5d1SDavid du Colombier 			continue;
1353e12c5d1SDavid du Colombier 		}
1363e12c5d1SDavid du Colombier 
1373e12c5d1SDavid du Colombier 		if(debug)
1383ff48bf5SDavid du Colombier 			syslog(debug, rlog, "rcv se %E si %V te %E ti %V",
1393e12c5d1SDavid du Colombier 				 rp->sha, rp->spa, rp->tha, rp->tpa);
1403e12c5d1SDavid du Colombier 
1413e12c5d1SDavid du Colombier 		sprint(ebuf, "%E", rp->tha);
142*da51d93aSDavid du Colombier 		if(lookup("ether", ebuf, "ip", ipbuf, sizeof ipbuf) == nil){
1433e12c5d1SDavid du Colombier 			syslog(debug, rlog, "client lookup failed: %s", ebuf);
1443e12c5d1SDavid du Colombier 			continue;
1453e12c5d1SDavid du Colombier 		}
1467dd7cddfSDavid du Colombier 		v4parseip(rp->tpa, ipbuf);
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier 		memmove(rp->sha, myether, sizeof(rp->sha));
1493ff48bf5SDavid du Colombier 		v6tov4(rp->spa, myip);
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 		rp->op[0] = 0;
1523e12c5d1SDavid du Colombier 		rp->op[1] = 4;
1533e12c5d1SDavid du Colombier 		memmove(rp->edst, rp->esrc, sizeof(rp->edst));
1543e12c5d1SDavid du Colombier 
1553e12c5d1SDavid du Colombier 		if(debug)
1563ff48bf5SDavid du Colombier 			syslog(debug, rlog, "send se %E si %V te %E ti %V",
1573e12c5d1SDavid du Colombier 				 rp->sha, rp->spa, rp->tha, rp->tpa);
1583e12c5d1SDavid du Colombier 
1593ff48bf5SDavid du Colombier 		if(write(edata, buf, 60) != 60)
1603e12c5d1SDavid du Colombier 			error("write failed");
1613e12c5d1SDavid du Colombier 
162219b2ee8SDavid du Colombier 		if(arp < 0)
163219b2ee8SDavid du Colombier 			continue;
1643ff48bf5SDavid du Colombier 		if(fprint(arp, "add %E %V", rp->esrc, rp->tpa) < 0)
1657dd7cddfSDavid du Colombier 			fprint(2, "can't write arp entry\n");
1663e12c5d1SDavid du Colombier 	}
1673e12c5d1SDavid du Colombier }
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier char*
lookup(char * sattr,char * sval,char * tattr,char * tval,int len)170*da51d93aSDavid du Colombier lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
1717dd7cddfSDavid du Colombier {
1727dd7cddfSDavid du Colombier 	static Ndb *db;
1737dd7cddfSDavid du Colombier 	char *attrs[1];
1747dd7cddfSDavid du Colombier 	Ndbtuple *t;
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier 	if(db == nil)
1777dd7cddfSDavid du Colombier 		db = ndbopen(0);
1787dd7cddfSDavid du Colombier 	if(db == nil)
1797dd7cddfSDavid du Colombier 		return nil;
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier 	if(sattr == nil)
1827dd7cddfSDavid du Colombier 		sattr = ipattr(sval);
1837dd7cddfSDavid du Colombier 
1847dd7cddfSDavid du Colombier 	attrs[0] = tattr;
1857dd7cddfSDavid du Colombier 	t = ndbipinfo(db, sattr, sval, attrs, 1);
1867dd7cddfSDavid du Colombier 	if(t == nil)
1877dd7cddfSDavid du Colombier 		return nil;
188*da51d93aSDavid du Colombier 	strncpy(tval, t->val, len);
189*da51d93aSDavid du Colombier 	tval[len-1] = 0;
1907dd7cddfSDavid du Colombier 	ndbfree(t);
1917dd7cddfSDavid du Colombier 	return tval;
1927dd7cddfSDavid du Colombier }
193