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