Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
30
usage(void)
31
{
32
	fprint(2, "usage: trampoline [-9] [-a addr] [-m netdir] addr\n");
33
	exits("usage");
34
}
35
 
36
void
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
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
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
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 *
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
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*
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
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
}