19a747e4fSDavid du Colombier /*
29a747e4fSDavid du Colombier * Point-to-point Tunneling Protocol (PPTP)
39a747e4fSDavid du Colombier * See RFC 2637, pptpd.c
49a747e4fSDavid du Colombier */
59a747e4fSDavid du Colombier
69a747e4fSDavid du Colombier #include <u.h>
79a747e4fSDavid du Colombier #include <libc.h>
89a747e4fSDavid du Colombier #include <bio.h>
99a747e4fSDavid du Colombier #include <ip.h>
109a747e4fSDavid du Colombier #include <thread.h>
119a747e4fSDavid du Colombier
129a747e4fSDavid du Colombier int ack;
139a747e4fSDavid du Colombier int alarmed;
149a747e4fSDavid du Colombier int ctlechotime;
159a747e4fSDavid du Colombier int ctlfd;
169a747e4fSDavid du Colombier int ctlrcvtime;
179a747e4fSDavid du Colombier int debug;
189a747e4fSDavid du Colombier int grefd;
199a747e4fSDavid du Colombier uchar localip[IPaddrlen];
209a747e4fSDavid du Colombier int localwin;
21bedadc12SDavid du Colombier char *keyspec;
229a747e4fSDavid du Colombier int now;
239a747e4fSDavid du Colombier char *pppnetmntpt;
249a747e4fSDavid du Colombier int pid;
259a747e4fSDavid du Colombier Channel *pidchan;
269a747e4fSDavid du Colombier int pppfd;
279a747e4fSDavid du Colombier int primary;
289a747e4fSDavid du Colombier int rack;
299a747e4fSDavid du Colombier Channel *rdchan;
309a747e4fSDavid du Colombier int rdexpect;
319a747e4fSDavid du Colombier int remid;
329a747e4fSDavid du Colombier uchar remoteip[IPaddrlen];
339a747e4fSDavid du Colombier int remwin;
349a747e4fSDavid du Colombier int rseq;
359a747e4fSDavid du Colombier int seq;
369a747e4fSDavid du Colombier char tcpdir[40];
379a747e4fSDavid du Colombier Channel *tickchan;
389a747e4fSDavid du Colombier int topppfd;
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier int aread(int, int, void*, int);
419a747e4fSDavid du Colombier int catchalarm(void*, char*);
429a747e4fSDavid du Colombier void dumpctlpkt(uchar*);
439a747e4fSDavid du Colombier void getaddrs(void);
449a747e4fSDavid du Colombier void *emalloc(long);
459a747e4fSDavid du Colombier void ewrite(int, void*, int);
469a747e4fSDavid du Colombier void myfatal(char*, ...);
479a747e4fSDavid du Colombier #pragma varargck argpos myfatal 1
489a747e4fSDavid du Colombier int pptp(char*);
499a747e4fSDavid du Colombier void pushppp(int);
509a747e4fSDavid du Colombier void recordack(int);
519a747e4fSDavid du Colombier int schedack(int, uchar*, int);
529a747e4fSDavid du Colombier void waitacks(void);
539a747e4fSDavid du Colombier
549a747e4fSDavid du Colombier void
usage(void)559a747e4fSDavid du Colombier usage(void)
569a747e4fSDavid du Colombier {
57*912e5f54SDavid du Colombier fprint(2, "usage: ip/pptp [-Pd] [-k keyspec] [-x pppnetmntpt] [-w window] server\n");
589a747e4fSDavid du Colombier exits("usage");
599a747e4fSDavid du Colombier }
609a747e4fSDavid du Colombier
619a747e4fSDavid du Colombier void
threadmain(int argc,char ** argv)629a747e4fSDavid du Colombier threadmain(int argc, char **argv)
639a747e4fSDavid du Colombier {
649a747e4fSDavid du Colombier int fd;
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier ARGBEGIN{
679a747e4fSDavid du Colombier case 'P':
689a747e4fSDavid du Colombier primary = 1;
699a747e4fSDavid du Colombier break;
709a747e4fSDavid du Colombier case 'd':
719a747e4fSDavid du Colombier debug++;
729a747e4fSDavid du Colombier break;
73bedadc12SDavid du Colombier case 'k':
74bedadc12SDavid du Colombier keyspec = EARGF(usage());
759a747e4fSDavid du Colombier break;
769a747e4fSDavid du Colombier case 'w':
779a747e4fSDavid du Colombier localwin = atoi(EARGF(usage()));
789a747e4fSDavid du Colombier break;
799a747e4fSDavid du Colombier case 'x':
809a747e4fSDavid du Colombier pppnetmntpt = EARGF(usage());
819a747e4fSDavid du Colombier break;
829a747e4fSDavid du Colombier default:
839a747e4fSDavid du Colombier usage();
849a747e4fSDavid du Colombier }ARGEND
859a747e4fSDavid du Colombier
869a747e4fSDavid du Colombier if(argc != 1)
879a747e4fSDavid du Colombier usage();
889a747e4fSDavid du Colombier
899a747e4fSDavid du Colombier fmtinstall('E', eipfmt);
909a747e4fSDavid du Colombier fmtinstall('I', eipfmt);
919a747e4fSDavid du Colombier
929a747e4fSDavid du Colombier rfork(RFNOTEG);
939a747e4fSDavid du Colombier atnotify(catchalarm, 1);
949a747e4fSDavid du Colombier fd = pptp(argv[0]);
959a747e4fSDavid du Colombier pushppp(fd);
969a747e4fSDavid du Colombier exits(nil);
979a747e4fSDavid du Colombier }
989a747e4fSDavid du Colombier
999a747e4fSDavid du Colombier int
catchalarm(void * a,char * msg)1009a747e4fSDavid du Colombier catchalarm(void *a, char *msg)
1019a747e4fSDavid du Colombier {
1029a747e4fSDavid du Colombier USED(a);
1039a747e4fSDavid du Colombier
1049a747e4fSDavid du Colombier if(strstr(msg, "alarm")){
1059a747e4fSDavid du Colombier alarmed = 1;
1069a747e4fSDavid du Colombier return 1;
1079a747e4fSDavid du Colombier }
1089a747e4fSDavid du Colombier if(debug)
1099a747e4fSDavid du Colombier fprint(2, "note rcved: %s\n", msg);
1109a747e4fSDavid du Colombier return 0;
1119a747e4fSDavid du Colombier }
1129a747e4fSDavid du Colombier
1139a747e4fSDavid du Colombier enum {
1149a747e4fSDavid du Colombier Stack = 8192,
1159a747e4fSDavid du Colombier
1169a747e4fSDavid du Colombier PptpProto = 0x0100,
1179a747e4fSDavid du Colombier
1189a747e4fSDavid du Colombier Magic = 0x1a2b3c4d,
1199a747e4fSDavid du Colombier Window = 16, /* default window size */
1209a747e4fSDavid du Colombier Timeout = 60, /* timeout in seconds for control channel */
1219a747e4fSDavid du Colombier Pktsize = 2000, /* maximum packet size */
1229a747e4fSDavid du Colombier Tick = 500, /* tick length in milliseconds */
1239a747e4fSDavid du Colombier Sendtimeout = 4, /* in ticks */
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier Servertimeout = 5*60*1000/Tick,
1269a747e4fSDavid du Colombier Echointerval = 60*1000/Tick,
1279a747e4fSDavid du Colombier };
1289a747e4fSDavid du Colombier
1299a747e4fSDavid du Colombier enum {
1309a747e4fSDavid du Colombier Syncframe = 0x1,
1319a747e4fSDavid du Colombier Asyncframe = 0x2,
1329a747e4fSDavid du Colombier Analog = 0x1,
1339a747e4fSDavid du Colombier Digital = 0x2,
1349a747e4fSDavid du Colombier Version = 0x100,
1359a747e4fSDavid du Colombier };
1369a747e4fSDavid du Colombier
1379a747e4fSDavid du Colombier enum {
1389a747e4fSDavid du Colombier Tstart = 1,
1399a747e4fSDavid du Colombier Rstart = 2,
1409a747e4fSDavid du Colombier Tstop = 3,
1419a747e4fSDavid du Colombier Rstop = 4,
1429a747e4fSDavid du Colombier Techo = 5,
1439a747e4fSDavid du Colombier Recho = 6,
1449a747e4fSDavid du Colombier Tcallout = 7,
1459a747e4fSDavid du Colombier Rcallout = 8,
1469a747e4fSDavid du Colombier Tcallreq = 9,
1479a747e4fSDavid du Colombier Rcallreq = 10,
1489a747e4fSDavid du Colombier Acallcon = 11,
1499a747e4fSDavid du Colombier Tcallclear = 12,
1509a747e4fSDavid du Colombier Acalldis = 13,
1519a747e4fSDavid du Colombier Awaninfo = 14,
1529a747e4fSDavid du Colombier Alinkinfo = 15,
1539a747e4fSDavid du Colombier };
1549a747e4fSDavid du Colombier
1559a747e4fSDavid du Colombier void
recho(uchar * in)1569a747e4fSDavid du Colombier recho(uchar *in)
1579a747e4fSDavid du Colombier {
1589a747e4fSDavid du Colombier uchar out[20];
1599a747e4fSDavid du Colombier
1609a747e4fSDavid du Colombier if(nhgets(in) < 16)
1619a747e4fSDavid du Colombier return;
1629a747e4fSDavid du Colombier
1639a747e4fSDavid du Colombier memset(out, 0, sizeof out);
1649a747e4fSDavid du Colombier hnputs(out, sizeof out);
1659a747e4fSDavid du Colombier hnputs(out+2, 1);
1669a747e4fSDavid du Colombier hnputl(out+4, Magic);
1679a747e4fSDavid du Colombier hnputs(out+8, Recho);
1689a747e4fSDavid du Colombier memmove(out+12, in+12, 4);
1699a747e4fSDavid du Colombier out[16] = 1;
1709a747e4fSDavid du Colombier
1719a747e4fSDavid du Colombier ewrite(ctlfd, out, sizeof out);
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier
1749a747e4fSDavid du Colombier void
sendecho(void)1759a747e4fSDavid du Colombier sendecho(void)
1769a747e4fSDavid du Colombier {
1779a747e4fSDavid du Colombier uchar out[16];
1789a747e4fSDavid du Colombier
1799a747e4fSDavid du Colombier ctlechotime = now;
1809a747e4fSDavid du Colombier memset(out, 0, sizeof out);
1819a747e4fSDavid du Colombier hnputs(out, sizeof out);
1829a747e4fSDavid du Colombier hnputs(out+2, 1);
1839a747e4fSDavid du Colombier hnputl(out+4, Magic);
1849a747e4fSDavid du Colombier hnputs(out+8, Techo);
1859a747e4fSDavid du Colombier
1869a747e4fSDavid du Colombier ewrite(ctlfd, out, sizeof out);
1879a747e4fSDavid du Colombier }
1889a747e4fSDavid du Colombier
1899a747e4fSDavid du Colombier void
pptpctlproc(void *)1909a747e4fSDavid du Colombier pptpctlproc(void*)
1919a747e4fSDavid du Colombier {
1929a747e4fSDavid du Colombier uchar pkt[1600], *p;
1939a747e4fSDavid du Colombier int len;
1949a747e4fSDavid du Colombier
1959a747e4fSDavid du Colombier for(;;){
1969a747e4fSDavid du Colombier if(readn(ctlfd, pkt, 2) != 2)
1979a747e4fSDavid du Colombier myfatal("pptpread: %r");
1989a747e4fSDavid du Colombier len = nhgets(pkt);
199439478acSDavid du Colombier if(len < 12 || len+2 >= sizeof pkt)
2009a747e4fSDavid du Colombier myfatal("pptpread: bad length %d", len);
2019a747e4fSDavid du Colombier if(readn(ctlfd, pkt+2, len-2) != len-2)
2029a747e4fSDavid du Colombier myfatal("pptpread: %r");
2039a747e4fSDavid du Colombier if(nhgetl(pkt+4) != Magic)
2049a747e4fSDavid du Colombier myfatal("pptpread bad magic");
2059a747e4fSDavid du Colombier if(nhgets(pkt+2) != 1)
2069a747e4fSDavid du Colombier myfatal("pptpread bad message type");
2079a747e4fSDavid du Colombier if(debug)
2089a747e4fSDavid du Colombier dumpctlpkt(pkt);
2099a747e4fSDavid du Colombier ctlrcvtime = now;
2109a747e4fSDavid du Colombier
2119a747e4fSDavid du Colombier switch(nhgets(pkt+8)){
2129a747e4fSDavid du Colombier case Tstart:
2139a747e4fSDavid du Colombier case Tstop:
2149a747e4fSDavid du Colombier case Tcallout:
2159a747e4fSDavid du Colombier case Tcallreq:
2169a747e4fSDavid du Colombier case Tcallclear:
2179a747e4fSDavid du Colombier case Acallcon:
2189a747e4fSDavid du Colombier case Acalldis:
2199a747e4fSDavid du Colombier case Awaninfo:
2209a747e4fSDavid du Colombier myfatal("unexpected msg type %d", nhgets(pkt+8));
2219a747e4fSDavid du Colombier case Techo:
2229a747e4fSDavid du Colombier recho(pkt);
2239a747e4fSDavid du Colombier break;
2249a747e4fSDavid du Colombier case Recho:
2259a747e4fSDavid du Colombier break;
2269a747e4fSDavid du Colombier case Rstart:
2279a747e4fSDavid du Colombier case Rstop:
2289a747e4fSDavid du Colombier case Rcallout:
2299a747e4fSDavid du Colombier case Rcallreq:
2309a747e4fSDavid du Colombier if(rdexpect != nhgets(pkt+8))
2319a747e4fSDavid du Colombier continue;
2329a747e4fSDavid du Colombier p = emalloc(len);
2339a747e4fSDavid du Colombier memmove(p, pkt, len);
2349a747e4fSDavid du Colombier sendp(rdchan, p);
2359a747e4fSDavid du Colombier break;
2369a747e4fSDavid du Colombier case Alinkinfo:
2379a747e4fSDavid du Colombier myfatal("cannot change ppp params on the fly");
2389a747e4fSDavid du Colombier }
2399a747e4fSDavid du Colombier }
2409a747e4fSDavid du Colombier }
2419a747e4fSDavid du Colombier
2429a747e4fSDavid du Colombier enum {
2439a747e4fSDavid du Colombier Seqnum = 0x1000,
2449a747e4fSDavid du Colombier Acknum = 0x0080,
2459a747e4fSDavid du Colombier
2469a747e4fSDavid du Colombier GrePPP = 0x880B,
2479a747e4fSDavid du Colombier };
2489a747e4fSDavid du Colombier
2499a747e4fSDavid du Colombier void
grereadproc(void *)2509a747e4fSDavid du Colombier grereadproc(void*)
2519a747e4fSDavid du Colombier {
2529a747e4fSDavid du Colombier int datoff, flags, len, n, pass;
2539a747e4fSDavid du Colombier uchar pkt[1600];
2549a747e4fSDavid du Colombier uchar src[IPaddrlen], dst[IPaddrlen];
2559a747e4fSDavid du Colombier
2569a747e4fSDavid du Colombier rfork(RFFDG);
2579a747e4fSDavid du Colombier close(pppfd);
2589a747e4fSDavid du Colombier sendul(pidchan, getpid());
2599a747e4fSDavid du Colombier
2609a747e4fSDavid du Colombier while((n = read(grefd, pkt, sizeof pkt)) > 0){
2619a747e4fSDavid du Colombier if(n == sizeof pkt)
2629a747e4fSDavid du Colombier myfatal("gre pkt buffer too small");
2639a747e4fSDavid du Colombier if(n < 16){
2649a747e4fSDavid du Colombier if(debug)
2659a747e4fSDavid du Colombier fprint(2, "small pkt len %d ignored\n", n);
2669a747e4fSDavid du Colombier continue;
2679a747e4fSDavid du Colombier }
2689a747e4fSDavid du Colombier v4tov6(src, pkt);
2699a747e4fSDavid du Colombier v4tov6(dst, pkt+4);
2709a747e4fSDavid du Colombier if(ipcmp(src, remoteip) != 0 || ipcmp(dst, localip) != 0)
2719a747e4fSDavid du Colombier myfatal("%I: gre read bad address src=%I dst=%I",
2729a747e4fSDavid du Colombier remoteip, src, dst);
2739a747e4fSDavid du Colombier if(nhgets(pkt+10) != GrePPP)
2749a747e4fSDavid du Colombier myfatal("%I: gre read bad protocol 0x%x",
2759a747e4fSDavid du Colombier remoteip, nhgets(pkt+10));
2769a747e4fSDavid du Colombier
2779a747e4fSDavid du Colombier flags = nhgets(pkt+8);
2789a747e4fSDavid du Colombier if((flags&0xEF7F) != 0x2001){
2799a747e4fSDavid du Colombier if(debug)
2809a747e4fSDavid du Colombier fprint(2, "bad flags in gre hdr 0x%x\n", flags);
2819a747e4fSDavid du Colombier continue;
2829a747e4fSDavid du Colombier }
2839a747e4fSDavid du Colombier datoff = 8+8;
2849a747e4fSDavid du Colombier pass = 0;
2859a747e4fSDavid du Colombier len = nhgets(pkt+8+4);
2869a747e4fSDavid du Colombier if(len > n-datoff){
2879a747e4fSDavid du Colombier fprint(2, "bad payload length %d > %d\n",
2889a747e4fSDavid du Colombier len, n-datoff);
2899a747e4fSDavid du Colombier continue;
2909a747e4fSDavid du Colombier }
2919a747e4fSDavid du Colombier if(flags&Seqnum)
2929a747e4fSDavid du Colombier datoff += 4;
2939a747e4fSDavid du Colombier if(flags&Acknum){
2949a747e4fSDavid du Colombier recordack(nhgetl(pkt+datoff));
2959a747e4fSDavid du Colombier datoff += 4;
2969a747e4fSDavid du Colombier }
2979a747e4fSDavid du Colombier if(flags&Seqnum)
2989a747e4fSDavid du Colombier pass = schedack(nhgetl(pkt+8+8), pkt+datoff, len);
2999a747e4fSDavid du Colombier if(debug)
3009a747e4fSDavid du Colombier fprint(2, "got gre callid %d len %d flag 0x%x pass %d seq %d rseq %d\n", nhgets(pkt+8+6),
3019a747e4fSDavid du Colombier len, flags, pass, nhgetl(pkt+8+8), rseq);
3029a747e4fSDavid du Colombier }
3039a747e4fSDavid du Colombier threadexits(nil);
3049a747e4fSDavid du Colombier }
3059a747e4fSDavid du Colombier
3069a747e4fSDavid du Colombier void
pppreadproc(void *)3079a747e4fSDavid du Colombier pppreadproc(void*)
3089a747e4fSDavid du Colombier {
3099a747e4fSDavid du Colombier int n, myrseq;
3109a747e4fSDavid du Colombier uchar pkt[1600];
3119a747e4fSDavid du Colombier enum {
3129a747e4fSDavid du Colombier Hdr = 8+16,
3139a747e4fSDavid du Colombier };
3149a747e4fSDavid du Colombier
3159a747e4fSDavid du Colombier rfork(RFFDG);
3169a747e4fSDavid du Colombier close(pppfd);
3179a747e4fSDavid du Colombier sendul(pidchan, getpid());
3189a747e4fSDavid du Colombier
3199a747e4fSDavid du Colombier while((n = read(topppfd, pkt+Hdr, sizeof pkt-Hdr)) > 0){
3209a747e4fSDavid du Colombier if(n == sizeof pkt-Hdr)
3219a747e4fSDavid du Colombier myfatal("ppp pkt buffer too small");
3229a747e4fSDavid du Colombier v6tov4(pkt+0, localip);
3239a747e4fSDavid du Colombier v6tov4(pkt+4, remoteip);
3249a747e4fSDavid du Colombier hnputs(pkt+8, 0x2001 | Seqnum | Acknum);
3259a747e4fSDavid du Colombier hnputs(pkt+10, GrePPP);
3269a747e4fSDavid du Colombier hnputs(pkt+12, n);
3279a747e4fSDavid du Colombier hnputs(pkt+14, remid);
3289a747e4fSDavid du Colombier hnputl(pkt+16, ++seq);
3299a747e4fSDavid du Colombier myrseq = rseq;
3309a747e4fSDavid du Colombier hnputl(pkt+20, myrseq);
3319a747e4fSDavid du Colombier rack = myrseq;
3329a747e4fSDavid du Colombier if(debug)
3339a747e4fSDavid du Colombier fprint(2, "wrote gre callid %d len %d flag 0x%x seq %d rseq %d\n", nhgets(pkt+8+6),
3349a747e4fSDavid du Colombier n, nhgets(pkt+8), nhgetl(pkt+16), nhgetl(pkt+20));
3359a747e4fSDavid du Colombier if(write(grefd, pkt, n+Hdr) != n+Hdr)
3369a747e4fSDavid du Colombier myfatal("gre write: %r");
3379a747e4fSDavid du Colombier waitacks();
3389a747e4fSDavid du Colombier }
3399a747e4fSDavid du Colombier threadexits(nil);
3409a747e4fSDavid du Colombier }
3419a747e4fSDavid du Colombier
3429a747e4fSDavid du Colombier void
sendack(void)3439a747e4fSDavid du Colombier sendack(void)
3449a747e4fSDavid du Colombier {
3459a747e4fSDavid du Colombier int myrseq;
3469a747e4fSDavid du Colombier uchar pkt[20];
3479a747e4fSDavid du Colombier
3489a747e4fSDavid du Colombier v6tov4(pkt+0, localip);
3499a747e4fSDavid du Colombier v6tov4(pkt+4, remoteip);
3509a747e4fSDavid du Colombier hnputs(pkt+8, 0x2001 | Acknum);
3519a747e4fSDavid du Colombier hnputs(pkt+10, GrePPP);
3529a747e4fSDavid du Colombier hnputs(pkt+12, 0);
3539a747e4fSDavid du Colombier hnputs(pkt+14, remid);
3549a747e4fSDavid du Colombier myrseq = rseq;
3559a747e4fSDavid du Colombier rack = myrseq;
3569a747e4fSDavid du Colombier hnputs(pkt+16, myrseq);
3579a747e4fSDavid du Colombier
3589a747e4fSDavid du Colombier if(write(grefd, pkt, sizeof pkt) != sizeof pkt)
3599a747e4fSDavid du Colombier myfatal("gre write: %r");
3609a747e4fSDavid du Colombier }
3619a747e4fSDavid du Colombier
3629a747e4fSDavid du Colombier int
schedack(int n,uchar * dat,int len)3639a747e4fSDavid du Colombier schedack(int n, uchar *dat, int len)
3649a747e4fSDavid du Colombier {
3659a747e4fSDavid du Colombier static uchar sdat[1600];
3669a747e4fSDavid du Colombier static int srseq, slen;
3679a747e4fSDavid du Colombier
3689a747e4fSDavid du Colombier if(n-rseq <= 0){
3699a747e4fSDavid du Colombier fprint(2, "skipping pkt %d len %d, have %d\n", n, len, rseq);
3709a747e4fSDavid du Colombier return 0;
3719a747e4fSDavid du Colombier }
3729a747e4fSDavid du Colombier
3739a747e4fSDavid du Colombier /* missed one pkt, maybe a swap happened, save pkt */
3749a747e4fSDavid du Colombier if(n==rseq+2){
3759a747e4fSDavid du Colombier memmove(sdat, dat, len);
3769a747e4fSDavid du Colombier slen = len;
3779a747e4fSDavid du Colombier srseq = n;
3789a747e4fSDavid du Colombier return 0;
3799a747e4fSDavid du Colombier }
3809a747e4fSDavid du Colombier
3819a747e4fSDavid du Colombier if(n-rseq > 1){
3829a747e4fSDavid du Colombier if(slen && srseq == n-1){
3839a747e4fSDavid du Colombier fprint(2, "reswapped pkts %d and %d\n", srseq, n);
3849a747e4fSDavid du Colombier write(topppfd, sdat, slen);
3859a747e4fSDavid du Colombier slen = 0;
3869a747e4fSDavid du Colombier }else
3879a747e4fSDavid du Colombier fprint(2, "missed pkts %d-%d, got %d len %d\n", rseq+1, n-1, n, len);
3889a747e4fSDavid du Colombier }
3899a747e4fSDavid du Colombier write(topppfd, dat, len);
3909a747e4fSDavid du Colombier rseq = n;
3919a747e4fSDavid du Colombier
3929a747e4fSDavid du Colombier /* send ack if we haven't recently */
3939a747e4fSDavid du Colombier if((int)(rseq-rack) > (localwin>>1))
3949a747e4fSDavid du Colombier sendack();
3959a747e4fSDavid du Colombier
3969a747e4fSDavid du Colombier return 1;
3979a747e4fSDavid du Colombier }
3989a747e4fSDavid du Colombier
3999a747e4fSDavid du Colombier void
gretimeoutproc(void *)4009a747e4fSDavid du Colombier gretimeoutproc(void*)
4019a747e4fSDavid du Colombier {
4029a747e4fSDavid du Colombier for(;;){
4039a747e4fSDavid du Colombier sleep(Tick);
4049a747e4fSDavid du Colombier now++;
4059a747e4fSDavid du Colombier nbsendul(tickchan, now);
4069a747e4fSDavid du Colombier if(now - ctlrcvtime > Servertimeout)
4079a747e4fSDavid du Colombier myfatal("server timeout");
4089a747e4fSDavid du Colombier if(now - ctlechotime > Echointerval)
4099a747e4fSDavid du Colombier sendecho();
4109a747e4fSDavid du Colombier }
4119a747e4fSDavid du Colombier }
4129a747e4fSDavid du Colombier
4139a747e4fSDavid du Colombier void
recordack(int n)4149a747e4fSDavid du Colombier recordack(int n)
4159a747e4fSDavid du Colombier {
4169a747e4fSDavid du Colombier ack = n;
4179a747e4fSDavid du Colombier }
4189a747e4fSDavid du Colombier
4199a747e4fSDavid du Colombier void
waitacks(void)4209a747e4fSDavid du Colombier waitacks(void)
4219a747e4fSDavid du Colombier {
422b85a8364SDavid du Colombier /*
4239a747e4fSDavid du Colombier int start;
4249a747e4fSDavid du Colombier
4259a747e4fSDavid du Colombier start = now;
4269a747e4fSDavid du Colombier while(seq-ack > remwin && now-start < Sendtimeout){
4279a747e4fSDavid du Colombier print("seq %d ack %d remwin %d now %d start %d\n",
4289a747e4fSDavid du Colombier seq, ack, remwin, now, start);
4299a747e4fSDavid du Colombier recvul(tickchan);
4309a747e4fSDavid du Colombier }
431b85a8364SDavid du Colombier */
4329a747e4fSDavid du Colombier }
4339a747e4fSDavid du Colombier
4349a747e4fSDavid du Colombier void
tstart(void)4359a747e4fSDavid du Colombier tstart(void)
4369a747e4fSDavid du Colombier {
4379a747e4fSDavid du Colombier char *name;
4389a747e4fSDavid du Colombier uchar pkt[200], *rpkt;
4399a747e4fSDavid du Colombier
4409a747e4fSDavid du Colombier memset(pkt, 0, sizeof pkt);
4419a747e4fSDavid du Colombier
4429a747e4fSDavid du Colombier hnputs(pkt+0, 156);
4439a747e4fSDavid du Colombier hnputs(pkt+2, 1);
4449a747e4fSDavid du Colombier hnputl(pkt+4, Magic);
4459a747e4fSDavid du Colombier hnputs(pkt+8, Tstart);
4469a747e4fSDavid du Colombier hnputs(pkt+12, PptpProto);
4479a747e4fSDavid du Colombier hnputl(pkt+16, 1);
4489a747e4fSDavid du Colombier hnputl(pkt+20, 1);
4499a747e4fSDavid du Colombier hnputs(pkt+24, 1);
4509a747e4fSDavid du Colombier name = sysname();
4519a747e4fSDavid du Colombier if(name == nil)
4529a747e4fSDavid du Colombier name = "gnot";
4539a747e4fSDavid du Colombier strcpy((char*)pkt+28, name);
4549a747e4fSDavid du Colombier strcpy((char*)pkt+92, "plan 9");
4559a747e4fSDavid du Colombier
4569a747e4fSDavid du Colombier if(debug)
4579a747e4fSDavid du Colombier dumpctlpkt(pkt);
4589a747e4fSDavid du Colombier
4599a747e4fSDavid du Colombier rdexpect = Rstart;
4609a747e4fSDavid du Colombier ewrite(ctlfd, pkt, 156);
4619a747e4fSDavid du Colombier
4629a747e4fSDavid du Colombier rpkt = recvp(rdchan);
4639a747e4fSDavid du Colombier if(rpkt == nil)
4649a747e4fSDavid du Colombier myfatal("recvp: %r");
4659a747e4fSDavid du Colombier if(nhgets(rpkt) != 156)
4669a747e4fSDavid du Colombier myfatal("Rstart wrong length %d != 156", nhgets(rpkt));
4679a747e4fSDavid du Colombier if(rpkt[14] != 1)
4689a747e4fSDavid du Colombier myfatal("Rstart error %d", rpkt[15]);
4699a747e4fSDavid du Colombier free(rpkt);
4709a747e4fSDavid du Colombier }
4719a747e4fSDavid du Colombier
4729a747e4fSDavid du Colombier void
tcallout(void)4739a747e4fSDavid du Colombier tcallout(void)
4749a747e4fSDavid du Colombier {
4759a747e4fSDavid du Colombier uchar pkt[200], *rpkt;
4769a747e4fSDavid du Colombier
4779a747e4fSDavid du Colombier pid = getpid();
4789a747e4fSDavid du Colombier
4799a747e4fSDavid du Colombier memset(pkt, 0, sizeof pkt);
4809a747e4fSDavid du Colombier hnputs(pkt+0, 168);
4819a747e4fSDavid du Colombier hnputs(pkt+2, 1);
4829a747e4fSDavid du Colombier hnputl(pkt+4, Magic);
4839a747e4fSDavid du Colombier hnputs(pkt+8, Tcallout);
4849a747e4fSDavid du Colombier
4859a747e4fSDavid du Colombier hnputl(pkt+16, 56000);
4869a747e4fSDavid du Colombier hnputl(pkt+20, 768000);
4879a747e4fSDavid du Colombier hnputl(pkt+24, 3);
4889a747e4fSDavid du Colombier hnputl(pkt+28, 3);
4899a747e4fSDavid du Colombier if(localwin == 0)
4909a747e4fSDavid du Colombier localwin = Window;
4919a747e4fSDavid du Colombier hnputs(pkt+32, localwin);
4929a747e4fSDavid du Colombier
4939a747e4fSDavid du Colombier if(debug)
4949a747e4fSDavid du Colombier dumpctlpkt(pkt);
4959a747e4fSDavid du Colombier
4969a747e4fSDavid du Colombier rdexpect = Rcallout;
4979a747e4fSDavid du Colombier ewrite(ctlfd, pkt, 168);
4989a747e4fSDavid du Colombier
4999a747e4fSDavid du Colombier rpkt = recvp(rdchan);
5009a747e4fSDavid du Colombier if(rpkt == nil)
5019a747e4fSDavid du Colombier myfatal("recvp: %r");
5029a747e4fSDavid du Colombier if(nhgets(rpkt) != 32)
5039a747e4fSDavid du Colombier myfatal("Rcallreq wrong length %d != 32", nhgets(rpkt));
5049a747e4fSDavid du Colombier if(rpkt[16] != 1)
5059a747e4fSDavid du Colombier myfatal("Rcallreq error %d", rpkt[17]);
5069a747e4fSDavid du Colombier remid = nhgets(pkt+12);
5079a747e4fSDavid du Colombier remwin = nhgets(pkt+24);
5089a747e4fSDavid du Colombier free(rpkt);
5099a747e4fSDavid du Colombier }
5109a747e4fSDavid du Colombier
5119a747e4fSDavid du Colombier /*
5129a747e4fSDavid du Colombier void
5139a747e4fSDavid du Colombier tcallreq(void)
5149a747e4fSDavid du Colombier {
5159a747e4fSDavid du Colombier uchar pkt[200], *rpkt;
5169a747e4fSDavid du Colombier
5179a747e4fSDavid du Colombier pid = getpid();
5189a747e4fSDavid du Colombier
5199a747e4fSDavid du Colombier memset(pkt, 0, sizeof pkt);
5209a747e4fSDavid du Colombier hnputs(pkt+0, 220);
5219a747e4fSDavid du Colombier hnputs(pkt+2, 1);
5229a747e4fSDavid du Colombier hnputl(pkt+4, Magic);
5239a747e4fSDavid du Colombier hnputs(pkt+8, Tcallreq);
5249a747e4fSDavid du Colombier
5259a747e4fSDavid du Colombier if(debug)
5269a747e4fSDavid du Colombier dumpctlpkt(pkt);
5279a747e4fSDavid du Colombier
5289a747e4fSDavid du Colombier rdexpect = Rcallreq;
5299a747e4fSDavid du Colombier ewrite(ctlfd, pkt, 220);
5309a747e4fSDavid du Colombier
5319a747e4fSDavid du Colombier rpkt = recvp(rdchan);
5329a747e4fSDavid du Colombier if(rpkt == nil)
5339a747e4fSDavid du Colombier myfatal("recvp: %r");
5349a747e4fSDavid du Colombier if(nhgets(rpkt) != 24)
5359a747e4fSDavid du Colombier myfatal("Rcallreq wrong length %d != 24", nhgets(rpkt));
5369a747e4fSDavid du Colombier if(rpkt[16] != 1)
5379a747e4fSDavid du Colombier myfatal("Rcallreq error %d", rpkt[17]);
5389a747e4fSDavid du Colombier remid = nhgets(pkt+12);
5399a747e4fSDavid du Colombier remwin = nhgets(pkt+18);
5409a747e4fSDavid du Colombier free(rpkt);
5419a747e4fSDavid du Colombier }
5429a747e4fSDavid du Colombier
5439a747e4fSDavid du Colombier void
5449a747e4fSDavid du Colombier acallcon(void)
5459a747e4fSDavid du Colombier {
5469a747e4fSDavid du Colombier uchar pkt[200];
5479a747e4fSDavid du Colombier
5489a747e4fSDavid du Colombier memset(pkt, 0, sizeof pkt);
5499a747e4fSDavid du Colombier hnputs(pkt+0, 28);
5509a747e4fSDavid du Colombier hnputs(pkt+2, 1);
5519a747e4fSDavid du Colombier hnputl(pkt+4, Magic);
5529a747e4fSDavid du Colombier hnputs(pkt+8, Acallcon);
5539a747e4fSDavid du Colombier hnputs(pkt+12, remid);
5549a747e4fSDavid du Colombier if(localwin == 0)
5559a747e4fSDavid du Colombier localwin = Window;
5569a747e4fSDavid du Colombier hnputs(pkt+20, localwin);
5579a747e4fSDavid du Colombier hnputl(pkt+24, 1);
5589a747e4fSDavid du Colombier
5599a747e4fSDavid du Colombier if(debug)
5609a747e4fSDavid du Colombier dumpctlpkt(pkt);
5619a747e4fSDavid du Colombier
5629a747e4fSDavid du Colombier ewrite(ctlfd, pkt, 28);
5639a747e4fSDavid du Colombier }
5649a747e4fSDavid du Colombier */
5659a747e4fSDavid du Colombier
5669a747e4fSDavid du Colombier int
pptp(char * addr)5679a747e4fSDavid du Colombier pptp(char *addr)
5689a747e4fSDavid du Colombier {
5699a747e4fSDavid du Colombier int p[2];
5709a747e4fSDavid du Colombier char greaddr[128];
5719a747e4fSDavid du Colombier
5729a747e4fSDavid du Colombier addr = netmkaddr(addr, "net", "pptp");
5739a747e4fSDavid du Colombier ctlfd = dial(addr, nil, tcpdir, nil);
5749a747e4fSDavid du Colombier if(ctlfd < 0)
5759a747e4fSDavid du Colombier myfatal("dial %s: %r", addr);
5769a747e4fSDavid du Colombier getaddrs();
5779a747e4fSDavid du Colombier
5789a747e4fSDavid du Colombier rdchan = chancreate(sizeof(void*), 0);
5799a747e4fSDavid du Colombier proccreate(pptpctlproc, nil, Stack);
5809a747e4fSDavid du Colombier
5819a747e4fSDavid du Colombier tstart();
5829a747e4fSDavid du Colombier tcallout();
5839a747e4fSDavid du Colombier
5849a747e4fSDavid du Colombier if(pipe(p) < 0)
5859a747e4fSDavid du Colombier myfatal("pipe: %r");
5869a747e4fSDavid du Colombier
5879a747e4fSDavid du Colombier pppfd = p[0];
5889a747e4fSDavid du Colombier topppfd = p[1];
5899a747e4fSDavid du Colombier
5909a747e4fSDavid du Colombier strcpy(greaddr, tcpdir);
5919a747e4fSDavid du Colombier *strrchr(greaddr, '/') = '\0';
5929a747e4fSDavid du Colombier sprint(strrchr(greaddr, '/')+1, "gre!%I!%d", remoteip, GrePPP);
5939a747e4fSDavid du Colombier
5949a747e4fSDavid du Colombier print("local %I remote %I gre %s remid %d remwin %d\n",
5959a747e4fSDavid du Colombier localip, remoteip, greaddr, remid, remwin);
5969a747e4fSDavid du Colombier
5979a747e4fSDavid du Colombier grefd = dial(greaddr, nil, nil, nil);
5989a747e4fSDavid du Colombier if(grefd < 0)
5999a747e4fSDavid du Colombier myfatal("dial gre: %r");
6009a747e4fSDavid du Colombier
6019a747e4fSDavid du Colombier tickchan = chancreate(sizeof(int), 0);
6029a747e4fSDavid du Colombier proccreate(gretimeoutproc, nil, Stack);
6039a747e4fSDavid du Colombier
6049a747e4fSDavid du Colombier pidchan = chancreate(sizeof(int), 0);
6059a747e4fSDavid du Colombier proccreate(grereadproc, nil, Stack);
6069a747e4fSDavid du Colombier recvul(pidchan);
6079a747e4fSDavid du Colombier proccreate(pppreadproc, nil, Stack);
6089a747e4fSDavid du Colombier recvul(pidchan);
6099a747e4fSDavid du Colombier
6109a747e4fSDavid du Colombier close(topppfd);
6119a747e4fSDavid du Colombier return pppfd;
6129a747e4fSDavid du Colombier }
6139a747e4fSDavid du Colombier
6149a747e4fSDavid du Colombier void
pushppp(int fd)6159a747e4fSDavid du Colombier pushppp(int fd)
6169a747e4fSDavid du Colombier {
6179a747e4fSDavid du Colombier char *argv[16];
6189a747e4fSDavid du Colombier int argc;
6199a747e4fSDavid du Colombier
6209a747e4fSDavid du Colombier argc = 0;
6219a747e4fSDavid du Colombier argv[argc++] = "/bin/ip/ppp";
6229a747e4fSDavid du Colombier argv[argc++] = "-C";
6239a747e4fSDavid du Colombier argv[argc++] = "-m1450";
6249a747e4fSDavid du Colombier if(debug)
6259a747e4fSDavid du Colombier argv[argc++] = "-d";
6269a747e4fSDavid du Colombier if(primary)
6279a747e4fSDavid du Colombier argv[argc++] = "-P";
6289a747e4fSDavid du Colombier if(pppnetmntpt){
6299a747e4fSDavid du Colombier argv[argc++] = "-x";
6309a747e4fSDavid du Colombier argv[argc++] = pppnetmntpt;
6319a747e4fSDavid du Colombier }
632bedadc12SDavid du Colombier if(keyspec){
633bedadc12SDavid du Colombier argv[argc++] = "-k";
634bedadc12SDavid du Colombier argv[argc++] = keyspec;
6359a747e4fSDavid du Colombier }
6369a747e4fSDavid du Colombier argv[argc] = nil;
6379a747e4fSDavid du Colombier
6389a747e4fSDavid du Colombier switch(fork()){
6399a747e4fSDavid du Colombier case -1:
6409a747e4fSDavid du Colombier myfatal("fork: %r");
6419a747e4fSDavid du Colombier default:
6429a747e4fSDavid du Colombier return;
6439a747e4fSDavid du Colombier case 0:
6449a747e4fSDavid du Colombier dup(fd, 0);
6459a747e4fSDavid du Colombier dup(fd, 1);
6469a747e4fSDavid du Colombier exec(argv[0], argv);
6479a747e4fSDavid du Colombier myfatal("exec: %r");
6489a747e4fSDavid du Colombier }
6499a747e4fSDavid du Colombier }
6509a747e4fSDavid du Colombier
6519a747e4fSDavid du Colombier int
aread(int timeout,int fd,void * buf,int nbuf)6529a747e4fSDavid du Colombier aread(int timeout, int fd, void *buf, int nbuf)
6539a747e4fSDavid du Colombier {
6549a747e4fSDavid du Colombier int n;
6559a747e4fSDavid du Colombier
6569a747e4fSDavid du Colombier alarmed = 0;
6579a747e4fSDavid du Colombier alarm(timeout);
6589a747e4fSDavid du Colombier n = read(fd, buf, nbuf);
6599a747e4fSDavid du Colombier alarm(0);
6609a747e4fSDavid du Colombier if(alarmed)
6619a747e4fSDavid du Colombier return -1;
6629a747e4fSDavid du Colombier if(n < 0)
6639a747e4fSDavid du Colombier myfatal("read: %r");
6649a747e4fSDavid du Colombier if(n == 0)
6659a747e4fSDavid du Colombier myfatal("short read");
6669a747e4fSDavid du Colombier return n;
6679a747e4fSDavid du Colombier }
6689a747e4fSDavid du Colombier
6699a747e4fSDavid du Colombier void
ewrite(int fd,void * buf,int nbuf)6709a747e4fSDavid du Colombier ewrite(int fd, void *buf, int nbuf)
6719a747e4fSDavid du Colombier {
6729a747e4fSDavid du Colombier char e[ERRMAX], path[64];
6739a747e4fSDavid du Colombier
6749a747e4fSDavid du Colombier if(write(fd, buf, nbuf) != nbuf){
6759a747e4fSDavid du Colombier rerrstr(e, sizeof e);
6769a747e4fSDavid du Colombier strcpy(path, "unknown");
6779a747e4fSDavid du Colombier fd2path(fd, path, sizeof path);
6789a747e4fSDavid du Colombier myfatal("write %d to %s: %s", nbuf, path, e);
6799a747e4fSDavid du Colombier }
6809a747e4fSDavid du Colombier }
6819a747e4fSDavid du Colombier
6829a747e4fSDavid du Colombier void*
emalloc(long n)6839a747e4fSDavid du Colombier emalloc(long n)
6849a747e4fSDavid du Colombier {
6859a747e4fSDavid du Colombier void *v;
6869a747e4fSDavid du Colombier
6879a747e4fSDavid du Colombier v = malloc(n);
6889a747e4fSDavid du Colombier if(v == nil)
6899a747e4fSDavid du Colombier myfatal("out of memory");
6909a747e4fSDavid du Colombier return v;
6919a747e4fSDavid du Colombier }
6929a747e4fSDavid du Colombier
6939a747e4fSDavid du Colombier int
thread(void (* f)(void *),void * a)6949a747e4fSDavid du Colombier thread(void(*f)(void*), void *a)
6959a747e4fSDavid du Colombier {
6969a747e4fSDavid du Colombier int pid;
6979a747e4fSDavid du Colombier pid=rfork(RFNOWAIT|RFMEM|RFPROC);
6989a747e4fSDavid du Colombier if(pid < 0)
6999a747e4fSDavid du Colombier myfatal("rfork: %r");
7009a747e4fSDavid du Colombier if(pid != 0)
7019a747e4fSDavid du Colombier return pid;
7029a747e4fSDavid du Colombier (*f)(a);
7039a747e4fSDavid du Colombier _exits(nil);
7049a747e4fSDavid du Colombier return 0; // never reaches here
7059a747e4fSDavid du Colombier }
7069a747e4fSDavid du Colombier
7079a747e4fSDavid du Colombier void
dumpctlpkt(uchar * pkt)7089a747e4fSDavid du Colombier dumpctlpkt(uchar *pkt)
7099a747e4fSDavid du Colombier {
7109a747e4fSDavid du Colombier fprint(2, "pkt len %d mtype %d cookie 0x%.8ux type %d\n",
7119a747e4fSDavid du Colombier nhgets(pkt), nhgets(pkt+2),
7129a747e4fSDavid du Colombier nhgetl(pkt+4), nhgets(pkt+8));
7139a747e4fSDavid du Colombier
7149a747e4fSDavid du Colombier switch(nhgets(pkt+8)){
7159a747e4fSDavid du Colombier default:
7169a747e4fSDavid du Colombier fprint(2, "\tunknown type\n");
7179a747e4fSDavid du Colombier break;
7189a747e4fSDavid du Colombier case Tstart:
7199a747e4fSDavid du Colombier fprint(2, "\tTstart proto %d framing %d bearer %d maxchan %d firmware %d\n",
7209a747e4fSDavid du Colombier nhgets(pkt+12), nhgetl(pkt+16),
7219a747e4fSDavid du Colombier nhgetl(pkt+20), nhgets(pkt+24),
7229a747e4fSDavid du Colombier nhgets(pkt+26));
7239a747e4fSDavid du Colombier fprint(2, "\thost %.64s\n", (char*)pkt+28);
7249a747e4fSDavid du Colombier fprint(2, "\tvendor %.64s\n", (char*)pkt+92);
7259a747e4fSDavid du Colombier break;
7269a747e4fSDavid du Colombier case Rstart:
7279a747e4fSDavid du Colombier fprint(2, "\tRstart proto %d res %d err %d framing %d bearer %d maxchan %d firmware %d\n",
7289a747e4fSDavid du Colombier nhgets(pkt+12), pkt[14], pkt[15],
7299a747e4fSDavid du Colombier nhgetl(pkt+16),
7309a747e4fSDavid du Colombier nhgetl(pkt+20), nhgets(pkt+24),
7319a747e4fSDavid du Colombier nhgets(pkt+26));
7329a747e4fSDavid du Colombier fprint(2, "\thost %.64s\n", (char*)pkt+28);
7339a747e4fSDavid du Colombier fprint(2, "\tvendor %.64s\n", (char*)pkt+92);
7349a747e4fSDavid du Colombier break;
7359a747e4fSDavid du Colombier
7369a747e4fSDavid du Colombier case Tstop:
7379a747e4fSDavid du Colombier fprint(2, "\tTstop reason %d\n", pkt[12]);
7389a747e4fSDavid du Colombier break;
7399a747e4fSDavid du Colombier
7409a747e4fSDavid du Colombier case Rstop:
7419a747e4fSDavid du Colombier fprint(2, "\tRstop res %d err %d\n", pkt[12], pkt[13]);
7429a747e4fSDavid du Colombier break;
7439a747e4fSDavid du Colombier
7449a747e4fSDavid du Colombier case Techo:
7459a747e4fSDavid du Colombier fprint(2, "\tTecho id %.8ux\n", nhgetl(pkt+12));
7469a747e4fSDavid du Colombier break;
7479a747e4fSDavid du Colombier
7489a747e4fSDavid du Colombier case Recho:
7499a747e4fSDavid du Colombier fprint(2, "\tRecho id %.8ux res %d err %d\n", nhgetl(pkt+12), pkt[16], pkt[17]);
7509a747e4fSDavid du Colombier break;
7519a747e4fSDavid du Colombier
7529a747e4fSDavid du Colombier case Tcallout:
7539a747e4fSDavid du Colombier fprint(2, "\tTcallout id %d serno %d bps %d-%d\n",
7549a747e4fSDavid du Colombier nhgets(pkt+12), nhgets(pkt+14),
7559a747e4fSDavid du Colombier nhgetl(pkt+16), nhgetl(pkt+20));
7569a747e4fSDavid du Colombier fprint(2, "\tbearer 0x%x framing 0x%x recvwin %d delay %d\n",
7579a747e4fSDavid du Colombier nhgetl(pkt+24), nhgetl(pkt+28),
7589a747e4fSDavid du Colombier nhgets(pkt+32), nhgets(pkt+34));
7599a747e4fSDavid du Colombier fprint(2, "\tphone len %d num %.64s\n",
7609a747e4fSDavid du Colombier nhgets(pkt+36), (char*)pkt+40);
7619a747e4fSDavid du Colombier fprint(2, "\tsubaddr %.64s\n", (char*)pkt+104);
7629a747e4fSDavid du Colombier break;
7639a747e4fSDavid du Colombier
7649a747e4fSDavid du Colombier case Rcallout:
7659a747e4fSDavid du Colombier fprint(2, "\tRcallout id %d peerid %d res %d err %d cause %d\n",
7669a747e4fSDavid du Colombier nhgets(pkt+12), nhgets(pkt+14),
7679a747e4fSDavid du Colombier pkt[16], pkt[17], nhgets(pkt+18));
7689a747e4fSDavid du Colombier fprint(2, "\tconnect %d recvwin %d delay %d chan 0x%.8ux\n",
7699a747e4fSDavid du Colombier nhgetl(pkt+20), nhgets(pkt+24),
7709a747e4fSDavid du Colombier nhgets(pkt+26), nhgetl(pkt+28));
7719a747e4fSDavid du Colombier break;
7729a747e4fSDavid du Colombier
7739a747e4fSDavid du Colombier case Tcallreq:
7749a747e4fSDavid du Colombier fprint(2, "\tTcallreq id %d serno %d bearer 0x%x id 0x%x\n",
7759a747e4fSDavid du Colombier nhgets(pkt+12), nhgets(pkt+14),
7769a747e4fSDavid du Colombier nhgetl(pkt+16), nhgetl(pkt+20));
7779a747e4fSDavid du Colombier fprint(2, "\tdialed len %d num %.64s\n",
7789a747e4fSDavid du Colombier nhgets(pkt+24), (char*)pkt+28);
7799a747e4fSDavid du Colombier fprint(2, "\tdialing len %d num %.64s\n",
7809a747e4fSDavid du Colombier nhgets(pkt+26), (char*)pkt+92);
7819a747e4fSDavid du Colombier fprint(2, "\tsubaddr %.64s\n", (char*)pkt+156);
7829a747e4fSDavid du Colombier break;
7839a747e4fSDavid du Colombier
7849a747e4fSDavid du Colombier case Rcallreq:
7859a747e4fSDavid du Colombier fprint(2, "\tRcallout id %d peerid %d res %d err %d recvwin %d delay %d\n",
7869a747e4fSDavid du Colombier nhgets(pkt+12), nhgets(pkt+14),
7879a747e4fSDavid du Colombier pkt[16], pkt[17], nhgets(pkt+18),
7889a747e4fSDavid du Colombier nhgets(pkt+20));
7899a747e4fSDavid du Colombier break;
7909a747e4fSDavid du Colombier
7919a747e4fSDavid du Colombier case Acallcon:
7929a747e4fSDavid du Colombier fprint(2, "\tAcallcon peerid %d connect %d recvwin %d delay %d framing 0x%x\n",
7939a747e4fSDavid du Colombier nhgets(pkt+12), nhgetl(pkt+16),
7949a747e4fSDavid du Colombier nhgets(pkt+20), nhgets(pkt+22),
7959a747e4fSDavid du Colombier nhgetl(pkt+24));
7969a747e4fSDavid du Colombier break;
7979a747e4fSDavid du Colombier
7989a747e4fSDavid du Colombier case Tcallclear:
7999a747e4fSDavid du Colombier fprint(2, "\tTcallclear callid %d\n",
8009a747e4fSDavid du Colombier nhgets(pkt+12));
8019a747e4fSDavid du Colombier break;
8029a747e4fSDavid du Colombier
8039a747e4fSDavid du Colombier case Acalldis:
8049a747e4fSDavid du Colombier fprint(2, "\tAcalldis callid %d res %d err %d cause %d\n",
8059a747e4fSDavid du Colombier nhgets(pkt+12), pkt[14], pkt[15],
8069a747e4fSDavid du Colombier nhgets(pkt+16));
8079a747e4fSDavid du Colombier fprint(2, "\tstats %.128s\n", (char*)pkt+20);
8089a747e4fSDavid du Colombier break;
8099a747e4fSDavid du Colombier
8109a747e4fSDavid du Colombier case Awaninfo:
8119a747e4fSDavid du Colombier fprint(2, "\tAwaninfo peerid %d\n", nhgets(pkt+12));
8129a747e4fSDavid du Colombier fprint(2, "\tcrc errors %d\n", nhgetl(pkt+16));
8139a747e4fSDavid du Colombier fprint(2, "\tframe errors %d\n", nhgetl(pkt+20));
8149a747e4fSDavid du Colombier fprint(2, "\thardware overruns %d\n", nhgetl(pkt+24));
8159a747e4fSDavid du Colombier fprint(2, "\tbuffer overruns %d\n", nhgetl(pkt+28));
8169a747e4fSDavid du Colombier fprint(2, "\ttime-out errors %d\n", nhgetl(pkt+32));
8179a747e4fSDavid du Colombier fprint(2, "\talignment errors %d\n", nhgetl(pkt+36));
8189a747e4fSDavid du Colombier break;
8199a747e4fSDavid du Colombier
8209a747e4fSDavid du Colombier case Alinkinfo:
8219a747e4fSDavid du Colombier fprint(2, "\tAlinkinfo peerid %d sendaccm 0x%ux recvaccm 0x%ux\n",
8229a747e4fSDavid du Colombier nhgets(pkt+12), nhgetl(pkt+16),
8239a747e4fSDavid du Colombier nhgetl(pkt+20));
8249a747e4fSDavid du Colombier break;
8259a747e4fSDavid du Colombier }
8269a747e4fSDavid du Colombier }
8279a747e4fSDavid du Colombier
8289a747e4fSDavid du Colombier void
getaddrs(void)8299a747e4fSDavid du Colombier getaddrs(void)
8309a747e4fSDavid du Colombier {
8319a747e4fSDavid du Colombier char buf[128];
8329a747e4fSDavid du Colombier int fd, n;
8339a747e4fSDavid du Colombier
8349a747e4fSDavid du Colombier sprint(buf, "%s/local", tcpdir);
8359a747e4fSDavid du Colombier if((fd = open(buf, OREAD)) < 0)
8369a747e4fSDavid du Colombier myfatal("could not open %s: %r", buf);
8379a747e4fSDavid du Colombier if((n = read(fd, buf, sizeof(buf))) < 0)
8389a747e4fSDavid du Colombier myfatal("could not read %s: %r", buf);
8399a747e4fSDavid du Colombier buf[n] = 0;
8409a747e4fSDavid du Colombier parseip(localip, buf);
8419a747e4fSDavid du Colombier close(fd);
8429a747e4fSDavid du Colombier
8439a747e4fSDavid du Colombier sprint(buf, "%s/remote", tcpdir);
8449a747e4fSDavid du Colombier if((fd = open(buf, OREAD)) < 0)
8459a747e4fSDavid du Colombier myfatal("could not open %s: %r", buf);
8469a747e4fSDavid du Colombier if((n = read(fd, buf, sizeof(buf))) < 0)
8479a747e4fSDavid du Colombier myfatal("could not read %s: %r", buf);
8489a747e4fSDavid du Colombier buf[n] = 0;
8499a747e4fSDavid du Colombier parseip(remoteip, buf);
8509a747e4fSDavid du Colombier close(fd);
8519a747e4fSDavid du Colombier }
8529a747e4fSDavid du Colombier
8539a747e4fSDavid du Colombier void
myfatal(char * fmt,...)8549a747e4fSDavid du Colombier myfatal(char *fmt, ...)
8559a747e4fSDavid du Colombier {
8569a747e4fSDavid du Colombier char sbuf[512];
8579a747e4fSDavid du Colombier va_list arg;
8589a747e4fSDavid du Colombier uchar buf[16];
8599a747e4fSDavid du Colombier
8609a747e4fSDavid du Colombier memset(buf, 0, sizeof(buf));
8619a747e4fSDavid du Colombier hnputs(buf+0, sizeof(buf)); /* length */
8629a747e4fSDavid du Colombier hnputs(buf+2, 1); /* message type */
8639a747e4fSDavid du Colombier hnputl(buf+4, Magic); /* magic */
8649a747e4fSDavid du Colombier hnputs(buf+8, Tstop); /* op */
8659a747e4fSDavid du Colombier buf[12] = 3; /* local shutdown */
8669a747e4fSDavid du Colombier write(ctlfd, buf, sizeof(buf));
8679a747e4fSDavid du Colombier
8689a747e4fSDavid du Colombier va_start(arg, fmt);
8699a747e4fSDavid du Colombier vseprint(sbuf, sbuf+sizeof(sbuf), fmt, arg);
8709a747e4fSDavid du Colombier va_end(arg);
8719a747e4fSDavid du Colombier
8729a747e4fSDavid du Colombier fprint(2, "fatal: %s\n", sbuf);
8739a747e4fSDavid du Colombier threadexitsall(nil);
8749a747e4fSDavid du Colombier }
875