xref: /plan9/sys/src/cmd/ip/rarpd.c (revision da51d93a95fd527106ceeb0537961de9ab01e9ec)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ip.h>
5 #include <ndb.h>
6 #include "arp.h"
7 
8 typedef struct Rarp	Rarp;
9 
10 struct Rarp
11 {
12 	uchar	edst[6];
13 	uchar	esrc[6];
14 	uchar	type[2];
15 	uchar	hrd[2];
16 	uchar	pro[2];
17 	uchar	hln;
18 	uchar	pln;
19 	uchar	op[2];
20 	uchar	sha[6];
21 	uchar	spa[4];
22 	uchar	tha[6];
23 	uchar	tpa[4];
24 };
25 
26 uchar	myip[IPaddrlen];
27 uchar	myether[6];
28 char	rlog[] = "ipboot";
29 char	*device = "ether0";
30 int	debug;
31 Ndb	*db;
32 
33 char*	lookup(char*, char*, char*, char*, int);
34 
35 void
error(char * s)36 error(char *s)
37 {
38 	syslog(1, rlog, "error %s: %r", s);
39 	exits(s);
40 }
41 
42 char net[32];
43 
44 void
usage(void)45 usage(void)
46 {
47 	fprint(2, "usage: %s [-e device] [-x netmtpt] [-f ndb-file] [-d]\n", argv0);
48 	exits("usage");
49 }
50 
51 void
main(int argc,char * argv[])52 main(int argc, char *argv[])
53 {
54 	int edata, ectl;
55 	uchar buf[2048];
56 	long n;
57 	Rarp *rp;
58 	char ebuf[16];
59 	char ipbuf[64];
60 	char file[128];
61 	int arp;
62 	char *p, *ndbfile;
63 
64 	ndbfile = nil;
65 	setnetmtpt(net, sizeof(net), nil);
66 	ARGBEGIN{
67 	case 'e':
68 		p = ARGF();
69 		if(p == nil)
70 			usage();
71 		device = p;
72 		break;
73 	case 'd':
74 		debug = 1;
75 		break;
76 	case 'f':
77 		p = ARGF();
78 		if(p == nil)
79 			usage();
80 		ndbfile = p;
81 		break;
82 	case 'x':
83 		p = ARGF();
84 		if(p == nil)
85 			usage();
86 		setnetmtpt(net, sizeof(net), p);
87 		break;
88 	}ARGEND
89 	USED(argc, argv);
90 
91 	fmtinstall('E', eipfmt);
92 	fmtinstall('I', eipfmt);
93 	fmtinstall('V', eipfmt);
94 
95 	db = ndbopen(ndbfile);
96 	if(db == 0)
97 		error("can't open the database");
98 
99 	edata = dial(netmkaddr("0x8035", device, 0), 0, 0, &ectl);
100 	if(edata < 0)
101 		error("can't open ethernet");
102 
103 	if(myipaddr(myip, net) < 0)
104 		error("can't get my ip address");
105 	sprint(ebuf, "%s/%s", net, device);
106 	if(myetheraddr(myether, ebuf) < 0)
107 		error("can't get my ether address");
108 
109 	snprint(file, sizeof(file), "%s/arp", net);
110 	if((arp = open(file, ORDWR)) < 0)
111 		fprint(2, "rarpd: can't open %s\n", file);
112 
113 	switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
114 	case -1:
115 		error("fork");
116 	case 0:
117 		break;
118 	default:
119 		exits(0);
120 	}
121 
122 	for(;;){
123 		n = read(edata, buf, sizeof(buf));
124 		if(n <= 0)
125 			error("reading");
126 		if(n < sizeof(Rarp)){
127 			syslog(debug, rlog, "bad packet size %ld", n);
128 			continue;
129 		}
130 		rp = (Rarp*)buf;
131 		if(rp->op[0]!=0 && rp->op[1]!=3){
132 			syslog(debug, rlog, "bad op %d %d %E",
133 				rp->op[1], rp->op[0], rp->esrc);
134 			continue;
135 		}
136 
137 		if(debug)
138 			syslog(debug, rlog, "rcv se %E si %V te %E ti %V",
139 				 rp->sha, rp->spa, rp->tha, rp->tpa);
140 
141 		sprint(ebuf, "%E", rp->tha);
142 		if(lookup("ether", ebuf, "ip", ipbuf, sizeof ipbuf) == nil){
143 			syslog(debug, rlog, "client lookup failed: %s", ebuf);
144 			continue;
145 		}
146 		v4parseip(rp->tpa, ipbuf);
147 
148 		memmove(rp->sha, myether, sizeof(rp->sha));
149 		v6tov4(rp->spa, myip);
150 
151 		rp->op[0] = 0;
152 		rp->op[1] = 4;
153 		memmove(rp->edst, rp->esrc, sizeof(rp->edst));
154 
155 		if(debug)
156 			syslog(debug, rlog, "send se %E si %V te %E ti %V",
157 				 rp->sha, rp->spa, rp->tha, rp->tpa);
158 
159 		if(write(edata, buf, 60) != 60)
160 			error("write failed");
161 
162 		if(arp < 0)
163 			continue;
164 		if(fprint(arp, "add %E %V", rp->esrc, rp->tpa) < 0)
165 			fprint(2, "can't write arp entry\n");
166 	}
167 }
168 
169 char*
lookup(char * sattr,char * sval,char * tattr,char * tval,int len)170 lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
171 {
172 	static Ndb *db;
173 	char *attrs[1];
174 	Ndbtuple *t;
175 
176 	if(db == nil)
177 		db = ndbopen(0);
178 	if(db == nil)
179 		return nil;
180 
181 	if(sattr == nil)
182 		sattr = ipattr(sval);
183 
184 	attrs[0] = tattr;
185 	t = ndbipinfo(db, sattr, sval, attrs, 1);
186 	if(t == nil)
187 		return nil;
188 	strncpy(tval, t->val, len);
189 	tval[len-1] = 0;
190 	ndbfree(t);
191 	return tval;
192 }
193