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
usage(void)30 usage(void)
31 {
32 fprint(2, "usage: trampoline [-9] [-a addr] [-m netdir] addr\n");
33 exits("usage");
34 }
35
36 void
main(int argc,char ** argv)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
xfer(int from,int to)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
xfer9p(int from,int to)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
getendpoint(char * dir,char * file,char ** sysp,char ** servp)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 *
getendpoints(char * dir)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
freeendpoints(Endpoints * ep)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*
iptomac(char * ip,char * net)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
macok(char * mac)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 }
242