📄 main.c
字号:
if(last == nil){ if(f->pr == root) return f; f = fillin(f, root); if(f == nil) return nil; return addnode(f, root); } /* breadth first search though the protocol graph */ nf = f; for(i = 1; i < 20; i++){ nf = _fillin(f, last, i); if(nf != nil) break; } return nf;}/* * massage tree so that all paths from the root to a leaf * contain a filter node for each header. * * also, set f->pr where possible */Filter*complete(Filter *f, Proto *last){ Proto *pr; if(f == nil) return f; /* do a depth first traversal of the filter tree */ switch(f->op){ case '!': f->l = complete(f->l, last); break; case LAND: case LOR: f->l = complete(f->l, last); f->r = complete(f->r, last); break; case '=': break; case WORD: pr = findproto(f->s); f->pr = pr; if(pr == nil){ if(f->l != nil){ fprint(2, "%s unknown proto, ignoring params\n", f->s); f->l = nil; } } else { f->l = complete(f->l, pr); f = fillin(f, last); if(f == nil) sysfatal("internal error: can't get to %s", pr->name); } break; } return f;}/* * merge common nodes under | and & moving the merged node * above the | or &. * * do some constant foldong, e.g. `true & x' becomes x and * 'true | x' becomes true. */static int changed;static Filter*_optimize(Filter *f){ Filter *l; if(f == nil) return f; switch(f->op){ case '!': /* is child also a not */ if(f->l->op == '!'){ changed = 1; return f->l->l; } break; case LOR: /* are two children the same protocol? */ if(f->l->op != f->r->op || f->r->op != WORD || f->l->pr != f->r->pr || f->l->pr == nil) break; /* no optimization */ changed = 1; /* constant folding */ /* if either child is childless, just return that */ if(f->l->l == nil) return f->l; else if(f->r->l == nil) return f->r; /* move the common node up, thow away one node */ l = f->l; f->l = l->l; f->r = f->r->l; l->l = f; return l; case LAND: /* are two children the same protocol? */ if(f->l->op != f->r->op || f->r->op != WORD || f->l->pr != f->r->pr || f->l->pr == nil) break; /* no optimization */ changed = 1; /* constant folding */ /* if either child is childless, ignore it */ if(f->l->l == nil) return f->r; else if(f->r->l == nil) return f->l; /* move the common node up, thow away one node */ l = f->l; f->l = _optimize(l->l); f->r = _optimize(f->r->l); l->l = f; return l; } f->l = _optimize(f->l); f->r = _optimize(f->r); return f;}Filter*optimize(Filter *f){ do{ changed = 0; f = _optimize(f); }while(changed); return f;}/* * find any top level nodes that aren't the root */intfindbogus(Filter *f){ int rv; if(f->op != WORD){ rv = findbogus(f->l); if(f->r) rv |= findbogus(f->r); return rv; } else if(f->pr != root){ fprint(2, "bad top-level protocol: %s\n", f->s); return 1; } return 0;}/* * compile the filter */static void_compile(Filter *f, Proto *last){ if(f == nil) return; switch(f->op){ case '!': _compile(f->l, last); break; case LOR: case LAND: _compile(f->l, last); _compile(f->r, last); break; case WORD: if(last != nil){ if(last->compile == nil) sysfatal("unknown %s subprotocol: %s", f->pr->name, f->s); (*last->compile)(f); } if(f->l) _compile(f->l, f->pr); break; case '=': if(last == nil) sysfatal("internal error: compilewalk: badly formed tree"); if(last->compile == nil) sysfatal("unknown %s field: %s", f->pr->name, f->s); (*last->compile)(f); break; default: sysfatal("internal error: compilewalk op: %d", f->op); }}Filter*compile(Filter *f){ if(f == nil) return f; /* fill in the missing header filters */ f = complete(f, nil); /* constant folding */ f = optimize(f); if(!toflag) printfilter(f, "after optimize"); /* protocol specific compilations */ _compile(f, nil); /* at this point, the root had better be the root proto */ if(findbogus(f)){ fprint(2, "bogus filter\n"); exits("bad filter"); } return f;}/* * parse a byte array */intparseba(uchar *to, char *from){ char nip[4]; char *p; int i; p = from; for(i = 0; i < 16; i++){ if(*p == 0) return -1; nip[0] = *p++; if(*p == 0) return -1; nip[1] = *p++; nip[2] = 0; to[i] = strtoul(nip, 0, 16); } return i;}/* * compile WORD = WORD, becomes a single node with a subop */voidcompile_cmp(char *proto, Filter *f, Field *fld){ uchar x[IPaddrlen]; if(f->op != '=') sysfatal("internal error: compile_cmp %s: not a cmp", proto); for(; fld->name != nil; fld++){ if(strcmp(f->l->s, fld->name) == 0){ f->op = WORD; f->subop = fld->subop; switch(fld->ftype){ case Fnum: f->ulv = atoi(f->r->s); break; case Fether: parseether(f->a, f->r->s); break; case Fv4ip: f->ulv = parseip(x, f->r->s); break; case Fv6ip: parseip(f->a, f->r->s); break; case Fba: parseba(f->a, f->r->s); break; default: sysfatal("internal error: compile_cmp %s: %d", proto, fld->ftype); } f->l = f->r = nil; return; } } sysfatal("unknown %s field in: %s = %s", proto, f->l->s, f->r->s);}void_pf(Filter *f){ char *s; if(f == nil) return; s = nil; switch(f->op){ case '!': fprint(2, "!"); _pf(f->l); break; case WORD: fprint(2, "%s", f->s); if(f->l != nil){ fprint(2, "("); _pf(f->l); fprint(2, ")"); } break; case LAND: s = "&&"; goto print; case LOR: s = "||"; goto print; case '=': print: _pf(f->l); if(s) fprint(2, " %s ", s); else fprint(2, " %c ", f->op); _pf(f->r); break; default: fprint(2, "???"); break; }}voidprintfilter(Filter *f, char *tag){ fprint(2, "%s: ", tag); _pf(f); fprint(2, "\n");}voidcat(void){ char buf[1024]; int n; while((n = read(0, buf, sizeof buf)) > 0) write(1, buf, n);}static int fd1 = -1;voidstartmc(void){ int p[2]; if(fd1 == -1) fd1 = dup(1, -1); if(pipe(p) < 0) return; switch(fork()){ case -1: return; default: close(p[0]); dup(p[1], 1); if(p[1] != 1) close(p[1]); return; case 0: close(p[1]); dup(p[0], 0); if(p[0] != 0) close(p[0]); execl("/bin/mc", "mc", nil); cat(); _exits(0); }}voidstopmc(void){ close(1); dup(fd1, 1); waitpid();}voidprinthelp(char *name){ int len; Proto *pr, **l; Mux *m; Field *f; char fmt[40]; if(name == nil){ print("protocols:\n"); startmc(); for(l=protos; (pr=*l) != nil; l++) print(" %s\n", pr->name); stopmc(); return; } pr = findproto(name); if(pr == nil){ print("unknown protocol %s\n", name); return; } if(pr->field){ print("%s's filter attributes:\n", pr->name); len = 0; for(f=pr->field; f->name; f++) if(len < strlen(f->name)) len = strlen(f->name); startmc(); for(f=pr->field; f->name; f++) print(" %-*s - %s\n", len, f->name, f->help); stopmc(); } if(pr->mux){ print("%s's subprotos:\n", pr->name); startmc(); snprint(fmt, sizeof fmt, " %s %%s\n", pr->valfmt); for(m=pr->mux; m->name != nil; m++) print(fmt, m->val, m->name); stopmc(); }}/* * demultiplex to next prototol header */voiddemux(Mux *mx, ulong val1, ulong val2, Msg *m, Proto *def){ m->pr = def; for(mx = mx; mx->name != nil; mx++){ if(val1 == mx->val || val2 == mx->val){ m->pr = mx->pr; break; } }}/* * default framer just assumes the input packet is * a single read */intdefaultframer(int fd, uchar *pkt, int pktlen){ return read(fd, pkt, pktlen);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -