18 char *prom = "promiscuous";
29 vlong starttime, pkttime;
32 int filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int);
33 void printpkt(char *p, char *e, uchar *ps, uchar *pe);
34 void mkprotograph(void);
35 Proto* findproto(char *name);
36 Filter* compile(Filter *f);
37 void printfilter(Filter *f, char *tag);
38 void printhelp(char*);
39 void tracepkt(uchar*, int);
43 u64int ts; /* time stamp */
44 u32int caplen; /* length of portion present */
45 u32int len; /* length this packet (off wire) */
52 fprint(2, "usage: %s [-CDdpst] [-N n] [-f filter] [-h first-header] path\n", argv0);
53 fprint(2, " for protocol help: %s -? [proto]\n", argv0);
64 main(int argc, char **argv)
67 char *buf, *file, *p, *e;
71 Binit(&out, 1, OWRITE);
73 fmtinstall('E', eipfmt);
74 fmtinstall('V', eipfmt);
75 fmtinstall('I', eipfmt);
76 fmtinstall('H', encodefmt);
77 fmtinstall('F', fcallfmt);
79 pkt = malloc(Pktlen+16);
114 sysfatal("unknown protocol: %s", p);
148 sysfatal("must specify file with -t");
149 fd = open(file, OREAD);
151 sysfatal("opening %s: %r", file);
153 fd = opendevice(file, pflag);
155 sysfatal("opening device %s: %r", file);
163 filter = compile(filter);
166 /* read a trace file */
169 struct pcap_pkthdr *goo;
170 n = read(fd, pkt, 16);
173 goo = (struct pcap_pkthdr*)pkt;
177 n = read(fd, pkt, 10);
180 pkttime = NetL(pkt+2);
181 pkttime = (pkttime<<32) | NetL(pkt+6);
186 if(readn(fd, pkt, n) != n)
188 if(filterpkt(filter, pkt, pkt+n, root, 1))
192 printpkt(buf, e, pkt, pkt+n);
195 /* read a real time stream */
198 n = root->framer(fd, pkt, Pktlen);
202 if(filterpkt(filter, pkt, pkt+n, root, 1))
206 printpkt(buf, e, pkt, pkt+n);
211 /* create a new filter node */
217 f = mallocz(sizeof(*f), 1);
219 sysfatal("newfilter: %r");
224 * apply filter to packet
227 _filterpkt(Filter *f, Msg *m)
236 return !_filterpkt(f->l, m);
239 return _filterpkt(f->l, &ma) && _filterpkt(f->r, m);
242 return _filterpkt(f->l, &ma) || _filterpkt(f->r, m);
249 if(m->pr && (m->pr->filter==nil || !(m->pr->filter)(f, m)))
255 return _filterpkt(f->l, m);
257 sysfatal("internal error: filterpkt op: %d", f->op);
261 filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int needroot)
268 m.needroot = needroot;
272 return _filterpkt(f, &m);
276 * from the Unix world
278 #define PCAP_VERSION_MAJOR 2
279 #define PCAP_VERSION_MINOR 4
280 #define TCPDUMP_MAGIC 0xa1b2c3d4
282 struct pcap_file_header {
284 u16int version_major;
285 u16int version_minor;
286 s32int thiszone; /* gmt to local correction */
287 u32int sigfigs; /* accuracy of timestamps */
288 u32int snaplen; /* max length saved portion of each pkt */
289 u32int linktype; /* data link type (DLT_*) */
299 struct pcap_file_header hdr;
301 if(readn(fd, &hdr, sizeof hdr) != sizeof hdr)
302 sysfatal("short header");
303 if(hdr.magic != TCPDUMP_MAGIC)
304 sysfatal("packet header %ux != %ux", hdr.magic, TCPDUMP_MAGIC);
305 if(hdr.version_major != PCAP_VERSION_MAJOR || hdr.version_minor != PCAP_VERSION_MINOR)
306 sysfatal("version %d.%d != %d.%d", hdr.version_major, hdr.version_minor, PCAP_VERSION_MAJOR, PCAP_VERSION_MINOR);
307 if(hdr.linktype != 1)
308 sysfatal("unknown linktype %d != 1 (ethernet)", hdr.linktype);
311 struct pcap_file_header hdr;
313 hdr.magic = TCPDUMP_MAGIC;
314 hdr.version_major = PCAP_VERSION_MAJOR;
315 hdr.version_minor = PCAP_VERSION_MINOR;
322 write(1, &hdr, sizeof(hdr));
327 * write out a packet trace
330 tracepkt(uchar *ps, int len)
332 struct pcap_pkthdr *goo;
335 goo = (struct pcap_pkthdr*)(ps-16);
339 write(1, goo, len+16);
342 hnputl(ps-8, pkttime>>32);
343 hnputl(ps-4, pkttime);
344 write(1, ps-10, len+10);
349 * format and print a packet
352 printpkt(char *p, char *e, uchar *ps, uchar *pe)
357 dt = (pkttime-starttime)/1000000LL;
358 m.p = seprint(p, e, "%6.6uld ms ", dt);
365 m.p = seprint(m.p, m.e, "\n\t");
366 m.p = seprint(m.p, m.e, "%s(", m.pr->name);
367 if((*m.pr->seprint)(&m) < 0){
368 m.p = seprint(m.p, m.e, "TOO SHORT");
371 m.p = seprint(m.p, m.e, ")");
372 if(m.pr == nil || m.ps >= m.pe)
377 if(write(1, p, m.p - p) < 0)
378 sysfatal("stdout: %r");
384 /* look up a protocol by its name */
386 findproto(char *name)
390 for(i = 0; i < nprotos; i++)
391 if(strcmp(xprotos[i]->name, name) == 0)
397 * add an undefined protocol to protos[]
404 xprotos = realloc(xprotos, (nprotos+1)*sizeof(Proto*));
405 pr = malloc(sizeof *pr);
408 xprotos[nprotos++] = pr;
413 * build a graph of protocols, this could easily be circular. This
414 * links together all the multiplexing in the protocol modules.
423 /* copy protos into a reallocable area */
424 for(nprotos = 0; protos[nprotos] != nil; nprotos++)
426 xprotos = malloc(nprotos*sizeof(Proto*));
427 memmove(xprotos, protos, nprotos*sizeof(Proto*));
429 for(l = protos; *l != nil; l++){
431 for(m = pr->mux; m != nil && m->name != nil; m++){
432 m->pr = findproto(m->name);
434 m->pr = addproto(m->name);
440 * add in a protocol node
443 addnode(Filter *f, Proto *pr)
455 * recurse through the protocol graph adding missing nodes
456 * to the filter if we reach the filter's protocol
459 _fillin(Filter *f, Proto *last, int depth)
467 for(m = last->mux; m != nil && m->name != nil; m++){
472 nf = _fillin(f, m->pr, depth);
474 return addnode(nf, m->pr);
480 fillin(Filter *f, Proto *last)
485 /* hack to make sure top level node is the root */
492 return addnode(f, root);
495 /* breadth first search though the protocol graph */
497 for(i = 1; i < 20; i++){
498 nf = _fillin(f, last, i);
506 * massage tree so that all paths from the root to a leaf
507 * contain a filter node for each header.
509 * also, set f->pr where possible
512 complete(Filter *f, Proto *last)
519 /* do a depth first traversal of the filter tree */
522 f->l = complete(f->l, last);
526 f->l = complete(f->l, last);
527 f->r = complete(f->r, last);
532 pr = findproto(f->s);
536 fprint(2, "%s unknown proto, ignoring params\n",
541 f->l = complete(f->l, pr);
544 sysfatal("internal error: can't get to %s", pr->name);
552 * merge common nodes under | and & moving the merged node
555 * do some constant foldong, e.g. `true & x' becomes x and
556 * 'true | x' becomes true.
570 /* is child also a not */
577 /* are two children the same protocol? */
578 if(f->l->op != f->r->op || f->r->op != WORD
579 || f->l->pr != f->r->pr || f->l->pr == nil)
580 break; /* no optimization */
584 /* constant folding */
585 /* if either child is childless, just return that */
588 else if(f->r->l == nil)
591 /* move the common node up, thow away one node */
598 /* are two children the same protocol? */
599 if(f->l->op != f->r->op || f->r->op != WORD
600 || f->l->pr != f->r->pr || f->l->pr == nil)
601 break; /* no optimization */
605 /* constant folding */
606 /* if either child is childless, ignore it */
609 else if(f->r->l == nil)
612 /* move the common node up, thow away one node */
614 f->l = _optimize(l->l);
615 f->r = _optimize(f->r->l);
619 f->l = _optimize(f->l);
620 f->r = _optimize(f->r);
636 * find any top level nodes that aren't the root
644 rv = findbogus(f->l);
646 rv |= findbogus(f->r);
648 } else if(f->pr != root){
649 fprint(2, "bad top-level protocol: %s\n", f->s);
659 _compile(Filter *f, Proto *last)
666 _compile(f->l, last);
670 _compile(f->l, last);
671 _compile(f->r, last);
675 if(last->compile == nil)
676 sysfatal("unknown %s subprotocol: %s", f->pr->name, f->s);
680 _compile(f->l, f->pr);
684 sysfatal("internal error: compilewalk: badly formed tree");
686 if(last->compile == nil)
687 sysfatal("unknown %s field: %s", f->pr->name, f->s);
691 sysfatal("internal error: compilewalk op: %d", f->op);
701 /* fill in the missing header filters */
702 f = complete(f, nil);
704 /* constant folding */
707 printfilter(f, "after optimize");
709 /* protocol specific compilations */
712 /* at this point, the root had better be the root proto */
714 fprint(2, "bogus filter\n");
725 parseba(uchar *to, char *from)
732 for(i = 0; i < 16; i++){
740 to[i] = strtoul(nip, 0, 16);
746 * compile WORD = WORD, becomes a single node with a subop
749 compile_cmp(char *proto, Filter *f, Field *fld)
754 sysfatal("internal error: compile_cmp %s: not a cmp", proto);
756 for(; fld->name != nil; fld++){
757 if(strcmp(f->l->s, fld->name) == 0){
759 f->subop = fld->subop;
762 f->ulv = atoi(f->r->s);
765 parseether(f->a, f->r->s);
768 f->ulv = parseip(x, f->r->s);
771 parseip(f->a, f->r->s);
774 parseba(f->a, f->r->s);
777 sysfatal("internal error: compile_cmp %s: %d",
784 sysfatal("unknown %s field in: %s = %s", proto, f->l->s, f->r->s);
802 fprint(2, "%s", f->s);
819 fprint(2, " %s ", s);
821 fprint(2, " %c ", f->op);
831 printfilter(Filter *f, char *tag)
833 fprint(2, "%s: ", tag);
844 while((n = read(0, buf, sizeof buf)) > 0)
873 execl("/bin/mc", "mc", nil);
888 printhelp(char *name)
897 print("protocols:\n");
899 for(l=protos; (pr=*l) != nil; l++)
900 print(" %s\n", pr->name);
905 pr = findproto(name);
907 print("unknown protocol %s\n", name);
912 print("%s's filter attributes:\n", pr->name);
914 for(f=pr->field; f->name; f++)
915 if(len < strlen(f->name))
916 len = strlen(f->name);
918 for(f=pr->field; f->name; f++)
919 print(" %-*s - %s\n", len, f->name, f->help);
923 print("%s's subprotos:\n", pr->name);
925 snprint(fmt, sizeof fmt, " %s %%s\n", pr->valfmt);
926 for(m=pr->mux; m->name != nil; m++)
927 print(fmt, m->val, m->name);
933 * demultiplex to next prototol header
936 demux(Mux *mx, ulong val1, ulong val2, Msg *m, Proto *def)
939 for(mx = mx; mx->name != nil; mx++){
940 if(val1 == mx->val || val2 == mx->val){
948 * default framer just assumes the input packet is
952 defaultframer(int fd, uchar *pkt, int pktlen)
954 return read(fd, pkt, pktlen);