#include #include #include #include #include #include /* #include */ #include #include #include #include #include #include #include #include dev_type_open(pfopen); dev_type_close(pfclose); dev_type_ioctl(pfioctl); const struct cdevsw pf_cdevsw = { pfopen, pfclose, noread, nowrite, pfioctl, nostop, notty, nopoll, nommap, nokqfilter, D_TTY }; static int pfil_hooked = 0; MOD_DEV("pf", "pf", NULL, -1, &pf_cdevsw, -1); extern int pf_test(int, struct ifnet *, struct mbuf **); static int pf_hook(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) { struct ip *h; int rval; /* * Unlike OpenBSD, we keep those in network byte order. * It's easier to make a temporary swap instead of changing * all the pf code. */ h = mtod(*mp, struct ip *); NTOHS(h->ip_len); NTOHS(h->ip_off); rval = pf_test(dir, ifp, mp); if (*mp != NULL) { h = mtod(*mp, struct ip *); HTONS(h->ip_len); HTONS(h->ip_off); } return (rval); } int pfmodule_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) { DISPATCH(lkmtp, cmd, ver, pfmodule_lkmload, pfmodule_lkmunload, lkm_nofunc); } int pfmodule_lkmload(struct lkm_table *lkmtp, int cmd) { struct pfil_head *ph; if (pfil_hooked) { printf("Error: pflkm already loaded\n"); return (EEXIST); } if (lkmexists(lkmtp)) return (EEXIST); ph = pfil_head_get(PFIL_TYPE_AF, AF_INET); if (ph == NULL) { printf("Error: couldn't find AF_INET pfil head.\n" "Make sure you compiled your kernel with PFIL_HOOKS.\n"); return (EINVAL); } pfil_add_hook(pf_hook, NULL, PFIL_ALL, ph); pfil_hooked = 1; /* XXX look for AF_INET6 head and install hook there, too */ pfattach(1); pflogattach(1); pfsyncattach(1); return (0); } int pfmodule_lkmunload(struct lkm_table *lkmtp, int cmd) { struct pfil_head *ph; if (pfil_hooked) { ph = pfil_head_get(PFIL_TYPE_AF, AF_INET); if (ph == NULL) panic("Couldn't get pfil inet head"); else pfil_remove_hook(pf_hook, NULL, PFIL_ALL, ph); /* XXX look for AF_INET6 head and remove hook ifdef INET6 */ pfil_hooked = 0; } pfsyncdetach(1); pflogdetach(1); pfdetach(1); return (0); }