#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "ip.h"
enum {
Qdir,
Qstats,
Qctl,
};
enum {
GEMProtoIP4,
GEMProtoIP6,
GEMProtoTCP,
GEMProtoUDP,
GEMProtoICMP,
}
static void GEMparse(char *, long);
static char *GEMstats(void);
static void GEMgetip(uchar *, uchar *, uint *, uint *);
static ulong GEMdb;
static ulong GEMsize;
static char *ruleset;
static Dirtab GEMtab[] = {
".", { Qdir, 0, QTDIR }, 0, 0555,
"stats", { Qstats, 0 }, 0, 0600,
"ctl", { Qctl, 0 }, 0, 0600,
};
static Chan *
GEMattach(char *spec)
{
return devattach('ƒ', spec);
}
static Walkqid *
GEMwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, GEMtab, nelem(GEMtab), devgen);
}
static int
GEMstat(Chan *c, uchar *dp, int n)
{
return devstat(c, dp, n, GEMtab, nelem(GEMtab), devgen);
}
static Chan *
GEMopen(Chan *c, int mode)
{
return devopen(c, mode, GEMtab, nelem(GEMtab), devgen);
}
static long
GEMread(Chan *c, void *a, long n, vlong off)
{
switch((ulong)c->qid.path) {
case Qdir:
return devdirread(c, a, n, GEMtab, nelem(GEMtab), devgen);
case Qctl:
return readstr(off, a, n, ruleset);
case Qstats:
return readstr(off, a, n, GEMstats());
default:
n = 0;
break;
}
return n;
}
static long
GEMwrite(Chan *c, void *a, long n, vlong off)
{
USED(off)
switch((ulong)c->qid.path) {
case Qctl:
GEMparse((char *)a, n);
break;
default:
error(Ebadusefd);
}
return n;
}
static char *
GEMstats(void)
{
char *stats;
}
static void
GEMgetip(uchar addr1[4], uchar addr2[4], uint *l_item, uint *r_item)
{
*l_item = nhgetl(addr1)&nhgetl(addr2);
*r_item = *l_item + (!nhgetl(addr2));
}
/* XXX proto is always TCP on IPv4 for right now */
static int
GEMsearch(const void *iphdr, const void *protohdr, struct GEMlist *h, int ipver,
int proto)
{
uint arg1, arg2, i, start, end, packet[4], curlevel;
ulong src, dst;
GEMlevel *l, *l2;
/*if (ipver == GEMProtoIP4) {*/
packet[0] = nhgetl((Ip4hdr *)iphdr->src);
packet[1] = nhgetl((Ip4hdr *)iphdr->dst);
packet[2] = nhgets((Tcp4hdr *)protohdr->tcpsport);
packet[3] = nhgets((Tcp4hdr *)protohdr->tcpdport);
/*} else {
packet[0] = nhgetl((Ip6hdr *)iphdr->src);
packet[1] = nhgetl((Ip6hdr *)iphdr->dst);
packet[2] = nhgetl((Tcp6hdr *)protohdr->tcpsport);
packet[3] = nhgetl((Tcp6hdr *)protohdr->tcpdport);
}*/
l = l2 = h;
for (curlevel = 0; curlevel <= GEMNumLevels; curlevel++,
l2 = l + l->nextlevel) {
start = 0;
end = l->levelsize - 1;
while (start != end) {
i = (start + end) >> 1;
arg1 = (l2)[i].lower_border;
if (i + 1 < h->size)
arg2 = (l2)[i + 1].lower_border
else
arg2 = h->levelmax[curlevel];
if (packet[h->levels[curlevel]] < arg1)
end = i - 1;
else if (packet[h->levels[curlevel]] < arg2)
start = end = i;
else
start = i+1;
}
l = &((l2->nextlevel)[start]);
}
return (l + l->nextlevel)[start].nextlevel;
}
Dev GEMdevtab = {
'ƒ',
"GEMfilter",
devreset,
devinit,
GEMattach,
GEMwalk,
GEMstat,
GEMopen,
devcreate,
GEMclose,
GEMread,
devbread,
GEMwrite,
devbwrite,
devremove,
devwstat,
};
|