pptp.c 16 KB

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