#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, };