diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/trampoline.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/trampoline.c')
-rwxr-xr-x | sys/src/cmd/aux/trampoline.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/trampoline.c b/sys/src/cmd/aux/trampoline.c new file mode 100755 index 000000000..6a5c0dee8 --- /dev/null +++ b/sys/src/cmd/aux/trampoline.c @@ -0,0 +1,241 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <ndb.h> +#include <fcall.h> + +enum +{ + Maxpath= 128, +}; + +typedef struct Endpoints Endpoints; +struct Endpoints +{ + char *net; + char *lsys; + char *lserv; + char *rsys; + char *rserv; +}; + +void xfer(int, int); +void xfer9p(int, int); +Endpoints* getendpoints(char*); +void freeendpoints(Endpoints*); +char* iptomac(char*, char*); +int macok(char*); + +void +usage(void) +{ + fprint(2, "usage: trampoline [-9] [-a addr] [-m netdir] addr\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *altaddr, *checkmac, *mac; + int fd, fd0, fd1; + void (*x)(int, int); + Endpoints *ep; + + checkmac = nil; + altaddr = nil; + x = xfer; + ARGBEGIN{ + case '9': + x = xfer9p; + break; + case 'a': + altaddr = EARGF(usage()); + break; + case 'm': + checkmac = EARGF(usage()); + break; + default: + usage(); + }ARGEND; + + if(argc != 1) + usage(); + + if(checkmac){ + ep = getendpoints(checkmac); + mac = iptomac(ep->rsys, ep->net); + if(!macok(mac)){ + syslog(0, "trampoline", "badmac %s from %s!%s for %s!%s on %s", + mac, ep->rsys, ep->rserv, ep->lsys, ep->lserv, ep->net); + exits("bad mac"); + } + } + + fd0 = 0; + fd1 = 1; + if(altaddr){ + fd0 = dial(altaddr, 0, 0, 0); + if(fd0 < 0) + sysfatal("dial %s: %r", altaddr); + fd1 = fd0; + } + fd = dial(argv[0], 0, 0, 0); + if(fd < 0) + sysfatal("dial %s: %r", argv[0]); + + rfork(RFNOTEG); + switch(fork()){ + case -1: + fprint(2, "%s: fork: %r\n", argv0); + exits("dial"); + case 0: + (*x)(fd0, fd); + break; + default: + (*x)(fd, fd1); + break; + } + postnote(PNGROUP, getpid(), "die yankee pig dog"); + exits(0); +} + +void +xfer(int from, int to) +{ + char buf[12*1024]; + int n; + + while((n = read(from, buf, sizeof buf)) > 0) + if(write(to, buf, n) < 0) + break; +} + +void +xfer9p(int from, int to) +{ + uchar *buf; + uint nbuf; + int n; + + nbuf = 256; + buf = malloc(nbuf); + if(buf == nil) + sysfatal("xfer: malloc %ud: %r", nbuf); + + for(;;){ + if(readn(from, buf, 4) != 4) + break; + n = GBIT32(buf); + if(n > nbuf){ + nbuf = n+8192; + buf = realloc(buf, nbuf); + if(buf == nil) + sysfatal("xfer: realloc %ud: %r", nbuf); + } + if(readn(from, buf+4, n-4) != n-4) + break; + if(write(to, buf, n) != n){ + sysfatal("oops: %r"); + break; + } + } +} + +void +getendpoint(char *dir, char *file, char **sysp, char **servp) +{ + int fd, n; + char buf[Maxpath]; + char *sys, *serv; + + sys = serv = 0; + + snprint(buf, sizeof buf, "%s/%s", dir, file); + fd = open(buf, OREAD); + if(fd >= 0){ + n = read(fd, buf, sizeof(buf)-1); + if(n>0){ + buf[n-1] = 0; + serv = strchr(buf, '!'); + if(serv){ + *serv++ = 0; + serv = strdup(serv); + } + sys = strdup(buf); + } + close(fd); + } + if(serv == 0) + serv = strdup("unknown"); + if(sys == 0) + sys = strdup("unknown"); + *servp = serv; + *sysp = sys; +} + +Endpoints * +getendpoints(char *dir) +{ + Endpoints *ep; + char *p; + + ep = malloc(sizeof(*ep)); + ep->net = strdup(dir); + p = strchr(ep->net+1, '/'); + if(p == nil){ + free(ep->net); + ep->net = "/net"; + } else + *p = 0; + getendpoint(dir, "local", &ep->lsys, &ep->lserv); + getendpoint(dir, "remote", &ep->rsys, &ep->rserv); + return ep; +} + +void +freeendpoints(Endpoints *ep) +{ + free(ep->lsys); + free(ep->rsys); + free(ep->lserv); + free(ep->rserv); + free(ep); +} + +char* +iptomac(char *ip, char *net) +{ + char file[Maxpath]; + Biobuf *b; + char *p; + char *f[5]; + + snprint(file, sizeof(file), "%s/arp", net); + b = Bopen(file, OREAD); + if(b == nil) + return nil; + while((p = Brdline(b, '\n')) != nil){ + p[Blinelen(b)-1] = 0; + if(tokenize(p, f, nelem(f)) < 4) + continue; + if(strcmp(f[1], "OK") == 0 + && strcmp(f[2], ip) == 0){ + p = strdup(f[3]); + Bterm(b); + return p; + } + } + Bterm(b); + return nil; +} + +int +macok(char *mac) +{ + char *p; + + if(mac == nil) + return 0; + free(p = csgetvalue("/net", "ether", mac, "trampok", nil)); + return !(p == nil); +} |