## 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);
.
|