/* fwbase.c */ #include "fwdd.h" #include "fwcomm.h" extern struct timeval xtime; /* This structure defines a firewall network entry */ #define VALID 1 #define DENY 2 #define ALLOW 4 #define LOG 8 #define DYNAM 16 #define PERMIT 32 #define MAX_IN 256 #define FW_MAJOR 88 #define TIME_TO_LIVE 120 #define PFX_LENGTH 32 int time_to_live = TIME_TO_LIVE; int pfx_length = PFX_LENGTH; static struct fwlrtype logrec[MAX_LOG]; int nextin = 0; int nextout = 0; int cd_registered = 0; static struct fwnetype { unsigned int prefix; int pfxlen; unsigned int action; int timeout; }; /* 130.127.206.14 */ static struct fwnetype indata[MAX_IN] = { 0x00000000, 0, PERMIT | DENY | LOG, -1, /* Matches all */ 0x00000000, 32, DENY, -1, /* 0.0.0.0 */ 0xc0a80000, 16, ALLOW, -1, 0x0a000000, 8, ALLOW, -1, 0x80c10000, 16, ALLOW -1, /* ORST */ 0x827f0000, 16, ALLOW, -1, /* Clemson */ 0x7f000000, 8, ALLOW, -1 /* Local host */ }; #if 0 0x827f3800, 24, ALLOW, -1, /* 130.127.56 */ 0x827f3C00, 24, ALLOW, -1, /* 130.127.60 */ 0x827f0e0e, 32, ALLOW, -1, /* Mickey */ /* 0x00000000, 0, DENY | LOG, -1, Matches all */ /* 0x3f000000, 8, DENY | LOG, -1, UUnet -- */ #endif static int incount = sizeof(indata) / sizeof(struct fwnetype); static int outcount; int fw_ioctl(); int fw_open(); int fw_release(); static struct file_operations fw_fops = { #if LINUX_VERSION_CODE >= 0x20312 NULL, /* module owner */ #endif NULL, /* lseek */ NULL, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* select */ fw_ioctl, /* ioctl */ NULL, /* mmap */ fw_open, /* open */ NULL, /* flush */ fw_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL /* revalidate */ }; static int fw_log( struct iphdr *ip, unsigned int addr, int action) { struct fwlrtype *fwlr; fwlr = logrec + nextin; fwlr->time = xtime.tv_sec; fwlr->addr = addr; fwlr->action = action; nextin += 1; if (nextin == nextout) nextout += 1; if (nextin == MAX_LOG) nextin = 0; if (nextout == MAX_LOG) nextout = 0; return(0); } static unsigned int fw_mkpfx( unsigned int addr, int pfxlen) { unsigned int pfx; pfx = addr; if (pfxlen < 32) { pfx >>= (32 - pfxlen); pfx <<= (32 - pfxlen); } return(pfx); } /**/ /* Add a dynamic entry to the access list */ static struct fwnetype *fw_add( struct fwnetype *tab, int *count, unsigned int addr) { int i; struct fwnetype *fwe; fwe = tab; for (i = 0; i < *count; i++) { /* See if we can just use an old timed-out entry */ if ((fwe->timeout != -1) && (xtime.tv_sec >= fwe->timeout)) { fwe->pfxlen = pfx_length; fwe->prefix = fw_mkpfx(addr, pfx_length); fwe->timeout = xtime.tv_sec + time_to_live; fwe->action = ALLOW | DYNAM; /* printk("Firewall added prefix %08x \n", fwe->prefix); */ return; } fwe += 1; } if (*count < (MAX_IN - 1)) { fwe = tab + *count; fwe->pfxlen = pfx_length; fwe->prefix = fw_mkpfx(addr, pfx_length); /* printk("Firewall added prefix %08x \n", fwe->prefix); */ fwe->timeout = xtime.tv_sec + time_to_live; fwe->action = ALLOW | DYNAM; *count += 1; } else { printk("Firewall failed to add prefix.. outta table space \n"); } } static struct fwnetype *fw_match( struct fwnetype *tab, int count, unsigned int addr) { int i; int matchlen; struct fwnetype *bestmatch; struct fwnetype *fwe; int shift; matchlen = -1; fwe = tab; for (i = 0; i < count; i++) { /* printk("%08x %d \n", fwe->prefix, fwe->timeout); */ if ((fwe->timeout == -1) || (xtime.tv_sec < fwe->timeout)) { shift = 32 - fwe->pfxlen; /* printk("Comparing %08x with %08x \n", (fwe->prefix >> shift), (addr >> shift)); */ if ((shift == 32) || ((fwe->prefix >> shift) == (addr >> shift))) { if (fwe->pfxlen > matchlen) { /* printk("Matched %d \n", i); */ matchlen = fwe->pfxlen; bestmatch = fwe; } } } fwe += 1; } if (matchlen >= 0) { printk("Matched %d \n", bestmatch - indata); return(bestmatch); } else { printk("Yeow: Failed to match %x \n", addr); return((struct fwnetype *)0); } } /**/ /* Processing of input packets */ static int fw_input( unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int addr; struct iphdr *iph; struct fwnetype *ne; iph = (*pskb)->nh.iph; addr = ntohl(iph->saddr); /* printk("Calling match with count %d \n", incount); */ ne = fw_match(indata, incount, addr); if (ne == 0) { return(NF_DROP); } else { if (ne->action & LOG) fw_log(iph, addr, FW_INPUT); if (ne->action & DYNAM) ne->timeout = xtime.tv_sec + time_to_live; if (ne->action & ALLOW) return(NF_ACCEPT); else { printk("Firewall blocked input %8x %d.%d.%d.%d \n", addr, (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); return(NF_DROP); } } } static int fw_output( unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int addr; struct iphdr *iph; struct fwnetype *ne; /* Recover destination address from packet header */ iph = (*pskb)->nh.iph; addr = ntohl(iph->daddr); /* printk("Output address was %x \n", addr); */ /* See if this address is presently in our tables */ ne = fw_match(indata, incount, addr); if (ne == 0) { fw_log(iph, addr, FW_OUTPUT); return(NF_DROP); } else if (ne->action & DYNAM) { ne->timeout = xtime.tv_sec + time_to_live; } else if (ne->action & PERMIT) { fw_add(indata, &incount, addr); fw_log(iph, addr, FW_ADDPFX); } else if (ne->action & ALLOW) { } else { fw_log(iph, addr, FW_OUTPUT); return(NF_DROP); } return(NF_ACCEPT); } static int fw_forward( unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { return(NF_ACCEPT); } static struct nf_hook_ops preroute_ops = { { NULL, NULL }, fw_input, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FILTER }; static struct nf_hook_ops postroute_ops = { { NULL, NULL }, fw_output, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FILTER }; static struct nf_hook_ops forward_ops = { { NULL, NULL }, fw_forward, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER }; int init_module(void) { int rc; int rc2; /* Register hooks */ rc = nf_register_hook(&preroute_ops); if (rc < 0) { printk("Register preroute failed with %d \n", rc); return(-1); } rc = nf_register_hook(&postroute_ops); if (rc < 0) { printk("Register postroute failed \n"); return(-1); } rc = nf_register_hook(&forward_ops); if (rc < 0) { printk("Register forward failed \n"); return(-1); } printk("Register firewall returned %d \n", rc); if (rc2 = register_chrdev(FW_MAJOR, "xfw1", &fw_fops)) printk( "FW: cannot register chr dev; received %d\n", rc2); else cd_registered = 1; return(0); } int cleanup_module(void) { nf_unregister_hook(&preroute_ops); nf_unregister_hook(&postroute_ops); nf_unregister_hook(&forward_ops); if (cd_registered) { unregister_chrdev(FW_MAJOR, "xfw1"); } }