pptp.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Point-to-point Tunneling Protocol (PPTP)
  11. * See RFC 2637, pptpd.c
  12. */
  13. #include <u.h>
  14. #include <libc.h>
  15. #include <bio.h>
  16. #include <ip.h>
  17. #include <thread.h>
  18. int ack;
  19. int alarmed;
  20. int ctlechotime;
  21. int ctlfd;
  22. int ctlrcvtime;
  23. int debug;
  24. int grefd;
  25. uint8_t localip[IPaddrlen];
  26. int localwin;
  27. char *keyspec;
  28. int now;
  29. char *pppnetmntpt;
  30. int pid;
  31. Channel *pidchan;
  32. int pppfd;
  33. int primary;
  34. int rack;
  35. Channel *rdchan;
  36. int rdexpect;
  37. int remid;
  38. uint8_t remoteip[IPaddrlen];
  39. int remwin;
  40. int rseq;
  41. int seq;
  42. char tcpdir[40];
  43. Channel *tickchan;
  44. int topppfd;
  45. int aread(int, int, void*, int);
  46. int catchalarm(void*, char*);
  47. void dumpctlpkt(uint8_t*);
  48. void getaddrs(void);
  49. void *emalloc(int32_t);
  50. void ewrite(int, void*, int);
  51. void myfatal(char*, ...);
  52. #pragma varargck argpos myfatal 1
  53. int pptp(char*);
  54. void pushppp(int);
  55. void recordack(int);
  56. int schedack(int, uint8_t*, int);
  57. void waitacks(void);
  58. void
  59. usage(void)
  60. {
  61. fprint(2, "usage: ip/pptp [-Pd] [-k keyspec] [-x pppnetmntpt] [-w window] server\n");
  62. exits("usage");
  63. }
  64. void
  65. threadmain(int argc, char **argv)
  66. {
  67. int fd;
  68. ARGBEGIN{
  69. case 'P':
  70. primary = 1;
  71. break;
  72. case 'd':
  73. debug++;
  74. break;
  75. case 'k':
  76. keyspec = EARGF(usage());
  77. break;
  78. case 'w':
  79. localwin = atoi(EARGF(usage()));
  80. break;
  81. case 'x':
  82. pppnetmntpt = EARGF(usage());
  83. break;
  84. default:
  85. usage();
  86. }ARGEND
  87. if(argc != 1)
  88. usage();
  89. fmtinstall('E', eipfmt);
  90. fmtinstall('I', eipfmt);
  91. rfork(RFNOTEG);
  92. atnotify(catchalarm, 1);
  93. fd = pptp(argv[0]);
  94. pushppp(fd);
  95. exits(nil);
  96. }
  97. int
  98. catchalarm(void *a, char *msg)
  99. {
  100. USED(a);
  101. if(strstr(msg, "alarm")){
  102. alarmed = 1;
  103. return 1;
  104. }
  105. if(debug)
  106. fprint(2, "note rcved: %s\n", msg);
  107. return 0;
  108. }
  109. enum {
  110. Stack = 8192,
  111. PptpProto = 0x0100,
  112. Magic = 0x1a2b3c4d,
  113. Window = 16, /* default window size */
  114. Timeout = 60, /* timeout in seconds for control channel */
  115. Pktsize = 2000, /* maximum packet size */
  116. Tick = 500, /* tick length in milliseconds */
  117. Sendtimeout = 4, /* in ticks */
  118. Servertimeout = 5*60*1000/Tick,
  119. Echointerval = 60*1000/Tick,
  120. };
  121. enum {
  122. Syncframe = 0x1,
  123. Asyncframe = 0x2,
  124. Analog = 0x1,
  125. Digital = 0x2,
  126. Version = 0x100,
  127. };
  128. enum {
  129. Tstart = 1,
  130. Rstart = 2,
  131. Tstop = 3,
  132. Rstop = 4,
  133. Techo = 5,
  134. Recho = 6,
  135. Tcallout = 7,
  136. Rcallout = 8,
  137. Tcallreq = 9,
  138. Rcallreq = 10,
  139. Acallcon = 11,
  140. Tcallclear = 12,
  141. Acalldis = 13,
  142. Awaninfo = 14,
  143. Alinkinfo = 15,
  144. };
  145. void
  146. recho(uint8_t *in)
  147. {
  148. uint8_t out[20];
  149. if(nhgets(in) < 16)
  150. return;
  151. memset(out, 0, sizeof out);
  152. hnputs(out, sizeof out);
  153. hnputs(out+2, 1);
  154. hnputl(out+4, Magic);
  155. hnputs(out+8, Recho);
  156. memmove(out+12, in+12, 4);
  157. out[16] = 1;
  158. ewrite(ctlfd, out, sizeof out);
  159. }
  160. void
  161. sendecho(void)
  162. {
  163. uint8_t out[16];
  164. ctlechotime = now;
  165. memset(out, 0, sizeof out);
  166. hnputs(out, sizeof out);
  167. hnputs(out+2, 1);
  168. hnputl(out+4, Magic);
  169. hnputs(out+8, Techo);
  170. ewrite(ctlfd, out, sizeof out);
  171. }
  172. void
  173. pptpctlproc(void *v)
  174. {
  175. uint8_t pkt[1600], *p;
  176. int len;
  177. for(;;){
  178. if(readn(ctlfd, pkt, 2) != 2)
  179. myfatal("pptpread: %r");
  180. len = nhgets(pkt);
  181. if(len < 12 || len+2 >= sizeof pkt)
  182. myfatal("pptpread: bad length %d", len);
  183. if(readn(ctlfd, pkt+2, len-2) != len-2)
  184. myfatal("pptpread: %r");
  185. if(nhgetl(pkt+4) != Magic)
  186. myfatal("pptpread bad magic");
  187. if(nhgets(pkt+2) != 1)
  188. myfatal("pptpread bad message type");
  189. if(debug)
  190. dumpctlpkt(pkt);
  191. ctlrcvtime = now;
  192. switch(nhgets(pkt+8)){
  193. case Tstart:
  194. case Tstop:
  195. case Tcallout:
  196. case Tcallreq:
  197. case Tcallclear:
  198. case Acallcon:
  199. case Acalldis:
  200. case Awaninfo:
  201. myfatal("unexpected msg type %d", nhgets(pkt+8));
  202. case Techo:
  203. recho(pkt);
  204. break;
  205. case Recho:
  206. break;
  207. case Rstart:
  208. case Rstop:
  209. case Rcallout:
  210. case Rcallreq:
  211. if(rdexpect != nhgets(pkt+8))
  212. continue;
  213. p = emalloc(len);
  214. memmove(p, pkt, len);
  215. sendp(rdchan, p);
  216. break;
  217. case Alinkinfo:
  218. myfatal("cannot change ppp params on the fly");
  219. }
  220. }
  221. }
  222. enum {
  223. Seqnum = 0x1000,
  224. Acknum = 0x0080,
  225. GrePPP = 0x880B,
  226. };
  227. void
  228. grereadproc(void *v)
  229. {
  230. int datoff, flags, len, n, pass;
  231. uint8_t pkt[1600];
  232. uint8_t src[IPaddrlen], dst[IPaddrlen];
  233. rfork(RFFDG);
  234. close(pppfd);
  235. sendul(pidchan, getpid());
  236. while((n = read(grefd, pkt, sizeof pkt)) > 0){
  237. if(n == sizeof pkt)
  238. myfatal("gre pkt buffer too small");
  239. if(n < 16){
  240. if(debug)
  241. fprint(2, "small pkt len %d ignored\n", n);
  242. continue;
  243. }
  244. v4tov6(src, pkt);
  245. v4tov6(dst, pkt+4);
  246. if(ipcmp(src, remoteip) != 0 || ipcmp(dst, localip) != 0)
  247. myfatal("%I: gre read bad address src=%I dst=%I",
  248. remoteip, src, dst);
  249. if(nhgets(pkt+10) != GrePPP)
  250. myfatal("%I: gre read bad protocol 0x%x",
  251. remoteip, nhgets(pkt+10));
  252. flags = nhgets(pkt+8);
  253. if((flags&0xEF7F) != 0x2001){
  254. if(debug)
  255. fprint(2, "bad flags in gre hdr 0x%x\n", flags);
  256. continue;
  257. }
  258. datoff = 8+8;
  259. pass = 0;
  260. len = nhgets(pkt+8+4);
  261. if(len > n-datoff){
  262. fprint(2, "bad payload length %d > %d\n",
  263. len, n-datoff);
  264. continue;
  265. }
  266. if(flags&Seqnum)
  267. datoff += 4;
  268. if(flags&Acknum){
  269. recordack(nhgetl(pkt+datoff));
  270. datoff += 4;
  271. }
  272. if(flags&Seqnum)
  273. pass = schedack(nhgetl(pkt+8+8), pkt+datoff, len);
  274. if(debug)
  275. fprint(2, "got gre callid %d len %d flag 0x%x pass %d seq %d rseq %d\n", nhgets(pkt+8+6),
  276. len, flags, pass, nhgetl(pkt+8+8), rseq);
  277. }
  278. threadexits(nil);
  279. }
  280. void
  281. pppreadproc(void *v)
  282. {
  283. int n, myrseq;
  284. uint8_t pkt[1600];
  285. enum {
  286. Hdr = 8+16,
  287. };
  288. rfork(RFFDG);
  289. close(pppfd);
  290. sendul(pidchan, getpid());
  291. while((n = read(topppfd, pkt+Hdr, sizeof pkt-Hdr)) > 0){
  292. if(n == sizeof pkt-Hdr)
  293. myfatal("ppp pkt buffer too small");
  294. v6tov4(pkt+0, localip);
  295. v6tov4(pkt+4, remoteip);
  296. hnputs(pkt+8, 0x2001 | Seqnum | Acknum);
  297. hnputs(pkt+10, GrePPP);
  298. hnputs(pkt+12, n);
  299. hnputs(pkt+14, remid);
  300. hnputl(pkt+16, ++seq);
  301. myrseq = rseq;
  302. hnputl(pkt+20, myrseq);
  303. rack = myrseq;
  304. if(debug)
  305. fprint(2, "wrote gre callid %d len %d flag 0x%x seq %d rseq %d\n", nhgets(pkt+8+6),
  306. n, nhgets(pkt+8), nhgetl(pkt+16), nhgetl(pkt+20));
  307. if(write(grefd, pkt, n+Hdr) != n+Hdr)
  308. myfatal("gre write: %r");
  309. waitacks();
  310. }
  311. threadexits(nil);
  312. }
  313. void
  314. sendack(void)
  315. {
  316. int myrseq;
  317. uint8_t pkt[20];
  318. v6tov4(pkt+0, localip);
  319. v6tov4(pkt+4, remoteip);
  320. hnputs(pkt+8, 0x2001 | Acknum);
  321. hnputs(pkt+10, GrePPP);
  322. hnputs(pkt+12, 0);
  323. hnputs(pkt+14, remid);
  324. myrseq = rseq;
  325. rack = myrseq;
  326. hnputs(pkt+16, myrseq);
  327. if(write(grefd, pkt, sizeof pkt) != sizeof pkt)
  328. myfatal("gre write: %r");
  329. }
  330. int
  331. schedack(int n, uint8_t *dat, int len)
  332. {
  333. static uint8_t sdat[1600];
  334. static int srseq, slen;
  335. if(n-rseq <= 0){
  336. fprint(2, "skipping pkt %d len %d, have %d\n", n, len, rseq);
  337. return 0;
  338. }
  339. /* missed one pkt, maybe a swap happened, save pkt */
  340. if(n==rseq+2){
  341. memmove(sdat, dat, len);
  342. slen = len;
  343. srseq = n;
  344. return 0;
  345. }
  346. if(n-rseq > 1){
  347. if(slen && srseq == n-1){
  348. fprint(2, "reswapped pkts %d and %d\n", srseq, n);
  349. write(topppfd, sdat, slen);
  350. slen = 0;
  351. }else
  352. fprint(2, "missed pkts %d-%d, got %d len %d\n", rseq+1, n-1, n, len);
  353. }
  354. write(topppfd, dat, len);
  355. rseq = n;
  356. /* send ack if we haven't recently */
  357. if((int)(rseq-rack) > (localwin>>1))
  358. sendack();
  359. return 1;
  360. }
  361. void
  362. gretimeoutproc(void *v)
  363. {
  364. for(;;){
  365. sleep(Tick);
  366. now++;
  367. nbsendul(tickchan, now);
  368. if(now - ctlrcvtime > Servertimeout)
  369. myfatal("server timeout");
  370. if(now - ctlechotime > Echointerval)
  371. sendecho();
  372. }
  373. }
  374. void
  375. recordack(int n)
  376. {
  377. ack = n;
  378. }
  379. void
  380. waitacks(void)
  381. {
  382. /*
  383. int start;
  384. start = now;
  385. while(seq-ack > remwin && now-start < Sendtimeout){
  386. print("seq %d ack %d remwin %d now %d start %d\n",
  387. seq, ack, remwin, now, start);
  388. recvul(tickchan);
  389. }
  390. */
  391. }
  392. void
  393. tstart(void)
  394. {
  395. char *name;
  396. uint8_t pkt[200], *rpkt;
  397. memset(pkt, 0, sizeof pkt);
  398. hnputs(pkt+0, 156);
  399. hnputs(pkt+2, 1);
  400. hnputl(pkt+4, Magic);
  401. hnputs(pkt+8, Tstart);
  402. hnputs(pkt+12, PptpProto);
  403. hnputl(pkt+16, 1);
  404. hnputl(pkt+20, 1);
  405. hnputs(pkt+24, 1);
  406. name = sysname();
  407. if(name == nil)
  408. name = "gnot";
  409. strcpy((char*)pkt+28, name);
  410. strcpy((char*)pkt+92, "plan 9");
  411. if(debug)
  412. dumpctlpkt(pkt);
  413. rdexpect = Rstart;
  414. ewrite(ctlfd, pkt, 156);
  415. rpkt = recvp(rdchan);
  416. if(rpkt == nil)
  417. myfatal("recvp: %r");
  418. if(nhgets(rpkt) != 156)
  419. myfatal("Rstart wrong length %d != 156", nhgets(rpkt));
  420. if(rpkt[14] != 1)
  421. myfatal("Rstart error %d", rpkt[15]);
  422. free(rpkt);
  423. }
  424. void
  425. tcallout(void)
  426. {
  427. uint8_t pkt[200], *rpkt;
  428. pid = getpid();
  429. memset(pkt, 0, sizeof pkt);
  430. hnputs(pkt+0, 168);
  431. hnputs(pkt+2, 1);
  432. hnputl(pkt+4, Magic);
  433. hnputs(pkt+8, Tcallout);
  434. hnputl(pkt+16, 56000);
  435. hnputl(pkt+20, 768000);
  436. hnputl(pkt+24, 3);
  437. hnputl(pkt+28, 3);
  438. if(localwin == 0)
  439. localwin = Window;
  440. hnputs(pkt+32, localwin);
  441. if(debug)
  442. dumpctlpkt(pkt);
  443. rdexpect = Rcallout;
  444. ewrite(ctlfd, pkt, 168);
  445. rpkt = recvp(rdchan);
  446. if(rpkt == nil)
  447. myfatal("recvp: %r");
  448. if(nhgets(rpkt) != 32)
  449. myfatal("Rcallreq wrong length %d != 32", nhgets(rpkt));
  450. if(rpkt[16] != 1)
  451. myfatal("Rcallreq error %d", rpkt[17]);
  452. remid = nhgets(pkt+12);
  453. remwin = nhgets(pkt+24);
  454. free(rpkt);
  455. }
  456. /*
  457. void
  458. tcallreq(void)
  459. {
  460. uint8_t pkt[200], *rpkt;
  461. pid = getpid();
  462. memset(pkt, 0, sizeof pkt);
  463. hnputs(pkt+0, 220);
  464. hnputs(pkt+2, 1);
  465. hnputl(pkt+4, Magic);
  466. hnputs(pkt+8, Tcallreq);
  467. if(debug)
  468. dumpctlpkt(pkt);
  469. rdexpect = Rcallreq;
  470. ewrite(ctlfd, pkt, 220);
  471. rpkt = recvp(rdchan);
  472. if(rpkt == nil)
  473. myfatal("recvp: %r");
  474. if(nhgets(rpkt) != 24)
  475. myfatal("Rcallreq wrong length %d != 24", nhgets(rpkt));
  476. if(rpkt[16] != 1)
  477. myfatal("Rcallreq error %d", rpkt[17]);
  478. remid = nhgets(pkt+12);
  479. remwin = nhgets(pkt+18);
  480. free(rpkt);
  481. }
  482. void
  483. acallcon(void)
  484. {
  485. uint8_t pkt[200];
  486. memset(pkt, 0, sizeof pkt);
  487. hnputs(pkt+0, 28);
  488. hnputs(pkt+2, 1);
  489. hnputl(pkt+4, Magic);
  490. hnputs(pkt+8, Acallcon);
  491. hnputs(pkt+12, remid);
  492. if(localwin == 0)
  493. localwin = Window;
  494. hnputs(pkt+20, localwin);
  495. hnputl(pkt+24, 1);
  496. if(debug)
  497. dumpctlpkt(pkt);
  498. ewrite(ctlfd, pkt, 28);
  499. }
  500. */
  501. int
  502. pptp(char *addr)
  503. {
  504. int p[2];
  505. char greaddr[128];
  506. addr = netmkaddr(addr, "net", "pptp");
  507. ctlfd = dial(addr, nil, tcpdir, nil);
  508. if(ctlfd < 0)
  509. myfatal("dial %s: %r", addr);
  510. getaddrs();
  511. rdchan = chancreate(sizeof(void*), 0);
  512. proccreate(pptpctlproc, nil, Stack);
  513. tstart();
  514. tcallout();
  515. if(pipe(p) < 0)
  516. myfatal("pipe: %r");
  517. pppfd = p[0];
  518. topppfd = p[1];
  519. strcpy(greaddr, tcpdir);
  520. *strrchr(greaddr, '/') = '\0';
  521. sprint(strrchr(greaddr, '/')+1, "gre!%I!%d", remoteip, GrePPP);
  522. print("local %I remote %I gre %s remid %d remwin %d\n",
  523. localip, remoteip, greaddr, remid, remwin);
  524. grefd = dial(greaddr, nil, nil, nil);
  525. if(grefd < 0)
  526. myfatal("dial gre: %r");
  527. tickchan = chancreate(sizeof(int), 0);
  528. proccreate(gretimeoutproc, nil, Stack);
  529. pidchan = chancreate(sizeof(int), 0);
  530. proccreate(grereadproc, nil, Stack);
  531. recvul(pidchan);
  532. proccreate(pppreadproc, nil, Stack);
  533. recvul(pidchan);
  534. close(topppfd);
  535. return pppfd;
  536. }
  537. void
  538. pushppp(int fd)
  539. {
  540. char *argv[16];
  541. int argc;
  542. argc = 0;
  543. argv[argc++] = "/bin/ip/ppp";
  544. argv[argc++] = "-C";
  545. argv[argc++] = "-m1450";
  546. if(debug)
  547. argv[argc++] = "-d";
  548. if(primary)
  549. argv[argc++] = "-P";
  550. if(pppnetmntpt){
  551. argv[argc++] = "-x";
  552. argv[argc++] = pppnetmntpt;
  553. }
  554. if(keyspec){
  555. argv[argc++] = "-k";
  556. argv[argc++] = keyspec;
  557. }
  558. argv[argc] = nil;
  559. switch(fork()){
  560. case -1:
  561. myfatal("fork: %r");
  562. default:
  563. return;
  564. case 0:
  565. dup(fd, 0);
  566. dup(fd, 1);
  567. exec(argv[0], argv);
  568. myfatal("exec: %r");
  569. }
  570. }
  571. int
  572. aread(int timeout, int fd, void *buf, int nbuf)
  573. {
  574. int n;
  575. alarmed = 0;
  576. alarm(timeout);
  577. n = read(fd, buf, nbuf);
  578. alarm(0);
  579. if(alarmed)
  580. return -1;
  581. if(n < 0)
  582. myfatal("read: %r");
  583. if(n == 0)
  584. myfatal("short read");
  585. return n;
  586. }
  587. void
  588. ewrite(int fd, void *buf, int nbuf)
  589. {
  590. char e[ERRMAX], path[64];
  591. if(write(fd, buf, nbuf) != nbuf){
  592. rerrstr(e, sizeof e);
  593. strcpy(path, "unknown");
  594. fd2path(fd, path, sizeof path);
  595. myfatal("write %d to %s: %s", nbuf, path, e);
  596. }
  597. }
  598. void*
  599. emalloc(int32_t n)
  600. {
  601. void *v;
  602. v = malloc(n);
  603. if(v == nil)
  604. myfatal("out of memory");
  605. return v;
  606. }
  607. int
  608. thread(void(*f)(void*), void *a)
  609. {
  610. int pid;
  611. pid=rfork(RFNOWAIT|RFMEM|RFPROC);
  612. if(pid < 0)
  613. myfatal("rfork: %r");
  614. if(pid != 0)
  615. return pid;
  616. (*f)(a);
  617. _exits(nil);
  618. return 0; // never reaches here
  619. }
  620. void
  621. dumpctlpkt(uint8_t *pkt)
  622. {
  623. fprint(2, "pkt len %d mtype %d cookie 0x%.8ux type %d\n",
  624. nhgets(pkt), nhgets(pkt+2),
  625. nhgetl(pkt+4), nhgets(pkt+8));
  626. switch(nhgets(pkt+8)){
  627. default:
  628. fprint(2, "\tunknown type\n");
  629. break;
  630. case Tstart:
  631. fprint(2, "\tTstart proto %d framing %d bearer %d maxchan %d firmware %d\n",
  632. nhgets(pkt+12), nhgetl(pkt+16),
  633. nhgetl(pkt+20), nhgets(pkt+24),
  634. nhgets(pkt+26));
  635. fprint(2, "\thost %.64s\n", (char*)pkt+28);
  636. fprint(2, "\tvendor %.64s\n", (char*)pkt+92);
  637. break;
  638. case Rstart:
  639. fprint(2, "\tRstart proto %d res %d err %d framing %d bearer %d maxchan %d firmware %d\n",
  640. nhgets(pkt+12), pkt[14], pkt[15],
  641. nhgetl(pkt+16),
  642. nhgetl(pkt+20), nhgets(pkt+24),
  643. nhgets(pkt+26));
  644. fprint(2, "\thost %.64s\n", (char*)pkt+28);
  645. fprint(2, "\tvendor %.64s\n", (char*)pkt+92);
  646. break;
  647. case Tstop:
  648. fprint(2, "\tTstop reason %d\n", pkt[12]);
  649. break;
  650. case Rstop:
  651. fprint(2, "\tRstop res %d err %d\n", pkt[12], pkt[13]);
  652. break;
  653. case Techo:
  654. fprint(2, "\tTecho id %.8ux\n", nhgetl(pkt+12));
  655. break;
  656. case Recho:
  657. fprint(2, "\tRecho id %.8ux res %d err %d\n", nhgetl(pkt+12), pkt[16], pkt[17]);
  658. break;
  659. case Tcallout:
  660. fprint(2, "\tTcallout id %d serno %d bps %d-%d\n",
  661. nhgets(pkt+12), nhgets(pkt+14),
  662. nhgetl(pkt+16), nhgetl(pkt+20));
  663. fprint(2, "\tbearer 0x%x framing 0x%x recvwin %d delay %d\n",
  664. nhgetl(pkt+24), nhgetl(pkt+28),
  665. nhgets(pkt+32), nhgets(pkt+34));
  666. fprint(2, "\tphone len %d num %.64s\n",
  667. nhgets(pkt+36), (char*)pkt+40);
  668. fprint(2, "\tsubaddr %.64s\n", (char*)pkt+104);
  669. break;
  670. case Rcallout:
  671. fprint(2, "\tRcallout id %d peerid %d res %d err %d cause %d\n",
  672. nhgets(pkt+12), nhgets(pkt+14),
  673. pkt[16], pkt[17], nhgets(pkt+18));
  674. fprint(2, "\tconnect %d recvwin %d delay %d chan 0x%.8ux\n",
  675. nhgetl(pkt+20), nhgets(pkt+24),
  676. nhgets(pkt+26), nhgetl(pkt+28));
  677. break;
  678. case Tcallreq:
  679. fprint(2, "\tTcallreq id %d serno %d bearer 0x%x id 0x%x\n",
  680. nhgets(pkt+12), nhgets(pkt+14),
  681. nhgetl(pkt+16), nhgetl(pkt+20));
  682. fprint(2, "\tdialed len %d num %.64s\n",
  683. nhgets(pkt+24), (char*)pkt+28);
  684. fprint(2, "\tdialing len %d num %.64s\n",
  685. nhgets(pkt+26), (char*)pkt+92);
  686. fprint(2, "\tsubaddr %.64s\n", (char*)pkt+156);
  687. break;
  688. case Rcallreq:
  689. fprint(2, "\tRcallout id %d peerid %d res %d err %d recvwin %d delay %d\n",
  690. nhgets(pkt+12), nhgets(pkt+14),
  691. pkt[16], pkt[17], nhgets(pkt+18),
  692. nhgets(pkt+20));
  693. break;
  694. case Acallcon:
  695. fprint(2, "\tAcallcon peerid %d connect %d recvwin %d delay %d framing 0x%x\n",
  696. nhgets(pkt+12), nhgetl(pkt+16),
  697. nhgets(pkt+20), nhgets(pkt+22),
  698. nhgetl(pkt+24));
  699. break;
  700. case Tcallclear:
  701. fprint(2, "\tTcallclear callid %d\n",
  702. nhgets(pkt+12));
  703. break;
  704. case Acalldis:
  705. fprint(2, "\tAcalldis callid %d res %d err %d cause %d\n",
  706. nhgets(pkt+12), pkt[14], pkt[15],
  707. nhgets(pkt+16));
  708. fprint(2, "\tstats %.128s\n", (char*)pkt+20);
  709. break;
  710. case Awaninfo:
  711. fprint(2, "\tAwaninfo peerid %d\n", nhgets(pkt+12));
  712. fprint(2, "\tcrc errors %d\n", nhgetl(pkt+16));
  713. fprint(2, "\tframe errors %d\n", nhgetl(pkt+20));
  714. fprint(2, "\thardware overruns %d\n", nhgetl(pkt+24));
  715. fprint(2, "\tbuffer overruns %d\n", nhgetl(pkt+28));
  716. fprint(2, "\ttime-out errors %d\n", nhgetl(pkt+32));
  717. fprint(2, "\talignment errors %d\n", nhgetl(pkt+36));
  718. break;
  719. case Alinkinfo:
  720. fprint(2, "\tAlinkinfo peerid %d sendaccm 0x%x recvaccm 0x%x\n",
  721. nhgets(pkt+12), nhgetl(pkt+16),
  722. nhgetl(pkt+20));
  723. break;
  724. }
  725. }
  726. void
  727. getaddrs(void)
  728. {
  729. char buf[128];
  730. int fd, n;
  731. sprint(buf, "%s/local", tcpdir);
  732. if((fd = open(buf, OREAD)) < 0)
  733. myfatal("could not open %s: %r", buf);
  734. if((n = read(fd, buf, sizeof(buf))) < 0)
  735. myfatal("could not read %s: %r", buf);
  736. buf[n] = 0;
  737. parseip(localip, buf);
  738. close(fd);
  739. sprint(buf, "%s/remote", tcpdir);
  740. if((fd = open(buf, OREAD)) < 0)
  741. myfatal("could not open %s: %r", buf);
  742. if((n = read(fd, buf, sizeof(buf))) < 0)
  743. myfatal("could not read %s: %r", buf);
  744. buf[n] = 0;
  745. parseip(remoteip, buf);
  746. close(fd);
  747. }
  748. void
  749. myfatal(char *fmt, ...)
  750. {
  751. char sbuf[512];
  752. va_list arg;
  753. uint8_t buf[16];
  754. memset(buf, 0, sizeof(buf));
  755. hnputs(buf+0, sizeof(buf)); /* length */
  756. hnputs(buf+2, 1); /* message type */
  757. hnputl(buf+4, Magic); /* magic */
  758. hnputs(buf+8, Tstop); /* op */
  759. buf[12] = 3; /* local shutdown */
  760. write(ctlfd, buf, sizeof(buf));
  761. va_start(arg, fmt);
  762. vseprint(sbuf, sbuf+sizeof(sbuf), fmt, arg);
  763. va_end(arg);
  764. fprint(2, "fatal: %s\n", sbuf);
  765. threadexitsall(nil);
  766. }