## diffname ip/ipmux.c 1998/0324 ## diff -e /dev/null /n/emeliedump/1998/0324/sys/src/brazil/ip/ipmux.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "ip.h" #define DPRINT if(0)print typedef struct Iphdr Iphdr; enum { IPHDR = 20, /* sizeof(Iphdr) */ }; struct Iphdr { uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* ip->identification */ uchar frag[2]; /* Fragment information */ uchar ttl; /* Time to live */ uchar proto; /* Protocol */ uchar cksum[2]; /* Header checksum */ uchar src[4]; /* IP source */ uchar dst[4]; /* IP destination */ }; enum { Tproto, Tdata, Tdst, Tsrc, Tifc, }; char *ftname[] = { [Tproto] "proto", [Tdata] "data", [Tdst] "dst", [Tsrc] "src", [Tifc] "ifc", }; typedef struct Ipmux Ipmux; struct Ipmux { Ipmux *yes; Ipmux *no; uchar type; ushort len; /* length in bytes of item to compare */ ushort off; /* offset of comparison */ int n; /* number of items val points to */ uchar *val; uchar *mask; int ref; /* so we can garbage collect */ }; static char* skipwhite(char *p) { while(*p == ' ' || *p == '\t') p++; return p; } static char* follows(char *p, char c) { char *f; f = strchr(p, c); if(f == nil) return nil; *f++ = 0; f = skipwhite(f); if(*f == 0) return nil; return f; } static Ipmux* parseop(char **pp) { char *p = *pp; int type, off, end, len; Ipmux *f; off = 0; p = skipwhite(p); if(strncmp(p, "dst", 3) == 0){ type = Tdst; len = IPaddrlen; p += 3; } else if(strncmp(p, "src", 3) == 0){ type = Tsrc; len = IPaddrlen; p += 3; } else if(strncmp(p, "ifc", 3) == 0){ type = Tifc; len = IPaddrlen; p += 3; } else if(strncmp(p, "proto", 5) == 0){ type = Tproto; len = 1; p += 5; } else if(strncmp(p, "data", 4) == 0){ type = Tdata; p += 4; p = skipwhite(p); if(*p != '[') return nil; p++; off = strtoul(p, &p, 0); p = skipwhite(p); if(*p != ':') end = off; else { p++; p = skipwhite(p); end = strtoul(p, &p, 0); if(end < off) return nil; p = skipwhite(p); } if(*p != ']') return nil; len = end - off + 1; p++; } else return nil; f = smalloc(sizeof(*f)); f->type = type; f->len = len; f->off = off; f->val = nil; f->mask = nil; f->n = 1; f->ref = 1; return f; } static int htoi(char x) { if(x >= '0' && x <= '9') x -= '0'; else if(x >= 'a' && x <= 'f') x -= 'a' - 10; else if(x >= 'A' && x <= 'F') x -= 'A' - 10; else x = 0; return x; } static int hextoi(char *p) { return (htoi(p[0])<<4) | htoi(p[1]); } static void parseval(uchar *v, char *p, int len) { while(*p && len-- > 0){ *v++ = hextoi(p); p += 2; } } static Ipmux* parsedemux(char *p) { int n; Ipmux *f; char *val; char *mask; char *vals[20]; uchar *v; /* parse operand */ f = parseop(&p); if(f == nil) return nil; /* find value */ val = follows(p, '='); if(val == nil) goto parseerror; /* parse mask */ mask = follows(p, '&'); if(mask != nil){ switch(f->type){ case Tsrc: case Tdst: case Tifc: f->mask = smalloc(f->len); parseipmask(f->mask, mask); break; case Tdata: f->mask = smalloc(f->len); parseval(f->mask, mask, f->len); break; default: goto parseerror; } } else f->mask = nil; /* parse vals */ f->n = tokenize(val, vals, sizeof(vals)/sizeof(char*)); if(f->n == 0) goto parseerror; f->val = smalloc(f->n*f->len); v = f->val; for(n = 0; n < f->n; n++){ switch(f->type){ case Tsrc: case Tdst: case Tifc: parseip(v, vals[n]); break; case Tproto: case Tdata: parseval(v, vals[n], f->len); break; } v += f->len; } return f; parseerror: if(f->mask) free(f->mask); if(f->val) free(f->val); free(f); return nil; } /* * Compare relative ordering of two ipmuxs. This doesn't compare the * values, just the fields being looked at. * * returns: <0 if a is a more specific match * 0 if a and b are matching on the same fields * >0 if b is a more specific match */ static int ipmuxcmp(Ipmux *a, Ipmux *b) { int n; /* compare types, lesser ones are more important */ n = a->type - b->type; if(n != 0) return n; /* compare offsets, call earlier ones more specific */ n = a->off - b->off; if(n != 0) return n; /* compare match lengths, longer ones are more specific */ n = b->len - a->len; if(n != 0) return n; /* * if we get here we have two entries matching * the same bytes of the record. Now check * the mask for equality. Longer masks are * more specific. */ if(a->mask != nil && b->mask == nil) return -1; if(a->mask == nil && b->mask != nil) return 1; if(a->mask != nil && b->mask != nil){ n = memcmp(b->mask, a->mask, a->len); if(n != 0) return n; } return 0; } /* * Compare the values of two ipmuxs. We're assuming that ipmuxcmp * returned 0 comparing them. */ static int ipmuxvalcmp(Ipmux *a, Ipmux *b) { int n; n = b->len*b->n - a->len*a->n; if(n != 0) return n; return memcmp(a->val, b->val, a->len*a->n); } /* * add onto an existing ipmux chain in the canonical comparison * order */ static void ipmuxchain(Ipmux **l, Ipmux *f) { for(; *l; l = &(*l)->yes) if(ipmuxcmp(f, *l) < 0) break; f->yes = *l; *l = f; } /* * copy a tree */ static Ipmux* ipmuxcopy(Ipmux *f) { Ipmux *nf; if(f == nil) return nil; nf = smalloc(sizeof *nf); *nf = *f; nf->no = ipmuxcopy(f->no); nf->yes = ipmuxcopy(f->yes); nf->val = smalloc(f->n*f->len); memmove(nf->val, f->val, f->n*f->len); return nf; } static void ipmuxfree(Ipmux *f) { if(f->val != nil) free(f->val); free(f); } static void ipmuxtreefree(Ipmux *f) { if(f->no != nil) ipmuxfree(f->no); if(f->yes != nil) ipmuxfree(f->yes); ipmuxfree(f); } /* * merge two trees */ static Ipmux* ipmuxmerge(Ipmux *a, Ipmux *b) { int n; Ipmux *f; if(a == nil) return b; if(b == nil) return a; n = ipmuxcmp(a, b); if(n < 0){ f = ipmuxcopy(b); a->yes = ipmuxmerge(a->yes, b); a->no = ipmuxmerge(a->no, f); return a; } if(n > 0){ f = ipmuxcopy(a); b->yes = ipmuxmerge(b->yes, a); b->no = ipmuxmerge(b->no, f); return b; } if(ipmuxvalcmp(a, b) == 0){ a->yes = ipmuxmerge(a->yes, b->yes); a->no = ipmuxmerge(a->no, b->no); a->ref++; ipmuxfree(b); return a; } a->no = ipmuxmerge(a->no, b); return a; } /* * remove a chain from a demux tree. This is like merging accept that * we remove instead of insert. */ int ipmuxremove(Ipmux **l, Ipmux *f) { int n, rv; Ipmux *ft; if(f == nil) return 0; /* we've removed it all */ if(*l == nil) return -1; ft = *l; n = ipmuxcmp(ft, f); if(n < 0){ /* *l is maching an earlier field, descend both paths */ rv = ipmuxremove(&ft->yes, f); rv += ipmuxremove(&ft->no, f); return rv; } if(n > 0){ /* f represents an earlier field than *l, this should be impossible */ return -1; } /* if we get here f and *l are comparing the same fields */ if(ipmuxvalcmp(ft, f) != 0){ /* different values mean mutually exclusive */ return ipmuxremove(&ft->no, f); } /* we found a match */ if(--(ft->ref) == 0){ /* * a dead node implies the whole yes side is also dead. * since our chain is constrained to be on that side, * we're done. */ ipmuxtreefree(ft->yes); *l = ft->no; ipmuxfree(ft); return 0; } /* * free the rest of the chain. it is constrained to match the * yes side. */ return ipmuxremove(&ft->yes, f->yes); } void printtree(Biobuf *b, Ipmux *f, int level) { int i, j; uchar *p; if(f == nil) { Bprint(b, "\n"); return; } for(i = 0; i < level; i++) Bprint(b, " "); Bprint(b, "%s", ftname[f->type]); if(f->type == Tdata) Bprint(b, "[%d:%d]", f->off, f->off+f->len-1); if(f->mask){ switch(f->type){ case Tifc: case Tsrc: case Tdst: Bprint(b, " & %M", f->mask); break; case Tproto: case Tdata: Bprint(b, " & "); for(j = 0; j < f->len; j++) Bprint(b, "%2.2ux", f->mask[j]); break; } } p = f->val; Bprint(b, " ="); for(i = 0; i < f->n; i++){ switch(f->type){ case Tifc: case Tsrc: case Tdst: Bprint(b, " %I", p); break; case Tproto: case Tdata: Bprint(b, " "); for(j = 0; j < f->len; j++) Bprint(b, "%2.2ux", p[j]); break; } p += f->len; } Bprint(b, "\n"); printtree(b, f->yes, level+1); printtree(b, f->no, level+1); } void main(void) { Ipmux *f, *f1, *f2, *f1copy, *f2copy; Ipmux *root; Biobuf out; Binit(&out, 1, OWRITE); fmtinstall('I', eipconv); fmtinstall('M', eipconv); Bprint(&out, "demux 1:\n"); f1 = parsedemux("data[0:3] = 12345678 23456789 3456789a"); f = parsedemux("ifc = 135.104.9.2"); ipmuxchain(&f1, f); f = parsedemux("src & 255.255.255.0 = 135.104.9.2"); ipmuxchain(&f1, f); f = parsedemux("proto = 17"); ipmuxchain(&f1, f); printtree(&out, f1, 0); f1copy = ipmuxcopy(f1); Bprint(&out, "demux 2:\n"); f2 = parsedemux("data[0:3] = 12345678 23456789 3456789a"); f = parsedemux("ifc = 135.104.9.1"); ipmuxchain(&f2, f); f = parsedemux("src & 255.255.255.0 = 135.104.9.3"); ipmuxchain(&f2, f); printtree(&out, f2, 0); f2copy = ipmuxcopy(f2); Bprint(&out, "merged demux:\n"); root = ipmuxmerge(f1, f2); printtree(&out, root, 0); Bprint(&out, "demux 1 removed:\n"); ipmuxremove(&root, f1copy); printtree(&out, root, 0); Bprint(&out, "demux 2 removed:\n"); ipmuxremove(&root, f2copy); printtree(&out, root, 0); } enum { Tproto, Tdata, Tdst, Tsrc, Tifc, }; char *ftname[] = { [Tdata] "data", [Tdst] "dst", [Tsrc] "src", [Tifc] "ifc", }; struct Ipmux { Ipmux *yes; Ipmux *no; uchar type; ushort len; /* length in bytes of item to compare */ ushort off; /* offset of comparison */ int n; /* number of items val points to */ uchar *val; uchar *mask; Conv *c; int ref; /* so we can garbage collect */ }; /* * connection request is a semi separated list of filters * e.g. proto=17;dat[0:4]=11aa22bb;ifc=135.104.9.2 * * there's no protection against overlapping specs. */ static char* ipmuxconnect(Conv *c, char **argv, int argc) { int n, proto; char *field[10]; Ipmux *mux, *chain; Fs *f; f = c->p->f; if(argc != 2) return Ebadarg; n = parsefields(argv[1], field, nelem(field), ";"); if(n <= 0) return Ebadarg; chain = nil; for(i = 0; i < n; i++){ mux = ipmuxparse(field[i]); if(mux == nil){ ipmuxtreefree(chain); return Ebadarg; } ipmuxchain(&chain, mux); } /* optimize the protocol into an array lookup */ if(chain->type != Tproto){ ipmuxtreefree(chain); return "need proto rule"; } mux = chain; proto = mux->val; chain = chain->yes; ipmuxfree(mux); /* save a copy of the chain so we can later remove it */ mux->conv = c; mux = ipmuxcopy(chain); *(Ipmux***)(c->ptcl) = chain; /* add the chain to the protocol demultiplexor tree */ qlock(p); f->t2m[proto] = ipmuxmerge(f->t2m[proto], mux); qunlock(p); Fsconnected(c, nil); return nil; } static int ipmuxstate(Conv *c, char *state, int n) { USED(c); return snprint(state, n, "%s", "Datagram"); } static void ipmuxcreate(Conv *c) { c->rq = qopen(64*1024, 0, 0, c); c->wq = qopen(64*1024, 0, 0, 0); *(IPmux**)(c->ptcl) = nil; } static char* ipmuxannounce(Conv*, char**, int) { return "ipmux does not support announce"; } static void ipmuxclose(Conv *c) { qclose(c->rq); qclose(c->wq); qclose(c->eq); ipmove(c->laddr, IPnoaddr); ipmove(c->raddr, IPnoaddr); c->lport = 0; c->rport = 0; unlock(c); } /* * takes a fully formed ip packet and just passes it down * the stack */ static void ipmuxkick(Conv *c, int l) { } static void ipmuxiput(Proto *ipmux, uchar*, Block *bp) { } int ipmuxstats(Proto *ipmux, char *buf, int len) { return 0; } void ipmuxinit(Fs *fs) { Proto *ipmux; ipmux = smalloc(sizeof(Proto)); ipmux->priv = smalloc(sizeof(GREpriv)); ipmux->name = "ipmux"; ipmux->kick = ipmuxkick; ipmux->connect = ipmuxconnect; ipmux->announce = ipmuxannounce; ipmux->state = ipmuxstate; ipmux->create = ipmuxcreate; ipmux->close = ipmuxclose; ipmux->rcv = ipmuxiput; ipmux->ctl = nil; ipmux->advise = nil; ipmux->stats = ipmuxstats; ipmux->ipproto = -1; ipmux->nc = 64; ipmux->ptclsize = sizeof(Ipmux*); Fsproto(fs, ipmux); } . ## diffname ip/ipmux.c 1998/0325 ## diff -e /n/emeliedump/1998/0324/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0325/sys/src/brazil/ip/ipmux.c 725c ipmux->ptclsize = sizeof(Ipmuxrock); . 711c ipmux->priv = nil; . 700c ipmuxstats(Proto *p, char *buf, int len) . 696a int len; Iphdr *ip; Fs *f = p->f; uchar *p; Conv *c; ip = bp->rptr; rlock(f); mux = f->t2m[ip->proto]; if(mux == nil) goto out; /* run the v4 filter */ len = BLEN(bp); if(len < 64 && bp->next){ bp = concatblock(bp); len = BLEN(bp); } c = nil; while(mux != nil){ while(mux){ switch(mux->type){ case Tia: p = ia; break; case Tsrc: p = ip->src; break; case Tdst: p = ip->dst; break; case Tdata: p = ip->data; if(mux->off+mux->len > len) goto no; break; } } if(mux->mask != nil){ } else { } no: mux = mux->no; continue; } out: /* doesn't match any filter, hand it to the specific protocol handler */ runlock(f); p = f->t2p[ip->proto]; if(p) (*p->rcv)(p, ia, bp); else freeblist(bp); return; . 695c ipmuxiput(Proto *p, uchar *ia, Block *bp) . 681a wlock(f); ipmuxremove(&(f->t2m[r->proto]), r->chain); wunlock(f); ipmuxtreefree(f->chain); . 673a Ipmuxrock *r; r = (Ipmuxrock*)(c->ptcl); r->chain = chain; r->proto = proto; . 644c wunlock(f); . 642c wlock(f); . 639c r = (Ipmuxrock*)(c->ptcl); r->chain = chain; r->proto = proto; . 604a Ipmuxrock *r; . 462,592d 412c static int . 66a /* * someplace to hold per conversation data */ struct Ipmuxrock { Ipmux *chain; int proto; }; . 51,52c /* * a node in the decision tree */ . 30a uchar data[1]; /* start of data */ . 12c typedef struct Iphdr Iphdr; typedef struct Ipmuxrock Ipmuxrock; typedef struct Ipmux Ipmux; . ## diffname ip/ipmux.c 1998/0326 ## diff -e /n/emeliedump/1998/0325/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0326/sys/src/brazil/ip/ipmux.c 631,634c . 629a if(v == ve){ if(mux->c != nil) c = mux->c; mux = mux->yes; if( . 613,628c v = mux->val; for(e = v + mux->n*mux->len; v < e; v = ve){ m = mux->mask; hp = h + mux->off; for(ve = v + mux->len; v < ve; v++){ if((*hp++ & *m++) != *v++) break; . 610a memmove(h, ia+IPv4off, ia); /* run the v4 filter */ . 605,609c /* make interface address part of packet */ h = bp->rptr - IPHDR - IPv4addrlen; if(h < bp->base){ bp = padblock(bp, IPHDR + IPv4addrlen); h = bp->rptr; bp->rptr += IPHDR + IPv4addrlen; . 599d 596c uchar *m, *h, *v, *e, *ve, *hp; . 594d 62c uchar len; /* length in bytes of item to compare */ . ## diffname ip/ipmux.c 1998/0327 ## diff -e /n/emeliedump/1998/0326/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0327/sys/src/brazil/ip/ipmux.c 673c f->ipmux = ipmux; /* hack for Fsrcvpcol */ Fsproto(f, ipmux); . 652c ipmuxinit(Fs *f) . 648c int n; Fs *f = p->f; rlock(f); n = ipmuxsprint(p->priv, 0, buf, len); runlock(f); return n; . 645c static int ipmuxsprint(Ipmux *mux, int level, char *buf, int len) { int i, j, n; n = 0; if(mux == nil) return n; for(i = 0; i < level; i++) n += snprint(buf+n, len-n, " "); n += snprint(buf+n, len-n, "h[%d:%d] & ", mux->off, mux->off+mux->len-1); for(i = 0; i < mux->len; i++) n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]); for(j = 0; j < mux->n; j++){ for(i = 0; i < mux->len; i++) n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]); n += snprint(buf+n, len-n, "|"); } level++; n += ipmuxsprint(mux->no, level, buf+n, len-n); n += ipmuxsprint(mux->yes, level, buf+n, len-n); return n; } static int . 642c return; . 636a if(c != nil){ bp->rp -= IPHDR; if(bp->next){ bp = concatblock(bp); if(bp == 0) panic("ilpullup"); } qpass(c->rq, bp); } nomatch: /* doesn't match any filter, hand it to the specific protocol handler */ ip = (Iphdr*)bp->rp; . 634,635d 630,632c if(v == e) mux = mux->no; . 627,628c break; } . 624,625c if(mux->conv != nil) c = mux->conv; . 614a if(mux->len + mux->off > len){ mux = mux->no; continue; } . 613a mux = f->ipmux->priv; . 612c /* run the v4 filter (needs optimizing) */ rlock(f); . 610c memmove(h, ia+IPv4off, IPv4addrlen); len = BLEN(bp); . 607,608c h = bp->rp; bp->rp += IPHDR + IPv4addrlen; . 604c h = bp->rp - IPHDR - IPv4addrlen; . 598,601c if(p->priv == nil) goto nomatch; . 596a Ipmux *mux; Iphdr *ip; . 587a Block *bp; bp = qget(c->wq); if(bp == nil) return; ipoput(c->p->f, bp, 0, 0); . 586c ipmuxkick(Conv *c, int) . 576c ipmuxtreefree(r->chain); . 574c ipmuxremove(&(c->p->priv), r->chain); . 562,563d 559a Fs *f = c->p->f; . 547c r = (Ipmuxrock*)(c->ptcl); r->chain = nil; . 544a Ipmuxrock *r; . 528c f->ipmux->priv = ipmuxmerge(f->ipmux->priv, mux); . 524d 520d 509,518d 507a if(chain == nil) return Ebadarg; mux->conv = c; . 501c mux = parsemux(field[i]); . 499c chain = nil; mux = nil; . 484c int i, n; . 376a if(f == nil) return; . 241c f->n = parsefields(val, vals, sizeof(vals)/sizeof(char*), "|"); . 237,238c } else { f->mask = smalloc(f->len); memset(f->mask, 0xff, f->len); } . 201c parsemux(char *p) . 154a len = end - off + 1; off += ((ulong)(ipoff->data)) - IPHDR; . 153d 139a if(off < 0 || off > (64-IPHDR)) return nil; . 128a off = ((ulong)&(ipoff->proto)) - IPHDR; . 124c off = -IPv4addrlen - IPHDR; len = IPv4addrlen; . 119c off = ((ulong)(ipoff->src)) - IPHDR; len = IPv4addrlen; . 114c off = ((ulong)(ipoff->dst)) - IPHDR; len = IPv4addrlen; . 110d 77d 68a Conv *conv; . 34a Iphdr *ipoff = 0; . ## diffname ip/ipmux.c 1998/0328 ## diff -e /n/emeliedump/1998/0327/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0328/sys/src/brazil/ip/ipmux.c 691a n += snprint(buf+n, len-n, "\n"); . 689c n += snprint(buf+n, len - n, "%2.2ux", *v++); . 686a n += snprint(buf+n, len-n, "="); v = mux->val; . 684c if(mux == nil){ n += snprint(buf+n, len-n, "\n"); return n; } n += snprint(buf+n, len-n, "h[%d:%d]&", mux->off, mux->off+mux->len-1); . 680,681d 677a uchar *v; . 660a return; . 654d 648,649c mux = mux->no; match:; . 645c goto match; . 638c if((*hp++ & *m++) != *v) . 621c h = bp->rp; memmove(h-IPv4addrlen, ia+IPv4off, IPv4addrlen); . 615,619c if(bp->rp - bp->base < IPv4addrlen){ bp = padblock(bp, IPv4addrlen); bp->rp += IPv4addrlen; . 581a r->chain = nil; . 541,542c Ipmuxrock *r; r = (Ipmuxrock*)(c->ptcl); return ipmuxsprint(r->chain, 0, state, n); . 260c v4parseip(v, vals[n]); . 235c v4parseip(f->mask, mask); . 161c off += (ulong)(ipoff->data); . 132c off = (ulong)&(ipoff->proto); . 126c off = -IPv4addrlen; . 120c off = (ulong)(ipoff->src); . 114c off = (ulong)(ipoff->dst); . 80a static int ipmuxsprint(Ipmux*, int, char*, int); . 64c short off; /* offset of comparison */ . ## diffname ip/ipmux.c 1998/0401 ## diff -e /n/emeliedump/1998/0328/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0401/sys/src/brazil/ip/ipmux.c 653d 638c for(e = mux->e; v < e; v = ve){ . 631a match: . 372a nf->e = nf->val + f->n*f->len; . 271a f->e = f->val + f->n*f->len; . 67a uchar *e; /* val + n*len */ . 65d 63a uchar n; /* number of items val points to */ . 62c uchar type; /* type of field (Txxxx) */ . ## diffname ip/ipmux.c 1998/0402 ## diff -e /n/emeliedump/1998/0401/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0402/sys/src/brazil/ip/ipmux.c 658,669d 656a continue; yes: if(mux->conv != nil) c = mux->conv; mux = mux->yes; . 649,654d 641,647c hp = h + mux->off; switch(mux->ctype){ case Cbyte: if(*mux->val == *hp) goto yes; break; case Cmbyte: if((*mux->val & *mux->mask) == *hp) goto yes; break; case Cshort: if(*((ushort*)mux->val) == *(ushort*)hp) goto yes; break; case Cmshort: if((*((ushort*)mux->val) & (*((ushort*)mux->mask))) == *(ushort*)hp) goto yes; break; case Clong: if(*((ulong*)mux->val) == *(ulong*)hp) goto yes; break; case Cmlong: if((*((ulong*)mux->val) & (*((ulong*)mux->mask))) == *(ulong*)hp) goto yes; break; case Cifc: if(*((ulong*)mux->val) == *(ulong*)ia) goto yes; break; case Cmifc: if((*((ulong*)mux->val) & (*((ulong*)mux->mask))) == *(ulong*)ia) goto yes; break; default: v = mux->val; for(e = mux->e; v < e; v = ve){ m = mux->mask; hp = h + mux->off; for(ve = v + mux->len; v < ve; v++){ if((*hp++ & *m++) != *v) break; } if(v == ve) goto yes; . 637c if(mux->eoff > len){ . 635d 631c /* run the v4 filter */ . 628d 622,626d 375c nf->e = nf->val + f->len*f->n; . 273a f->ctype = Cother; if(f->n == 1){ switch(f->len){ case 1: f->ctype = nomask ? Cbyte : Cmbyte; break; case 2: f->ctype = nomask ? Cshort : Cmshort; break; case 4: if(f->type == Cifc) f->ctype = nomask ? Cifc : Cmifc; else f->ctype = nomask ? Clong : Cmlong; break; } } . 272a f->eoff = f->off + f->len; . 247a nomask = 1; . 246a nomask = 0; . 213c int n, nomask; . 65a short eoff; /* end offset of comparison */ . 62a uchar ctype; /* tupe of comparison (Cxxxx) */ . 43a Cother = 0, Cbyte, /* single byte */ Cmbyte, /* single byte with mask */ Cshort, /* single short */ Cmshort, /* single short with mask */ Clong, /* single long */ Cmlong, /* single long with mask */ Cifc, Cmifc, . ## diffname ip/ipmux.c 1998/0403 ## diff -e /n/emeliedump/1998/0402/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0403/sys/src/brazil/ip/ipmux.c 719a if(c != nil){ qpass(c->rq, bp); return; } runlock(f); . ## diffname ip/ipmux.c 1998/0414 ## diff -e /n/emeliedump/1998/0403/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0414/sys/src/brazil/ip/ipmux.c 724c . 719a runlock(f); . 638c ih = (Iphdr*)(bp->rp); ipoput(c->p->f, bp, 0, ih->ttl); . 633a Iphdr *ih; . ## diffname ip/ipmux.c 1998/0502 ## diff -e /n/emeliedump/1998/0414/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0502/sys/src/brazil/ip/ipmux.c 525c * e.g. proto=17;dat[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0 . ## diffname ip/ipmux.c 1998/0507 ## diff -e /n/emeliedump/1998/0502/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0507/sys/src/brazil/ip/ipmux.c 701c if((*(ulong*)(ia + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val)) . 697c if(*((ulong*)mux->val) == *(ulong*)(ia + IPv4off)) . 693c if((*(ulong*)hp & (*((ulong*)mux->mask))) == *((ulong*)mux->val)) . 685c if((*(ushort*)hp & (*((ushort*)mux->mask))) == *((ushort*)mux->val)) . 677c if((*hp & *mux->mask) == *mux->val) . 299c if(f->type == Tifc) . ## diffname ip/ipmux.c 1998/0602 ## diff -e /n/emeliedump/1998/0507/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0602/sys/src/brazil/ip/ipmux.c 726a /* tack on interface address */ bp = padblock(bp, IPaddrlen); ipmove(bp->rp, ia); . ## diffname ip/ipmux.c 1998/0627 ## diff -e /n/emeliedump/1998/0602/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0627/sys/src/brazil/ip/ipmux.c 730c bp = concatblock(bp); if(bp != nil) qpass(c->rq, bp); . ## diffname ip/ipmux.c 1998/0630 ## diff -e /n/emeliedump/1998/0627/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0630/sys/src/brazil/ip/ipmux.c 727,732c qpass(c->rq, bp); . ## diffname ip/ipmux.c 1998/0701 ## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/ipmux.c /n/emeliedump/1998/0701/sys/src/brazil/ip/ipmux.c 727c /* tack on interface address */ bp = padblock(bp, IPaddrlen); ipmove(bp->rp, ia); bp = concatblock(bp); if(bp != nil) if (qpass(c->rq, bp) < 0) print("Q"); . ## diffname ip/ipmux.c 1999/0302 ## diff -e /n/emeliedump/1998/0701/sys/src/brazil/ip/ipmux.c /n/emeliedump/1999/0302/sys/src/brazil/ip/ipmux.c 623c qunlock(c); . ## diffname ip/ipmux.c 1999/0817 ## diff -e /n/emeliedump/1999/0302/sys/src/brazil/ip/ipmux.c /n/emeliedump/1999/0817/sys/src/brazil/ip/ipmux.c 642c ipoput(c->p->f, bp, 0, ih->ttl, ih->tos); . ## diffname ip/ipmux.c 2000/0308 ## diff -e /n/emeliedump/1999/0817/sys/src/brazil/ip/ipmux.c /n/emeliedump/2000/0308/sys/src/9/ip/ipmux.c 543c n = getfields(argv[1], field, nelem(field), 1, ";"); . 267c f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|"); . ## diffname ip/ipmux.c 2000/1220 ## diff -e /n/emeliedump/2000/0308/sys/src/9/ip/ipmux.c /n/emeliedump/2000/1220/sys/src/9/ip/ipmux.c 622,623d ## diffname ip/ipmux.c 2001/0127 ## diff -e /n/emeliedump/2000/1220/sys/src/9/ip/ipmux.c /n/emeliedump/2001/0127/sys/src/9/ip/ipmux.c 589c c->rq = qopen(64*1024, 1, 0, c); . ## diffname ip/ipmux.c 2001/0306 ## diff -e /n/emeliedump/2001/0127/sys/src/9/ip/ipmux.c /n/emeliedump/2001/0306/sys/src/9/ip/ipmux.c 629c ipmuxkick(Conv *c) . ## diffname ip/ipmux.c 2001/0623 ## diff -e /n/emeliedump/2001/0306/sys/src/9/ip/ipmux.c /n/emeliedump/2001/0623/sys/src/9/ip/ipmux.c 740c (*p->rcv)(p, ifc, bp); . 652a ia = ifc->lifc->local; . 651a uchar *ia; . 644c ipmuxiput(Proto *p, Ipifc *ifc, Block *bp) . ## diffname ip/ipmux.c 2002/0507 ## diff -e /n/emeliedump/2001/0623/sys/src/9/ip/ipmux.c /n/emeliedump/2002/0507/sys/src/9/ip/ipmux.c 762c n += snprint(buf+n, len-n, "h[%d:%d]&", mux->off+((int)mux->skiphdr)*((int)ipoff->data), mux->off+(((int)mux->skiphdr)*((int)ipoff->data))+mux->len-1); . 740,742c ip = (Ip4hdr*)bp->rp; if((ip->vihl&0xF0)==0x40) { p = f->t2p[ip->proto]; } else { ip6 = (Ip6hdr*)bp->rp; p = f->t2p[ip6->proto]; } if(p && p->rcv) . 733c if(qpass(c->rq, bp) < 0) . 730c ipmove(bp->rp, ifc->lifc->local); . 702c if((*(ulong*)(ifc->lifc->local + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val)) . 698c if(*((ulong*)mux->val) == *(ulong*)(ifc->lifc->local + IPv4off)) . 671c hp = h + mux->off + ((int)mux->skiphdr)*hl; . 654c ip = (Ip4hdr*)bp->rp; hl = (ip->vihl&0x0F)<<2; . 651,652c Ip4hdr *ip; Ip6hdr *ip6; . 646c int len, hl; . 637,640c else { Ip4hdr *ih4 = (Ip4hdr*)(bp->rp); if((ih4->vihl)&0xF0 != 0x60) ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos); else { ih6 = (struct Ip6hdr*)ih4; ipoput6(c->p->f, bp, 0, ih6->ttl, 0); } } . 632c struct Ip6hdr *ih6; . 336c n = (a->off+((int)a->skiphdr)*(ulong)ipoff->data) - (b->off+((int)b->skiphdr)*(ulong)ipoff->data); . 280a case Tiph: . 252a case Tiph: . 188a if(type == Tdata) f->skiphdr = 1; else f->skiphdr = 0; . 178c else . 176d 151,153c else if(strncmp(p, "data", 4) == 0 || strncmp(p, "iph", 3) == 0){ if(strncmp(p, "data", 4) == 0) { type = Tdata; p += 4; } else { type = Tiph; p += 3; } . 72,77c uchar type; /* type of field (Txxxx) */ uchar ctype; /* tupe of comparison (Cxxxx) */ uchar len; /* length in bytes of item to compare */ uchar n; /* number of items val points to */ short off; /* offset of comparison */ short eoff; /* end offset of comparison */ uchar skiphdr; /* should offset start after ip header */ . 59a [Tiph] "iph", . 40a Tiph, . 36a struct Ip6hdr { uchar vcf[4]; /* version, class label, and flow label */ uchar ploadlen[2]; /* payload length */ uchar proto; /* next header, i.e. proto */ uchar ttl; /* hop limit, i.e. ttl */ uchar src[16]; /* IP source */ uchar dst[16]; /* IP destination */ }; . 35c Ip4hdr *ipoff = 0; . 21c struct Ip4hdr . 18c IPHDR = 20, /* sizeof(Ip4hdr) */ . 12,14c typedef struct Ipmuxrock Ipmuxrock; typedef struct Ipmux Ipmux; typedef struct Ip4hdr Ip4hdr; typedef struct Ip6hdr Ip6hdr; . 9d ## diffname ip/ipmux.c 2002/0711 ## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/ipmux.c /n/emeliedump/2002/0711/sys/src/9/ip/ipmux.c 615c c->rq = qopen(64*1024, Qmsg, 0, c); . ## diffname ip/ipmux.c 2002/0712 ## diff -e /n/emeliedump/2002/0711/sys/src/9/ip/ipmux.c /n/emeliedump/2002/0712/sys/src/9/ip/ipmux.c 839d 656a Conv *c = x; . 655c ipmuxkick(void *x) . 616c c->wq = qopen(64*1024, Qkick, ipmuxkick, c); . 108a static void ipmuxkick(void *x); . ## diffname ip/ipmux.c 2002/1108 ## diff -e /n/emeliedump/2002/0712/sys/src/9/ip/ipmux.c /n/emeliedump/2002/1108/sys/src/9/ip/ipmux.c 687,688c ip = (Ip4hdr*)bp->rp; hl = (ip->vihl&0x0F)<<2; . 363c (b->off+((int)b->skiphdr)*(ulong)ipoff->data); . 306c case Tiph: . 277c case Tiph: . 209,212c if(type == Tdata) f->skiphdr = 1; else f->skiphdr = 0; . 167,174c if(strncmp(p, "data", 4) == 0) { type = Tdata; p += 4; } else { type = Tiph; p += 3; } . 94c uchar *e; /* val+n*len*/ . 85,91c uchar type; /* type of field(Txxxx) */ uchar ctype; /* tupe of comparison(Cxxxx) */ uchar len; /* length in bytes of item to compare */ uchar n; /* number of items val points to */ short off; /* offset of comparison */ short eoff; /* end offset of comparison */ uchar skiphdr; /* should offset start after ipheader */ . 72c [Tiph] "iph", . 52c Tiph, . 39,44c uchar vcf[4]; /* version, class label, and flow label */ uchar ploadlen[2]; /* payload length */ uchar proto; /* next header, i.e. proto */ uchar ttl; /* hop limit, i.e. ttl */ uchar src[16]; /* IP source */ uchar dst[16]; /* IP destination */ . ## diffname ip/ipmux.c 2003/0308 ## diff -e /n/emeliedump/2002/1108/sys/src/9/ip/ipmux.c /n/emeliedump/2003/0308/sys/src/9/ip/ipmux.c 671c ipoput6(c->p->f, bp, 0, ih6->ttl, 0, nil); . 668c ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil); .