main.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include <bio.h>
  5. #include <fcall.h>
  6. #include <libsec.h>
  7. #include "dat.h"
  8. #include "protos.h"
  9. #include "y.tab.h"
  10. int Cflag;
  11. int pflag;
  12. int Nflag;
  13. int Mflag;
  14. int sflag;
  15. int tiflag;
  16. int toflag;
  17. char *prom = "promiscuous";
  18. enum
  19. {
  20. Pktlen= 64*1024,
  21. Blen= 16*1024,
  22. };
  23. Filter *filter;
  24. Proto *root;
  25. Biobuf out;
  26. vlong starttime, pkttime;
  27. int pcap;
  28. int filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int);
  29. void printpkt(char *p, char *e, uchar *ps, uchar *pe);
  30. void mkprotograph(void);
  31. Proto* findproto(char *name);
  32. Filter* compile(Filter *f);
  33. void printfilter(Filter *f, char *tag);
  34. void printhelp(char*);
  35. void tracepkt(uchar*, int);
  36. void pcaphdr(void);
  37. void
  38. printusage(void)
  39. {
  40. fprint(2, "usage: %s [-CDdpst] [-N n] [-f filter] [-h first-header] path\n", argv0);
  41. fprint(2, " for protocol help: %s -? [proto]\n", argv0);
  42. }
  43. void
  44. usage(void)
  45. {
  46. printusage();
  47. exits("usage");
  48. }
  49. void
  50. main(int argc, char **argv)
  51. {
  52. uchar *pkt;
  53. char *buf, *file, *p, *e;
  54. int fd, cfd;
  55. int n;
  56. Binit(&out, 1, OWRITE);
  57. fmtinstall('E', eipfmt);
  58. fmtinstall('V', eipfmt);
  59. fmtinstall('I', eipfmt);
  60. fmtinstall('H', encodefmt);
  61. fmtinstall('F', fcallfmt);
  62. pkt = malloc(Pktlen+16);
  63. pkt += 16;
  64. buf = malloc(Blen);
  65. e = buf+Blen-1;
  66. pflag = 1;
  67. Nflag = 32;
  68. sflag = 0;
  69. mkprotograph();
  70. ARGBEGIN{
  71. default:
  72. usage();
  73. case '?':
  74. printusage();
  75. printhelp(ARGF());
  76. exits(0);
  77. break;
  78. case 'M':
  79. p = EARGF(usage());
  80. Mflag = atoi(p);
  81. break;
  82. case 'N':
  83. p = EARGF(usage());
  84. Nflag = atoi(p);
  85. break;
  86. case 'f':
  87. p = EARGF(usage());
  88. yyinit(p);
  89. yyparse();
  90. break;
  91. case 's':
  92. sflag = 1;
  93. break;
  94. case 'h':
  95. p = EARGF(usage());
  96. root = findproto(p);
  97. if(root == nil)
  98. sysfatal("unknown protocol: %s", p);
  99. break;
  100. case 'd':
  101. toflag = 1;
  102. break;
  103. case 'D':
  104. toflag = 1;
  105. pcap = 1;
  106. break;
  107. case 't':
  108. tiflag = 1;
  109. break;
  110. case 'C':
  111. Cflag = 1;
  112. break;
  113. case 'p':
  114. pflag = 0;
  115. break;
  116. }ARGEND;
  117. if(pcap)
  118. pcaphdr();
  119. if(argc == 0){
  120. file = "/net/ether0";
  121. if(root != nil)
  122. root = &ether;
  123. } else
  124. file = argv[0];
  125. if((!tiflag) && strstr(file, "ether")){
  126. if(root == nil)
  127. root = &ether;
  128. snprint(buf, Blen, "%s!-1", file);
  129. fd = dial(buf, 0, 0, &cfd);
  130. if(fd < 0)
  131. sysfatal("dialing %s", buf);
  132. if(pflag && fprint(cfd, prom, strlen(prom)) < 0)
  133. sysfatal("setting %s", prom);
  134. } else if((!tiflag) && strstr(file, "ipifc")){
  135. if(root == nil)
  136. root = &ip;
  137. snprint(buf, Blen, "%s/snoop", file);
  138. fd = open(buf, OREAD);
  139. if(fd < 0)
  140. sysfatal("opening %s: %r", buf);
  141. } else {
  142. if(root == nil)
  143. root = &ether;
  144. fd = open(file, OREAD);
  145. if(fd < 0)
  146. sysfatal("opening %s: %r", file);
  147. }
  148. filter = compile(filter);
  149. if(tiflag){
  150. /* read a trace file */
  151. for(;;){
  152. n = read(fd, pkt, 10);
  153. if(n != 10)
  154. break;
  155. pkttime = NetL(pkt+2);
  156. pkttime = (pkttime<<32) | NetL(pkt+6);
  157. if(starttime == 0LL)
  158. starttime = pkttime;
  159. n = NetS(pkt);
  160. if(readn(fd, pkt, n) != n)
  161. break;
  162. if(filterpkt(filter, pkt, pkt+n, root, 1))
  163. if(toflag)
  164. tracepkt(pkt, n);
  165. else
  166. printpkt(buf, e, pkt, pkt+n);
  167. }
  168. } else {
  169. /* read a real time stream */
  170. starttime = nsec();
  171. for(;;){
  172. n = root->framer(fd, pkt, Pktlen);
  173. if(n <= 0)
  174. break;
  175. pkttime = nsec();
  176. if(filterpkt(filter, pkt, pkt+n, root, 1))
  177. if(toflag)
  178. tracepkt(pkt, n);
  179. else
  180. printpkt(buf, e, pkt, pkt+n);
  181. }
  182. }
  183. }
  184. /* create a new filter node */
  185. Filter*
  186. newfilter(void)
  187. {
  188. Filter *f;
  189. f = mallocz(sizeof(*f), 1);
  190. if(f == nil)
  191. sysfatal("newfilter: %r");
  192. return f;
  193. }
  194. /*
  195. * apply filter to packet
  196. */
  197. int
  198. _filterpkt(Filter *f, Msg *m)
  199. {
  200. Msg ma;
  201. if(f == nil)
  202. return 1;
  203. switch(f->op){
  204. case '!':
  205. return !_filterpkt(f->l, m);
  206. case LAND:
  207. ma = *m;
  208. return _filterpkt(f->l, &ma) && _filterpkt(f->r, m);
  209. case LOR:
  210. ma = *m;
  211. return _filterpkt(f->l, &ma) || _filterpkt(f->r, m);
  212. case WORD:
  213. if(m->needroot){
  214. if(m->pr != f->pr)
  215. return 0;
  216. m->needroot = 0;
  217. }else{
  218. if(m->pr && (m->pr->filter==nil || !(m->pr->filter)(f, m)))
  219. return 0;
  220. }
  221. if(f->l == nil)
  222. return 1;
  223. m->pr = f->pr;
  224. return _filterpkt(f->l, m);
  225. }
  226. sysfatal("internal error: filterpkt op: %d", f->op);
  227. return 0;
  228. }
  229. int
  230. filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int needroot)
  231. {
  232. Msg m;
  233. if(f == nil)
  234. return 1;
  235. m.needroot = needroot;
  236. m.ps = ps;
  237. m.pe = pe;
  238. m.pr = pr;
  239. return _filterpkt(f, &m);
  240. }
  241. /*
  242. * from the Unix world
  243. */
  244. #define PCAP_VERSION_MAJOR 2
  245. #define PCAP_VERSION_MINOR 4
  246. #define TCPDUMP_MAGIC 0xa1b2c3d4
  247. struct pcap_file_header {
  248. ulong magic;
  249. ushort version_major;
  250. ushort version_minor;
  251. long thiszone; /* gmt to local correction */
  252. ulong sigfigs; /* accuracy of timestamps */
  253. ulong snaplen; /* max length saved portion of each pkt */
  254. ulong linktype; /* data link type (DLT_*) */
  255. };
  256. struct pcap_pkthdr {
  257. uvlong ts; /* time stamp */
  258. ulong caplen; /* length of portion present */
  259. ulong len; /* length this packet (off wire) */
  260. };
  261. /*
  262. * pcap trace header
  263. */
  264. void
  265. pcaphdr(void)
  266. {
  267. struct pcap_file_header hdr;
  268. hdr.magic = TCPDUMP_MAGIC;
  269. hdr.version_major = PCAP_VERSION_MAJOR;
  270. hdr.version_minor = PCAP_VERSION_MINOR;
  271. hdr.thiszone = 0;
  272. hdr.snaplen = 1500;
  273. hdr.sigfigs = 0;
  274. hdr.linktype = 1;
  275. write(1, &hdr, sizeof(hdr));
  276. }
  277. /*
  278. * write out a packet trace
  279. */
  280. void
  281. tracepkt(uchar *ps, int len)
  282. {
  283. struct pcap_pkthdr *goo;
  284. if(Mflag && len > Mflag)
  285. len = Mflag;
  286. if(pcap){
  287. goo = (struct pcap_pkthdr*)(ps-16);
  288. goo->ts = pkttime;
  289. goo->caplen = len;
  290. goo->len = len;
  291. write(1, goo, len+16);
  292. } else {
  293. hnputs(ps-10, len);
  294. hnputl(ps-8, pkttime>>32);
  295. hnputl(ps-4, pkttime);
  296. write(1, ps-10, len+10);
  297. }
  298. }
  299. /*
  300. * format and print a packet
  301. */
  302. void
  303. printpkt(char *p, char *e, uchar *ps, uchar *pe)
  304. {
  305. Msg m;
  306. ulong dt;
  307. dt = (pkttime-starttime)/1000000LL;
  308. m.p = seprint(p, e, "%6.6uld ms ", dt);
  309. m.ps = ps;
  310. m.pe = pe;
  311. m.e = e;
  312. m.pr = root;
  313. while(m.p < m.e){
  314. if(!sflag)
  315. m.p = seprint(m.p, m.e, "\n\t");
  316. m.p = seprint(m.p, m.e, "%s(", m.pr->name);
  317. if((*m.pr->seprint)(&m) < 0){
  318. m.p = seprint(m.p, m.e, "TOO SHORT");
  319. m.ps = m.pe;
  320. }
  321. m.p = seprint(m.p, m.e, ")");
  322. if(m.pr == nil || m.ps >= m.pe)
  323. break;
  324. }
  325. *m.p++ = '\n';
  326. if(write(1, p, m.p - p) < 0)
  327. sysfatal("stdout: %r");
  328. }
  329. Proto **xprotos;
  330. int nprotos;
  331. /* look up a protocol by its name */
  332. Proto*
  333. findproto(char *name)
  334. {
  335. int i;
  336. for(i = 0; i < nprotos; i++)
  337. if(strcmp(xprotos[i]->name, name) == 0)
  338. return xprotos[i];
  339. return nil;
  340. }
  341. /*
  342. * add an undefined protocol to protos[]
  343. */
  344. Proto*
  345. addproto(char *name)
  346. {
  347. Proto *pr;
  348. xprotos = realloc(xprotos, (nprotos+1)*sizeof(Proto*));
  349. pr = malloc(sizeof *pr);
  350. *pr = dump;
  351. pr->name = name;
  352. xprotos[nprotos++] = pr;
  353. return pr;
  354. }
  355. /*
  356. * build a graph of protocols, this could easily be circular. This
  357. * links together all the multiplexing in the protocol modules.
  358. */
  359. void
  360. mkprotograph(void)
  361. {
  362. Proto **l;
  363. Proto *pr;
  364. Mux *m;
  365. /* copy protos into a reallocable area */
  366. for(nprotos = 0; protos[nprotos] != nil; nprotos++)
  367. ;
  368. xprotos = malloc(nprotos*sizeof(Proto*));
  369. memmove(xprotos, protos, nprotos*sizeof(Proto*));
  370. for(l = protos; *l != nil; l++){
  371. pr = *l;
  372. for(m = pr->mux; m != nil && m->name != nil; m++){
  373. m->pr = findproto(m->name);
  374. if(m->pr == nil)
  375. m->pr = addproto(m->name);
  376. }
  377. }
  378. }
  379. /*
  380. * add in a protocol node
  381. */
  382. static Filter*
  383. addnode(Filter *f, Proto *pr)
  384. {
  385. Filter *nf;
  386. nf = newfilter();
  387. nf->pr = pr;
  388. nf->s = pr->name;
  389. nf->l = f;
  390. nf->op = WORD;
  391. return nf;
  392. }
  393. /*
  394. * recurse through the protocol graph adding missing nodes
  395. * to the filter if we reach the filter's protocol
  396. */
  397. static Filter*
  398. _fillin(Filter *f, Proto *last, int depth)
  399. {
  400. Mux *m;
  401. Filter *nf;
  402. if(depth-- <= 0)
  403. return nil;
  404. for(m = last->mux; m != nil && m->name != nil; m++){
  405. if(m->pr == nil)
  406. continue;
  407. if(f->pr == m->pr)
  408. return f;
  409. nf = _fillin(f, m->pr, depth);
  410. if(nf != nil)
  411. return addnode(nf, m->pr);
  412. }
  413. return nil;
  414. }
  415. static Filter*
  416. fillin(Filter *f, Proto *last)
  417. {
  418. int i;
  419. Filter *nf;
  420. /* hack to make sure top level node is the root */
  421. if(last == nil){
  422. if(f->pr == root)
  423. return f;
  424. f = fillin(f, root);
  425. if(f == nil)
  426. return nil;
  427. return addnode(f, root);
  428. }
  429. /* breadth first search though the protocol graph */
  430. nf = f;
  431. for(i = 1; i < 20; i++){
  432. nf = _fillin(f, last, i);
  433. if(nf != nil)
  434. break;
  435. }
  436. return nf;
  437. }
  438. /*
  439. * massage tree so that all paths from the root to a leaf
  440. * contain a filter node for each header.
  441. *
  442. * also, set f->pr where possible
  443. */
  444. Filter*
  445. complete(Filter *f, Proto *last)
  446. {
  447. Proto *pr;
  448. if(f == nil)
  449. return f;
  450. /* do a depth first traversal of the filter tree */
  451. switch(f->op){
  452. case '!':
  453. f->l = complete(f->l, last);
  454. break;
  455. case LAND:
  456. case LOR:
  457. f->l = complete(f->l, last);
  458. f->r = complete(f->r, last);
  459. break;
  460. case '=':
  461. break;
  462. case WORD:
  463. pr = findproto(f->s);
  464. f->pr = pr;
  465. if(pr == nil){
  466. if(f->l != nil){
  467. fprint(2, "%s unknown proto, ignoring params\n",
  468. f->s);
  469. f->l = nil;
  470. }
  471. } else {
  472. f->l = complete(f->l, pr);
  473. f = fillin(f, last);
  474. if(f == nil)
  475. sysfatal("internal error: can't get to %s", pr->name);
  476. }
  477. break;
  478. }
  479. return f;
  480. }
  481. /*
  482. * merge common nodes under | and & moving the merged node
  483. * above the | or &.
  484. *
  485. * do some constant foldong, e.g. `true & x' becomes x and
  486. * 'true | x' becomes true.
  487. */
  488. static int changed;
  489. static Filter*
  490. _optimize(Filter *f)
  491. {
  492. Filter *l;
  493. if(f == nil)
  494. return f;
  495. switch(f->op){
  496. case '!':
  497. /* is child also a not */
  498. if(f->l->op == '!'){
  499. changed = 1;
  500. return f->l->l;
  501. }
  502. break;
  503. case LOR:
  504. /* are two children the same protocol? */
  505. if(f->l->op != f->r->op || f->r->op != WORD
  506. || f->l->pr != f->r->pr || f->l->pr == nil)
  507. break; /* no optimization */
  508. changed = 1;
  509. /* constant folding */
  510. /* if either child is childless, just return that */
  511. if(f->l->l == nil)
  512. return f->l;
  513. else if(f->r->l == nil)
  514. return f->r;
  515. /* move the common node up, thow away one node */
  516. l = f->l;
  517. f->l = l->l;
  518. f->r = f->r->l;
  519. l->l = f;
  520. return l;
  521. case LAND:
  522. /* are two children the same protocol? */
  523. if(f->l->op != f->r->op || f->r->op != WORD
  524. || f->l->pr != f->r->pr || f->l->pr == nil)
  525. break; /* no optimization */
  526. changed = 1;
  527. /* constant folding */
  528. /* if either child is childless, ignore it */
  529. if(f->l->l == nil)
  530. return f->r;
  531. else if(f->r->l == nil)
  532. return f->l;
  533. /* move the common node up, thow away one node */
  534. l = f->l;
  535. f->l = _optimize(l->l);
  536. f->r = _optimize(f->r->l);
  537. l->l = f;
  538. return l;
  539. }
  540. f->l = _optimize(f->l);
  541. f->r = _optimize(f->r);
  542. return f;
  543. }
  544. Filter*
  545. optimize(Filter *f)
  546. {
  547. do{
  548. changed = 0;
  549. f = _optimize(f);
  550. }while(changed);
  551. return f;
  552. }
  553. /*
  554. * find any top level nodes that aren't the root
  555. */
  556. int
  557. findbogus(Filter *f)
  558. {
  559. int rv;
  560. if(f->op != WORD){
  561. rv = findbogus(f->l);
  562. if(f->r)
  563. rv |= findbogus(f->r);
  564. return rv;
  565. } else if(f->pr != root){
  566. fprint(2, "bad top-level protocol: %s\n", f->s);
  567. return 1;
  568. }
  569. return 0;
  570. }
  571. /*
  572. * compile the filter
  573. */
  574. static void
  575. _compile(Filter *f, Proto *last)
  576. {
  577. if(f == nil)
  578. return;
  579. switch(f->op){
  580. case '!':
  581. _compile(f->l, last);
  582. break;
  583. case LOR:
  584. case LAND:
  585. _compile(f->l, last);
  586. _compile(f->r, last);
  587. break;
  588. case WORD:
  589. if(last != nil){
  590. if(last->compile == nil)
  591. sysfatal("unknown %s subprotocol: %s", f->pr->name, f->s);
  592. (*last->compile)(f);
  593. }
  594. if(f->l)
  595. _compile(f->l, f->pr);
  596. break;
  597. case '=':
  598. if(last == nil)
  599. sysfatal("internal error: compilewalk: badly formed tree");
  600. if(last->compile == nil)
  601. sysfatal("unknown %s field: %s", f->pr->name, f->s);
  602. (*last->compile)(f);
  603. break;
  604. default:
  605. sysfatal("internal error: compilewalk op: %d", f->op);
  606. }
  607. }
  608. Filter*
  609. compile(Filter *f)
  610. {
  611. if(f == nil)
  612. return f;
  613. /* fill in the missing header filters */
  614. f = complete(f, nil);
  615. /* constant folding */
  616. f = optimize(f);
  617. if(!toflag)
  618. printfilter(f, "after optimize");
  619. /* protocol specific compilations */
  620. _compile(f, nil);
  621. /* at this point, the root had better be the root proto */
  622. if(findbogus(f)){
  623. fprint(2, "bogus filter\n");
  624. exits("bad filter");
  625. }
  626. return f;
  627. }
  628. /*
  629. * parse a byte array
  630. */
  631. int
  632. parseba(uchar *to, char *from)
  633. {
  634. char nip[4];
  635. char *p;
  636. int i;
  637. p = from;
  638. for(i = 0; i < 16; i++){
  639. if(*p == 0)
  640. return -1;
  641. nip[0] = *p++;
  642. if(*p == 0)
  643. return -1;
  644. nip[1] = *p++;
  645. nip[2] = 0;
  646. to[i] = strtoul(nip, 0, 16);
  647. }
  648. return i;
  649. }
  650. /*
  651. * compile WORD = WORD, becomes a single node with a subop
  652. */
  653. void
  654. compile_cmp(char *proto, Filter *f, Field *fld)
  655. {
  656. uchar x[IPaddrlen];
  657. if(f->op != '=')
  658. sysfatal("internal error: compile_cmp %s: not a cmp", proto);
  659. for(; fld->name != nil; fld++){
  660. if(strcmp(f->l->s, fld->name) == 0){
  661. f->op = WORD;
  662. f->subop = fld->subop;
  663. switch(fld->ftype){
  664. case Fnum:
  665. f->ulv = atoi(f->r->s);
  666. break;
  667. case Fether:
  668. parseether(f->a, f->r->s);
  669. break;
  670. case Fv4ip:
  671. f->ulv = parseip(x, f->r->s);
  672. break;
  673. case Fv6ip:
  674. parseip(f->a, f->r->s);
  675. break;
  676. case Fba:
  677. parseba(f->a, f->r->s);
  678. break;
  679. default:
  680. sysfatal("internal error: compile_cmp %s: %d",
  681. proto, fld->ftype);
  682. }
  683. f->l = f->r = nil;
  684. return;
  685. }
  686. }
  687. sysfatal("unknown %s field in: %s = %s", proto, f->l->s, f->r->s);
  688. }
  689. void
  690. _pf(Filter *f)
  691. {
  692. char *s;
  693. if(f == nil)
  694. return;
  695. s = nil;
  696. switch(f->op){
  697. case '!':
  698. fprint(2, "!");
  699. _pf(f->l);
  700. break;
  701. case WORD:
  702. fprint(2, "%s", f->s);
  703. if(f->l != nil){
  704. fprint(2, "(");
  705. _pf(f->l);
  706. fprint(2, ")");
  707. }
  708. break;
  709. case LAND:
  710. s = "&&";
  711. goto print;
  712. case LOR:
  713. s = "||";
  714. goto print;
  715. case '=':
  716. print:
  717. _pf(f->l);
  718. if(s)
  719. fprint(2, " %s ", s);
  720. else
  721. fprint(2, " %c ", f->op);
  722. _pf(f->r);
  723. break;
  724. default:
  725. fprint(2, "???");
  726. break;
  727. }
  728. }
  729. void
  730. printfilter(Filter *f, char *tag)
  731. {
  732. fprint(2, "%s: ", tag);
  733. _pf(f);
  734. fprint(2, "\n");
  735. }
  736. void
  737. cat(void)
  738. {
  739. char buf[1024];
  740. int n;
  741. while((n = read(0, buf, sizeof buf)) > 0)
  742. write(1, buf, n);
  743. }
  744. static int fd1 = -1;
  745. void
  746. startmc(void)
  747. {
  748. int p[2];
  749. if(fd1 == -1)
  750. fd1 = dup(1, -1);
  751. if(pipe(p) < 0)
  752. return;
  753. switch(fork()){
  754. case -1:
  755. return;
  756. default:
  757. close(p[0]);
  758. dup(p[1], 1);
  759. if(p[1] != 1)
  760. close(p[1]);
  761. return;
  762. case 0:
  763. close(p[1]);
  764. dup(p[0], 0);
  765. if(p[0] != 0)
  766. close(p[0]);
  767. execl("/bin/mc", "mc", nil);
  768. cat();
  769. _exits(0);
  770. }
  771. }
  772. void
  773. stopmc(void)
  774. {
  775. close(1);
  776. dup(fd1, 1);
  777. waitpid();
  778. }
  779. void
  780. printhelp(char *name)
  781. {
  782. int len;
  783. Proto *pr, **l;
  784. Mux *m;
  785. Field *f;
  786. char fmt[40];
  787. if(name == nil){
  788. print("protocols:\n");
  789. startmc();
  790. for(l=protos; (pr=*l) != nil; l++)
  791. print(" %s\n", pr->name);
  792. stopmc();
  793. return;
  794. }
  795. pr = findproto(name);
  796. if(pr == nil){
  797. print("unknown protocol %s\n", name);
  798. return;
  799. }
  800. if(pr->field){
  801. print("%s's filter attributes:\n", pr->name);
  802. len = 0;
  803. for(f=pr->field; f->name; f++)
  804. if(len < strlen(f->name))
  805. len = strlen(f->name);
  806. startmc();
  807. for(f=pr->field; f->name; f++)
  808. print(" %-*s - %s\n", len, f->name, f->help);
  809. stopmc();
  810. }
  811. if(pr->mux){
  812. print("%s's subprotos:\n", pr->name);
  813. startmc();
  814. snprint(fmt, sizeof fmt, " %s %%s\n", pr->valfmt);
  815. for(m=pr->mux; m->name != nil; m++)
  816. print(fmt, m->val, m->name);
  817. stopmc();
  818. }
  819. }
  820. /*
  821. * demultiplex to next prototol header
  822. */
  823. void
  824. demux(Mux *mx, ulong val1, ulong val2, Msg *m, Proto *def)
  825. {
  826. m->pr = def;
  827. for(mx = mx; mx->name != nil; mx++){
  828. if(val1 == mx->val || val2 == mx->val){
  829. m->pr = mx->pr;
  830. break;
  831. }
  832. }
  833. }
  834. /*
  835. * default framer just assumes the input packet is
  836. * a single read
  837. */
  838. int
  839. defaultframer(int fd, uchar *pkt, int pktlen)
  840. {
  841. return read(fd, pkt, pktlen);
  842. }