devip: implement ipv6 support in ipmux packet filter
Added a ver= field to the filter to distinguish the ip version. By default, a filter is parsed as ipv6, and after parsing proto, src and dst fields are converted to ipv4. When no ver= field is specified, a ip version filter is implicitely added and both protocols are parsed. This change also gets rid of the fast compare types as the filed might not be aligned correctly in the packet. This also fixes the ifc= filter, as we have to check any local address.
This commit is contained in:
parent
8f087e019f
commit
5474646164
2 changed files with 183 additions and 174 deletions
|
@ -1126,6 +1126,10 @@ of a packet to match. The possible relations are:
|
||||||
.TF "\fLdata[\fIn\fL:\fIm\fL]=\fIexpr\fR "
|
.TF "\fLdata[\fIn\fL:\fIm\fL]=\fIexpr\fR "
|
||||||
.PD
|
.PD
|
||||||
.TP
|
.TP
|
||||||
|
.BI ver= n
|
||||||
|
the IP version must be
|
||||||
|
.IR n .
|
||||||
|
.TP
|
||||||
.BI proto= n
|
.BI proto= n
|
||||||
the IP protocol number must be
|
the IP protocol number must be
|
||||||
.IR n .
|
.IR n .
|
||||||
|
@ -1135,7 +1139,7 @@ bytes
|
||||||
.I n
|
.I n
|
||||||
through
|
through
|
||||||
.I m
|
.I m
|
||||||
following the IP packet must match
|
following the IP header must match
|
||||||
.IR expr .
|
.IR expr .
|
||||||
.TP
|
.TP
|
||||||
.BI iph[ n : m ]= expr
|
.BI iph[ n : m ]= expr
|
||||||
|
|
|
@ -14,52 +14,15 @@
|
||||||
typedef struct Ipmuxrock Ipmuxrock;
|
typedef struct Ipmuxrock Ipmuxrock;
|
||||||
typedef struct Ipmux Ipmux;
|
typedef struct Ipmux Ipmux;
|
||||||
|
|
||||||
typedef struct Myip4hdr Myip4hdr;
|
|
||||||
struct Myip4hdr
|
|
||||||
{
|
|
||||||
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 */
|
|
||||||
|
|
||||||
uchar data[1]; /* start of data */
|
|
||||||
};
|
|
||||||
Myip4hdr *ipoff = 0;
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
Tver,
|
||||||
Tproto,
|
Tproto,
|
||||||
Tdata,
|
Tdata,
|
||||||
Tiph,
|
Tiph,
|
||||||
Tdst,
|
Tdst,
|
||||||
Tsrc,
|
Tsrc,
|
||||||
Tifc,
|
Tifc,
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
char *ftname[] =
|
|
||||||
{
|
|
||||||
[Tproto] "proto",
|
|
||||||
[Tdata] "data",
|
|
||||||
[Tiph] "iph",
|
|
||||||
[Tdst] "dst",
|
|
||||||
[Tsrc] "src",
|
|
||||||
[Tifc] "ifc",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -70,16 +33,12 @@ struct Ipmux
|
||||||
Ipmux *yes;
|
Ipmux *yes;
|
||||||
Ipmux *no;
|
Ipmux *no;
|
||||||
uchar type; /* type of field(Txxxx) */
|
uchar type; /* type of field(Txxxx) */
|
||||||
uchar ctype; /* tupe of comparison(Cxxxx) */
|
|
||||||
uchar len; /* length in bytes of item to compare */
|
uchar len; /* length in bytes of item to compare */
|
||||||
uchar n; /* number of items val points to */
|
uchar n; /* number of items val points to */
|
||||||
short off; /* offset of comparison */
|
int off; /* offset of comparison */
|
||||||
short eoff; /* end offset of comparison */
|
|
||||||
uchar skiphdr; /* should offset start after ipheader */
|
|
||||||
uchar *val;
|
uchar *val;
|
||||||
uchar *mask;
|
uchar *mask;
|
||||||
uchar *e; /* val+n*len*/
|
uchar *e; /* val+n*len*/
|
||||||
|
|
||||||
int ref; /* so we can garbage collect */
|
int ref; /* so we can garbage collect */
|
||||||
Conv *conv;
|
Conv *conv;
|
||||||
};
|
};
|
||||||
|
@ -94,6 +53,7 @@ struct Ipmuxrock
|
||||||
|
|
||||||
static int ipmuxsprint(Ipmux*, int, char*, int);
|
static int ipmuxsprint(Ipmux*, int, char*, int);
|
||||||
static void ipmuxkick(void *x);
|
static void ipmuxkick(void *x);
|
||||||
|
static void ipmuxfree(Ipmux *f);
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
skipwhite(char *p)
|
skipwhite(char *p)
|
||||||
|
@ -126,27 +86,33 @@ parseop(char **pp)
|
||||||
Ipmux *f;
|
Ipmux *f;
|
||||||
|
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
if(strncmp(p, "dst", 3) == 0){
|
if(strncmp(p, "ver", 3) == 0){
|
||||||
|
type = Tver;
|
||||||
|
off = 0;
|
||||||
|
len = 1;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
else if(strncmp(p, "dst", 3) == 0){
|
||||||
type = Tdst;
|
type = Tdst;
|
||||||
off = (int)(uintptr)(ipoff->dst);
|
off = offsetof(Ip6hdr, dst[0]);
|
||||||
len = IPv4addrlen;
|
len = IPaddrlen;
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
else if(strncmp(p, "src", 3) == 0){
|
else if(strncmp(p, "src", 3) == 0){
|
||||||
type = Tsrc;
|
type = Tsrc;
|
||||||
off = (int)(uintptr)(ipoff->src);
|
off = offsetof(Ip6hdr, src[0]);
|
||||||
len = IPv4addrlen;
|
len = IPaddrlen;
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
else if(strncmp(p, "ifc", 3) == 0){
|
else if(strncmp(p, "ifc", 3) == 0){
|
||||||
type = Tifc;
|
type = Tifc;
|
||||||
off = -IPv4addrlen;
|
off = -IPaddrlen;
|
||||||
len = IPv4addrlen;
|
len = IPaddrlen;
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
else if(strncmp(p, "proto", 5) == 0){
|
else if(strncmp(p, "proto", 5) == 0){
|
||||||
type = Tproto;
|
type = Tproto;
|
||||||
off = (int)(uintptr)&(ipoff->proto);
|
off = offsetof(Ip6hdr, proto);
|
||||||
len = 1;
|
len = 1;
|
||||||
p += 5;
|
p += 5;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +130,7 @@ parseop(char **pp)
|
||||||
return nil;
|
return nil;
|
||||||
p++;
|
p++;
|
||||||
off = strtoul(p, &p, 0);
|
off = strtoul(p, &p, 0);
|
||||||
if(off < 0 || off > (64-IP4HDR))
|
if(off < 0)
|
||||||
return nil;
|
return nil;
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
if(*p != ':')
|
if(*p != ':')
|
||||||
|
@ -193,11 +159,6 @@ parseop(char **pp)
|
||||||
f->mask = nil;
|
f->mask = nil;
|
||||||
f->n = 1;
|
f->n = 1;
|
||||||
f->ref = 1;
|
f->ref = 1;
|
||||||
if(type == Tdata)
|
|
||||||
f->skiphdr = 1;
|
|
||||||
else
|
|
||||||
f->skiphdr = 0;
|
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +194,7 @@ parseval(uchar *v, char *p, int len)
|
||||||
static Ipmux*
|
static Ipmux*
|
||||||
parsemux(char *p)
|
parsemux(char *p)
|
||||||
{
|
{
|
||||||
int n, nomask;
|
int n;
|
||||||
Ipmux *f;
|
Ipmux *f;
|
||||||
char *val;
|
char *val;
|
||||||
char *mask;
|
char *mask;
|
||||||
|
@ -258,7 +219,7 @@ parsemux(char *p)
|
||||||
case Tdst:
|
case Tdst:
|
||||||
case Tifc:
|
case Tifc:
|
||||||
f->mask = smalloc(f->len);
|
f->mask = smalloc(f->len);
|
||||||
v4parseip(f->mask, mask);
|
parseipmask(f->mask, mask, 0);
|
||||||
break;
|
break;
|
||||||
case Tdata:
|
case Tdata:
|
||||||
case Tiph:
|
case Tiph:
|
||||||
|
@ -268,25 +229,34 @@ parsemux(char *p)
|
||||||
default:
|
default:
|
||||||
goto parseerror;
|
goto parseerror;
|
||||||
}
|
}
|
||||||
nomask = 0;
|
} else if(f->type == Tver){
|
||||||
} else {
|
|
||||||
nomask = 1;
|
|
||||||
f->mask = smalloc(f->len);
|
f->mask = smalloc(f->len);
|
||||||
memset(f->mask, 0xff, f->len);
|
f->mask[0] = 0xF0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse vals */
|
/* parse vals */
|
||||||
f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|");
|
f->n = getfields(val, vals, nelem(vals), 1, "|");
|
||||||
if(f->n == 0)
|
if(f->n == 0)
|
||||||
goto parseerror;
|
goto parseerror;
|
||||||
f->val = smalloc(f->n*f->len);
|
f->val = smalloc(f->n*f->len);
|
||||||
v = f->val;
|
v = f->val;
|
||||||
for(n = 0; n < f->n; n++){
|
for(n = 0; n < f->n; n++){
|
||||||
switch(f->type){
|
switch(f->type){
|
||||||
|
case Tver:
|
||||||
|
if(f->n != 1)
|
||||||
|
goto parseerror;
|
||||||
|
if(strcmp(vals[n], "6") == 0)
|
||||||
|
*v = IP_VER6;
|
||||||
|
else if(strcmp(vals[n], "4") == 0)
|
||||||
|
*v = IP_VER4;
|
||||||
|
else
|
||||||
|
goto parseerror;
|
||||||
|
break;
|
||||||
case Tsrc:
|
case Tsrc:
|
||||||
case Tdst:
|
case Tdst:
|
||||||
case Tifc:
|
case Tifc:
|
||||||
v4parseip(v, vals[n]);
|
if(parseip(v, vals[n]) == -1)
|
||||||
|
goto parseerror;
|
||||||
break;
|
break;
|
||||||
case Tproto:
|
case Tproto:
|
||||||
case Tdata:
|
case Tdata:
|
||||||
|
@ -296,34 +266,11 @@ parsemux(char *p)
|
||||||
}
|
}
|
||||||
v += f->len;
|
v += f->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->eoff = f->off + f->len;
|
|
||||||
f->e = f->val + f->n*f->len;
|
f->e = f->val + f->n*f->len;
|
||||||
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 == Tifc)
|
|
||||||
f->ctype = nomask ? Cifc : Cmifc;
|
|
||||||
else
|
|
||||||
f->ctype = nomask ? Clong : Cmlong;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return f;
|
return f;
|
||||||
|
|
||||||
parseerror:
|
parseerror:
|
||||||
if(f->mask)
|
ipmuxfree(f);
|
||||||
free(f->mask);
|
|
||||||
if(f->val)
|
|
||||||
free(f->val);
|
|
||||||
free(f);
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,8 +293,7 @@ ipmuxcmp(Ipmux *a, Ipmux *b)
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
/* compare offsets, call earlier ones more specific */
|
/* compare offsets, call earlier ones more specific */
|
||||||
n = (a->off+((int)a->skiphdr)*(int)(uintptr)ipoff->data) -
|
n = a->off - b->off;
|
||||||
(b->off+((int)b->skiphdr)*(int)(uintptr)ipoff->data);
|
|
||||||
if(n != 0)
|
if(n != 0)
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
|
@ -417,6 +363,10 @@ ipmuxcopy(Ipmux *f)
|
||||||
*nf = *f;
|
*nf = *f;
|
||||||
nf->no = ipmuxcopy(f->no);
|
nf->no = ipmuxcopy(f->no);
|
||||||
nf->yes = ipmuxcopy(f->yes);
|
nf->yes = ipmuxcopy(f->yes);
|
||||||
|
if(f->mask != nil){
|
||||||
|
nf->mask = smalloc(f->len);
|
||||||
|
memmove(nf->mask, f->mask, f->len);
|
||||||
|
}
|
||||||
nf->val = smalloc(f->n*f->len);
|
nf->val = smalloc(f->n*f->len);
|
||||||
nf->e = nf->val + f->len*f->n;
|
nf->e = nf->val + f->len*f->n;
|
||||||
memmove(nf->val, f->val, f->n*f->len);
|
memmove(nf->val, f->val, f->n*f->len);
|
||||||
|
@ -426,8 +376,10 @@ ipmuxcopy(Ipmux *f)
|
||||||
static void
|
static void
|
||||||
ipmuxfree(Ipmux *f)
|
ipmuxfree(Ipmux *f)
|
||||||
{
|
{
|
||||||
if(f->val != nil)
|
if(f == nil)
|
||||||
free(f->val);
|
return;
|
||||||
|
free(f->val);
|
||||||
|
free(f->mask);
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,10 +388,8 @@ ipmuxtreefree(Ipmux *f)
|
||||||
{
|
{
|
||||||
if(f == nil)
|
if(f == nil)
|
||||||
return;
|
return;
|
||||||
if(f->no != nil)
|
ipmuxfree(f->no);
|
||||||
ipmuxfree(f->no);
|
ipmuxfree(f->yes);
|
||||||
if(f->yes != nil)
|
|
||||||
ipmuxfree(f->yes);
|
|
||||||
ipmuxfree(f);
|
ipmuxfree(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +464,8 @@ ipmuxremove(Ipmux **l, Ipmux *f)
|
||||||
return ipmuxremove(&ft->no, f);
|
return ipmuxremove(&ft->no, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipmuxremove(&ft->no, f->no);
|
||||||
|
|
||||||
/* we found a match */
|
/* we found a match */
|
||||||
if(--(ft->ref) == 0){
|
if(--(ft->ref) == 0){
|
||||||
/*
|
/*
|
||||||
|
@ -534,9 +486,56 @@ ipmuxremove(Ipmux **l, Ipmux *f)
|
||||||
return ipmuxremove(&ft->yes, f->yes);
|
return ipmuxremove(&ft->yes, f->yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* convert to ipv4 filter
|
||||||
|
*/
|
||||||
|
static Ipmux*
|
||||||
|
ipmuxconv4(Ipmux *f)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
if(f == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
switch(f->type){
|
||||||
|
case Tproto:
|
||||||
|
f->off = offsetof(Ip4hdr, proto);
|
||||||
|
break;
|
||||||
|
case Tdst:
|
||||||
|
f->off = offsetof(Ip4hdr, dst[0]);
|
||||||
|
if(0){
|
||||||
|
case Tsrc:
|
||||||
|
f->off = offsetof(Ip4hdr, src[0]);
|
||||||
|
}
|
||||||
|
if(f->len != IPaddrlen)
|
||||||
|
break;
|
||||||
|
n = 0;
|
||||||
|
for(i = 0; i < f->n; i++){
|
||||||
|
if(isv4(f->val + i*IPaddrlen)){
|
||||||
|
memmove(f->val + n*IPv4addrlen, f->val + i*IPaddrlen + IPv4off, IPv4addrlen);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(n == 0){
|
||||||
|
ipmuxtreefree(f);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
f->n = n;
|
||||||
|
f->len = IPv4addrlen;
|
||||||
|
if(f->mask != nil)
|
||||||
|
memmove(f->mask, f->mask+IPv4off, IPv4addrlen);
|
||||||
|
}
|
||||||
|
f->e = f->val + f->n*f->len;
|
||||||
|
|
||||||
|
f->yes = ipmuxconv4(f->yes);
|
||||||
|
f->no = ipmuxconv4(f->no);
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* connection request is a semi separated list of filters
|
* connection request is a semi separated list of filters
|
||||||
* e.g. proto=17;data[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0
|
* e.g. ver=4;proto=17;data[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0
|
||||||
*
|
*
|
||||||
* there's no protection against overlapping specs.
|
* there's no protection against overlapping specs.
|
||||||
*/
|
*/
|
||||||
|
@ -572,6 +571,18 @@ ipmuxconnect(Conv *c, char **argv, int argc)
|
||||||
return Ebadarg;
|
return Ebadarg;
|
||||||
mux->conv = c;
|
mux->conv = c;
|
||||||
|
|
||||||
|
if(chain->type != Tver) {
|
||||||
|
char ver6[] = "ver=6";
|
||||||
|
mux = parsemux(ver6);
|
||||||
|
mux->yes = chain;
|
||||||
|
mux->no = ipmuxcopy(chain);
|
||||||
|
chain = mux;
|
||||||
|
}
|
||||||
|
if(*chain->val == IP_VER4)
|
||||||
|
chain->yes = ipmuxconv4(chain->yes);
|
||||||
|
else
|
||||||
|
chain->no = ipmuxconv4(chain->no);
|
||||||
|
|
||||||
/* save a copy of the chain so we can later remove it */
|
/* save a copy of the chain so we can later remove it */
|
||||||
mux = ipmuxcopy(chain);
|
mux = ipmuxcopy(chain);
|
||||||
r = (Ipmuxrock*)(c->ptcl);
|
r = (Ipmuxrock*)(c->ptcl);
|
||||||
|
@ -647,7 +658,7 @@ ipmuxkick(void *x)
|
||||||
|
|
||||||
bp = qget(c->wq);
|
bp = qget(c->wq);
|
||||||
if(bp != nil) {
|
if(bp != nil) {
|
||||||
Myip4hdr *ih4 = (Myip4hdr*)(bp->rp);
|
Ip4hdr *ih4 = (Ip4hdr*)(bp->rp);
|
||||||
|
|
||||||
if((ih4->vihl & 0xF0) != IP_VER6)
|
if((ih4->vihl & 0xF0) != IP_VER6)
|
||||||
ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);
|
ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);
|
||||||
|
@ -656,82 +667,74 @@ ipmuxkick(void *x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
maskmemcmp(uchar *m, uchar *v, uchar *c, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(m == nil)
|
||||||
|
return memcmp(v, c, n) != 0;
|
||||||
|
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
if((v[i] & m[i]) != c[i])
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ipmuxiput(Proto *p, Ipifc *ifc, Block *bp)
|
ipmuxiput(Proto *p, Ipifc *ifc, Block *bp)
|
||||||
{
|
{
|
||||||
int len, hl;
|
|
||||||
Fs *f = p->f;
|
Fs *f = p->f;
|
||||||
uchar *m, *h, *v, *e, *ve, *hp;
|
|
||||||
Conv *c;
|
Conv *c;
|
||||||
|
Iplifc *lifc;
|
||||||
Ipmux *mux;
|
Ipmux *mux;
|
||||||
Myip4hdr *ip;
|
uchar *v;
|
||||||
|
Ip4hdr *ip4;
|
||||||
Ip6hdr *ip6;
|
Ip6hdr *ip6;
|
||||||
|
int off, hl;
|
||||||
|
|
||||||
ip = (Myip4hdr*)bp->rp;
|
ip4 = (Ip4hdr*)bp->rp;
|
||||||
hl = (ip->vihl&0x0F)<<2;
|
if((ip4->vihl & 0xF0) == IP_VER4) {
|
||||||
|
hl = (ip4->vihl&0x0F)<<2;
|
||||||
|
ip6 = nil;
|
||||||
|
} else {
|
||||||
|
hl = IP6HDR;
|
||||||
|
ip6 = (Ip6hdr*)ip4;
|
||||||
|
}
|
||||||
|
|
||||||
if(p->priv == nil)
|
if(p->priv == nil)
|
||||||
goto nomatch;
|
goto nomatch;
|
||||||
|
|
||||||
h = bp->rp;
|
|
||||||
len = BLEN(bp);
|
|
||||||
|
|
||||||
/* run the v4 filter */
|
|
||||||
rlock(f);
|
|
||||||
c = nil;
|
c = nil;
|
||||||
|
lifc = nil;
|
||||||
|
|
||||||
|
/* run the filter */
|
||||||
|
rlock(f);
|
||||||
mux = f->ipmux->priv;
|
mux = f->ipmux->priv;
|
||||||
while(mux != nil){
|
while(mux != nil){
|
||||||
if(mux->eoff > len){
|
switch(mux->type){
|
||||||
mux = mux->no;
|
case Tifc:
|
||||||
continue;
|
if(mux->len != IPaddrlen)
|
||||||
}
|
goto no;
|
||||||
hp = h + mux->off + ((int)mux->skiphdr)*hl;
|
for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next)
|
||||||
switch(mux->ctype){
|
for(v = mux->val; v < mux->e; v += IPaddrlen)
|
||||||
case Cbyte:
|
if(maskmemcmp(mux->mask, lifc->local, v, IPaddrlen) == 0)
|
||||||
if(*mux->val == *hp)
|
goto yes;
|
||||||
goto yes;
|
goto no;
|
||||||
break;
|
case Tdata:
|
||||||
case Cmbyte:
|
off = hl;
|
||||||
if((*hp & *mux->mask) == *mux->val)
|
|
||||||
goto yes;
|
|
||||||
break;
|
|
||||||
case Cshort:
|
|
||||||
if(*((ushort*)mux->val) == *(ushort*)hp)
|
|
||||||
goto yes;
|
|
||||||
break;
|
|
||||||
case Cmshort:
|
|
||||||
if((*(ushort*)hp & (*((ushort*)mux->mask))) == *((ushort*)mux->val))
|
|
||||||
goto yes;
|
|
||||||
break;
|
|
||||||
case Clong:
|
|
||||||
if(*((ulong*)mux->val) == *(ulong*)hp)
|
|
||||||
goto yes;
|
|
||||||
break;
|
|
||||||
case Cmlong:
|
|
||||||
if((*(ulong*)hp & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
|
|
||||||
goto yes;
|
|
||||||
break;
|
|
||||||
case Cifc:
|
|
||||||
if(*((ulong*)mux->val) == *(ulong*)(ifc->lifc->local + IPv4off))
|
|
||||||
goto yes;
|
|
||||||
break;
|
|
||||||
case Cmifc:
|
|
||||||
if((*(ulong*)(ifc->lifc->local + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
|
|
||||||
goto yes;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
v = mux->val;
|
off = 0;
|
||||||
for(e = mux->e; v < e; v = ve){
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
off += mux->off;
|
||||||
|
if(off < 0 || off + mux->len > BLEN(bp))
|
||||||
|
goto no;
|
||||||
|
for(v = mux->val; v < mux->e; v += mux->len)
|
||||||
|
if(maskmemcmp(mux->mask, bp->rp + off, v, mux->len) == 0)
|
||||||
|
goto yes;
|
||||||
|
no:
|
||||||
mux = mux->no;
|
mux = mux->no;
|
||||||
continue;
|
continue;
|
||||||
yes:
|
yes:
|
||||||
|
@ -744,25 +747,24 @@ yes:
|
||||||
if(c != nil){
|
if(c != nil){
|
||||||
/* tack on interface address */
|
/* tack on interface address */
|
||||||
bp = padblock(bp, IPaddrlen);
|
bp = padblock(bp, IPaddrlen);
|
||||||
ipmove(bp->rp, ifc->lifc->local);
|
if(lifc == nil)
|
||||||
|
lifc = ifc->lifc;
|
||||||
|
ipmove(bp->rp, lifc != nil ? lifc->local : IPnoaddr);
|
||||||
qpass(c->rq, concatblock(bp));
|
qpass(c->rq, concatblock(bp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nomatch:
|
nomatch:
|
||||||
/* doesn't match any filter, hand it to the specific protocol handler */
|
/* doesn't match any filter, hand it to the specific protocol handler */
|
||||||
ip = (Myip4hdr*)bp->rp;
|
if(ip6 != nil)
|
||||||
if((ip->vihl & 0xF0) == IP_VER4) {
|
|
||||||
p = f->t2p[ip->proto];
|
|
||||||
} else {
|
|
||||||
ip6 = (Ip6hdr*)bp->rp;
|
|
||||||
p = f->t2p[ip6->proto];
|
p = f->t2p[ip6->proto];
|
||||||
}
|
|
||||||
if(p != nil && p->rcv != nil)
|
|
||||||
(*p->rcv)(p, ifc, bp);
|
|
||||||
else
|
else
|
||||||
freeblist(bp);
|
p = f->t2p[ip4->proto];
|
||||||
return;
|
if(p != nil && p->rcv != nil){
|
||||||
|
(*p->rcv)(p, ifc, bp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
freeblist(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -778,11 +780,14 @@ ipmuxsprint(Ipmux *mux, int level, char *buf, int len)
|
||||||
n += snprint(buf+n, len-n, "\n");
|
n += snprint(buf+n, len-n, "\n");
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
n += snprint(buf+n, len-n, "h[%d:%d]&",
|
n += snprint(buf+n, len-n, "%s[%d:%d]",
|
||||||
mux->off+((int)mux->skiphdr)*((int)(uintptr)ipoff->data),
|
mux->type == Tdata ? "data": "iph",
|
||||||
mux->off+(((int)mux->skiphdr)*((int)(uintptr)ipoff->data))+mux->len-1);
|
mux->off, mux->off+mux->len-1);
|
||||||
for(i = 0; i < mux->len; i++)
|
if(mux->mask != nil){
|
||||||
n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
|
n += snprint(buf+n, len-n, "&");
|
||||||
|
for(i = 0; i < mux->len; i++)
|
||||||
|
n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
|
||||||
|
}
|
||||||
n += snprint(buf+n, len-n, "=");
|
n += snprint(buf+n, len-n, "=");
|
||||||
v = mux->val;
|
v = mux->val;
|
||||||
for(j = 0; j < mux->n; j++){
|
for(j = 0; j < mux->n; j++){
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue