netfilter例子改写5

lwfw.c
--------------------Begin-----------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

#include "lwfw.h"

/* Local function prototypes */
static int set_if_rule (char *name);
static int set_ip_rule (unsigned int ip);
static int set_port_rule (unsigned short port);
static int check_ip_packet (struct sk_buff *skb);
static int check_tcp_packet (struct sk_buff *skb);
static int copy_stats (struct lwfw_stats *statbuff);

/* Some function prototypes to be used by lwfw_fops below. */
static long lwfw_ioctl (struct file *file, unsigned int cmd, unsigned long arg);
static int lwfw_open (struct inode *inode, struct file *file);
static int lwfw_release (struct inode *inode, struct file *file);

/* Various flags used by the module */
/* This flag makes sure that only one instance of the lwfw device
 * can be in use at any one time. */
static int lwfw_ctrl_in_use = 0;

/* This flag marks whether LWFW should actually attempt rule checking.
 * If this is zero then LWFW automatically allows all packets. */
static int active = 0;

/* Specifies options for the LWFW module */
static unsigned int lwfw_options = (LWFW_IF_DENY_ACTIVE
                                    | LWFW_IP_DENY_ACTIVE
                                    | LWFW_PORT_DENY_ACTIVE);

static int major = 0;           /* Control device major number */

/* This struct will describe our hook procedure. */
struct nf_hook_ops nfkiller;

/* Module statistics structure */
static struct lwfw_stats lwfw_statistics = { 0, 0, 0, 0, 0 };

/* Actual rule 'definitions'. */
/* TODO:  One day LWFW might actually support many simultaneous rules.
 * Just as soon as I figure out the list_head mechanism... */
static char *deny_if = NULL;    /* Interface to deny */
static unsigned int deny_ip = 0x00000000;       /* IP address to deny */
static unsigned short deny_port = 0x0000;       /* TCP port to deny */

/*
 * This is the interface device's file_operations structure
 */
struct file_operations lwfw_fops = {
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        lwfw_ioctl,
        NULL,
        lwfw_open,
        NULL,
        lwfw_release,
        NULL,                   /* Will be NULL'ed from here... */
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL
};

MODULE_LICENSE("GPL");
MODULE_AUTHOR ("bioforge");
MODULE_DESCRIPTION ("Light-Weight Firewall for Linux 3.2.0");

/*
 * This is the function that will be called by the hook
 */
unsigned int
lwfw_hookfn (unsigned int hooknum,
             struct sk_buff *skb,
             const struct net_device *in,
             const struct net_device *out, int (*okfn) (struct sk_buff *))
{
        unsigned int ret = NF_ACCEPT;

        /* If LWFW is not currently active, immediately return ACCEPT */
        if (!active)
                return NF_ACCEPT;

        lwfw_statistics.total_seen++;

        /* Check the interface rule first */
        if (deny_if && DENY_IF_ACTIVE) {
                if (strcmp (in->name, deny_if) == 0) {  /* Deny this interface */
                        lwfw_statistics.if_dropped++;
                        lwfw_statistics.total_dropped++;
                        return NF_DROP;
                }
        }

        /* Check the IP address rule */
        if (deny_ip && DENY_IP_ACTIVE) {
                ret = check_ip_packet (skb);
                if (ret != NF_ACCEPT)
                        return ret;
        }

        /* Finally, check the TCP port rule */
        if (deny_port && DENY_PORT_ACTIVE) {
                ret = check_tcp_packet (skb);
                if (ret != NF_ACCEPT)
                        return ret;
        }

        return NF_ACCEPT;       /* We are happy to keep the packet */
}

/* Function to copy the LWFW statistics to a userspace buffer */
static int
copy_stats (struct lwfw_stats *statbuff)
{
        NULL_CHECK (statbuff);

        copy_to_user (statbuff, &lwfw_statistics, sizeof (struct lwfw_stats));

        return 0;
}

/* Function that compares a received TCP packet's destination port
 * with the port specified in the Port Deny Rule. If a processing
 * error occurs, NF_ACCEPT will be returned so that the packet is
 * not lost. */
static int
check_tcp_packet (struct sk_buff *skb)
{
        /* Seperately defined pointers to header structures are used
         * to access the TCP fields because it seems that the so-called
         * transport header from skb is the same as its network header TCP packets.
         * If you don't believe me then print the addresses of skb->nh.iph
         * and skb->h.th.
         * It would have been nicer if the network header only was IP and
         * the transport header was TCP but what can you do? */
        struct tcphdr *thead;
        struct iphdr *iphdr = NULL;
        /* We don't want any NULL pointers in the chain to the TCP header. */
        if (!skb)
                return NF_ACCEPT;
        iphdr = ip_hdr(skb);
        if (!(iphdr))
                return NF_ACCEPT;

        /* Be sure this is a TCP packet first */
        if (iphdr->protocol != IPPROTO_TCP) {
                return NF_ACCEPT;
        }

        thead = tcp_hdr(skb);//(struct tcphdr *) (skb->data + (skb->nh.iph->ihl * 4));

        /* Now check the destination port */
        if ((thead->dest) == deny_port) {
                /* Update statistics */
                lwfw_statistics.total_dropped++;
                lwfw_statistics.tcp_dropped++;

                return NF_DROP;
        }

        return NF_ACCEPT;
}

/* Function that compares a received IPv4 packet's source address
 * with the address specified in the IP Deny Rule. If a processing
 * error occurs, NF_ACCEPT will be returned so that the packet is
 * not lost. */
static int
check_ip_packet (struct sk_buff *skb)
{
        struct iphdr *iphdr = NULL;
        /* We don't want any NULL pointers in the chain to the IP header. */
        if (!skb)
                return NF_ACCEPT;
        iphdr = ip_hdr(skb);
        if (!(iphdr))
                return NF_ACCEPT;

        if (iphdr->saddr == deny_ip) {  /* Matches the address. Barf. */
                lwfw_statistics.ip_dropped++;   /* Update the statistics */
                lwfw_statistics.total_dropped++;

                return NF_DROP;
        }

        return NF_ACCEPT;
}

static int
set_if_rule (char *name)
{
        int ret = 0;
        char *if_dup;           /* Duplicate interface */

        /* Make sure the name is non-null */
        NULL_CHECK (name);

        /* Free any previously saved interface name */
        if (deny_if) {
                kfree (deny_if);
                deny_if = NULL;
        }

        if ((if_dup = kmalloc (strlen ((char *) name) + 1, GFP_KERNEL))
            == NULL) {
                ret = -ENOMEM;
        }
        else {
                memset (if_dup, 0x00, strlen ((char *) name) + 1);
                memcpy (if_dup, (char *) name, strlen ((char *) name));
        }

        deny_if = if_dup;
        lwfw_statistics.if_dropped = 0; /* Reset drop count for IF rule */
        printk ("LWFW: Set to deny from interface: %s\n", deny_if);

        return ret;
}

static int
set_ip_rule (unsigned int ip)
{
        deny_ip = ip;
        lwfw_statistics.ip_dropped = 0; /* Reset drop count for IP rule */

        printk ("LWFW: Set to deny from IP address: %d.%d.%d.%d\n",
                ip & 0x000000FF, (ip & 0x0000FF00) >> 8,
                (ip & 0x00FF0000) >> 16, (ip & 0xFF000000) >> 24);

        return 0;
}

static int
set_port_rule (unsigned short port)
{
        deny_port = port;
        lwfw_statistics.tcp_dropped = 0;        /* Reset drop count for TCP rule */

        printk ("LWFW: Set to deny for TCP port: %d\n",
                ((port & 0xFF00) >> 8 | (port & 0x00FF) << 8));

        return 0;
}

/*********************************************/
/*
 * File operations functions for control device
 */
static long
lwfw_ioctl (struct file *file,
            unsigned int cmd, unsigned long arg)
{
        long ret = 0;

        switch (cmd) {
        case LWFW_GET_VERS:
                return LWFW_VERS;
        case LWFW_ACTIVATE:{
                        active = 1;
                        printk ("LWFW: Activated.\n");
                        if (!deny_if && !deny_ip && !deny_port) {
                                printk ("LWFW: No deny options set.\n");
                        }
                        break;
                }
        case LWFW_DEACTIVATE:{
                        active ^= active;
                        printk ("LWFW: Deactivated.\n");
                        break;
                }
        case LWFW_GET_STATS:{
                        ret = copy_stats ((struct lwfw_stats *) arg);
                        break;
                }
        case LWFW_DENY_IF:{
                        ret = set_if_rule ((char *) arg);
                        break;
                }
        case LWFW_DENY_IP:{
                        ret = set_ip_rule ((unsigned int) arg);
                        break;
                }
        case LWFW_DENY_PORT:{
                        ret = set_port_rule ((unsigned short) arg);
                        break;
                }
        default:
                ret = -EBADRQC;
        };

        return ret;
}

/* Called whenever open() is called on the device file */
static int
lwfw_open (struct inode *inode, struct file *file)
{
        if (lwfw_ctrl_in_use) {
                return -EBUSY;
        }
        else {
                try_module_get(THIS_MODULE);
        //      MOD_INC_USE_COUNT;
                lwfw_ctrl_in_use++;
                return 0;
        }
        return 0;
}

/* Called whenever close() is called on the device file */
static int
lwfw_release (struct inode *inode, struct file *file)
{
        lwfw_ctrl_in_use ^= lwfw_ctrl_in_use;
        //MOD_DEC_USE_COUNT;
        module_put(THIS_MODULE);
        return 0;
}

/*********************************************/
/*
 * Module initialisation and cleanup follow...
 */
int
init_module ()
{
        /* Register the control device, /dev/lwfw */
        //SET_MODULE_OWNER (&lwfw_fops);

        /* Attempt to register the LWFW control device */
        if ((major = register_chrdev (LWFW_MAJOR, LWFW_NAME, &lwfw_fops)) < 0) {
                printk ("LWFW: Failed registering control device!\n");
                printk ("LWFW: Module installation aborted.\n");
                return major;
        }

        /* Make sure the usage marker for the control device is cleared */
        lwfw_ctrl_in_use ^= lwfw_ctrl_in_use;

        printk ("\nLWFW: Control device successfully registered.\n");

        /* Now register the network hooks */
        nfkiller.hook = lwfw_hookfn;
        nfkiller.hooknum = NF_INET_PRE_ROUTING; /* First stage hook */
        nfkiller.pf = PF_INET;  /* IPV4 protocol hook */
        nfkiller.priority = NF_IP_PRI_FIRST;    /* Hook to come first */

        /* And register... */
        nf_register_hook (&nfkiller);

        printk ("LWFW: Network hooks successfully installed.\n");

        printk ("LWFW: Module installation successful.\n");
        return 0;
}

void
cleanup_module ()
{
        //int ret;

        /* Remove IPV4 hook */
        nf_unregister_hook (&nfkiller);

        /* Now unregister control device */
        unregister_chrdev (LWFW_MAJOR, LWFW_NAME);

        /* If anything was allocated for the deny rules, free it here */
        if (deny_if)
                kfree (deny_if);

        printk ("LWFW: Removal of module successful.\n");
}
-------------------------End----------------------------------
lwfw.h
-------------------------Begin-------------------------------

#ifndef __LWFW_INCLUDE__
#define __LWFW_INCLUDE__

/* NOTE: The LWFW_MAJOR symbol is only made available for kernel code.
 * Userspace code has no business knowing about it. */
#define LWFW_NAME        "lwfw"

/* Version of LWFW */
#define LWFW_VERS        0x0001 /* 0.1 */

/* Definition of the LWFW_TALKATIVE symbol controls whether LWFW will
 * print anything with printk(). This is included for debugging purposes.
 */
#define LWFW_TALKATIVE

/* These are the IOCTL codes used for the control device */
#define LWFW_CTRL_SET   0xFEED0000      /* The 0xFEED... prefix is arbitrary */
#define LWFW_GET_VERS   0xFEED0001      /* Get the version of LWFM */
#define LWFW_ACTIVATE   0xFEED0002
#define LWFW_DEACTIVATE 0xFEED0003
#define LWFW_GET_STATS  0xFEED0004
#define LWFW_DENY_IF    0xFEED0005
#define LWFW_DENY_IP    0xFEED0006
#define LWFW_DENY_PORT  0xFEED0007

/* Control flags/Options */
#define LWFW_IF_DENY_ACTIVE   0x00000001
#define LWFW_IP_DENY_ACTIVE   0x00000002
#define LWFW_PORT_DENY_ACTIVE 0x00000004

/* Statistics structure for LWFW.
 * Note that whenever a rule's condition is changed the related
 * xxx_dropped field is reset.
 */
struct lwfw_stats
{
        unsigned int if_dropped;        /* Packets dropped by interface rule */
        unsigned int ip_dropped;        /* Packets dropped by IP addr. rule */
        unsigned int tcp_dropped;       /* Packets dropped by TCP port rule */
        unsigned long total_dropped;    /* Total packets dropped */
        unsigned long total_seen;       /* Total packets seen by filter */
};

/*
 * From here on is used solely for the actual kernel module
 */
#ifdef __KERNEL__
#define LWFW_MAJOR       241    /* This exists in the experimental range */

/* This macro is used to prevent dereferencing of NULL pointers. If
 * a pointer argument is NULL, this will return -EINVAL */
#define NULL_CHECK(ptr)    \
   if ((ptr) == NULL)  return -EINVAL

/* Macros for accessing options */
#define DENY_IF_ACTIVE    (lwfw_options & LWFW_IF_DENY_ACTIVE)
#define DENY_IP_ACTIVE    (lwfw_options & LWFW_IP_DENY_ACTIVE)
#define DENY_PORT_ACTIVE  (lwfw_options & LWFW_PORT_DENY_ACTIVE)

#endif /* __KERNEL__ */
#endif
--------------------------End---------------------------------------------------

lwfw_test.c
-------------------------------Begin-----------------------
#include
#include
#include
#include
#include
#include
#include
#include "lwfw.h"
main ()
{
        int fd;
        int i;
        struct lwfw_stats data;
        int retval;
        char msg[128];

        char *deny_ip = "192.168.1.105";

        char *ifcfg = "eth0";

        unsigned char *port = "\x00\x16";

        fd = open (LWFW_NAME, O_RDONLY);
        if (fd == -1) {
                perror ("open fail!");
                exit (-1);
        }

        if (ioctl (fd, LWFW_ACTIVATE, 0) == -1) {
                perror ("ioctl LWFW_ACTIVATE fail!\n");
                exit (-1);
        }

        if (ioctl (fd, LWFW_DENY_IP, inet_addr (deny_ip)) == -1) {
                printf ("ioctl LWFW_DENY_IP fail\n");
                exit (-1);
        }

        if (ioctl (fd, LWFW_DENY_PORT, *(unsigned short *) port) == -1) {
                printf ("ioctl LWFW_DENY_PORT fail!\n");
                exit (-1);
        }

        if (ioctl (fd, LWFW_GET_STATS, *(unsigned long *) &data) == -1) {
                printf ("iotcl LWFW_GET_STATS fail!\n");
                exit (-1);
        }
/*
if(ioctl(fd, LWFW_DENY_IF, (unsigned*)ifcfg) == -1)
{
printf("ioctl LWFW_DENY_IF fail!\n");
exit(-1);
}
*/
        printf ("ip dropped : %d\n", data.ip_dropped);
        printf ("if dropped : %d\n", data.if_dropped);
        printf ("tcp dropped : %d\n", data.tcp_dropped);
        printf ("total dropped : %ld\n", data.total_dropped);
        printf ("total seen: %ld\n", data.total_seen);
        close (fd);
}
---------------------------End------------------------------------

Makefile

--------------------------Begin-----------------------------------------
MODULE_NAME:=lwfw
ifneq ($(KERNELRELEASE),)
mymodule-objs:=${MODULE_NAME}.o
obj-m:=${MODULE_NAME}.o
else
PWD:=$(shell pwd)
KVER:=$(shell uname -r)

KDIR:=/usr/src/linux-source-3.2.0/linux-source-3.2.0
all:lwfw_test.o
        gcc -o lwfw_test lwfw_test.o
        $(MAKE) -C $(KDIR) M=$(PWD)
clean:
        @rm -rf .*.com *.o *.mod.c *.ko .tmp_versions modules.order Module.symvers lwfw_test
install:
        @insmod ${MODULE_NAME}.ko
uninstall:
        @rmmod ${MODULE_NAME}.ko
lwfw_test.o:lwfw_test.c
        gcc -c lwfw_test.c
endif
----------------------End-----------------------------------------------------

你可能感兴趣的:(netfilter例子改写5)