123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874 |
- /*
- * Point-to-point Tunneling Protocol (PPTP)
- * See RFC 2637, pptpd.c
- */
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <ip.h>
- #include <thread.h>
- int ack;
- int alarmed;
- int ctlechotime;
- int ctlfd;
- int ctlrcvtime;
- int debug;
- int grefd;
- uchar localip[IPaddrlen];
- int localwin;
- char *keyspec;
- int now;
- char *pppnetmntpt;
- int pid;
- Channel *pidchan;
- int pppfd;
- int primary;
- int rack;
- Channel *rdchan;
- int rdexpect;
- int remid;
- uchar remoteip[IPaddrlen];
- int remwin;
- int rseq;
- int seq;
- char tcpdir[40];
- Channel *tickchan;
- int topppfd;
- int aread(int, int, void*, int);
- int catchalarm(void*, char*);
- void dumpctlpkt(uchar*);
- void getaddrs(void);
- void *emalloc(long);
- void ewrite(int, void*, int);
- void myfatal(char*, ...);
- #pragma varargck argpos myfatal 1
- int pptp(char*);
- void pushppp(int);
- void recordack(int);
- int schedack(int, uchar*, int);
- void waitacks(void);
- void
- usage(void)
- {
- fprint(2, "usage: ip/pptp [-Pd] [-k keyspec] [-x pppnetmntpt] [-w window] server\n");
- exits("usage");
- }
- void
- threadmain(int argc, char **argv)
- {
- int fd;
- ARGBEGIN{
- case 'P':
- primary = 1;
- break;
- case 'd':
- debug++;
- break;
- case 'k':
- keyspec = EARGF(usage());
- break;
- case 'w':
- localwin = atoi(EARGF(usage()));
- break;
- case 'x':
- pppnetmntpt = EARGF(usage());
- break;
- default:
- usage();
- }ARGEND
- if(argc != 1)
- usage();
- fmtinstall('E', eipfmt);
- fmtinstall('I', eipfmt);
- rfork(RFNOTEG);
- atnotify(catchalarm, 1);
- fd = pptp(argv[0]);
- pushppp(fd);
- exits(nil);
- }
- int
- catchalarm(void *a, char *msg)
- {
- USED(a);
- if(strstr(msg, "alarm")){
- alarmed = 1;
- return 1;
- }
- if(debug)
- fprint(2, "note rcved: %s\n", msg);
- return 0;
- }
- enum {
- Stack = 8192,
- PptpProto = 0x0100,
- Magic = 0x1a2b3c4d,
- Window = 16, /* default window size */
- Timeout = 60, /* timeout in seconds for control channel */
- Pktsize = 2000, /* maximum packet size */
- Tick = 500, /* tick length in milliseconds */
- Sendtimeout = 4, /* in ticks */
- Servertimeout = 5*60*1000/Tick,
- Echointerval = 60*1000/Tick,
- };
- enum {
- Syncframe = 0x1,
- Asyncframe = 0x2,
- Analog = 0x1,
- Digital = 0x2,
- Version = 0x100,
- };
- enum {
- Tstart = 1,
- Rstart = 2,
- Tstop = 3,
- Rstop = 4,
- Techo = 5,
- Recho = 6,
- Tcallout = 7,
- Rcallout = 8,
- Tcallreq = 9,
- Rcallreq = 10,
- Acallcon = 11,
- Tcallclear = 12,
- Acalldis = 13,
- Awaninfo = 14,
- Alinkinfo = 15,
- };
- void
- recho(uchar *in)
- {
- uchar out[20];
- if(nhgets(in) < 16)
- return;
- memset(out, 0, sizeof out);
- hnputs(out, sizeof out);
- hnputs(out+2, 1);
- hnputl(out+4, Magic);
- hnputs(out+8, Recho);
- memmove(out+12, in+12, 4);
- out[16] = 1;
- ewrite(ctlfd, out, sizeof out);
- }
- void
- sendecho(void)
- {
- uchar out[16];
- ctlechotime = now;
- memset(out, 0, sizeof out);
- hnputs(out, sizeof out);
- hnputs(out+2, 1);
- hnputl(out+4, Magic);
- hnputs(out+8, Techo);
- ewrite(ctlfd, out, sizeof out);
- }
- void
- pptpctlproc(void*)
- {
- uchar pkt[1600], *p;
- int len;
- for(;;){
- if(readn(ctlfd, pkt, 2) != 2)
- myfatal("pptpread: %r");
- len = nhgets(pkt);
- if(len < 12 || len+2 >= sizeof pkt)
- myfatal("pptpread: bad length %d", len);
- if(readn(ctlfd, pkt+2, len-2) != len-2)
- myfatal("pptpread: %r");
- if(nhgetl(pkt+4) != Magic)
- myfatal("pptpread bad magic");
- if(nhgets(pkt+2) != 1)
- myfatal("pptpread bad message type");
- if(debug)
- dumpctlpkt(pkt);
- ctlrcvtime = now;
- switch(nhgets(pkt+8)){
- case Tstart:
- case Tstop:
- case Tcallout:
- case Tcallreq:
- case Tcallclear:
- case Acallcon:
- case Acalldis:
- case Awaninfo:
- myfatal("unexpected msg type %d", nhgets(pkt+8));
- case Techo:
- recho(pkt);
- break;
- case Recho:
- break;
- case Rstart:
- case Rstop:
- case Rcallout:
- case Rcallreq:
- if(rdexpect != nhgets(pkt+8))
- continue;
- p = emalloc(len);
- memmove(p, pkt, len);
- sendp(rdchan, p);
- break;
- case Alinkinfo:
- myfatal("cannot change ppp params on the fly");
- }
- }
- }
- enum {
- Seqnum = 0x1000,
- Acknum = 0x0080,
- GrePPP = 0x880B,
- };
- void
- grereadproc(void*)
- {
- int datoff, flags, len, n, pass;
- uchar pkt[1600];
- uchar src[IPaddrlen], dst[IPaddrlen];
- rfork(RFFDG);
- close(pppfd);
- sendul(pidchan, getpid());
- while((n = read(grefd, pkt, sizeof pkt)) > 0){
- if(n == sizeof pkt)
- myfatal("gre pkt buffer too small");
- if(n < 16){
- if(debug)
- fprint(2, "small pkt len %d ignored\n", n);
- continue;
- }
- v4tov6(src, pkt);
- v4tov6(dst, pkt+4);
- if(ipcmp(src, remoteip) != 0 || ipcmp(dst, localip) != 0)
- myfatal("%I: gre read bad address src=%I dst=%I",
- remoteip, src, dst);
- if(nhgets(pkt+10) != GrePPP)
- myfatal("%I: gre read bad protocol 0x%x",
- remoteip, nhgets(pkt+10));
- flags = nhgets(pkt+8);
- if((flags&0xEF7F) != 0x2001){
- if(debug)
- fprint(2, "bad flags in gre hdr 0x%x\n", flags);
- continue;
- }
- datoff = 8+8;
- pass = 0;
- len = nhgets(pkt+8+4);
- if(len > n-datoff){
- fprint(2, "bad payload length %d > %d\n",
- len, n-datoff);
- continue;
- }
- if(flags&Seqnum)
- datoff += 4;
- if(flags&Acknum){
- recordack(nhgetl(pkt+datoff));
- datoff += 4;
- }
- if(flags&Seqnum)
- pass = schedack(nhgetl(pkt+8+8), pkt+datoff, len);
- if(debug)
- fprint(2, "got gre callid %d len %d flag 0x%x pass %d seq %d rseq %d\n", nhgets(pkt+8+6),
- len, flags, pass, nhgetl(pkt+8+8), rseq);
- }
- threadexits(nil);
- }
- void
- pppreadproc(void*)
- {
- int n, myrseq;
- uchar pkt[1600];
- enum {
- Hdr = 8+16,
- };
- rfork(RFFDG);
- close(pppfd);
- sendul(pidchan, getpid());
- while((n = read(topppfd, pkt+Hdr, sizeof pkt-Hdr)) > 0){
- if(n == sizeof pkt-Hdr)
- myfatal("ppp pkt buffer too small");
- v6tov4(pkt+0, localip);
- v6tov4(pkt+4, remoteip);
- hnputs(pkt+8, 0x2001 | Seqnum | Acknum);
- hnputs(pkt+10, GrePPP);
- hnputs(pkt+12, n);
- hnputs(pkt+14, remid);
- hnputl(pkt+16, ++seq);
- myrseq = rseq;
- hnputl(pkt+20, myrseq);
- rack = myrseq;
- if(debug)
- fprint(2, "wrote gre callid %d len %d flag 0x%x seq %d rseq %d\n", nhgets(pkt+8+6),
- n, nhgets(pkt+8), nhgetl(pkt+16), nhgetl(pkt+20));
- if(write(grefd, pkt, n+Hdr) != n+Hdr)
- myfatal("gre write: %r");
- waitacks();
- }
- threadexits(nil);
- }
- void
- sendack(void)
- {
- int myrseq;
- uchar pkt[20];
- v6tov4(pkt+0, localip);
- v6tov4(pkt+4, remoteip);
- hnputs(pkt+8, 0x2001 | Acknum);
- hnputs(pkt+10, GrePPP);
- hnputs(pkt+12, 0);
- hnputs(pkt+14, remid);
- myrseq = rseq;
- rack = myrseq;
- hnputs(pkt+16, myrseq);
- if(write(grefd, pkt, sizeof pkt) != sizeof pkt)
- myfatal("gre write: %r");
- }
- int
- schedack(int n, uchar *dat, int len)
- {
- static uchar sdat[1600];
- static int srseq, slen;
- if(n-rseq <= 0){
- fprint(2, "skipping pkt %d len %d, have %d\n", n, len, rseq);
- return 0;
- }
- /* missed one pkt, maybe a swap happened, save pkt */
- if(n==rseq+2){
- memmove(sdat, dat, len);
- slen = len;
- srseq = n;
- return 0;
- }
- if(n-rseq > 1){
- if(slen && srseq == n-1){
- fprint(2, "reswapped pkts %d and %d\n", srseq, n);
- write(topppfd, sdat, slen);
- slen = 0;
- }else
- fprint(2, "missed pkts %d-%d, got %d len %d\n", rseq+1, n-1, n, len);
- }
- write(topppfd, dat, len);
- rseq = n;
- /* send ack if we haven't recently */
- if((int)(rseq-rack) > (localwin>>1))
- sendack();
- return 1;
- }
- void
- gretimeoutproc(void*)
- {
- for(;;){
- sleep(Tick);
- now++;
- nbsendul(tickchan, now);
- if(now - ctlrcvtime > Servertimeout)
- myfatal("server timeout");
- if(now - ctlechotime > Echointerval)
- sendecho();
- }
- }
- void
- recordack(int n)
- {
- ack = n;
- }
- void
- waitacks(void)
- {
- /*
- int start;
- start = now;
- while(seq-ack > remwin && now-start < Sendtimeout){
- print("seq %d ack %d remwin %d now %d start %d\n",
- seq, ack, remwin, now, start);
- recvul(tickchan);
- }
- */
- }
- void
- tstart(void)
- {
- char *name;
- uchar pkt[200], *rpkt;
- memset(pkt, 0, sizeof pkt);
- hnputs(pkt+0, 156);
- hnputs(pkt+2, 1);
- hnputl(pkt+4, Magic);
- hnputs(pkt+8, Tstart);
- hnputs(pkt+12, PptpProto);
- hnputl(pkt+16, 1);
- hnputl(pkt+20, 1);
- hnputs(pkt+24, 1);
- name = sysname();
- if(name == nil)
- name = "gnot";
- strcpy((char*)pkt+28, name);
- strcpy((char*)pkt+92, "plan 9");
- if(debug)
- dumpctlpkt(pkt);
- rdexpect = Rstart;
- ewrite(ctlfd, pkt, 156);
- rpkt = recvp(rdchan);
- if(rpkt == nil)
- myfatal("recvp: %r");
- if(nhgets(rpkt) != 156)
- myfatal("Rstart wrong length %d != 156", nhgets(rpkt));
- if(rpkt[14] != 1)
- myfatal("Rstart error %d", rpkt[15]);
- free(rpkt);
- }
- void
- tcallout(void)
- {
- uchar pkt[200], *rpkt;
- pid = getpid();
- memset(pkt, 0, sizeof pkt);
- hnputs(pkt+0, 168);
- hnputs(pkt+2, 1);
- hnputl(pkt+4, Magic);
- hnputs(pkt+8, Tcallout);
- hnputl(pkt+16, 56000);
- hnputl(pkt+20, 768000);
- hnputl(pkt+24, 3);
- hnputl(pkt+28, 3);
- if(localwin == 0)
- localwin = Window;
- hnputs(pkt+32, localwin);
- if(debug)
- dumpctlpkt(pkt);
- rdexpect = Rcallout;
- ewrite(ctlfd, pkt, 168);
- rpkt = recvp(rdchan);
- if(rpkt == nil)
- myfatal("recvp: %r");
- if(nhgets(rpkt) != 32)
- myfatal("Rcallreq wrong length %d != 32", nhgets(rpkt));
- if(rpkt[16] != 1)
- myfatal("Rcallreq error %d", rpkt[17]);
- remid = nhgets(pkt+12);
- remwin = nhgets(pkt+24);
- free(rpkt);
- }
- /*
- void
- tcallreq(void)
- {
- uchar pkt[200], *rpkt;
- pid = getpid();
- memset(pkt, 0, sizeof pkt);
- hnputs(pkt+0, 220);
- hnputs(pkt+2, 1);
- hnputl(pkt+4, Magic);
- hnputs(pkt+8, Tcallreq);
- if(debug)
- dumpctlpkt(pkt);
- rdexpect = Rcallreq;
- ewrite(ctlfd, pkt, 220);
- rpkt = recvp(rdchan);
- if(rpkt == nil)
- myfatal("recvp: %r");
- if(nhgets(rpkt) != 24)
- myfatal("Rcallreq wrong length %d != 24", nhgets(rpkt));
- if(rpkt[16] != 1)
- myfatal("Rcallreq error %d", rpkt[17]);
- remid = nhgets(pkt+12);
- remwin = nhgets(pkt+18);
- free(rpkt);
- }
- void
- acallcon(void)
- {
- uchar pkt[200];
- memset(pkt, 0, sizeof pkt);
- hnputs(pkt+0, 28);
- hnputs(pkt+2, 1);
- hnputl(pkt+4, Magic);
- hnputs(pkt+8, Acallcon);
- hnputs(pkt+12, remid);
- if(localwin == 0)
- localwin = Window;
- hnputs(pkt+20, localwin);
- hnputl(pkt+24, 1);
- if(debug)
- dumpctlpkt(pkt);
- ewrite(ctlfd, pkt, 28);
- }
- */
- int
- pptp(char *addr)
- {
- int p[2];
- char greaddr[128];
- addr = netmkaddr(addr, "net", "pptp");
- ctlfd = dial(addr, nil, tcpdir, nil);
- if(ctlfd < 0)
- myfatal("dial %s: %r", addr);
- getaddrs();
- rdchan = chancreate(sizeof(void*), 0);
- proccreate(pptpctlproc, nil, Stack);
- tstart();
- tcallout();
- if(pipe(p) < 0)
- myfatal("pipe: %r");
- pppfd = p[0];
- topppfd = p[1];
- strcpy(greaddr, tcpdir);
- *strrchr(greaddr, '/') = '\0';
- sprint(strrchr(greaddr, '/')+1, "gre!%I!%d", remoteip, GrePPP);
- print("local %I remote %I gre %s remid %d remwin %d\n",
- localip, remoteip, greaddr, remid, remwin);
- grefd = dial(greaddr, nil, nil, nil);
- if(grefd < 0)
- myfatal("dial gre: %r");
- tickchan = chancreate(sizeof(int), 0);
- proccreate(gretimeoutproc, nil, Stack);
- pidchan = chancreate(sizeof(int), 0);
- proccreate(grereadproc, nil, Stack);
- recvul(pidchan);
- proccreate(pppreadproc, nil, Stack);
- recvul(pidchan);
- close(topppfd);
- return pppfd;
- }
-
- void
- pushppp(int fd)
- {
- char *argv[16];
- int argc;
- argc = 0;
- argv[argc++] = "/bin/ip/ppp";
- argv[argc++] = "-C";
- argv[argc++] = "-m1450";
- if(debug)
- argv[argc++] = "-d";
- if(primary)
- argv[argc++] = "-P";
- if(pppnetmntpt){
- argv[argc++] = "-x";
- argv[argc++] = pppnetmntpt;
- }
- if(keyspec){
- argv[argc++] = "-k";
- argv[argc++] = keyspec;
- }
- argv[argc] = nil;
- switch(fork()){
- case -1:
- myfatal("fork: %r");
- default:
- return;
- case 0:
- dup(fd, 0);
- dup(fd, 1);
- exec(argv[0], argv);
- myfatal("exec: %r");
- }
- }
- int
- aread(int timeout, int fd, void *buf, int nbuf)
- {
- int n;
- alarmed = 0;
- alarm(timeout);
- n = read(fd, buf, nbuf);
- alarm(0);
- if(alarmed)
- return -1;
- if(n < 0)
- myfatal("read: %r");
- if(n == 0)
- myfatal("short read");
- return n;
- }
- void
- ewrite(int fd, void *buf, int nbuf)
- {
- char e[ERRMAX], path[64];
- if(write(fd, buf, nbuf) != nbuf){
- rerrstr(e, sizeof e);
- strcpy(path, "unknown");
- fd2path(fd, path, sizeof path);
- myfatal("write %d to %s: %s", nbuf, path, e);
- }
- }
- void*
- emalloc(long n)
- {
- void *v;
- v = malloc(n);
- if(v == nil)
- myfatal("out of memory");
- return v;
- }
- int
- thread(void(*f)(void*), void *a)
- {
- int pid;
- pid=rfork(RFNOWAIT|RFMEM|RFPROC);
- if(pid < 0)
- myfatal("rfork: %r");
- if(pid != 0)
- return pid;
- (*f)(a);
- _exits(nil);
- return 0; // never reaches here
- }
- void
- dumpctlpkt(uchar *pkt)
- {
- fprint(2, "pkt len %d mtype %d cookie 0x%.8ux type %d\n",
- nhgets(pkt), nhgets(pkt+2),
- nhgetl(pkt+4), nhgets(pkt+8));
- switch(nhgets(pkt+8)){
- default:
- fprint(2, "\tunknown type\n");
- break;
- case Tstart:
- fprint(2, "\tTstart proto %d framing %d bearer %d maxchan %d firmware %d\n",
- nhgets(pkt+12), nhgetl(pkt+16),
- nhgetl(pkt+20), nhgets(pkt+24),
- nhgets(pkt+26));
- fprint(2, "\thost %.64s\n", (char*)pkt+28);
- fprint(2, "\tvendor %.64s\n", (char*)pkt+92);
- break;
- case Rstart:
- fprint(2, "\tRstart proto %d res %d err %d framing %d bearer %d maxchan %d firmware %d\n",
- nhgets(pkt+12), pkt[14], pkt[15],
- nhgetl(pkt+16),
- nhgetl(pkt+20), nhgets(pkt+24),
- nhgets(pkt+26));
- fprint(2, "\thost %.64s\n", (char*)pkt+28);
- fprint(2, "\tvendor %.64s\n", (char*)pkt+92);
- break;
- case Tstop:
- fprint(2, "\tTstop reason %d\n", pkt[12]);
- break;
- case Rstop:
- fprint(2, "\tRstop res %d err %d\n", pkt[12], pkt[13]);
- break;
- case Techo:
- fprint(2, "\tTecho id %.8ux\n", nhgetl(pkt+12));
- break;
- case Recho:
- fprint(2, "\tRecho id %.8ux res %d err %d\n", nhgetl(pkt+12), pkt[16], pkt[17]);
- break;
- case Tcallout:
- fprint(2, "\tTcallout id %d serno %d bps %d-%d\n",
- nhgets(pkt+12), nhgets(pkt+14),
- nhgetl(pkt+16), nhgetl(pkt+20));
- fprint(2, "\tbearer 0x%x framing 0x%x recvwin %d delay %d\n",
- nhgetl(pkt+24), nhgetl(pkt+28),
- nhgets(pkt+32), nhgets(pkt+34));
- fprint(2, "\tphone len %d num %.64s\n",
- nhgets(pkt+36), (char*)pkt+40);
- fprint(2, "\tsubaddr %.64s\n", (char*)pkt+104);
- break;
- case Rcallout:
- fprint(2, "\tRcallout id %d peerid %d res %d err %d cause %d\n",
- nhgets(pkt+12), nhgets(pkt+14),
- pkt[16], pkt[17], nhgets(pkt+18));
- fprint(2, "\tconnect %d recvwin %d delay %d chan 0x%.8ux\n",
- nhgetl(pkt+20), nhgets(pkt+24),
- nhgets(pkt+26), nhgetl(pkt+28));
- break;
- case Tcallreq:
- fprint(2, "\tTcallreq id %d serno %d bearer 0x%x id 0x%x\n",
- nhgets(pkt+12), nhgets(pkt+14),
- nhgetl(pkt+16), nhgetl(pkt+20));
- fprint(2, "\tdialed len %d num %.64s\n",
- nhgets(pkt+24), (char*)pkt+28);
- fprint(2, "\tdialing len %d num %.64s\n",
- nhgets(pkt+26), (char*)pkt+92);
- fprint(2, "\tsubaddr %.64s\n", (char*)pkt+156);
- break;
- case Rcallreq:
- fprint(2, "\tRcallout id %d peerid %d res %d err %d recvwin %d delay %d\n",
- nhgets(pkt+12), nhgets(pkt+14),
- pkt[16], pkt[17], nhgets(pkt+18),
- nhgets(pkt+20));
- break;
- case Acallcon:
- fprint(2, "\tAcallcon peerid %d connect %d recvwin %d delay %d framing 0x%x\n",
- nhgets(pkt+12), nhgetl(pkt+16),
- nhgets(pkt+20), nhgets(pkt+22),
- nhgetl(pkt+24));
- break;
- case Tcallclear:
- fprint(2, "\tTcallclear callid %d\n",
- nhgets(pkt+12));
- break;
- case Acalldis:
- fprint(2, "\tAcalldis callid %d res %d err %d cause %d\n",
- nhgets(pkt+12), pkt[14], pkt[15],
- nhgets(pkt+16));
- fprint(2, "\tstats %.128s\n", (char*)pkt+20);
- break;
- case Awaninfo:
- fprint(2, "\tAwaninfo peerid %d\n", nhgets(pkt+12));
- fprint(2, "\tcrc errors %d\n", nhgetl(pkt+16));
- fprint(2, "\tframe errors %d\n", nhgetl(pkt+20));
- fprint(2, "\thardware overruns %d\n", nhgetl(pkt+24));
- fprint(2, "\tbuffer overruns %d\n", nhgetl(pkt+28));
- fprint(2, "\ttime-out errors %d\n", nhgetl(pkt+32));
- fprint(2, "\talignment errors %d\n", nhgetl(pkt+36));
- break;
- case Alinkinfo:
- fprint(2, "\tAlinkinfo peerid %d sendaccm 0x%ux recvaccm 0x%ux\n",
- nhgets(pkt+12), nhgetl(pkt+16),
- nhgetl(pkt+20));
- break;
- }
- }
- void
- getaddrs(void)
- {
- char buf[128];
- int fd, n;
- sprint(buf, "%s/local", tcpdir);
- if((fd = open(buf, OREAD)) < 0)
- myfatal("could not open %s: %r", buf);
- if((n = read(fd, buf, sizeof(buf))) < 0)
- myfatal("could not read %s: %r", buf);
- buf[n] = 0;
- parseip(localip, buf);
- close(fd);
- sprint(buf, "%s/remote", tcpdir);
- if((fd = open(buf, OREAD)) < 0)
- myfatal("could not open %s: %r", buf);
- if((n = read(fd, buf, sizeof(buf))) < 0)
- myfatal("could not read %s: %r", buf);
- buf[n] = 0;
- parseip(remoteip, buf);
- close(fd);
- }
- void
- myfatal(char *fmt, ...)
- {
- char sbuf[512];
- va_list arg;
- uchar buf[16];
- memset(buf, 0, sizeof(buf));
- hnputs(buf+0, sizeof(buf)); /* length */
- hnputs(buf+2, 1); /* message type */
- hnputl(buf+4, Magic); /* magic */
- hnputs(buf+8, Tstop); /* op */
- buf[12] = 3; /* local shutdown */
- write(ctlfd, buf, sizeof(buf));
- va_start(arg, fmt);
- vseprint(sbuf, sbuf+sizeof(sbuf), fmt, arg);
- va_end(arg);
- fprint(2, "fatal: %s\n", sbuf);
- threadexitsall(nil);
- }
|