2016-11-25 17:18:40 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
|
|
* in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <bio.h>
|
|
|
|
#include <ndb.h>
|
2016-12-01 00:09:42 +01:00
|
|
|
#include <9P2000.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
|
|
|
|
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: ip/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]);
|
|
|
|
|
2019-11-26 02:25:23 +01:00
|
|
|
sys_rfork(RFNOTEG);
|
2016-11-25 17:18:40 +01:00
|
|
|
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;
|
|
|
|
|
2019-11-26 02:25:23 +01:00
|
|
|
while((n = jehanne_read(from, buf, sizeof buf)) > 0)
|
|
|
|
if(jehanne_write(to, buf, n) < 0)
|
2016-11-25 17:18:40 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xfer9p(int from, int to)
|
|
|
|
{
|
|
|
|
uint8_t *buf;
|
|
|
|
uint32_t 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;
|
2019-11-26 02:25:23 +01:00
|
|
|
if(jehanne_write(to, buf, n) != n){
|
2016-11-25 17:18:40 +01:00
|
|
|
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);
|
2019-11-26 02:25:23 +01:00
|
|
|
fd = sys_open(buf, OREAD);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(fd >= 0){
|
2019-11-26 02:25:23 +01:00
|
|
|
n = jehanne_read(fd, buf, sizeof(buf)-1);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(n>0){
|
|
|
|
buf[n-1] = 0;
|
|
|
|
serv = strchr(buf, '!');
|
|
|
|
if(serv){
|
|
|
|
*serv++ = 0;
|
|
|
|
serv = strdup(serv);
|
|
|
|
}
|
|
|
|
sys = strdup(buf);
|
|
|
|
}
|
2019-11-26 02:25:23 +01:00
|
|
|
sys_close(fd);
|
2016-11-25 17:18:40 +01:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|