]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/rarpd.c
add ip/tftpfs
[plan9front.git] / sys / src / cmd / ip / rarpd.c
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
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
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
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*
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 }