📄 main.c
字号:
#include <u.h>#include <libc.h>#include <ip.h>#include <bio.h>#include <fcall.h>#include <libsec.h>#include "dat.h"#include "protos.h"#include "y.tab.h"int Cflag;int pflag;int Nflag;int Mflag;int sflag;int tiflag;int toflag;char *prom = "promiscuous";enum{ Pktlen= 64*1024, Blen= 16*1024,};Filter *filter;Proto *root;Biobuf out;vlong starttime, pkttime;int pcap;int filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int);void printpkt(char *p, char *e, uchar *ps, uchar *pe);void mkprotograph(void);Proto* findproto(char *name);Filter* compile(Filter *f);void printfilter(Filter *f, char *tag);void printhelp(char*);void tracepkt(uchar*, int);void pcaphdr(void);voidprintusage(void){ fprint(2, "usage: %s [-CDdpst] [-N n] [-f filter] [-h first-header] path\n", argv0); fprint(2, " for protocol help: %s -? [proto]\n", argv0);}voidusage(void){ printusage(); exits("usage");}voidmain(int argc, char **argv){ uchar *pkt; char *buf, *file, *p, *e; int fd, cfd; int n; Binit(&out, 1, OWRITE); fmtinstall('E', eipfmt); fmtinstall('V', eipfmt); fmtinstall('I', eipfmt); fmtinstall('H', encodefmt); fmtinstall('F', fcallfmt); pkt = malloc(Pktlen+16); pkt += 16; buf = malloc(Blen); e = buf+Blen-1; pflag = 1; Nflag = 32; sflag = 0; mkprotograph(); ARGBEGIN{ default: usage(); case '?': printusage(); printhelp(ARGF()); exits(0); break; case 'M': p = EARGF(usage()); Mflag = atoi(p); break; case 'N': p = EARGF(usage()); Nflag = atoi(p); break; case 'f': p = EARGF(usage()); yyinit(p); yyparse(); break; case 's': sflag = 1; break; case 'h': p = EARGF(usage()); root = findproto(p); if(root == nil) sysfatal("unknown protocol: %s", p); break; case 'd': toflag = 1; break; case 'D': toflag = 1; pcap = 1; break; case 't': tiflag = 1; break; case 'C': Cflag = 1; break; case 'p': pflag = 0; break; }ARGEND; if(pcap) pcaphdr(); if(argc == 0){ file = "/net/ether0"; if(root != nil) root = ðer; } else file = argv[0]; if((!tiflag) && strstr(file, "ether")){ if(root == nil) root = ðer; snprint(buf, Blen, "%s!-1", file); fd = dial(buf, 0, 0, &cfd); if(fd < 0) sysfatal("dialing %s", buf); if(pflag && fprint(cfd, prom, strlen(prom)) < 0) sysfatal("setting %s", prom); } else if((!tiflag) && strstr(file, "ipifc")){ if(root == nil) root = &ip; snprint(buf, Blen, "%s/snoop", file); fd = open(buf, OREAD); if(fd < 0) sysfatal("opening %s: %r", buf); } else { if(root == nil) root = ðer; fd = open(file, OREAD); if(fd < 0) sysfatal("opening %s: %r", file); } filter = compile(filter); if(tiflag){ /* read a trace file */ for(;;){ n = read(fd, pkt, 10); if(n != 10) break; pkttime = NetL(pkt+2); pkttime = (pkttime<<32) | NetL(pkt+6); if(starttime == 0LL) starttime = pkttime; n = NetS(pkt); if(readn(fd, pkt, n) != n) break; if(filterpkt(filter, pkt, pkt+n, root, 1)) if(toflag) tracepkt(pkt, n); else printpkt(buf, e, pkt, pkt+n); } } else { /* read a real time stream */ starttime = nsec(); for(;;){ n = root->framer(fd, pkt, Pktlen); if(n <= 0) break; pkttime = nsec(); if(filterpkt(filter, pkt, pkt+n, root, 1)) if(toflag) tracepkt(pkt, n); else printpkt(buf, e, pkt, pkt+n); } }}/* create a new filter node */Filter*newfilter(void){ Filter *f; f = mallocz(sizeof(*f), 1); if(f == nil) sysfatal("newfilter: %r"); return f;}/* * apply filter to packet */int_filterpkt(Filter *f, Msg *m){ Msg ma; if(f == nil) return 1; switch(f->op){ case '!': return !_filterpkt(f->l, m); case LAND: ma = *m; return _filterpkt(f->l, &ma) && _filterpkt(f->r, m); case LOR: ma = *m; return _filterpkt(f->l, &ma) || _filterpkt(f->r, m); case WORD: if(m->needroot){ if(m->pr != f->pr) return 0; m->needroot = 0; }else{ if(m->pr && (m->pr->filter==nil || !(m->pr->filter)(f, m))) return 0; } if(f->l == nil) return 1; m->pr = f->pr; return _filterpkt(f->l, m); } sysfatal("internal error: filterpkt op: %d", f->op); return 0;}intfilterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int needroot){ Msg m; if(f == nil) return 1; m.needroot = needroot; m.ps = ps; m.pe = pe; m.pr = pr; return _filterpkt(f, &m);}/* * from the Unix world */#define PCAP_VERSION_MAJOR 2#define PCAP_VERSION_MINOR 4#define TCPDUMP_MAGIC 0xa1b2c3d4struct pcap_file_header { ulong magic; ushort version_major; ushort version_minor; long thiszone; /* gmt to local correction */ ulong sigfigs; /* accuracy of timestamps */ ulong snaplen; /* max length saved portion of each pkt */ ulong linktype; /* data link type (DLT_*) */};struct pcap_pkthdr { uvlong ts; /* time stamp */ ulong caplen; /* length of portion present */ ulong len; /* length this packet (off wire) */};/* * pcap trace header */voidpcaphdr(void){ struct pcap_file_header hdr; hdr.magic = TCPDUMP_MAGIC; hdr.version_major = PCAP_VERSION_MAJOR; hdr.version_minor = PCAP_VERSION_MINOR; hdr.thiszone = 0; hdr.snaplen = 1500; hdr.sigfigs = 0; hdr.linktype = 1; write(1, &hdr, sizeof(hdr));}/* * write out a packet trace */voidtracepkt(uchar *ps, int len){ struct pcap_pkthdr *goo; if(Mflag && len > Mflag) len = Mflag; if(pcap){ goo = (struct pcap_pkthdr*)(ps-16); goo->ts = pkttime; goo->caplen = len; goo->len = len; write(1, goo, len+16); } else { hnputs(ps-10, len); hnputl(ps-8, pkttime>>32); hnputl(ps-4, pkttime); write(1, ps-10, len+10); }}/* * format and print a packet */voidprintpkt(char *p, char *e, uchar *ps, uchar *pe){ Msg m; ulong dt; dt = (pkttime-starttime)/1000000LL; m.p = seprint(p, e, "%6.6uld ms ", dt); m.ps = ps; m.pe = pe; m.e = e; m.pr = root; while(m.p < m.e){ if(!sflag) m.p = seprint(m.p, m.e, "\n\t"); m.p = seprint(m.p, m.e, "%s(", m.pr->name); if((*m.pr->seprint)(&m) < 0){ m.p = seprint(m.p, m.e, "TOO SHORT"); m.ps = m.pe; } m.p = seprint(m.p, m.e, ")"); if(m.pr == nil || m.ps >= m.pe) break; } *m.p++ = '\n'; if(write(1, p, m.p - p) < 0) sysfatal("stdout: %r");}Proto **xprotos;int nprotos;/* look up a protocol by its name */Proto*findproto(char *name){ int i; for(i = 0; i < nprotos; i++) if(strcmp(xprotos[i]->name, name) == 0) return xprotos[i]; return nil;}/* * add an undefined protocol to protos[] */Proto*addproto(char *name){ Proto *pr; xprotos = realloc(xprotos, (nprotos+1)*sizeof(Proto*)); pr = malloc(sizeof *pr); *pr = dump; pr->name = name; xprotos[nprotos++] = pr; return pr;}/* * build a graph of protocols, this could easily be circular. This * links together all the multiplexing in the protocol modules. */voidmkprotograph(void){ Proto **l; Proto *pr; Mux *m; /* copy protos into a reallocable area */ for(nprotos = 0; protos[nprotos] != nil; nprotos++) ; xprotos = malloc(nprotos*sizeof(Proto*)); memmove(xprotos, protos, nprotos*sizeof(Proto*)); for(l = protos; *l != nil; l++){ pr = *l; for(m = pr->mux; m != nil && m->name != nil; m++){ m->pr = findproto(m->name); if(m->pr == nil) m->pr = addproto(m->name); } }}/* * add in a protocol node */static Filter*addnode(Filter *f, Proto *pr){ Filter *nf; nf = newfilter(); nf->pr = pr; nf->s = pr->name; nf->l = f; nf->op = WORD; return nf;}/* * recurse through the protocol graph adding missing nodes * to the filter if we reach the filter's protocol */static Filter*_fillin(Filter *f, Proto *last, int depth){ Mux *m; Filter *nf; if(depth-- <= 0) return nil; for(m = last->mux; m != nil && m->name != nil; m++){ if(m->pr == nil) continue; if(f->pr == m->pr) return f; nf = _fillin(f, m->pr, depth); if(nf != nil) return addnode(nf, m->pr); } return nil;}static Filter*fillin(Filter *f, Proto *last){ int i; Filter *nf; /* hack to make sure top level node is the root */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -