17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <ndb.h>
5d9306527SDavid du Colombier #include <fcall.h>
67dd7cddfSDavid du Colombier
79a747e4fSDavid du Colombier enum
87dd7cddfSDavid du Colombier {
99a747e4fSDavid du Colombier Maxpath= 128,
109a747e4fSDavid du Colombier };
117dd7cddfSDavid du Colombier
129a747e4fSDavid du Colombier typedef struct Endpoints Endpoints;
139a747e4fSDavid du Colombier struct Endpoints
149a747e4fSDavid du Colombier {
159a747e4fSDavid du Colombier char *net;
169a747e4fSDavid du Colombier char *lsys;
179a747e4fSDavid du Colombier char *lserv;
189a747e4fSDavid du Colombier char *rsys;
199a747e4fSDavid du Colombier char *rserv;
209a747e4fSDavid du Colombier };
217dd7cddfSDavid du Colombier
229a747e4fSDavid du Colombier void xfer(int, int);
23d9306527SDavid du Colombier void xfer9p(int, int);
249a747e4fSDavid du Colombier Endpoints* getendpoints(char*);
259a747e4fSDavid du Colombier void freeendpoints(Endpoints*);
269a747e4fSDavid du Colombier char* iptomac(char*, char*);
279a747e4fSDavid du Colombier int macok(char*);
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier void
usage(void)30*5741f218SDavid du Colombier usage(void)
31*5741f218SDavid du Colombier {
32*5741f218SDavid du Colombier fprint(2, "usage: trampoline [-9] [-a addr] [-m netdir] addr\n");
33*5741f218SDavid du Colombier exits("usage");
34*5741f218SDavid du Colombier }
35*5741f218SDavid du Colombier
36*5741f218SDavid du Colombier void
main(int argc,char ** argv)377dd7cddfSDavid du Colombier main(int argc, char **argv)
387dd7cddfSDavid du Colombier {
39*5741f218SDavid du Colombier char *altaddr, *checkmac, *mac;
40*5741f218SDavid du Colombier int fd, fd0, fd1;
41d9306527SDavid du Colombier void (*x)(int, int);
42*5741f218SDavid du Colombier Endpoints *ep;
437dd7cddfSDavid du Colombier
44*5741f218SDavid du Colombier checkmac = nil;
45*5741f218SDavid du Colombier altaddr = nil;
46d9306527SDavid du Colombier x = xfer;
477dd7cddfSDavid du Colombier ARGBEGIN{
48d9306527SDavid du Colombier case '9':
49d9306527SDavid du Colombier x = xfer9p;
50d9306527SDavid du Colombier break;
51*5741f218SDavid du Colombier case 'a':
52*5741f218SDavid du Colombier altaddr = EARGF(usage());
53*5741f218SDavid du Colombier break;
54*5741f218SDavid du Colombier case 'm':
55*5741f218SDavid du Colombier checkmac = EARGF(usage());
56*5741f218SDavid du Colombier break;
57*5741f218SDavid du Colombier default:
58*5741f218SDavid du Colombier usage();
597dd7cddfSDavid du Colombier }ARGEND;
607dd7cddfSDavid du Colombier
61*5741f218SDavid du Colombier if(argc != 1)
62*5741f218SDavid du Colombier usage();
63*5741f218SDavid du Colombier
64*5741f218SDavid du Colombier if(checkmac){
65*5741f218SDavid du Colombier ep = getendpoints(checkmac);
669a747e4fSDavid du Colombier mac = iptomac(ep->rsys, ep->net);
679a747e4fSDavid du Colombier if(!macok(mac)){
689a747e4fSDavid du Colombier syslog(0, "trampoline", "badmac %s from %s!%s for %s!%s on %s",
699a747e4fSDavid du Colombier mac, ep->rsys, ep->rserv, ep->lsys, ep->lserv, ep->net);
709a747e4fSDavid du Colombier exits("bad mac");
719a747e4fSDavid du Colombier }
729a747e4fSDavid du Colombier }
73*5741f218SDavid du Colombier
74*5741f218SDavid du Colombier fd0 = 0;
75*5741f218SDavid du Colombier fd1 = 1;
76*5741f218SDavid du Colombier if(altaddr){
77*5741f218SDavid du Colombier fd0 = dial(altaddr, 0, 0, 0);
78*5741f218SDavid du Colombier if(fd0 < 0)
79*5741f218SDavid du Colombier sysfatal("dial %s: %r", altaddr);
80*5741f218SDavid du Colombier fd1 = fd0;
817dd7cddfSDavid du Colombier }
82*5741f218SDavid du Colombier fd = dial(argv[0], 0, 0, 0);
83*5741f218SDavid du Colombier if(fd < 0)
84*5741f218SDavid du Colombier sysfatal("dial %s: %r", argv[0]);
85*5741f218SDavid du Colombier
867dd7cddfSDavid du Colombier rfork(RFNOTEG);
877dd7cddfSDavid du Colombier switch(fork()){
887dd7cddfSDavid du Colombier case -1:
897dd7cddfSDavid du Colombier fprint(2, "%s: fork: %r\n", argv0);
907dd7cddfSDavid du Colombier exits("dial");
917dd7cddfSDavid du Colombier case 0:
92*5741f218SDavid du Colombier (*x)(fd0, fd);
937dd7cddfSDavid du Colombier break;
947dd7cddfSDavid du Colombier default:
95*5741f218SDavid du Colombier (*x)(fd, fd1);
967dd7cddfSDavid du Colombier break;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier postnote(PNGROUP, getpid(), "die yankee pig dog");
997dd7cddfSDavid du Colombier exits(0);
1007dd7cddfSDavid du Colombier }
1019a747e4fSDavid du Colombier
1029a747e4fSDavid du Colombier void
xfer(int from,int to)1039a747e4fSDavid du Colombier xfer(int from, int to)
1049a747e4fSDavid du Colombier {
1059a747e4fSDavid du Colombier char buf[12*1024];
1069a747e4fSDavid du Colombier int n;
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier while((n = read(from, buf, sizeof buf)) > 0)
1099a747e4fSDavid du Colombier if(write(to, buf, n) < 0)
1109a747e4fSDavid du Colombier break;
1119a747e4fSDavid du Colombier }
1129a747e4fSDavid du Colombier
1139a747e4fSDavid du Colombier void
xfer9p(int from,int to)114d9306527SDavid du Colombier xfer9p(int from, int to)
115d9306527SDavid du Colombier {
116d9306527SDavid du Colombier uchar *buf;
117d9306527SDavid du Colombier uint nbuf;
118d9306527SDavid du Colombier int n;
119d9306527SDavid du Colombier
120d9306527SDavid du Colombier nbuf = 256;
121d9306527SDavid du Colombier buf = malloc(nbuf);
122d9306527SDavid du Colombier if(buf == nil)
123d9306527SDavid du Colombier sysfatal("xfer: malloc %ud: %r", nbuf);
124d9306527SDavid du Colombier
125d9306527SDavid du Colombier for(;;){
126d9306527SDavid du Colombier if(readn(from, buf, 4) != 4)
127d9306527SDavid du Colombier break;
128d9306527SDavid du Colombier n = GBIT32(buf);
129d9306527SDavid du Colombier if(n > nbuf){
130d9306527SDavid du Colombier nbuf = n+8192;
131d9306527SDavid du Colombier buf = realloc(buf, nbuf);
132d9306527SDavid du Colombier if(buf == nil)
133d9306527SDavid du Colombier sysfatal("xfer: realloc %ud: %r", nbuf);
134d9306527SDavid du Colombier }
135d9306527SDavid du Colombier if(readn(from, buf+4, n-4) != n-4)
136d9306527SDavid du Colombier break;
137d9306527SDavid du Colombier if(write(to, buf, n) != n){
138d9306527SDavid du Colombier sysfatal("oops: %r");
139d9306527SDavid du Colombier break;
140d9306527SDavid du Colombier }
141d9306527SDavid du Colombier }
142d9306527SDavid du Colombier }
143d9306527SDavid du Colombier
144d9306527SDavid du Colombier void
getendpoint(char * dir,char * file,char ** sysp,char ** servp)1459a747e4fSDavid du Colombier getendpoint(char *dir, char *file, char **sysp, char **servp)
1469a747e4fSDavid du Colombier {
1479a747e4fSDavid du Colombier int fd, n;
1489a747e4fSDavid du Colombier char buf[Maxpath];
1499a747e4fSDavid du Colombier char *sys, *serv;
1509a747e4fSDavid du Colombier
1519a747e4fSDavid du Colombier sys = serv = 0;
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s/%s", dir, file);
1549a747e4fSDavid du Colombier fd = open(buf, OREAD);
1559a747e4fSDavid du Colombier if(fd >= 0){
1569a747e4fSDavid du Colombier n = read(fd, buf, sizeof(buf)-1);
1579a747e4fSDavid du Colombier if(n>0){
1589a747e4fSDavid du Colombier buf[n-1] = 0;
1599a747e4fSDavid du Colombier serv = strchr(buf, '!');
1609a747e4fSDavid du Colombier if(serv){
1619a747e4fSDavid du Colombier *serv++ = 0;
1629a747e4fSDavid du Colombier serv = strdup(serv);
1639a747e4fSDavid du Colombier }
1649a747e4fSDavid du Colombier sys = strdup(buf);
1659a747e4fSDavid du Colombier }
1669a747e4fSDavid du Colombier close(fd);
1679a747e4fSDavid du Colombier }
1689a747e4fSDavid du Colombier if(serv == 0)
1699a747e4fSDavid du Colombier serv = strdup("unknown");
1709a747e4fSDavid du Colombier if(sys == 0)
1719a747e4fSDavid du Colombier sys = strdup("unknown");
1729a747e4fSDavid du Colombier *servp = serv;
1739a747e4fSDavid du Colombier *sysp = sys;
1749a747e4fSDavid du Colombier }
1759a747e4fSDavid du Colombier
1769a747e4fSDavid du Colombier Endpoints *
getendpoints(char * dir)1779a747e4fSDavid du Colombier getendpoints(char *dir)
1789a747e4fSDavid du Colombier {
1799a747e4fSDavid du Colombier Endpoints *ep;
1809a747e4fSDavid du Colombier char *p;
1819a747e4fSDavid du Colombier
1829a747e4fSDavid du Colombier ep = malloc(sizeof(*ep));
1839a747e4fSDavid du Colombier ep->net = strdup(dir);
1849a747e4fSDavid du Colombier p = strchr(ep->net+1, '/');
1859a747e4fSDavid du Colombier if(p == nil){
1869a747e4fSDavid du Colombier free(ep->net);
1879a747e4fSDavid du Colombier ep->net = "/net";
1889a747e4fSDavid du Colombier } else
1899a747e4fSDavid du Colombier *p = 0;
1909a747e4fSDavid du Colombier getendpoint(dir, "local", &ep->lsys, &ep->lserv);
1919a747e4fSDavid du Colombier getendpoint(dir, "remote", &ep->rsys, &ep->rserv);
1929a747e4fSDavid du Colombier return ep;
1939a747e4fSDavid du Colombier }
1949a747e4fSDavid du Colombier
1959a747e4fSDavid du Colombier void
freeendpoints(Endpoints * ep)1969a747e4fSDavid du Colombier freeendpoints(Endpoints *ep)
1979a747e4fSDavid du Colombier {
1989a747e4fSDavid du Colombier free(ep->lsys);
1999a747e4fSDavid du Colombier free(ep->rsys);
2009a747e4fSDavid du Colombier free(ep->lserv);
2019a747e4fSDavid du Colombier free(ep->rserv);
2029a747e4fSDavid du Colombier free(ep);
2039a747e4fSDavid du Colombier }
2049a747e4fSDavid du Colombier
2059a747e4fSDavid du Colombier char*
iptomac(char * ip,char * net)2069a747e4fSDavid du Colombier iptomac(char *ip, char *net)
2079a747e4fSDavid du Colombier {
2089a747e4fSDavid du Colombier char file[Maxpath];
2099a747e4fSDavid du Colombier Biobuf *b;
2109a747e4fSDavid du Colombier char *p;
2119a747e4fSDavid du Colombier char *f[5];
2129a747e4fSDavid du Colombier
2139a747e4fSDavid du Colombier snprint(file, sizeof(file), "%s/arp", net);
2149a747e4fSDavid du Colombier b = Bopen(file, OREAD);
2159a747e4fSDavid du Colombier if(b == nil)
2169a747e4fSDavid du Colombier return nil;
2179a747e4fSDavid du Colombier while((p = Brdline(b, '\n')) != nil){
2189a747e4fSDavid du Colombier p[Blinelen(b)-1] = 0;
2199a747e4fSDavid du Colombier if(tokenize(p, f, nelem(f)) < 4)
2209a747e4fSDavid du Colombier continue;
2219a747e4fSDavid du Colombier if(strcmp(f[1], "OK") == 0
2229a747e4fSDavid du Colombier && strcmp(f[2], ip) == 0){
2239a747e4fSDavid du Colombier p = strdup(f[3]);
2249a747e4fSDavid du Colombier Bterm(b);
2259a747e4fSDavid du Colombier return p;
2269a747e4fSDavid du Colombier }
2279a747e4fSDavid du Colombier }
2289a747e4fSDavid du Colombier Bterm(b);
2299a747e4fSDavid du Colombier return nil;
2309a747e4fSDavid du Colombier }
2319a747e4fSDavid du Colombier
2329a747e4fSDavid du Colombier int
macok(char * mac)2339a747e4fSDavid du Colombier macok(char *mac)
2349a747e4fSDavid du Colombier {
23557837e0bSDavid du Colombier char *p;
2369a747e4fSDavid du Colombier
2379a747e4fSDavid du Colombier if(mac == nil)
2389a747e4fSDavid du Colombier return 0;
23957837e0bSDavid du Colombier free(p = csgetvalue("/net", "ether", mac, "trampok", nil));
24057837e0bSDavid du Colombier return !(p == nil);
2419a747e4fSDavid du Colombier }
242