19a747e4fSDavid du Colombier #include <u.h> 29a747e4fSDavid du Colombier #include <libc.h> 39a747e4fSDavid du Colombier #include <ip.h> 49a747e4fSDavid du Colombier #include <bio.h> 59a747e4fSDavid du Colombier #include <fcall.h> 69a747e4fSDavid du Colombier #include <libsec.h> 79a747e4fSDavid du Colombier #include "dat.h" 89a747e4fSDavid du Colombier #include "protos.h" 99a747e4fSDavid du Colombier #include "y.tab.h" 109a747e4fSDavid du Colombier 119a747e4fSDavid du Colombier int Cflag; 129a747e4fSDavid du Colombier int pflag; 139a747e4fSDavid du Colombier int Nflag; 149a747e4fSDavid du Colombier int sflag; 159a747e4fSDavid du Colombier int tiflag; 169a747e4fSDavid du Colombier int toflag; 179a747e4fSDavid du Colombier 189a747e4fSDavid du Colombier char *prom = "promiscuous"; 199a747e4fSDavid du Colombier 209a747e4fSDavid du Colombier enum 219a747e4fSDavid du Colombier { 229a747e4fSDavid du Colombier Pktlen= 64*1024, 239a747e4fSDavid du Colombier Blen= 16*1024, 249a747e4fSDavid du Colombier }; 259a747e4fSDavid du Colombier 269a747e4fSDavid du Colombier Filter *filter; 279a747e4fSDavid du Colombier Proto *root; 289a747e4fSDavid du Colombier Biobuf out; 299a747e4fSDavid du Colombier vlong starttime, pkttime; 303ff48bf5SDavid du Colombier int pcap; 319a747e4fSDavid du Colombier 32*6b6b9ac8SDavid du Colombier int filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int); 339a747e4fSDavid du Colombier void printpkt(char *p, char *e, uchar *ps, uchar *pe); 349a747e4fSDavid du Colombier void mkprotograph(void); 359a747e4fSDavid du Colombier Proto* findproto(char *name); 369a747e4fSDavid du Colombier Filter* compile(Filter *f); 379a747e4fSDavid du Colombier void printfilter(Filter *f, char *tag); 389a747e4fSDavid du Colombier void printhelp(void); 399a747e4fSDavid du Colombier void tracepkt(uchar*, int); 403ff48bf5SDavid du Colombier void pcaphdr(void); 419a747e4fSDavid du Colombier 429a747e4fSDavid du Colombier void 439a747e4fSDavid du Colombier usage(void) 449a747e4fSDavid du Colombier { 459a747e4fSDavid du Colombier fprint(2, "usage: %s [-std?] [-c] [-N n] [-f filter] [-h first-header] path", argv0); 469a747e4fSDavid du Colombier exits("usage"); 479a747e4fSDavid du Colombier } 489a747e4fSDavid du Colombier 499a747e4fSDavid du Colombier void 509a747e4fSDavid du Colombier main(int argc, char **argv) 519a747e4fSDavid du Colombier { 529a747e4fSDavid du Colombier uchar *pkt; 539a747e4fSDavid du Colombier char *buf, *file, *p, *e; 549a747e4fSDavid du Colombier int fd, cfd; 559a747e4fSDavid du Colombier int n; 569a747e4fSDavid du Colombier 579a747e4fSDavid du Colombier Binit(&out, 1, OWRITE); 589a747e4fSDavid du Colombier 599a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 609a747e4fSDavid du Colombier fmtinstall('V', eipfmt); 619a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 629a747e4fSDavid du Colombier fmtinstall('H', encodefmt); 639a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 649a747e4fSDavid du Colombier 653ff48bf5SDavid du Colombier pkt = malloc(Pktlen+16); 663ff48bf5SDavid du Colombier pkt += 16; 679a747e4fSDavid du Colombier buf = malloc(Blen); 689a747e4fSDavid du Colombier e = buf+Blen-1; 699a747e4fSDavid du Colombier 709a747e4fSDavid du Colombier pflag = 1; 719a747e4fSDavid du Colombier Nflag = 32; 729a747e4fSDavid du Colombier sflag = 0; 739a747e4fSDavid du Colombier 749a747e4fSDavid du Colombier mkprotograph(); 759a747e4fSDavid du Colombier 769a747e4fSDavid du Colombier ARGBEGIN{ 779a747e4fSDavid du Colombier case '?': 789a747e4fSDavid du Colombier printhelp(); 799a747e4fSDavid du Colombier exits(0); 809a747e4fSDavid du Colombier break; 819a747e4fSDavid du Colombier case 'N': 829a747e4fSDavid du Colombier p = ARGF(); 839a747e4fSDavid du Colombier if(p == nil) 849a747e4fSDavid du Colombier usage(); 859a747e4fSDavid du Colombier Nflag = atoi(p); 869a747e4fSDavid du Colombier break; 879a747e4fSDavid du Colombier case 'f': 889a747e4fSDavid du Colombier p = ARGF(); 899a747e4fSDavid du Colombier if(p == nil) 909a747e4fSDavid du Colombier usage(); 919a747e4fSDavid du Colombier yyinit(p); 929a747e4fSDavid du Colombier yyparse(); 939a747e4fSDavid du Colombier break; 949a747e4fSDavid du Colombier case 's': 959a747e4fSDavid du Colombier sflag = 1; 969a747e4fSDavid du Colombier break; 979a747e4fSDavid du Colombier case 'h': 989a747e4fSDavid du Colombier p = ARGF(); 999a747e4fSDavid du Colombier if(p == nil) 1009a747e4fSDavid du Colombier usage(); 1019a747e4fSDavid du Colombier root = findproto(p); 1029a747e4fSDavid du Colombier if(root == nil) 1039a747e4fSDavid du Colombier sysfatal("unknown protocol: %s", p); 1049a747e4fSDavid du Colombier break; 1059a747e4fSDavid du Colombier case 'd': 1069a747e4fSDavid du Colombier toflag = 1; 1079a747e4fSDavid du Colombier break; 1083ff48bf5SDavid du Colombier case 'D': 1093ff48bf5SDavid du Colombier toflag = 1; 1103ff48bf5SDavid du Colombier pcap = 1; 1113ff48bf5SDavid du Colombier break; 1129a747e4fSDavid du Colombier case 't': 1139a747e4fSDavid du Colombier tiflag = 1; 1149a747e4fSDavid du Colombier break; 1159a747e4fSDavid du Colombier case 'C': 1169a747e4fSDavid du Colombier Cflag = 1; 1179a747e4fSDavid du Colombier break; 1189a747e4fSDavid du Colombier }ARGEND; 1199a747e4fSDavid du Colombier 1203ff48bf5SDavid du Colombier if(pcap) 1213ff48bf5SDavid du Colombier pcaphdr(); 1223ff48bf5SDavid du Colombier 1239a747e4fSDavid du Colombier if(argc == 0){ 1249a747e4fSDavid du Colombier file = "/net/ether0"; 1259a747e4fSDavid du Colombier if(root != nil) 1269a747e4fSDavid du Colombier root = ðer; 1279a747e4fSDavid du Colombier } else 1289a747e4fSDavid du Colombier file = argv[0]; 1299a747e4fSDavid du Colombier 1309a747e4fSDavid du Colombier if((!tiflag) && strstr(file, "ether")){ 1319a747e4fSDavid du Colombier if(root == nil) 1329a747e4fSDavid du Colombier root = ðer; 1339a747e4fSDavid du Colombier snprint(buf, Blen, "%s!-1", file); 1349a747e4fSDavid du Colombier fd = dial(buf, 0, 0, &cfd); 1359a747e4fSDavid du Colombier if(fd < 0) 1369a747e4fSDavid du Colombier sysfatal("dialing %s", buf); 1379a747e4fSDavid du Colombier if(pflag && fprint(cfd, prom, strlen(prom)) < 0) 1389a747e4fSDavid du Colombier sysfatal("setting %s", prom); 1399a747e4fSDavid du Colombier } else if((!tiflag) && strstr(file, "ipifc")){ 1409a747e4fSDavid du Colombier if(root == nil) 1419a747e4fSDavid du Colombier root = &ip; 1429a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s/snoopy", file); 1439a747e4fSDavid du Colombier fd = open(buf, OREAD); 1449a747e4fSDavid du Colombier if(fd < 0) 1459a747e4fSDavid du Colombier sysfatal("opening %s", buf); 1469a747e4fSDavid du Colombier } else { 1479a747e4fSDavid du Colombier if(root == nil) 1489a747e4fSDavid du Colombier root = ðer; 1499a747e4fSDavid du Colombier fd = open(file, OREAD); 1509a747e4fSDavid du Colombier if(fd < 0) 1519a747e4fSDavid du Colombier sysfatal("opening %s", file); 1529a747e4fSDavid du Colombier } 1539a747e4fSDavid du Colombier filter = compile(filter); 1549a747e4fSDavid du Colombier 1559a747e4fSDavid du Colombier if(tiflag){ 1563ff48bf5SDavid du Colombier /* read a trace file */ 1579a747e4fSDavid du Colombier for(;;){ 1589a747e4fSDavid du Colombier n = read(fd, pkt, 10); 1599a747e4fSDavid du Colombier if(n != 10) 1609a747e4fSDavid du Colombier break; 1619a747e4fSDavid du Colombier pkttime = NetL(pkt+2); 1629a747e4fSDavid du Colombier pkttime = (pkttime<<32) | NetL(pkt+6); 1639a747e4fSDavid du Colombier if(starttime == 0LL) 1649a747e4fSDavid du Colombier starttime = pkttime; 1659a747e4fSDavid du Colombier n = NetS(pkt); 1663ff48bf5SDavid du Colombier if(readn(fd, pkt, n) != n) 1679a747e4fSDavid du Colombier break; 168*6b6b9ac8SDavid du Colombier if(filterpkt(filter, pkt, pkt+n, root, 1)) 1699a747e4fSDavid du Colombier if(toflag) 1709a747e4fSDavid du Colombier tracepkt(pkt, n); 1719a747e4fSDavid du Colombier else 1729a747e4fSDavid du Colombier printpkt(buf, e, pkt, pkt+n); 1739a747e4fSDavid du Colombier } 1749a747e4fSDavid du Colombier } else { 1759a747e4fSDavid du Colombier /* read a real time stream */ 1769a747e4fSDavid du Colombier starttime = nsec(); 1779a747e4fSDavid du Colombier for(;;){ 1783ff48bf5SDavid du Colombier n = root->framer(fd, pkt, Pktlen); 1799a747e4fSDavid du Colombier if(n <= 0) 1809a747e4fSDavid du Colombier break; 1819a747e4fSDavid du Colombier pkttime = nsec(); 182*6b6b9ac8SDavid du Colombier if(filterpkt(filter, pkt, pkt+n, root, 1)) 1839a747e4fSDavid du Colombier if(toflag) 1849a747e4fSDavid du Colombier tracepkt(pkt, n); 1859a747e4fSDavid du Colombier else 1869a747e4fSDavid du Colombier printpkt(buf, e, pkt, pkt+n); 1879a747e4fSDavid du Colombier } 1889a747e4fSDavid du Colombier } 1899a747e4fSDavid du Colombier } 1909a747e4fSDavid du Colombier 1919a747e4fSDavid du Colombier /* create a new filter node */ 1929a747e4fSDavid du Colombier Filter* 1939a747e4fSDavid du Colombier newfilter(void) 1949a747e4fSDavid du Colombier { 1959a747e4fSDavid du Colombier Filter *f; 1969a747e4fSDavid du Colombier 1979a747e4fSDavid du Colombier f = mallocz(sizeof(*f), 1); 1989a747e4fSDavid du Colombier if(f == nil) 1999a747e4fSDavid du Colombier sysfatal("newfilter: %r"); 2009a747e4fSDavid du Colombier return f; 2019a747e4fSDavid du Colombier } 2029a747e4fSDavid du Colombier 2039a747e4fSDavid du Colombier /* 2049a747e4fSDavid du Colombier * apply filter to packet 2059a747e4fSDavid du Colombier */ 2069a747e4fSDavid du Colombier int 2079a747e4fSDavid du Colombier _filterpkt(Filter *f, Msg *m) 2089a747e4fSDavid du Colombier { 2099a747e4fSDavid du Colombier Msg ma; 2109a747e4fSDavid du Colombier 2119a747e4fSDavid du Colombier if(f == nil) 2129a747e4fSDavid du Colombier return 1; 2139a747e4fSDavid du Colombier 2149a747e4fSDavid du Colombier switch(f->op){ 215*6b6b9ac8SDavid du Colombier case '!': 216*6b6b9ac8SDavid du Colombier return !_filterpkt(f->l, m); 2179a747e4fSDavid du Colombier case LAND: 2189a747e4fSDavid du Colombier ma = *m; 2199a747e4fSDavid du Colombier return _filterpkt(f->l, &ma) && _filterpkt(f->r, m); 2209a747e4fSDavid du Colombier case LOR: 2219a747e4fSDavid du Colombier ma = *m; 2229a747e4fSDavid du Colombier return _filterpkt(f->l, &ma) || _filterpkt(f->r, m); 2239a747e4fSDavid du Colombier case WORD: 224*6b6b9ac8SDavid du Colombier if(m->needroot){ 225*6b6b9ac8SDavid du Colombier if(m->pr != f->pr) 226*6b6b9ac8SDavid du Colombier return 0; 227*6b6b9ac8SDavid du Colombier m->needroot = 0; 228*6b6b9ac8SDavid du Colombier }else{ 2299a747e4fSDavid du Colombier if(m->pr != nil && !(m->pr->filter)(f, m)) 2309a747e4fSDavid du Colombier return 0; 231*6b6b9ac8SDavid du Colombier } 2329a747e4fSDavid du Colombier if(f->l == nil) 2339a747e4fSDavid du Colombier return 1; 2349a747e4fSDavid du Colombier m->pr = f->pr; 2359a747e4fSDavid du Colombier return _filterpkt(f->l, m); 2369a747e4fSDavid du Colombier } 2379a747e4fSDavid du Colombier sysfatal("internal error: filterpkt op: %d", f->op); 2389a747e4fSDavid du Colombier return 0; 2399a747e4fSDavid du Colombier } 2409a747e4fSDavid du Colombier int 241*6b6b9ac8SDavid du Colombier filterpkt(Filter *f, uchar *ps, uchar *pe, Proto *pr, int needroot) 2429a747e4fSDavid du Colombier { 2439a747e4fSDavid du Colombier Msg m; 2449a747e4fSDavid du Colombier 2459a747e4fSDavid du Colombier if(f == nil) 2469a747e4fSDavid du Colombier return 1; 2479a747e4fSDavid du Colombier 248*6b6b9ac8SDavid du Colombier m.needroot = needroot; 2499a747e4fSDavid du Colombier m.ps = ps; 2509a747e4fSDavid du Colombier m.pe = pe; 2519a747e4fSDavid du Colombier m.pr = pr; 2529a747e4fSDavid du Colombier return _filterpkt(f, &m); 2539a747e4fSDavid du Colombier } 2549a747e4fSDavid du Colombier 2559a747e4fSDavid du Colombier /* 2563ff48bf5SDavid du Colombier * from the Unix world 2573ff48bf5SDavid du Colombier */ 2583ff48bf5SDavid du Colombier #define PCAP_VERSION_MAJOR 2 2593ff48bf5SDavid du Colombier #define PCAP_VERSION_MINOR 4 2603ff48bf5SDavid du Colombier #define TCPDUMP_MAGIC 0xa1b2c3d4 2613ff48bf5SDavid du Colombier 2623ff48bf5SDavid du Colombier struct pcap_file_header { 2633ff48bf5SDavid du Colombier ulong magic; 2643ff48bf5SDavid du Colombier ushort version_major; 2653ff48bf5SDavid du Colombier ushort version_minor; 2663ff48bf5SDavid du Colombier long thiszone; /* gmt to local correction */ 2673ff48bf5SDavid du Colombier ulong sigfigs; /* accuracy of timestamps */ 2683ff48bf5SDavid du Colombier ulong snaplen; /* max length saved portion of each pkt */ 2693ff48bf5SDavid du Colombier ulong linktype; /* data link type (DLT_*) */ 2703ff48bf5SDavid du Colombier }; 2713ff48bf5SDavid du Colombier 2723ff48bf5SDavid du Colombier struct pcap_pkthdr { 2733ff48bf5SDavid du Colombier uvlong ts; /* time stamp */ 2743ff48bf5SDavid du Colombier ulong caplen; /* length of portion present */ 2753ff48bf5SDavid du Colombier ulong len; /* length this packet (off wire) */ 2763ff48bf5SDavid du Colombier }; 2773ff48bf5SDavid du Colombier 2783ff48bf5SDavid du Colombier /* 2793ff48bf5SDavid du Colombier * pcap trace header 2803ff48bf5SDavid du Colombier */ 2813ff48bf5SDavid du Colombier void 2823ff48bf5SDavid du Colombier pcaphdr(void) 2833ff48bf5SDavid du Colombier { 2843ff48bf5SDavid du Colombier struct pcap_file_header hdr; 2853ff48bf5SDavid du Colombier 2863ff48bf5SDavid du Colombier hdr.magic = TCPDUMP_MAGIC; 2873ff48bf5SDavid du Colombier hdr.version_major = PCAP_VERSION_MAJOR; 2883ff48bf5SDavid du Colombier hdr.version_minor = PCAP_VERSION_MINOR; 2893ff48bf5SDavid du Colombier 2903ff48bf5SDavid du Colombier hdr.thiszone = 0; 2913ff48bf5SDavid du Colombier hdr.snaplen = 1500; 2923ff48bf5SDavid du Colombier hdr.sigfigs = 0; 2933ff48bf5SDavid du Colombier hdr.linktype = 1; 2943ff48bf5SDavid du Colombier 2953ff48bf5SDavid du Colombier write(1, &hdr, sizeof(hdr)); 2963ff48bf5SDavid du Colombier } 2973ff48bf5SDavid du Colombier 2983ff48bf5SDavid du Colombier /* 2999a747e4fSDavid du Colombier * write out a packet trace 3009a747e4fSDavid du Colombier */ 3019a747e4fSDavid du Colombier void 3029a747e4fSDavid du Colombier tracepkt(uchar *ps, int len) 3039a747e4fSDavid du Colombier { 3043ff48bf5SDavid du Colombier struct pcap_pkthdr *goo; 3053ff48bf5SDavid du Colombier 3063ff48bf5SDavid du Colombier if(pcap){ 3073ff48bf5SDavid du Colombier goo = (struct pcap_pkthdr*)(ps-16); 3083ff48bf5SDavid du Colombier goo->ts = pkttime; 3093ff48bf5SDavid du Colombier goo->caplen = len; 3103ff48bf5SDavid du Colombier goo->len = len; 3113ff48bf5SDavid du Colombier write(1, goo, len+16); 3123ff48bf5SDavid du Colombier } else { 3139a747e4fSDavid du Colombier hnputs(ps-10, len); 3149a747e4fSDavid du Colombier hnputl(ps-8, pkttime>>32); 3159a747e4fSDavid du Colombier hnputl(ps-4, pkttime); 3169a747e4fSDavid du Colombier write(1, ps-10, len+10); 3179a747e4fSDavid du Colombier } 3183ff48bf5SDavid du Colombier } 3199a747e4fSDavid du Colombier 3209a747e4fSDavid du Colombier /* 3219a747e4fSDavid du Colombier * format and print a packet 3229a747e4fSDavid du Colombier */ 3239a747e4fSDavid du Colombier void 3249a747e4fSDavid du Colombier printpkt(char *p, char *e, uchar *ps, uchar *pe) 3259a747e4fSDavid du Colombier { 3269a747e4fSDavid du Colombier Msg m; 3279a747e4fSDavid du Colombier ulong dt; 3289a747e4fSDavid du Colombier 3299a747e4fSDavid du Colombier dt = (pkttime-starttime)/1000000LL; 3309a747e4fSDavid du Colombier m.p = seprint(p, e, "%6.6uld ms ", dt); 3319a747e4fSDavid du Colombier m.ps = ps; 3329a747e4fSDavid du Colombier m.pe = pe; 3339a747e4fSDavid du Colombier m.e = e; 3349a747e4fSDavid du Colombier m.pr = root; 3359a747e4fSDavid du Colombier while(m.p < m.e){ 3369a747e4fSDavid du Colombier if(!sflag) 3379a747e4fSDavid du Colombier m.p = seprint(m.p, m.e, "\n\t"); 3389a747e4fSDavid du Colombier m.p = seprint(m.p, m.e, "%s(", m.pr->name); 3399a747e4fSDavid du Colombier if((*m.pr->seprint)(&m) < 0){ 3409a747e4fSDavid du Colombier m.p = seprint(m.p, m.e, "TOO SHORT"); 3419a747e4fSDavid du Colombier m.ps = m.pe; 3429a747e4fSDavid du Colombier } 3439a747e4fSDavid du Colombier m.p = seprint(m.p, m.e, ")"); 3449a747e4fSDavid du Colombier if(m.pr == nil || m.ps >= m.pe) 3459a747e4fSDavid du Colombier break; 3469a747e4fSDavid du Colombier } 3479a747e4fSDavid du Colombier *m.p++ = '\n'; 3489a747e4fSDavid du Colombier 3499a747e4fSDavid du Colombier if(write(1, p, m.p - p) < 0) 3509a747e4fSDavid du Colombier sysfatal("stdout: %r"); 3519a747e4fSDavid du Colombier } 3529a747e4fSDavid du Colombier 3539a747e4fSDavid du Colombier Proto **xprotos; 3549a747e4fSDavid du Colombier int nprotos; 3559a747e4fSDavid du Colombier 3569a747e4fSDavid du Colombier /* look up a protocol by its name */ 3579a747e4fSDavid du Colombier Proto* 3589a747e4fSDavid du Colombier findproto(char *name) 3599a747e4fSDavid du Colombier { 3609a747e4fSDavid du Colombier int i; 3619a747e4fSDavid du Colombier 3629a747e4fSDavid du Colombier for(i = 0; i < nprotos; i++) 3639a747e4fSDavid du Colombier if(strcmp(xprotos[i]->name, name) == 0) 3649a747e4fSDavid du Colombier return xprotos[i]; 3659a747e4fSDavid du Colombier return nil; 3669a747e4fSDavid du Colombier } 3679a747e4fSDavid du Colombier 3689a747e4fSDavid du Colombier /* 3699a747e4fSDavid du Colombier * add an undefined protocol to protos[] 3709a747e4fSDavid du Colombier */ 3719a747e4fSDavid du Colombier Proto* 3729a747e4fSDavid du Colombier addproto(char *name) 3739a747e4fSDavid du Colombier { 3749a747e4fSDavid du Colombier Proto *pr; 3759a747e4fSDavid du Colombier 3769a747e4fSDavid du Colombier xprotos = realloc(xprotos, (nprotos+1)*sizeof(Proto*)); 3779a747e4fSDavid du Colombier pr = malloc(sizeof *pr); 3789a747e4fSDavid du Colombier *pr = dump; 3799a747e4fSDavid du Colombier pr->name = name; 3809a747e4fSDavid du Colombier xprotos[nprotos++] = pr; 3819a747e4fSDavid du Colombier return pr; 3829a747e4fSDavid du Colombier } 3839a747e4fSDavid du Colombier 3849a747e4fSDavid du Colombier /* 3859a747e4fSDavid du Colombier * build a graph of protocols, this could easily be circular. This 3869a747e4fSDavid du Colombier * links together all the multiplexing in the protocol modules. 3879a747e4fSDavid du Colombier */ 3889a747e4fSDavid du Colombier void 3899a747e4fSDavid du Colombier mkprotograph(void) 3909a747e4fSDavid du Colombier { 3919a747e4fSDavid du Colombier Proto **l; 3929a747e4fSDavid du Colombier Proto *pr; 3939a747e4fSDavid du Colombier Mux *m; 3949a747e4fSDavid du Colombier 3959a747e4fSDavid du Colombier /* copy protos into a reallocable area */ 3969a747e4fSDavid du Colombier for(nprotos = 0; protos[nprotos] != nil; nprotos++) 3979a747e4fSDavid du Colombier ; 3989a747e4fSDavid du Colombier xprotos = malloc(nprotos*sizeof(Proto*)); 3999a747e4fSDavid du Colombier memmove(xprotos, protos, nprotos*sizeof(Proto*)); 4009a747e4fSDavid du Colombier 4019a747e4fSDavid du Colombier for(l = protos; *l != nil; l++){ 4029a747e4fSDavid du Colombier pr = *l; 4039a747e4fSDavid du Colombier for(m = pr->mux; m != nil && m->name != nil; m++){ 4049a747e4fSDavid du Colombier m->pr = findproto(m->name); 4059a747e4fSDavid du Colombier if(m->pr == nil) 4069a747e4fSDavid du Colombier m->pr = addproto(m->name); 4079a747e4fSDavid du Colombier } 4089a747e4fSDavid du Colombier } 4099a747e4fSDavid du Colombier } 4109a747e4fSDavid du Colombier 4119a747e4fSDavid du Colombier /* 4129a747e4fSDavid du Colombier * add in a protocol node 4139a747e4fSDavid du Colombier */ 4149a747e4fSDavid du Colombier static Filter* 4159a747e4fSDavid du Colombier addnode(Filter *f, Proto *pr) 4169a747e4fSDavid du Colombier { 4179a747e4fSDavid du Colombier Filter *nf; 4189a747e4fSDavid du Colombier nf = newfilter(); 4199a747e4fSDavid du Colombier nf->pr = pr; 4209a747e4fSDavid du Colombier nf->s = pr->name; 4219a747e4fSDavid du Colombier nf->l = f; 4229a747e4fSDavid du Colombier nf->op = WORD; 4239a747e4fSDavid du Colombier return nf; 4249a747e4fSDavid du Colombier } 4259a747e4fSDavid du Colombier 4269a747e4fSDavid du Colombier /* 4279a747e4fSDavid du Colombier * recurse through the protocol graph adding missing nodes 4289a747e4fSDavid du Colombier * to the filter if we reach the filter's protocol 4299a747e4fSDavid du Colombier */ 4309a747e4fSDavid du Colombier static Filter* 4319a747e4fSDavid du Colombier _fillin(Filter *f, Proto *last, int depth) 4329a747e4fSDavid du Colombier { 4339a747e4fSDavid du Colombier Mux *m; 4349a747e4fSDavid du Colombier Filter *nf; 4359a747e4fSDavid du Colombier 4369a747e4fSDavid du Colombier if(depth-- <= 0) 4379a747e4fSDavid du Colombier return nil; 4389a747e4fSDavid du Colombier 4399a747e4fSDavid du Colombier for(m = last->mux; m != nil && m->name != nil; m++){ 4409a747e4fSDavid du Colombier if(m->pr == nil) 4419a747e4fSDavid du Colombier continue; 4429a747e4fSDavid du Colombier if(f->pr == m->pr) 4439a747e4fSDavid du Colombier return f; 4449a747e4fSDavid du Colombier nf = _fillin(f, m->pr, depth); 4459a747e4fSDavid du Colombier if(nf != nil) 4469a747e4fSDavid du Colombier return addnode(nf, m->pr); 4479a747e4fSDavid du Colombier } 4489a747e4fSDavid du Colombier return nil; 4499a747e4fSDavid du Colombier } 4509a747e4fSDavid du Colombier 4519a747e4fSDavid du Colombier static Filter* 4529a747e4fSDavid du Colombier fillin(Filter *f, Proto *last) 4539a747e4fSDavid du Colombier { 4549a747e4fSDavid du Colombier int i; 4559a747e4fSDavid du Colombier Filter *nf; 4569a747e4fSDavid du Colombier 4579a747e4fSDavid du Colombier /* hack to make sure top level node is the root */ 4589a747e4fSDavid du Colombier if(last == nil){ 4599a747e4fSDavid du Colombier if(f->pr == root) 4609a747e4fSDavid du Colombier return f; 4619a747e4fSDavid du Colombier f = fillin(f, root); 4629a747e4fSDavid du Colombier if(f == nil) 4639a747e4fSDavid du Colombier return nil; 4649a747e4fSDavid du Colombier return addnode(f, root); 4659a747e4fSDavid du Colombier } 4669a747e4fSDavid du Colombier 4679a747e4fSDavid du Colombier /* breadth first search though the protocol graph */ 4689a747e4fSDavid du Colombier nf = f; 4699a747e4fSDavid du Colombier for(i = 1; i < 20; i++){ 4709a747e4fSDavid du Colombier nf = _fillin(f, last, i); 4719a747e4fSDavid du Colombier if(nf != nil) 4729a747e4fSDavid du Colombier break; 4739a747e4fSDavid du Colombier } 4749a747e4fSDavid du Colombier return nf; 4759a747e4fSDavid du Colombier } 4769a747e4fSDavid du Colombier 4779a747e4fSDavid du Colombier /* 4789a747e4fSDavid du Colombier * massage tree so that all paths from the root to a leaf 4799a747e4fSDavid du Colombier * contain a filter node for each header. 4809a747e4fSDavid du Colombier * 4819a747e4fSDavid du Colombier * also, set f->pr where possible 4829a747e4fSDavid du Colombier */ 4839a747e4fSDavid du Colombier Filter* 4849a747e4fSDavid du Colombier complete(Filter *f, Proto *last) 4859a747e4fSDavid du Colombier { 4869a747e4fSDavid du Colombier Proto *pr; 4879a747e4fSDavid du Colombier 4889a747e4fSDavid du Colombier if(f == nil) 4899a747e4fSDavid du Colombier return f; 4909a747e4fSDavid du Colombier 4919a747e4fSDavid du Colombier /* do a depth first traversal of the filter tree */ 4929a747e4fSDavid du Colombier switch(f->op){ 493*6b6b9ac8SDavid du Colombier case '!': 494*6b6b9ac8SDavid du Colombier f->l = complete(f->l, last); 495*6b6b9ac8SDavid du Colombier break; 4969a747e4fSDavid du Colombier case LAND: 4979a747e4fSDavid du Colombier case LOR: 4989a747e4fSDavid du Colombier f->l = complete(f->l, last); 4999a747e4fSDavid du Colombier f->r = complete(f->r, last); 5009a747e4fSDavid du Colombier break; 5019a747e4fSDavid du Colombier case '=': 5029a747e4fSDavid du Colombier break; 5039a747e4fSDavid du Colombier case WORD: 5049a747e4fSDavid du Colombier pr = findproto(f->s); 5059a747e4fSDavid du Colombier f->pr = pr; 5069a747e4fSDavid du Colombier if(pr == nil){ 5079a747e4fSDavid du Colombier if(f->l != nil){ 5089a747e4fSDavid du Colombier fprint(2, "%s unknown proto, ignoring params\n", 5099a747e4fSDavid du Colombier f->s); 5109a747e4fSDavid du Colombier f->l = nil; 5119a747e4fSDavid du Colombier } 5129a747e4fSDavid du Colombier } else { 5139a747e4fSDavid du Colombier f->l = complete(f->l, pr); 5149a747e4fSDavid du Colombier f = fillin(f, last); 5159a747e4fSDavid du Colombier if(f == nil) 5169a747e4fSDavid du Colombier sysfatal("internal error: can't get to %s", pr->name); 5179a747e4fSDavid du Colombier } 5189a747e4fSDavid du Colombier break; 5199a747e4fSDavid du Colombier } 5209a747e4fSDavid du Colombier return f; 5219a747e4fSDavid du Colombier } 5229a747e4fSDavid du Colombier 5239a747e4fSDavid du Colombier /* 5249a747e4fSDavid du Colombier * merge common nodes under | and & moving the merged node 5259a747e4fSDavid du Colombier * above the | or &. 5269a747e4fSDavid du Colombier * 5279a747e4fSDavid du Colombier * do some constant foldong, e.g. `true & x' becomes x and 5289a747e4fSDavid du Colombier * 'true | x' becomes true. 5299a747e4fSDavid du Colombier */ 5309a747e4fSDavid du Colombier static int changed; 5319a747e4fSDavid du Colombier 5329a747e4fSDavid du Colombier static Filter* 5339a747e4fSDavid du Colombier _optimize(Filter *f) 5349a747e4fSDavid du Colombier { 5359a747e4fSDavid du Colombier Filter *l; 5369a747e4fSDavid du Colombier 5379a747e4fSDavid du Colombier if(f == nil) 5389a747e4fSDavid du Colombier return f; 5399a747e4fSDavid du Colombier 5409a747e4fSDavid du Colombier switch(f->op){ 541*6b6b9ac8SDavid du Colombier case '!': 542*6b6b9ac8SDavid du Colombier /* is child also a not */ 543*6b6b9ac8SDavid du Colombier if(f->l->op == '!'){ 544*6b6b9ac8SDavid du Colombier changed = 1; 545*6b6b9ac8SDavid du Colombier return f->l->l; 546*6b6b9ac8SDavid du Colombier } 547*6b6b9ac8SDavid du Colombier break; 5489a747e4fSDavid du Colombier case LOR: 5499a747e4fSDavid du Colombier /* are two children the same protocol? */ 5509a747e4fSDavid du Colombier if(f->l->op != f->r->op || f->r->op != WORD 5519a747e4fSDavid du Colombier || f->l->pr != f->r->pr || f->l->pr == nil) 5529a747e4fSDavid du Colombier break; /* no optimization */ 5539a747e4fSDavid du Colombier 5549a747e4fSDavid du Colombier changed = 1; 5559a747e4fSDavid du Colombier 5569a747e4fSDavid du Colombier /* constant folding */ 5579a747e4fSDavid du Colombier /* if either child is childless, just return that */ 5589a747e4fSDavid du Colombier if(f->l->l == nil) 5599a747e4fSDavid du Colombier return f->l; 5609a747e4fSDavid du Colombier else if(f->r->l == nil) 5619a747e4fSDavid du Colombier return f->r; 5629a747e4fSDavid du Colombier 5639a747e4fSDavid du Colombier /* move the common node up, thow away one node */ 5649a747e4fSDavid du Colombier l = f->l; 5659a747e4fSDavid du Colombier f->l = l->l; 5669a747e4fSDavid du Colombier f->r = f->r->l; 5679a747e4fSDavid du Colombier l->l = f; 5689a747e4fSDavid du Colombier return l; 5699a747e4fSDavid du Colombier case LAND: 5709a747e4fSDavid du Colombier /* are two children the same protocol? */ 5719a747e4fSDavid du Colombier if(f->l->op != f->r->op || f->r->op != WORD 5729a747e4fSDavid du Colombier || f->l->pr != f->r->pr || f->l->pr == nil) 5739a747e4fSDavid du Colombier break; /* no optimization */ 5749a747e4fSDavid du Colombier 5759a747e4fSDavid du Colombier changed = 1; 5769a747e4fSDavid du Colombier 5779a747e4fSDavid du Colombier /* constant folding */ 5789a747e4fSDavid du Colombier /* if either child is childless, ignore it */ 5799a747e4fSDavid du Colombier if(f->l->l == nil) 5809a747e4fSDavid du Colombier return f->r; 5819a747e4fSDavid du Colombier else if(f->r->l == nil) 5829a747e4fSDavid du Colombier return f->l; 5839a747e4fSDavid du Colombier 5849a747e4fSDavid du Colombier /* move the common node up, thow away one node */ 5859a747e4fSDavid du Colombier l = f->l; 5869a747e4fSDavid du Colombier f->l = _optimize(l->l); 5879a747e4fSDavid du Colombier f->r = _optimize(f->r->l); 5889a747e4fSDavid du Colombier l->l = f; 5899a747e4fSDavid du Colombier return l; 5909a747e4fSDavid du Colombier } 5919a747e4fSDavid du Colombier f->l = _optimize(f->l); 5929a747e4fSDavid du Colombier f->r = _optimize(f->r); 5939a747e4fSDavid du Colombier return f; 5949a747e4fSDavid du Colombier } 5959a747e4fSDavid du Colombier 5969a747e4fSDavid du Colombier Filter* 5979a747e4fSDavid du Colombier optimize(Filter *f) 5989a747e4fSDavid du Colombier { 5999a747e4fSDavid du Colombier do{ 6009a747e4fSDavid du Colombier changed = 0; 6019a747e4fSDavid du Colombier f = _optimize(f); 6029a747e4fSDavid du Colombier }while(changed); 6039a747e4fSDavid du Colombier 6049a747e4fSDavid du Colombier return f; 6059a747e4fSDavid du Colombier } 6069a747e4fSDavid du Colombier 6079a747e4fSDavid du Colombier /* 6089a747e4fSDavid du Colombier * find any top level nodes that aren't the root 6099a747e4fSDavid du Colombier */ 610*6b6b9ac8SDavid du Colombier int 6119a747e4fSDavid du Colombier findbogus(Filter *f) 6129a747e4fSDavid du Colombier { 613*6b6b9ac8SDavid du Colombier int rv; 614*6b6b9ac8SDavid du Colombier 6159a747e4fSDavid du Colombier if(f->op != WORD){ 616*6b6b9ac8SDavid du Colombier rv = findbogus(f->l); 617*6b6b9ac8SDavid du Colombier if(f->r) 618*6b6b9ac8SDavid du Colombier rv |= findbogus(f->r); 619*6b6b9ac8SDavid du Colombier return rv; 620*6b6b9ac8SDavid du Colombier } else if(f->pr != root){ 621*6b6b9ac8SDavid du Colombier fprint(2, "bad top-level protocol: %s\n", f->s); 622*6b6b9ac8SDavid du Colombier return 1; 623*6b6b9ac8SDavid du Colombier } 624*6b6b9ac8SDavid du Colombier return 0; 6259a747e4fSDavid du Colombier } 6269a747e4fSDavid du Colombier 6279a747e4fSDavid du Colombier /* 6289a747e4fSDavid du Colombier * compile the filter 6299a747e4fSDavid du Colombier */ 6309a747e4fSDavid du Colombier static void 6319a747e4fSDavid du Colombier _compile(Filter *f, Proto *last) 6329a747e4fSDavid du Colombier { 6339a747e4fSDavid du Colombier if(f == nil) 6349a747e4fSDavid du Colombier return; 6359a747e4fSDavid du Colombier 6369a747e4fSDavid du Colombier switch(f->op){ 637*6b6b9ac8SDavid du Colombier case '!': 638*6b6b9ac8SDavid du Colombier _compile(f->l, last); 639*6b6b9ac8SDavid du Colombier break; 6409a747e4fSDavid du Colombier case LOR: 6419a747e4fSDavid du Colombier case LAND: 6429a747e4fSDavid du Colombier _compile(f->l, last); 6439a747e4fSDavid du Colombier _compile(f->r, last); 6449a747e4fSDavid du Colombier break; 6459a747e4fSDavid du Colombier case WORD: 6469a747e4fSDavid du Colombier if(last != nil) 6479a747e4fSDavid du Colombier (*last->compile)(f); 6489a747e4fSDavid du Colombier if(f->l) 6499a747e4fSDavid du Colombier _compile(f->l, f->pr); 6509a747e4fSDavid du Colombier break; 6519a747e4fSDavid du Colombier case '=': 6529a747e4fSDavid du Colombier if(last == nil) 6539a747e4fSDavid du Colombier sysfatal("internal error: compilewalk: badly formed tree"); 6549a747e4fSDavid du Colombier (*last->compile)(f); 6559a747e4fSDavid du Colombier break; 6569a747e4fSDavid du Colombier default: 6579a747e4fSDavid du Colombier sysfatal("internal error: compilewalk op: %d", f->op); 6589a747e4fSDavid du Colombier } 6599a747e4fSDavid du Colombier } 6609a747e4fSDavid du Colombier 6619a747e4fSDavid du Colombier Filter* 6629a747e4fSDavid du Colombier compile(Filter *f) 6639a747e4fSDavid du Colombier { 6649a747e4fSDavid du Colombier if(f == nil) 6659a747e4fSDavid du Colombier return f; 6669a747e4fSDavid du Colombier 6679a747e4fSDavid du Colombier /* fill in the missing header filters */ 6689a747e4fSDavid du Colombier f = complete(f, nil); 6699a747e4fSDavid du Colombier 6709a747e4fSDavid du Colombier /* constant folding */ 6719a747e4fSDavid du Colombier f = optimize(f); 6723ff48bf5SDavid du Colombier if(!toflag) 6739a747e4fSDavid du Colombier printfilter(f, "after optimize"); 6749a747e4fSDavid du Colombier 6759a747e4fSDavid du Colombier /* protocol specific compilations */ 6769a747e4fSDavid du Colombier _compile(f, nil); 6779a747e4fSDavid du Colombier 6789a747e4fSDavid du Colombier /* at this point, the root had better be the root proto */ 679*6b6b9ac8SDavid du Colombier if(findbogus(f)){ 680*6b6b9ac8SDavid du Colombier fprint(2, "bogus filter\n"); 681*6b6b9ac8SDavid du Colombier exits("bad filter"); 6829a747e4fSDavid du Colombier } 683*6b6b9ac8SDavid du Colombier 684*6b6b9ac8SDavid du Colombier return f; 6859a747e4fSDavid du Colombier } 6869a747e4fSDavid du Colombier 6879a747e4fSDavid du Colombier /* 6889a747e4fSDavid du Colombier * parse a byte array 6899a747e4fSDavid du Colombier */ 6909a747e4fSDavid du Colombier int 6919a747e4fSDavid du Colombier parseba(uchar *to, char *from) 6929a747e4fSDavid du Colombier { 6939a747e4fSDavid du Colombier char nip[4]; 6949a747e4fSDavid du Colombier char *p; 6959a747e4fSDavid du Colombier int i; 6969a747e4fSDavid du Colombier 6979a747e4fSDavid du Colombier p = from; 6989a747e4fSDavid du Colombier for(i = 0; i < 16; i++){ 6999a747e4fSDavid du Colombier if(*p == 0) 7009a747e4fSDavid du Colombier return -1; 7019a747e4fSDavid du Colombier nip[0] = *p++; 7029a747e4fSDavid du Colombier if(*p == 0) 7039a747e4fSDavid du Colombier return -1; 7049a747e4fSDavid du Colombier nip[1] = *p++; 7059a747e4fSDavid du Colombier nip[2] = 0; 7069a747e4fSDavid du Colombier to[i] = strtoul(nip, 0, 16); 7079a747e4fSDavid du Colombier } 7089a747e4fSDavid du Colombier return i; 7099a747e4fSDavid du Colombier } 7109a747e4fSDavid du Colombier 7119a747e4fSDavid du Colombier /* 7129a747e4fSDavid du Colombier * compile WORD = WORD, becomes a single node with a subop 7139a747e4fSDavid du Colombier */ 7149a747e4fSDavid du Colombier void 7159a747e4fSDavid du Colombier compile_cmp(char *proto, Filter *f, Field *fld) 7169a747e4fSDavid du Colombier { 7179a747e4fSDavid du Colombier uchar x[IPaddrlen]; 7189a747e4fSDavid du Colombier 7199a747e4fSDavid du Colombier if(f->op != '=') 7209a747e4fSDavid du Colombier sysfatal("internal error: compile_cmp %s: not a cmp", proto); 7219a747e4fSDavid du Colombier 7229a747e4fSDavid du Colombier for(; fld->name != nil; fld++){ 7239a747e4fSDavid du Colombier if(strcmp(f->l->s, fld->name) == 0){ 7249a747e4fSDavid du Colombier f->op = WORD; 7259a747e4fSDavid du Colombier f->subop = fld->subop; 7269a747e4fSDavid du Colombier switch(fld->ftype){ 7279a747e4fSDavid du Colombier case Fnum: 7289a747e4fSDavid du Colombier f->ulv = atoi(f->r->s); 7299a747e4fSDavid du Colombier break; 7309a747e4fSDavid du Colombier case Fether: 7319a747e4fSDavid du Colombier parseether(f->a, f->r->s); 7329a747e4fSDavid du Colombier break; 7339a747e4fSDavid du Colombier case Fv4ip: 7349a747e4fSDavid du Colombier f->ulv = parseip(x, f->r->s); 7359a747e4fSDavid du Colombier break; 7369a747e4fSDavid du Colombier case Fv6ip: 7379a747e4fSDavid du Colombier parseip(f->a, f->r->s); 7389a747e4fSDavid du Colombier break; 7399a747e4fSDavid du Colombier case Fba: 7409a747e4fSDavid du Colombier parseba(f->a, f->r->s); 7419a747e4fSDavid du Colombier break; 7429a747e4fSDavid du Colombier default: 7439a747e4fSDavid du Colombier sysfatal("internal error: compile_cmp %s: %d", 7449a747e4fSDavid du Colombier proto, fld->ftype); 7459a747e4fSDavid du Colombier } 7469a747e4fSDavid du Colombier f->l = f->r = nil; 7479a747e4fSDavid du Colombier return; 7489a747e4fSDavid du Colombier } 7499a747e4fSDavid du Colombier } 7509a747e4fSDavid du Colombier sysfatal("unknown %s field in: %s = %s", proto, f->l->s, f->r->s); 7519a747e4fSDavid du Colombier } 7529a747e4fSDavid du Colombier 7539a747e4fSDavid du Colombier void 7549a747e4fSDavid du Colombier _pf(Filter *f) 7559a747e4fSDavid du Colombier { 756*6b6b9ac8SDavid du Colombier char *s; 757*6b6b9ac8SDavid du Colombier 7589a747e4fSDavid du Colombier if(f == nil) 7599a747e4fSDavid du Colombier return; 7609a747e4fSDavid du Colombier 761*6b6b9ac8SDavid du Colombier s = nil; 7629a747e4fSDavid du Colombier switch(f->op){ 763*6b6b9ac8SDavid du Colombier case '!': 764*6b6b9ac8SDavid du Colombier fprint(2, "!"); 7659a747e4fSDavid du Colombier _pf(f->l); 766*6b6b9ac8SDavid du Colombier break; 767*6b6b9ac8SDavid du Colombier case WORD: 768*6b6b9ac8SDavid du Colombier fprint(2, "%s", f->s); 769*6b6b9ac8SDavid du Colombier if(f->l != nil){ 770*6b6b9ac8SDavid du Colombier fprint(2, "( "); 771*6b6b9ac8SDavid du Colombier _pf(f->l); 772*6b6b9ac8SDavid du Colombier fprint(2, " )"); 7739a747e4fSDavid du Colombier } 7749a747e4fSDavid du Colombier break; 7759a747e4fSDavid du Colombier case LAND: 776*6b6b9ac8SDavid du Colombier s = "&&"; 777*6b6b9ac8SDavid du Colombier goto print; 7789a747e4fSDavid du Colombier case LOR: 779*6b6b9ac8SDavid du Colombier s = "||"; 780*6b6b9ac8SDavid du Colombier goto print; 7819a747e4fSDavid du Colombier case '=': 782*6b6b9ac8SDavid du Colombier print: 7839a747e4fSDavid du Colombier _pf(f->l); 784*6b6b9ac8SDavid du Colombier if(s) 785*6b6b9ac8SDavid du Colombier fprint(2, " %s ", s); 786*6b6b9ac8SDavid du Colombier else 787*6b6b9ac8SDavid du Colombier fprint(2, " %c ", f->op); 7889a747e4fSDavid du Colombier _pf(f->r); 7899a747e4fSDavid du Colombier break; 7909a747e4fSDavid du Colombier default: 791*6b6b9ac8SDavid du Colombier fprint(2, "???"); 7929a747e4fSDavid du Colombier break; 7939a747e4fSDavid du Colombier } 7949a747e4fSDavid du Colombier } 7959a747e4fSDavid du Colombier 7969a747e4fSDavid du Colombier void 7979a747e4fSDavid du Colombier printfilter(Filter *f, char *tag) 7989a747e4fSDavid du Colombier { 799*6b6b9ac8SDavid du Colombier fprint(2, "%s: ", tag); 8009a747e4fSDavid du Colombier _pf(f); 801*6b6b9ac8SDavid du Colombier fprint(2, "\n"); 8029a747e4fSDavid du Colombier } 8039a747e4fSDavid du Colombier 8049a747e4fSDavid du Colombier void 8059a747e4fSDavid du Colombier printhelp(void) 8069a747e4fSDavid du Colombier { 8079a747e4fSDavid du Colombier Proto *pr, **l; 8089a747e4fSDavid du Colombier Mux *m; 8099a747e4fSDavid du Colombier Field *f; 8109a747e4fSDavid du Colombier 8119a747e4fSDavid du Colombier for(l = protos; *l != nil; l++){ 8129a747e4fSDavid du Colombier pr = *l; 8139a747e4fSDavid du Colombier if(pr->field != nil){ 8149a747e4fSDavid du Colombier print("%s's filter attr:\n", pr->name); 8159a747e4fSDavid du Colombier for(f = pr->field; f->name != nil; f++) 8169a747e4fSDavid du Colombier print("\t%s\t- %s\n", f->name, f->help); 8179a747e4fSDavid du Colombier } 8189a747e4fSDavid du Colombier if(pr->mux != nil){ 8199a747e4fSDavid du Colombier print("%s's subprotos:\n", pr->name); 8209a747e4fSDavid du Colombier for(m = pr->mux; m->name != nil; m++) 8219a747e4fSDavid du Colombier print("\t%s\n", m->name); 8229a747e4fSDavid du Colombier } 8239a747e4fSDavid du Colombier } 8249a747e4fSDavid du Colombier } 8259a747e4fSDavid du Colombier 8269a747e4fSDavid du Colombier /* 8279a747e4fSDavid du Colombier * demultiplex to next prototol header 8289a747e4fSDavid du Colombier */ 8299a747e4fSDavid du Colombier void 8309a747e4fSDavid du Colombier demux(Mux *mx, ulong val1, ulong val2, Msg *m, Proto *def) 8319a747e4fSDavid du Colombier { 8329a747e4fSDavid du Colombier m->pr = def; 8339a747e4fSDavid du Colombier for(mx = mx; mx->name != nil; mx++){ 8349a747e4fSDavid du Colombier if(val1 == mx->val || val2 == mx->val){ 8359a747e4fSDavid du Colombier m->pr = mx->pr; 8369a747e4fSDavid du Colombier break; 8379a747e4fSDavid du Colombier } 8389a747e4fSDavid du Colombier } 8399a747e4fSDavid du Colombier } 8403ff48bf5SDavid du Colombier 8413ff48bf5SDavid du Colombier /* 8423ff48bf5SDavid du Colombier * default framer just assumes the input packet is 8433ff48bf5SDavid du Colombier * a single read 8443ff48bf5SDavid du Colombier */ 8453ff48bf5SDavid du Colombier int 8463ff48bf5SDavid du Colombier defaultframer(int fd, uchar *pkt, int pktlen) 8473ff48bf5SDavid du Colombier { 8483ff48bf5SDavid du Colombier return read(fd, pkt, pktlen); 8493ff48bf5SDavid du Colombier } 850