xref: /plan9/sys/src/cmd/ip/pptpd.c (revision ea58ad6fbee60d5a3fca57ac646881779dd8f0ea)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ip.h>
5 
6 #define	LOG	"pptpd"
7 
8 typedef struct Call	Call;
9 typedef struct Event Event;
10 
11 #define	SDB	if(debug) fprint(2,
12 #define EDB	);
13 
14 enum {
15 	Magic	= 0x1a2b3c4d,
16 	Nhash	= 17,
17 	Nchan	= 10,		/* maximum number of channels */
18 	Window	= 8,		/* default window size */
19 	Timeout	= 60,		/* timeout in seconds for control channel */
20 	Pktsize = 2000,		/* maximum packet size */
21 	Tick	= 500,		/* tick length in milliseconds */
22 	Sendtimeout = 4,	/* in ticks */
23 };
24 
25 enum {
26 	Syncframe	= 0x1,
27 	Asyncframe	= 0x2,
28 	Analog		= 0x1,
29 	Digital		= 0x2,
30 	Version		= 0x100,
31 };
32 
33 enum {
34 	Tstart		= 1,
35 	Rstart		= 2,
36 	Tstop		= 3,
37 	Rstop		= 4,
38 	Techo		= 5,
39 	Recho		= 6,
40 	Tcallout	= 7,
41 	Rcallout	= 8,
42 	Tcallreq	= 9,
43 	Rcallreq	= 10,
44 	Acallcon	= 11,
45 	Tcallclear	= 12,
46 	Acalldis	= 13,
47 	Awaninfo	= 14,
48 	Alinkinfo	= 15,
49 };
50 
51 
52 struct Event {
53 	QLock;
54 	QLock waitlk;
55 	int	wait;
56 	int ready;
57 };
58 
59 struct Call {
60 	int	ref;
61 	QLock	lk;
62 	int	id;
63 	int	serial;
64 	int	pppfd;
65 
66 	int	closed;
67 
68 	int	pac;	/* server is acting as a PAC */
69 
70 	int	recvwindow;	/* recv windows */
71 	int	sendwindow;	/* send windows */
72 	int	delay;
73 
74 	int	sendaccm;
75 	int	recvaccm;
76 
77 	uint	seq;		/* current seq number - for send */
78 	uint	ack;		/* current acked mesg - for send */
79 	uint	rseq;		/* highest recv seq number for in order packet  */
80 	uint	rack;		/* highest ack sent */
81 
82 	Event	eack;		/* recved ack - for send */
83 	ulong	tick;
84 
85 	uchar	remoteip[IPaddrlen];	/* remote ip address */
86 	int	dhcpfd[2];	/* pipe to dhcpclient */
87 
88 	/* error stats */
89 	struct {
90 		int	crc;
91 		int	frame;
92 		int	hardware;
93 		int	overrun;
94 		int	timeout;
95 		int	align;
96 	} err;
97 
98 	struct {
99 		int	send;
100 		int	sendack;
101 		int	recv;
102 		int	recvack;
103 		int	dropped;
104 		int	missing;
105 		int	sendwait;
106 		int	sendtimeout;
107 	} stat;
108 
109 	Call	*next;
110 };
111 
112 struct {
113 	QLock	lk;
114 	int	start;
115 	int	grefd;
116 	int	grecfd;
117 	uchar	local[IPaddrlen];
118 	uchar	remote[IPaddrlen];
119 	char	*tcpdir;
120 	uchar	ipaddr[IPaddrlen];		/* starting ip addresss to allocate */
121 
122 	int	recvwindow;
123 
124 	char	*pppdir;
125 	char	*pppexec;
126 
127 	double	rcvtime;	/* time at which last request was received */
128 	int	echoid;		/* id of last echo request */
129 
130 	Call	*hash[Nhash];
131 } srv;
132 
133 /* GRE flag bits */
134 enum {
135 	GRE_chksum	= (1<<15),
136 	GRE_routing	= (1<<14),
137 	GRE_key		= (1<<13),
138 	GRE_seq		= (1<<12),
139 	GRE_srcrt	= (1<<11),
140 	GRE_recur	= (7<<8),
141 	GRE_ack		= (1<<7),
142 	GRE_ver		= 0x7,
143 };
144 
145 /* GRE protocols */
146 enum {
147 	GRE_ppp		= 0x880b,
148 };
149 
150 int	debug;
151 double	drop;
152 
153 void	myfatal(char *fmt, ...);
154 
155 #define	PSHORT(p, v)		((p)[0]=((v)>>8), (p)[1]=(v))
156 #define	PLONG(p, v)		(PSHORT(p, (v)>>16), PSHORT(p+2, (v)))
157 #define	PSTRING(d,s,n)		strncpy((char*)(d), s, n)
158 #define	GSHORT(p)		(((p)[0]<<8) | ((p)[1]<<0))
159 #define	GLONG(p)		((GSHORT((p))<<16) | ((GSHORT((p)+2))<<0))
160 #define	GSTRING(d,s,n)		strncpy(d, (char*)(s), n), d[(n)-1] = 0
161 
162 void	serve(void);
163 
164 int	sstart(uchar*, int);
165 int	sstop(uchar*, int);
166 int	secho(uchar*, int);
167 int	scallout(uchar*, int);
168 int	scallreq(uchar*, int);
169 int	scallcon(uchar*, int);
170 int	scallclear(uchar*, int);
171 int	scalldis(uchar*, int);
172 int	swaninfo(uchar*, int);
173 int	slinkinfo(uchar*, int);
174 
175 Call	*callalloc(int id);
176 void	callclose(Call*);
177 void	callfree(Call*);
178 Call	*calllookup(int id);
179 
180 void	gretimeout(void*);
181 void	pppread(void*);
182 
183 void	srvinit(void);
184 void	greinit(void);
185 void	greread(void*);
186 void	greack(Call *c);
187 
188 void	timeoutthread(void*);
189 
190 int	argatoi(char *p);
191 void	usage(void);
192 int	ipaddralloc(Call *c);
193 
194 void	*emallocz(int size);
195 void	esignal(Event *e);
196 void	ewait(Event *e);
197 int	proc(char **argv, int fd0, int fd1, int fd2);
198 double	realtime(void);
199 ulong	thread(void(*f)(void*), void *a);
200 
201 void
main(int argc,char * argv[])202 main(int argc, char *argv[])
203 {
204 	ARGBEGIN{
205 	case 'd': debug++; break;
206 	case 'p': srv.pppdir = ARGF(); break;
207 	case 'P': srv.pppexec = ARGF(); break;
208 	case 'w': srv.recvwindow = argatoi(ARGF()); break;
209 	case 'D': drop = atof(ARGF()); break;
210 	default:
211 		usage();
212 	}ARGEND
213 
214 	fmtinstall('I', eipfmt);
215 	fmtinstall('E', eipfmt);
216 	fmtinstall('V', eipfmt);
217 	fmtinstall('M', eipfmt);
218 
219 	rfork(RFNOTEG|RFREND);
220 
221 	if(argc != 1)
222 		usage();
223 
224 	srv.tcpdir = argv[0];
225 
226 	srvinit();
227 
228 	syslog(0, LOG, ": src=%I: pptp started: %d", srv.remote, getpid());
229 
230 	SDB  "\n\n\n%I: pptp started\n", srv.remote EDB
231 
232 	greinit();
233 
234 	thread(timeoutthread, 0);
235 
236 	serve();
237 
238 	syslog(0, LOG, ": src=%I: server exits", srv.remote);
239 
240 	exits(0);
241 }
242 
243 void
usage(void)244 usage(void)
245 {
246 	fprint(2, "usage: pptpd [-dD] [-p ppp-net] [-w window] tcpdir\n");
247 	exits("usage");
248 }
249 
250 void
serve(void)251 serve(void)
252 {
253 	uchar buf[2000], *p;
254 	int n, n2, len;
255 	int magic;
256 	int op, type;
257 
258 	n = 0;
259 	for(;;) {
260 		n2 = read(0, buf+n, sizeof(buf)-n);
261 		if(n2 < 0)
262 			myfatal("bad read on ctl channel: %r");
263 		if(n2 == 0)
264 			break;
265 		n += n2;
266 		p = buf;
267 		for(;;) {
268 			if(n < 12)
269 				break;
270 
271 			qlock(&srv.lk);
272 			srv.rcvtime = realtime();
273 			qunlock(&srv.lk);
274 
275 			len = GSHORT(p);
276 			type = GSHORT(p+2);
277 			magic = GLONG(p+4);
278 			op = GSHORT(p+8);
279 			if(magic != Magic)
280 				myfatal("bad magic number: got %x", magic);
281 			if(type != 1)
282 				myfatal("bad message type: %d", type);
283 			switch(op) {
284 			default:
285 				myfatal("unknown control op: %d", op);
286 			case Tstart:		/* start-control-connection-request */
287 				n2 = sstart(p, n);
288 				break;
289 			case Tstop:
290 				n2 = sstop(p, n);
291 				if(n2 > 0)
292 					return;
293 				break;
294 			case Techo:
295 				n2 = secho(p, n);
296 				break;
297 			case Tcallout:
298 				n2 = scallout(p, n);
299 				break;
300 			case Tcallreq:
301 				n2 = scallreq(p, n);
302 				break;
303 			case Acallcon:
304 				n2 = scallcon(p, n);
305 				break;
306 			case Tcallclear:
307 				n2 = scallclear(p, n);
308 				break;
309 			case Acalldis:
310 				n2 = scalldis(p, n);
311 				break;
312 			case Awaninfo:
313 				n2 = swaninfo(p, n);
314 				break;
315 			case Alinkinfo:
316 				n2 = slinkinfo(p, n);
317 				break;
318 			}
319 			if(n2 == 0)
320 				break;
321 			if(n2 != len)
322 				myfatal("op=%d: bad length: got %d expected %d", op, len, n2);
323 			n -= n2;
324 			p += n2;
325 
326 		}
327 
328 		/* move down partial message */
329 		if(p != buf && n != 0)
330 			memmove(buf, p, n);
331 	}
332 
333 }
334 
335 int
sstart(uchar * p,int n)336 sstart(uchar *p, int n)
337 {
338 	int ver, frame, bearer, maxchan, firm;
339 	char host[64], vendor[64], *sysname;
340 	uchar buf[156];
341 
342 	if(n < 156)
343 		return 0;
344 	ver = GSHORT(p+12);
345 	frame = GLONG(p+16);
346 	bearer = GLONG(p+20);
347 	maxchan = GSHORT(p+24);
348 	firm = GSHORT(p+26);
349 	GSTRING(host, p+28, 64);
350 	GSTRING(vendor, p+92, 64);
351 
352 	SDB "%I: start ver = %x f = %d b = %d maxchan = %d firm = %d host = %s vendor = %s\n",
353 		srv.remote, ver, frame, bearer, maxchan, firm, host, vendor EDB
354 
355 	if(ver != Version)
356 		myfatal("bad version: got %x expected %x", ver, Version);
357 
358 	if(srv.start)
359 		myfatal("multiple start messages");
360 
361 	srv.start = 1;
362 
363 	sysname = getenv("sysname");
364 	if(sysname == 0)
365 		strcpy(host, "gnot");
366 	else
367 		strncpy(host, sysname, 64);
368 	free(sysname);
369 
370 	memset(buf, 0, sizeof(buf));
371 
372 	PSHORT(buf+0, sizeof(buf));	/* length */
373 	PSHORT(buf+2, 1);		/* message type */
374 	PLONG(buf+4, Magic);		/* magic */
375 	PSHORT(buf+8, Rstart);		/* op */
376 	PSHORT(buf+12, Version);	/* version */
377 	buf[14] = 1;			/* result = ok */
378 	PLONG(buf+16, Syncframe|Asyncframe);	/* frameing */
379 	PLONG(buf+20, Digital|Analog);	/* berear capabilities */
380 	PSHORT(buf+24, Nchan);		/* max channels */
381 	PSHORT(buf+26, 1);		/* driver version */
382 	PSTRING(buf+28, host, 64);	/* host name */
383 	PSTRING(buf+92, "plan 9", 64);	/* vendor */
384 
385 	if(write(1, buf, sizeof(buf)) < sizeof(buf))
386 		myfatal("write failed: %r");
387 
388 	return 156;
389 }
390 
391 int
sstop(uchar * p,int n)392 sstop(uchar *p, int n)
393 {
394 	int reason;
395 	uchar buf[16];
396 
397 	if(n < 16)
398 		return 0;
399 	reason = p[12];
400 
401 	SDB "%I: stop %d\n", srv.remote, reason EDB
402 
403 	memset(buf, 0, sizeof(buf));
404 	PSHORT(buf+0, sizeof(buf));	/* length */
405 	PSHORT(buf+2, 1);		/* message type */
406 	PLONG(buf+4, Magic);		/* magic */
407 	PSHORT(buf+8, Rstop);		/* op */
408 	buf[12] = 1;			/* ok */
409 
410 	if(write(1, buf, sizeof(buf)) < sizeof(buf))
411 		myfatal("write failed: %r");
412 
413 	return 16;
414 }
415 
416 int
secho(uchar * p,int n)417 secho(uchar *p, int n)
418 {
419 	int id;
420 	uchar buf[20];
421 
422 	if(n < 16)
423 		return 0;
424 	id = GLONG(p+12);
425 
426 	SDB "%I: echo %d\n", srv.remote, id EDB
427 
428 	memset(buf, 0, sizeof(buf));
429 	PSHORT(buf+0, sizeof(buf));	/* length */
430 	PSHORT(buf+2, 1);		/* message type */
431 	PLONG(buf+4, Magic);		/* magic */
432 	PSHORT(buf+8, Recho);		/* op */
433 	PLONG(buf+12, id);		/* id */
434 	p[16] = 1;			/* ok */
435 
436 	if(write(1, buf, sizeof(buf)) < sizeof(buf))
437 		myfatal("write failed: %r");
438 
439 	return 16;
440 }
441 
442 int
scallout(uchar * p,int n)443 scallout(uchar *p, int n)
444 {
445 	int id, serial;
446 	int minbps, maxbps, bearer, frame;
447 	int window, delay;
448 	int nphone;
449 	char phone[64], sub[64], buf[32];
450 	Call *c;
451 
452 	if(n < 168)
453 		return 0;
454 
455 	if(!srv.start)
456 		myfatal("%I: did not recieve start message", srv.remote);
457 
458 	id = GSHORT(p+12);
459 	serial = GSHORT(p+14);
460 	minbps = GLONG(p+16);
461 	maxbps = GLONG(p+20);
462 	bearer = GLONG(p+24);
463 	frame = GLONG(p+28);
464 	window = GSHORT(p+32);
465 	delay = GSHORT(p+34);
466 	nphone = GSHORT(p+36);
467 	GSTRING(phone, p+40, 64);
468 	GSTRING(sub, p+104, 64);
469 
470 	SDB "%I: callout id = %d serial = %d bps=[%d,%d] b=%x f=%x win = %d delay = %d np=%d phone=%s sub=%s\n",
471 		srv.remote, id, serial, minbps, maxbps, bearer, frame, window, delay, nphone, phone, sub EDB
472 
473 	c = callalloc(id);
474 	c->sendwindow = window;
475 	c->delay = delay;
476 	c->pac = 1;
477 	c->recvwindow = srv.recvwindow;
478 
479 	memset(buf, 0, sizeof(buf));
480 	PSHORT(buf+0, sizeof(buf));	/* length */
481 	PSHORT(buf+2, 1);		/* message type */
482 	PLONG(buf+4, Magic);		/* magic */
483 	PSHORT(buf+8, Rcallout);	/* op */
484 	PSHORT(buf+12, id);		/* call id */
485 	PSHORT(buf+14, id);		/* peer id */
486 	buf[16] = 1;			/* ok */
487 	PLONG(buf+20, 10000000);	/* speed */
488 	PSHORT(buf+24, c->recvwindow);	/* window size */
489 	PSHORT(buf+26, 0);		/* delay */
490 	PLONG(buf+28, 0);		/* channel id */
491 
492 	if(write(1, buf, sizeof(buf)) < sizeof(buf))
493 		myfatal("write failed: %r");
494 
495 	return 168;
496 }
497 
498 int
scallreq(uchar * p,int n)499 scallreq(uchar *p, int n)
500 {
501 	USED(p);
502 	USED(n);
503 
504 	myfatal("callreq: not done yet");
505 	return 0;
506 }
507 
508 int
scallcon(uchar * p,int n)509 scallcon(uchar *p, int n)
510 {
511 	USED(p);
512 	USED(n);
513 
514 	myfatal("callcon: not done yet");
515 	return 0;
516 }
517 
518 int
scallclear(uchar * p,int n)519 scallclear(uchar *p, int n)
520 {
521 	Call *c;
522 	int id;
523 	uchar buf[148];
524 
525 	if(n < 16)
526 		return 0;
527 	id = GSHORT(p+12);
528 
529 	SDB "%I: callclear id=%d\n", srv.remote, id EDB
530 
531 	if(c = calllookup(id)) {
532 		callclose(c);
533 		callfree(c);
534 	}
535 
536 	memset(buf, 0, sizeof(buf));
537 	PSHORT(buf+0, sizeof(buf));	/* length */
538 	PSHORT(buf+2, 1);		/* message type */
539 	PLONG(buf+4, Magic);		/* magic */
540 	PSHORT(buf+8, Acalldis);	/* op */
541 	PSHORT(buf+12, id);		/* id */
542 	buf[14] = 3;			/* reply to callclear */
543 
544 	if(write(1, buf, sizeof(buf)) < sizeof(buf))
545 		myfatal("write failed: %r");
546 
547 	return 16;
548 }
549 
550 int
scalldis(uchar * p,int n)551 scalldis(uchar *p, int n)
552 {
553 	Call *c;
554 	int id, res;
555 
556 	if(n < 148)
557 		return 0;
558 	id = GSHORT(p+12);
559 	res = p[14];
560 
561 	SDB "%I: calldis id=%d res=%d\n", srv.remote, id, res EDB
562 
563 	if(c = calllookup(id)) {
564 		callclose(c);
565 		callfree(c);
566 	}
567 
568 	return 148;
569 }
570 
571 int
swaninfo(uchar * p,int n)572 swaninfo(uchar *p, int n)
573 {
574 	Call *c;
575 	int id;
576 
577 	if(n < 40)
578 		return 0;
579 
580 	id = GSHORT(p+12);
581 	SDB "%I: waninfo id = %d\n", srv.remote, id EDB
582 
583 	c = calllookup(id);
584 	if(c != 0) {
585 		c->err.crc = GLONG(p+16);
586 		c->err.frame = GLONG(p+20);
587 		c->err.hardware = GLONG(p+24);
588 		c->err.overrun = GLONG(p+28);
589 		c->err.timeout = GLONG(p+32);
590 		c->err.align = GLONG(p+36);
591 
592 		callfree(c);
593 	}
594 
595 
596 	return 40;
597 }
598 
599 int
slinkinfo(uchar * p,int n)600 slinkinfo(uchar *p, int n)
601 {
602 	Call *c;
603 	int id;
604 	int sendaccm, recvaccm;
605 
606 	if(n < 24)
607 		return 0;
608 	id = GSHORT(p+12);
609 	sendaccm = GLONG(p+16);
610 	recvaccm = GLONG(p+20);
611 
612 	SDB "%I: linkinfo id=%d saccm=%ux raccm=%ux\n", srv.remote, id, sendaccm, recvaccm EDB
613 
614 	if(c = calllookup(id)) {
615 		c->sendaccm = sendaccm;
616 		c->recvaccm = recvaccm;
617 
618 		callfree(c);
619 	}
620 
621 	return 24;
622 }
623 
624 Call*
callalloc(int id)625 callalloc(int id)
626 {
627 	uint h;
628 	Call *c;
629 	char buf[300], *argv[30], local[20], remote[20], **p;
630 	int fd, pfd[2], n;
631 
632 	h = id%Nhash;
633 
634 	qlock(&srv.lk);
635 	for(c=srv.hash[h]; c; c=c->next)
636 		if(c->id == id)
637 			myfatal("callalloc: duplicate id: %d", id);
638 	c = emallocz(sizeof(Call));
639 	c->ref = 1;
640 	c->id = id;
641 	c->sendaccm = ~0;
642 	c->recvaccm = ~0;
643 
644 	if(!ipaddralloc(c))
645 		myfatal("callalloc: could not alloc remote ip address");
646 
647 	if(pipe(pfd) < 0)
648 		myfatal("callalloc: pipe failed: %r");
649 
650 	sprint(buf, "%s/ipifc/clone", srv.pppdir);
651 	fd = open(buf, OWRITE);
652 	if(fd < 0)
653 		myfatal("callalloc: could not open %s: %r", buf);
654 
655 	n = sprint(buf, "iprouting");
656 	if(write(fd, buf, n) < n)
657 		myfatal("callalloc: write to ifc failed: %r");
658 	close(fd);
659 
660 	p = argv;
661 	*p++ = srv.pppexec;
662 	*p++ = "-SC";
663 	*p++ = "-x";
664 	*p++ = srv.pppdir;
665 	if(debug)
666 		*p++ = "-d";
667 	sprint(local, "%I", srv.ipaddr);
668 	*p++ = local;
669 	sprint(remote, "%I", c->remoteip);
670 	*p++ = remote;
671 	*p = 0;
672 
673 	proc(argv, pfd[0], pfd[0], 2);
674 
675 	close(pfd[0]);
676 
677 	c->pppfd = pfd[1];
678 
679 	c->next = srv.hash[h];
680 	srv.hash[h] = c;
681 
682 	qunlock(&srv.lk);
683 
684 	c->ref++;
685 	thread(pppread, c);
686 	c->ref++;
687 	thread(gretimeout, c);
688 
689 	syslog(0, LOG, ": src=%I: call started: id=%d: remote ip=%I", srv.remote, id, c->remoteip);
690 
691 	return c;
692 }
693 
694 void
callclose(Call * c)695 callclose(Call *c)
696 {
697 	Call *oc;
698 	int id;
699 	uint h;
700 
701 	syslog(0, LOG, ": src=%I: call closed: id=%d: send=%d sendack=%d recv=%d recvack=%d dropped=%d missing=%d sendwait=%d sendtimeout=%d",
702 		srv.remote, c->id, c->stat.send, c->stat.sendack, c->stat.recv, c->stat.recvack,
703 		c->stat.dropped, c->stat.missing, c->stat.sendwait, c->stat.sendtimeout);
704 
705 	qlock(&srv.lk);
706 	if(c->closed) {
707 		qunlock(&srv.lk);
708 		return;
709 	}
710 	c->closed = 1;
711 
712 	close(c->dhcpfd[0]);
713 	close(c->dhcpfd[1]);
714 	close(c->pppfd);
715 	c->pppfd = -1;
716 
717 	h = c->id%Nhash;
718 	id = c->id;
719 	for(c=srv.hash[h],oc=0; c; oc=c,c=c->next)
720 		if(c->id == id)
721 			break;
722 	if(oc == 0)
723 		srv.hash[h] = c->next;
724 	else
725 		oc->next = c->next;
726 	c->next = 0;
727 	qunlock(&srv.lk);
728 
729 	callfree(c);
730 }
731 
732 void
callfree(Call * c)733 callfree(Call *c)
734 {
735 	int ref;
736 
737 	qlock(&srv.lk);
738 	ref = --c->ref;
739 	qunlock(&srv.lk);
740 	if(ref > 0)
741 		return;
742 
743 	/* already unhooked from hash list - see callclose */
744 	assert(c->closed == 1);
745 	assert(ref == 0);
746 	assert(c->next == 0);
747 
748 SDB "call free\n" EDB
749 	free(c);
750 }
751 
752 Call*
calllookup(int id)753 calllookup(int id)
754 {
755 	uint h;
756 	Call *c;
757 
758 	h = id%Nhash;
759 
760 	qlock(&srv.lk);
761 	for(c=srv.hash[h]; c; c=c->next)
762 		if(c->id == id)
763 			break;
764 	if(c != 0)
765 		c->ref++;
766 	qunlock(&srv.lk);
767 
768 	return c;
769 }
770 
771 
772 void
srvinit(void)773 srvinit(void)
774 {
775 	char buf[100];
776 	int fd, n;
777 
778 	sprint(buf, "%s/local", srv.tcpdir);
779 	if((fd = open(buf, OREAD)) < 0)
780 		myfatal("could not open %s: %r", buf);
781 	if((n = read(fd, buf, sizeof(buf))) < 0)
782 		myfatal("could not read %s: %r", buf);
783 	buf[n] = 0;
784 	parseip(srv.local, buf);
785 	close(fd);
786 
787 	sprint(buf, "%s/remote", srv.tcpdir);
788 	if((fd = open(buf, OREAD)) < 0)
789 		myfatal("could not open %s: %r", buf);
790 	if((n = read(fd, buf, sizeof(buf))) < 0)
791 		myfatal("could not read %s: %r", buf);
792 	buf[n] = 0;
793 	parseip(srv.remote, buf);
794 	close(fd);
795 
796 	if(srv.pppdir == 0)
797 		srv.pppdir = "/net";
798 
799 	if(srv.pppexec == 0)
800 		srv.pppexec = "/bin/ip/ppp";
801 
802 	if(myipaddr(srv.ipaddr, srv.pppdir) < 0)
803 		myfatal("could not read local ip addr: %r");
804 	if(srv.recvwindow == 0)
805 		srv.recvwindow = Window;
806 }
807 
808 void
greinit(void)809 greinit(void)
810 {
811 	char addr[100], *p;
812 	int fd, cfd;
813 
814 	SDB "srv.tcpdir = %s\n", srv.tcpdir EDB
815 	strcpy(addr, srv.tcpdir);
816 	p = strrchr(addr, '/');
817 	if(p == 0)
818 		myfatal("bad tcp dir: %s", srv.tcpdir);
819 	*p = 0;
820 	p = strrchr(addr, '/');
821 	if(p == 0)
822 		myfatal("bad tcp dir: %s", srv.tcpdir);
823 	sprint(p, "/gre!%I!34827", srv.remote);
824 
825 	SDB "addr = %s\n", addr EDB
826 
827 	fd = dial(addr, 0, 0, &cfd);
828 
829 	if(fd < 0)
830 		myfatal("%I: dial %s failed: %r", srv.remote, addr);
831 
832 	srv.grefd = fd;
833 	srv.grecfd = cfd;
834 
835 	thread(greread, 0);
836 }
837 
838 void
greread(void *)839 greread(void *)
840 {
841 	uchar buf[Pktsize], *p;
842 	int n, i;
843 	int flag, prot, len, callid;
844 	uchar src[IPaddrlen], dst[IPaddrlen];
845 	uint rseq, ack;
846 	Call *c;
847 	static double t, last;
848 
849 	for(;;) {
850 		n = read(srv.grefd, buf, sizeof(buf));
851 		if(n < 0)
852 			myfatal("%I: bad read on gre: %r", srv.remote);
853 		if(n == sizeof(buf))
854 			myfatal("%I: gre read: buf too small", srv.remote);
855 
856 		p = buf;
857 		v4tov6(src, p);
858 		v4tov6(dst, p+4);
859 		flag = GSHORT(p+8);
860 		prot = GSHORT(p+10);
861 		p += 12; n -= 12;
862 
863 		if(ipcmp(src, srv.remote) != 0 || ipcmp(dst, srv.local) != 0)
864 			myfatal("%I: gre read bad address src=%I dst=%I", srv.remote, src, dst);
865 
866 		if(prot != GRE_ppp)
867 			myfatal("%I: gre read gave bad protocol", srv.remote);
868 
869 		if(flag & (GRE_chksum|GRE_routing)){
870 			p += 4; n -= 4;
871 		}
872 
873 		if(!(flag&GRE_key))
874 			myfatal("%I: gre packet does not contain a key: f=%ux",
875 				srv.remote, flag);
876 
877 		len = GSHORT(p);
878 		callid = GSHORT(p+2);
879 		p += 4; n -= 4;
880 
881 		c = calllookup(callid);
882 		if(c == 0) {
883 			SDB "%I: unknown callid: %d\n", srv.remote, callid EDB
884 			continue;
885 		}
886 
887 		qlock(&c->lk);
888 
889 		c->stat.recv++;
890 
891 		if(flag&GRE_seq) {
892 			rseq = GLONG(p);
893 			p += 4; n -= 4;
894 		} else
895 			rseq = c->rseq;
896 
897 		if(flag&GRE_ack){
898 			ack = GLONG(p);
899 			p += 4; n -= 4;
900 		} else
901 			ack = c->ack;
902 
903 		/* skip routing if present */
904 		if(flag&GRE_routing) {
905 			while((i=p[3]) != 0) {
906 				n -= i;
907 				p += i;
908 			}
909 		}
910 
911 		if(len > n)
912 			myfatal("%I: bad len in gre packet", srv.remote);
913 
914 		if((int)(ack-c->ack) > 0) {
915 			c->ack = ack;
916 			esignal(&c->eack);
917 		}
918 
919 		if(debug)
920 			t = realtime();
921 
922 		if(len == 0) {
923 			/* ack packet */
924 			c->stat.recvack++;
925 
926 SDB "%I: %.3f (%.3f): gre %d: recv ack a=%ux n=%d flag=%ux\n", srv.remote, t, t-last,
927 	c->id, ack, n, flag EDB
928 
929 		} else {
930 
931 SDB "%I: %.3f (%.3f): gre %d: recv s=%ux a=%ux len=%d\n", srv.remote, t, t-last,
932 	c->id, rseq, ack, len EDB
933 
934 			/*
935 			 * the following handles the case of a single pair of packets
936 			 * received out of order
937 			 */
938 			n = rseq-c->rseq;
939 			if(n > 0 && (drop == 0. || frand() > drop)) {
940 				c->stat.missing += n-1;
941 				/* current packet */
942 				write(c->pppfd, p, len);
943 			} else {
944 				/* out of sequence - drop on the floor */
945 				c->stat.dropped++;
946 
947 SDB "%I: %.3f: gre %d: recv out of order or dup packet: seq=%ux len=%d\n",
948 srv.remote, realtime(), c->id, rseq, len EDB
949 
950 			}
951 		}
952 
953 		if((int)(rseq-c->rseq) > 0)
954 			c->rseq = rseq;
955 
956 		if(debug)
957 			last=t;
958 
959 		/* open up client window */
960 		if((int)(c->rseq-c->rack) > (c->recvwindow>>1))
961 			greack(c);
962 
963 		qunlock(&c->lk);
964 
965 
966 		callfree(c);
967 	}
968 }
969 
970 void
greack(Call * c)971 greack(Call *c)
972 {
973 	uchar buf[20];
974 
975 	c->stat.sendack++;
976 
977 SDB "%I: %.3f: gre %d: send ack %ux\n", srv.remote, realtime(), c->id, c->rseq EDB
978 
979 	v6tov4(buf+0, srv.local);		/* source */
980 	v6tov4(buf+4, srv.remote);		/* source */
981 	PSHORT(buf+8, GRE_key|GRE_ack|1);
982 	PSHORT(buf+10, GRE_ppp);
983 	PSHORT(buf+12, 0);
984 	PSHORT(buf+14, c->id);
985 	PLONG(buf+16, c->rseq);
986 
987 	write(srv.grefd, buf, sizeof(buf));
988 
989 	c->rack = c->rseq;
990 
991 }
992 
993 void
gretimeout(void * a)994 gretimeout(void *a)
995 {
996 	Call *c;
997 
998 	c = a;
999 
1000 	while(!c->closed) {
1001 		sleep(Tick);
1002 		qlock(&c->lk);
1003 		c->tick++;
1004 		qunlock(&c->lk);
1005 		esignal(&c->eack);
1006 	}
1007 	callfree(c);
1008 	exits(0);
1009 }
1010 
1011 
1012 void
pppread(void * a)1013 pppread(void *a)
1014 {
1015 	Call *c;
1016 	uchar buf[2000], *p;
1017 	int n;
1018 	ulong tick;
1019 
1020 	c = a;
1021 	for(;;) {
1022 		p = buf+24;
1023 		n = read(c->pppfd, p, sizeof(buf)-24);
1024 		if(n <= 0)
1025 			break;
1026 
1027 		qlock(&c->lk);
1028 
1029 		/* add gre header */
1030 		c->seq++;
1031 		tick = c->tick;
1032 
1033 		while(c->seq-c->ack>c->sendwindow && c->tick-tick<Sendtimeout && !c->closed) {
1034 			c->stat.sendwait++;
1035 SDB "window full seq = %d ack = %ux window = %ux\n", c->seq, c->ack, c->sendwindow EDB
1036 			qunlock(&c->lk);
1037 			ewait(&c->eack);
1038 			qlock(&c->lk);
1039 		}
1040 
1041 		if(c->tick-tick >= Sendtimeout) {
1042 			c->stat.sendtimeout++;
1043 SDB "send timeout = %d ack = %ux window = %ux\n", c->seq, c->ack, c->sendwindow EDB
1044 		}
1045 
1046 		v6tov4(buf+0, srv.local);		/* source */
1047 		v6tov4(buf+4, srv.remote);		/* source */
1048 		PSHORT(buf+8, GRE_key|GRE_seq|GRE_ack|1);
1049 		PSHORT(buf+10, GRE_ppp);
1050 		PSHORT(buf+12, n);
1051 		PSHORT(buf+14, c->id);
1052 		PLONG(buf+16, c->seq);
1053 		PLONG(buf+20, c->rseq);
1054 
1055 		c->stat.send++;
1056 		c->rack = c->rseq;
1057 
1058 SDB "%I: %.3f: gre %d: send s=%ux a=%ux len=%d\n", srv.remote, realtime(),
1059 	c->id,  c->seq, c->rseq, n EDB
1060 
1061 		if(drop == 0. || frand() > drop)
1062 			if(write(srv.grefd, buf, n+24)<n+24)
1063 				myfatal("pppread: write failed: %r");
1064 
1065 		qunlock(&c->lk);
1066 	}
1067 
1068 	SDB "pppread exit: %d\n", c->id);
1069 
1070 	callfree(c);
1071 	exits(0);
1072 }
1073 
1074 void
timeoutthread(void *)1075 timeoutthread(void*)
1076 {
1077 	for(;;) {
1078 		sleep(30*1000);
1079 
1080 		qlock(&srv.lk);
1081 		if(realtime() - srv.rcvtime > 5*60)
1082 			myfatal("server timedout");
1083 		qunlock(&srv.lk);
1084 	}
1085 }
1086 
1087 
1088 /* use syslog() rather than fprint(2, ...) */
1089 void
myfatal(char * fmt,...)1090 myfatal(char *fmt, ...)
1091 {
1092 	char sbuf[512];
1093 	va_list arg;
1094 	uchar buf[16];
1095 
1096 	/* NT don't seem to like us just going away */
1097 	memset(buf, 0, sizeof(buf));
1098 	PSHORT(buf+0, sizeof(buf));	/* length */
1099 	PSHORT(buf+2, 1);		/* message type */
1100 	PLONG(buf+4, Magic);		/* magic */
1101 	PSHORT(buf+8, Tstop);		/* op */
1102 	buf[12] = 3;			/* local shutdown */
1103 
1104 	write(1, buf, sizeof(buf));
1105 
1106 	va_start(arg, fmt);
1107 	vseprint(sbuf, sbuf+sizeof(sbuf), fmt, arg);
1108 	va_end(arg);
1109 
1110 	SDB "%I: fatal: %s\n", srv.remote, sbuf EDB
1111 	syslog(0, LOG, ": src=%I: fatal: %s", srv.remote, sbuf);
1112 
1113 	close(0);
1114 	close(1);
1115 	close(srv.grefd);
1116 	close(srv.grecfd);
1117 
1118 	postnote(PNGROUP, getpid(), "die");
1119 	exits(sbuf);
1120 }
1121 
1122 int
argatoi(char * p)1123 argatoi(char *p)
1124 {
1125 	char *q;
1126 	int i;
1127 
1128 	if(p == 0)
1129 		usage();
1130 
1131 	i = strtol(p, &q, 0);
1132 	if(q == p)
1133 		usage();
1134 	return i;
1135 }
1136 
1137 void
dhcpclientwatch(void * a)1138 dhcpclientwatch(void *a)
1139 {
1140 	Call *c = a;
1141 	uchar buf[1];
1142 
1143 	for(;;) {
1144 		if(read(c->dhcpfd[0], buf, sizeof(buf)) <= 0)
1145 			break;
1146 	}
1147 	if(!c->closed)
1148 		myfatal("dhcpclient terminated");
1149 	callfree(c);
1150 	exits(0);
1151 }
1152 
1153 int
ipaddralloc(Call * c)1154 ipaddralloc(Call *c)
1155 {
1156 	int pfd[2][2];
1157 	char *argv[4], *p;
1158 	Biobuf bio;
1159 
1160 	argv[0] = "/bin/ip/dhcpclient";
1161 	argv[1] = "-x";
1162 	argv[2] = srv.pppdir;
1163 	argv[3] = 0;
1164 
1165 	if(pipe(pfd[0])<0)
1166 		myfatal("ipaddralloc: pipe failed: %r");
1167 	if(pipe(pfd[1])<0)
1168 		myfatal("ipaddralloc: pipe failed: %r");
1169 
1170 	if(proc(argv, pfd[0][0], pfd[1][1], 2) < 0)
1171 		myfatal("ipaddralloc: proc failed: %r");
1172 
1173 	close(pfd[0][0]);
1174 	close(pfd[1][1]);
1175 	c->dhcpfd[0] = pfd[1][0];
1176 	c->dhcpfd[1] = pfd[0][1];
1177 
1178 	Binit(&bio, pfd[1][0], OREAD);
1179 	for(;;) {
1180 		p = Brdline(&bio, '\n');
1181 		if(p == 0)
1182 			break;
1183 		if(strncmp(p, "ip=", 3) == 0) {
1184 			p += 3;
1185 			parseip(c->remoteip, p);
1186 		} else if(strncmp(p, "end\n", 4) == 0)
1187 			break;
1188 	}
1189 
1190 	Bterm(&bio);
1191 
1192 	c->ref++;
1193 
1194 	thread(dhcpclientwatch, c);
1195 
1196 	return ipcmp(c->remoteip, IPnoaddr) != 0;
1197 }
1198 
1199 
1200 void
esignal(Event * e)1201 esignal(Event *e)
1202 {
1203 	qlock(e);
1204 	if(e->wait == 0) {
1205 		e->ready = 1;
1206 		qunlock(e);
1207 		return;
1208 	}
1209 	assert(e->ready == 0);
1210 	e->wait = 0;
1211 	rendezvous(e, (void*)1);
1212 	qunlock(e);
1213 }
1214 
1215 void
ewait(Event * e)1216 ewait(Event *e)
1217 {
1218 	qlock(&e->waitlk);
1219 	qlock(e);
1220 	assert(e->wait == 0);
1221 	if(e->ready) {
1222 		e->ready = 0;
1223 	} else {
1224 		e->wait = 1;
1225 		qunlock(e);
1226 		rendezvous(e, (void*)2);
1227 		qlock(e);
1228 	}
1229 	qunlock(e);
1230 	qunlock(&e->waitlk);
1231 }
1232 
1233 ulong
thread(void (* f)(void *),void * a)1234 thread(void(*f)(void*), void *a)
1235 {
1236 	int pid;
1237 	pid=rfork(RFNOWAIT|RFMEM|RFPROC);
1238 	if(pid < 0)
1239 		myfatal("rfork failed: %r");
1240 	if(pid != 0)
1241 		return pid;
1242 	(*f)(a);
1243 	return 0; // never reaches here
1244 }
1245 
1246 double
realtime(void)1247 realtime(void)
1248 {
1249 	long times(long*);
1250 
1251 	return times(0) / 1000.0;
1252 }
1253 
1254 void *
emallocz(int size)1255 emallocz(int size)
1256 {
1257 	void *p;
1258 	p = malloc(size);
1259 	if(p == 0)
1260 		myfatal("malloc failed: %r");
1261 	memset(p, 0, size);
1262 	return p;
1263 }
1264 
1265 static void
fdclose(void)1266 fdclose(void)
1267 {
1268 	int fd, n, i;
1269 	Dir *d, *p;
1270 
1271 	if((fd = open("#d", OREAD)) < 0)
1272 		return;
1273 
1274 	n = dirreadall(fd, &d);
1275 	for(p = d; n > 0; n--, p++) {
1276 		i = atoi(p->name);
1277 		if(i > 2)
1278 			close(i);
1279 	}
1280 	free(d);
1281 }
1282 
1283 int
proc(char ** argv,int fd0,int fd1,int fd2)1284 proc(char **argv, int fd0, int fd1, int fd2)
1285 {
1286 	int r, flag;
1287 	char *arg0, file[200];
1288 
1289 	arg0 = argv[0];
1290 
1291 	strcpy(file, arg0);
1292 
1293 	if(access(file, 1) < 0) {
1294 		if(strncmp(arg0, "/", 1)==0
1295 		|| strncmp(arg0, "#", 1)==0
1296 		|| strncmp(arg0, "./", 2)==0
1297 		|| strncmp(arg0, "../", 3)==0)
1298 			return 0;
1299 		sprint(file, "/bin/%s", arg0);
1300 		if(access(file, 1) < 0)
1301 			return 0;
1302 	}
1303 
1304 	flag = RFPROC|RFFDG|RFENVG|RFNOWAIT;
1305 	if((r = rfork(flag)) != 0) {
1306 		if(r < 0)
1307 			return 0;
1308 		return r;
1309 	}
1310 
1311 	if(fd0 != 0) {
1312 		if(fd1 == 0)
1313 			fd1 = dup(0, -1);
1314 		if(fd2 == 0)
1315 			fd2 = dup(0, -1);
1316 		close(0);
1317 		if(fd0 >= 0)
1318 			dup(fd0, 0);
1319 	}
1320 
1321 	if(fd1 != 1) {
1322 		if(fd2 == 1)
1323 			fd2 = dup(1, -1);
1324 		close(1);
1325 		if(fd1 >= 0)
1326 			dup(fd1, 1);
1327 	}
1328 
1329 	if(fd2 != 2) {
1330 		close(2);
1331 		if(fd2 >= 0)
1332 			dup(fd2, 2);
1333 	}
1334 
1335 	fdclose();
1336 
1337 	exec(file, argv);
1338 	myfatal("proc: exec failed: %r");
1339 	return 0;
1340 }
1341 
1342