⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 example.c

📁 linux的网络编程的源代码
💻 C
字号:
#define __KERNEL__
#define MODULE

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/string.h>

#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

#include <linux/proc_fs.h>

#include <linux/interrupt.h>
#include <linux/spinlock.h>

#define PROC_BUFFER 4096

static ssize_t nfdemo_proc_read(struct file* file, char* buf, size_t count,
				loff_t *ppos);
static int info_read_proc(char* buf, char** start, off_t offs, int len);
static int last_read_proc(char* buf, char** start, off_t offs, int len);

struct nf_hook_ops input_filter;
struct nf_hook_ops output_filter;
struct proc_dir_entry *proc_nfdemo = NULL;
struct proc_dir_entry *proc_info = NULL;
struct proc_dir_entry *proc_last = NULL;

static rwlock_t last_lock = RW_LOCK_UNLOCKED;

static struct file_operations nfdemo_fops =
{
        NULL,                   /* lseek   */
        nfdemo_proc_read,	        /* read    */
        NULL,                   /* write   */
        NULL,                   /* readdir */
        NULL,                   /* select  */
        NULL,                   /* ioctl   */
        NULL,                   /* mmap    */
        NULL,                   /* no special open code    */
        NULL,                   /* flush */
        NULL,                   /* no special release code */
        NULL                    /* can't fsync */
};

static struct inode_operations nfdemo_inode =
{
        &nfdemo_fops,
        NULL,                   /* create */
        NULL,                   /* lookup */
        NULL,                   /* link */
        NULL,                   /* unlink */
        NULL,                   /* symlink */
        NULL,                   /* mkdir */
        NULL,                   /* rmdir */
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
        NULL,                   /* get_block */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* truncate */
        NULL,			/* permission */
        NULL                    /* revalidate */
};

static int counter_input_dropped = 0;
static int counter_input_processed = 0;
static int counter_output_dropped = 0;
static int counter_output_processed = 0;
static char *last_packet_data = NULL;

/* input_handler is called when a packet hits specified hook point */
unsigned int input_handler(	unsigned int hooknum,
				struct sk_buff **skb,
				const struct net_device *in,
				const struct net_device *out)
{
	struct iphdr *ip;
	struct tcphdr *tcp;
	int packet_size;

	/* inc processed counter */
	counter_input_processed++;

	/* IP filtering */
	/* as you can see the function receives a pointer to the
	 * struct sk_buff pointer, so it's possible to replace the
	 * sk_buff with another one. This can be used to rebuild
	 * from scratch the packet (the example don't use this) */
	ip  = (*skb)->nh.iph;

	/* save the packet -- for /proc/nfdemo/last */
	write_lock_bh(&last_lock);
	if (last_packet_data != NULL)
		kfree(last_packet_data);

	packet_size = ntohs(ip->tot_len);

	last_packet_data = kmalloc(packet_size, GFP_KERNEL);
	if (last_packet_data)
		memcpy(last_packet_data, ip, packet_size);
	write_unlock_bh(&last_lock);

	/* drop IP packets with options */
	if (ip->ihl != 5)
		goto drop;

	/* TCP filtering */
	if (ip->protocol != 6)
		goto accepted;

	tcp = (struct tcphdr*)((__u32 *)ip+ip->ihl);

	/* TCP flags sanity check */

	/* drops Xmas || Ymax */
	if (tcp->res2 != 0)
		goto drop;

	/* drops SYN without ACK but with others flags set */
	if ((tcp->syn && !tcp->ack)
		&& (tcp->fin || tcp->rst || tcp->psh || tcp->urg))
		goto drop;

	/* drops SYN/ACK with RST and/or FIN set */
	if ((tcp->syn && tcp->ack) && (tcp->fin || tcp->rst))
		goto drop;

	/* drops TCP packets with no-sense flags (or without flags set) */
	if (!tcp->fin && !tcp->syn && !tcp->rst && !tcp->ack)
		goto drop;

accepted:
	return NF_ACCEPT;

drop:
	counter_input_dropped++;
	return NF_DROP;
}


/* output_handler is called when a packet hits specified hook point */
unsigned int output_handler(	unsigned int hooknum,
				struct sk_buff **skb,
				const struct net_device *in,
				const struct net_device *out)
{
	struct iphdr *ip;
	struct tcphdr *tcp;
	struct icmphdr *icmp;

	/* inc processed counter */
	counter_output_processed++;

	/* IP filtering */
	ip  = (*skb)->nh.iph;

	/* TCP filtering */
	if (ip->protocol != 6)
		goto icmp_init;

	tcp = (struct tcphdr*)((__u32 *)ip+ip->ihl);

icmp_init:
	/* ICMP filtering */
	if (ip->protocol != 1)
		goto accepted;

	icmp = (struct icmphdr*)((__u32 *)ip+ip->ihl);

	if (icmp->type == 0) /* icmp echo request */
		goto drop;

accepted:
	return NF_ACCEPT;

drop:
	counter_output_dropped++;
	return NF_DROP;
}

int init_module(void)
{
	int result;

	/* input hook */
	input_filter.list.next = NULL;
	input_filter.list.prev = NULL;
	input_filter.hook = input_handler;
	input_filter.flush = NULL; /* still unused */
	input_filter.pf = PF_INET; /* IPv4 */
	input_filter.hooknum = NF_IP_LOCAL_IN;

	/* output hook */
	output_filter.list.next = NULL;
	output_filter.list.prev = NULL;
	output_filter.hook = output_handler;
	output_filter.flush = NULL; /* still unused */
	output_filter.pf = PF_INET; /* IPv4 */
	output_filter.hooknum = NF_IP_LOCAL_OUT;

	/* proc fs */
	proc_nfdemo = proc_mkdir("nfdemo", &proc_root);
	if (!proc_nfdemo)
		goto proc_failed;

	proc_info = create_proc_entry("info", 00400, proc_nfdemo);
	if (!proc_info)
		goto proc_failed;

	proc_info->ops = &nfdemo_inode;
	proc_info->get_info = info_read_proc;

	proc_last = create_proc_entry("last", 00400, proc_nfdemo);
	if (!proc_last)
		goto proc_failed;

	proc_last->ops = &nfdemo_inode;
	proc_last->get_info = last_read_proc;

	/* hooks registration */
	result = nf_register_hook(&input_filter);
	if (result) goto hook_failed;

	result = nf_register_hook(&output_filter);
	if (result) goto hook_failed;

	/* OK */
	printk(KERN_INFO "demo netfilter module loaded\n");
	return 0;

proc_failed:
	printk(KERN_INFO "nfdemo: error registering proc entry\n");
	return 1; /* error registering proc entry */

hook_failed:
	printk(KERN_INFO "nfdemo: error registering hook (%d)", result);
	return result; /* error registering hooks */
}

void cleanup_module(void)
{
	/* unregister hooks */
	nf_unregister_hook(&input_filter);
	nf_unregister_hook(&output_filter);

	/* unregister proc fs entry */
	if (proc_last)
		remove_proc_entry("last", proc_nfdemo);
	if (proc_info)
		remove_proc_entry("info", proc_nfdemo);
	if (proc_nfdemo)
		remove_proc_entry("nfdemo", &proc_root);

	printk(KERN_INFO "demo netfilter module removed\n");
}

/* this function handles /proc/nfdemo/info reading */
static int info_read_proc(char* buf, char** start, off_t offs, int len)
{
	return sprintf(	buf,
			"netfilter demo info:\n"
			"INPUT:\n"
			"processed datagrams: %d\n"
			"dropped   datagrams: %d\n"
			"OUTPUT:\n"
			"processed datagrams: %d\n"
			"dropped   datagrams: %d\n",
			counter_input_processed,
			counter_input_dropped,
			counter_output_processed,
			counter_output_dropped);
}

/* this function handles /proc/nfdemo/last reading */
static int last_read_proc(char* buf, char** start, off_t offs, int len)
{
	struct iphdr *ip;
	int packet_size = 0;

	read_lock(&last_lock);
	if (last_packet_data)
	{
		ip = (struct iphdr*) last_packet_data;
		packet_size = ntohs(ip->tot_len);

		if (packet_size > PROC_BUFFER)
			packet_size = PROC_BUFFER;

		memcpy(buf, ip, packet_size);
	}
	read_unlock(&last_lock);

	return packet_size;
}

/* nfdemo_proc_read() is derived from linux/net/wanrouter/wanproc.c of
   linux 2.3.31. This function should be fixed since it can create some
   inconguence trying to read from /proc/nfdemo/last calling read(2) more
   than one time for packet but since this is just an example it's enought */

#define min(x,y) x<y ? x : y
static ssize_t nfdemo_proc_read(struct file* file, char* buf, size_t count,
                                loff_t *ppos)
{
	struct inode *inode = file->f_dentry->d_inode;
	struct proc_dir_entry* dent;
	char* page;
	int pos, offs, len;

	if (count <= 0)
		return 0;

	dent = inode->u.generic_ip;
	if ((dent == NULL) || (dent->get_info == NULL))
		return 0;

	page = kmalloc(PROC_BUFFER, GFP_KERNEL);
	if (page == NULL)
		return -ENOBUFS;

	pos = dent->get_info(page, dent->data, 0, 0);
	offs = file->f_pos;
	if (offs < pos)
	{
		len = min(pos - offs, count);
		if(copy_to_user(buf, (page + offs), len))
			return -EFAULT;
		file->f_pos += len;
	}
	else
		len = 0;
	kfree(page);
	return len;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -