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