xref: /plan9/sys/src/cmd/aux/trampoline.c (revision 5741f218aafa73850887bbdc807950a4a496c955)
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