]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/trampoline.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / aux / trampoline.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ndb.h>
5 #include <fcall.h>
6
7 enum
8 {
9         Maxpath=        128,
10 };
11
12 typedef struct Endpoints Endpoints;
13 struct Endpoints
14 {
15         char    *net;
16         char    *lsys;
17         char    *lserv;
18         char    *rsys;
19         char    *rserv;
20 };
21
22 void            xfer(int, int);
23 void            xfer9p(int, int);
24 Endpoints*      getendpoints(char*);
25 void            freeendpoints(Endpoints*);
26 char*           iptomac(char*, char*);
27 int             macok(char*);
28
29 void
30 usage(void)
31 {
32         fprint(2, "usage: trampoline [-9] [-a addr] [-m netdir] addr\n");
33         exits("usage");
34 }
35
36 void
37 main(int argc, char **argv)
38 {
39         char *altaddr, *checkmac, *mac;
40         int fd, fd0, fd1;
41         void (*x)(int, int);
42         Endpoints *ep;
43
44         checkmac = nil;
45         altaddr = nil;
46         x = xfer;
47         ARGBEGIN{
48         case '9':
49                 x = xfer9p;
50                 break;
51         case 'a':
52                 altaddr = EARGF(usage());
53                 break;
54         case 'm':
55                 checkmac = EARGF(usage());
56                 break;
57         default:
58                 usage();
59         }ARGEND;
60
61         if(argc != 1)
62                 usage();
63
64         if(checkmac){
65                 ep = getendpoints(checkmac);
66                 mac = iptomac(ep->rsys, ep->net);
67                 if(!macok(mac)){
68                         syslog(0, "trampoline", "badmac %s from %s!%s for %s!%s on %s",
69                                 mac, ep->rsys, ep->rserv, ep->lsys, ep->lserv, ep->net);
70                         exits("bad mac");
71                 }
72         }
73         
74         fd0 = 0;
75         fd1 = 1;
76         if(altaddr){
77                 fd0 = dial(altaddr, 0, 0, 0);
78                 if(fd0 < 0)
79                         sysfatal("dial %s: %r", altaddr);
80                 fd1 = fd0;
81         }
82         fd = dial(argv[0], 0, 0, 0);
83         if(fd < 0)
84                 sysfatal("dial %s: %r", argv[0]);
85
86         rfork(RFNOTEG);
87         switch(fork()){
88         case -1:
89                 fprint(2, "%s: fork: %r\n", argv0);
90                 exits("dial");
91         case 0:
92                 (*x)(fd0, fd);
93                 break;
94         default:
95                 (*x)(fd, fd1);
96                 break;
97         }
98         postnote(PNGROUP, getpid(), "die yankee pig dog");
99         exits(0);
100 }
101
102 void
103 xfer(int from, int to)
104 {
105         char buf[12*1024];
106         int n;
107
108         while((n = read(from, buf, sizeof buf)) > 0)
109                 if(write(to, buf, n) < 0)
110                         break;
111 }
112
113 void
114 xfer9p(int from, int to)
115 {
116         uchar *buf;
117         uint nbuf;
118         int n;
119
120         nbuf = 256;
121         buf = malloc(nbuf);
122         if(buf == nil)
123                 sysfatal("xfer: malloc %ud: %r", nbuf);
124
125         for(;;){
126                 if(readn(from, buf, 4) != 4)
127                         break;
128                 n = GBIT32(buf);
129                 if(n > nbuf){
130                         nbuf = n+8192;
131                         buf = realloc(buf, nbuf);
132                         if(buf == nil)
133                                 sysfatal("xfer: realloc %ud: %r", nbuf);
134                 }
135                 if(readn(from, buf+4, n-4) != n-4)
136                         break;
137                 if(write(to, buf, n) != n){
138                         sysfatal("oops: %r");
139                         break;
140                 }
141         }
142 }
143
144 void
145 getendpoint(char *dir, char *file, char **sysp, char **servp)
146 {
147         int fd, n;
148         char buf[Maxpath];
149         char *sys, *serv;
150
151         sys = serv = 0;
152
153         snprint(buf, sizeof buf, "%s/%s", dir, file);
154         fd = open(buf, OREAD);
155         if(fd >= 0){
156                 n = read(fd, buf, sizeof(buf)-1);
157                 if(n>0){
158                         buf[n-1] = 0;
159                         serv = strchr(buf, '!');
160                         if(serv){
161                                 *serv++ = 0;
162                                 serv = strdup(serv);
163                         }
164                         sys = strdup(buf);
165                 }
166                 close(fd);
167         }
168         if(serv == 0)
169                 serv = strdup("unknown");
170         if(sys == 0)
171                 sys = strdup("unknown");
172         *servp = serv;
173         *sysp = sys;
174 }
175
176 Endpoints *
177 getendpoints(char *dir)
178 {
179         Endpoints *ep;
180         char *p;
181
182         ep = malloc(sizeof(*ep));
183         ep->net = strdup(dir);
184         p = strchr(ep->net+1, '/');
185         if(p == nil){
186                 free(ep->net);
187                 ep->net = "/net";
188         } else
189                 *p = 0;
190         getendpoint(dir, "local", &ep->lsys, &ep->lserv);
191         getendpoint(dir, "remote", &ep->rsys, &ep->rserv);
192         return ep;
193 }
194
195 void
196 freeendpoints(Endpoints *ep)
197 {
198         free(ep->lsys);
199         free(ep->rsys);
200         free(ep->lserv);
201         free(ep->rserv);
202         free(ep);
203 }
204
205 char*
206 iptomac(char *ip, char *net)
207 {
208         char file[Maxpath];
209         Biobuf *b;
210         char *p;
211         char *f[5];
212
213         snprint(file, sizeof(file), "%s/arp", net);
214         b = Bopen(file, OREAD);
215         if(b == nil)
216                 return nil;
217         while((p = Brdline(b, '\n')) != nil){
218                 p[Blinelen(b)-1] = 0;
219                 if(tokenize(p, f, nelem(f)) < 4)
220                         continue;
221                 if(strcmp(f[1], "OK") == 0
222                 && strcmp(f[2], ip) == 0){
223                         p = strdup(f[3]);
224                         Bterm(b);
225                         return p;
226                 }
227         }
228         Bterm(b);
229         return nil;
230 }
231
232 int
233 macok(char *mac)
234 {
235         char *p;
236
237         if(mac == nil)
238                 return 0;
239         free(p = csgetvalue("/net", "ether", mac, "trampok", nil));
240         return !(p == nil);
241 }