driver.c
#include <linux/init.h>
#include <linux/kernel.h>
// /usr/src/linux-headers-4.13.0-17
#include "linux/module.h"
#include <linux/types.h>
#include <linux/fs.h> //file_operations
#include <linux/cdev.h> //cdev
#include <linux/slab.h> //kmalloc kfree
#include <linux/uaccess.h> //copy_to_user copy_from_user
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter.h>
#include <linux/sched.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h> //init_net变量在其中
/******************************* Define Constant Macro ******************/
#ifndef DEVICE_NAME
#define DEVICE_NAME "KeyboardTouches"
#endif
#ifndef MINOR_COUNT
#define MINOR_COUNT 1
#endif
#ifndef RECV_SIZE
#define RECV_SIZE 512
#endif
/*******************************回调函数声明*********************************/
ssize_t fileRead(struct file *pFile,char __user *buffer,size_t count,loff_t *offset);
ssize_t fileWrite(struct file *pFile,const char __user *buffer,size_t count,loff_t *offset);
struct file_operations fop= {
.owner=THIS_MODULE,
.llseek=NULL,
.open=NULL,
//.ioctl=NULL,
.release=NULL,
.read=fileRead,
.write=fileWrite,
.release=NULL
};
/**************************变量定义*************************/
char *recvBuffer=NULL;
int result=0;
static struct nf_hook_ops nfhop;
struct cdev device;
dev_t deviceNo;
struct net_device *nd;
/************************** Function: filterSocket******************************/
unsigned int filterSocket(void *priv,struct sk_buff *skb,const struct nf_hook_state *state){
printk(KERN_INFO "%s execute in driver:%s .\n",__FUNCTION__,DEVICE_NAME);
//无条件丢包,阻断一切与外界的联系
return NF_DROP;
}
int fileOpen(struct inode *node,struct file *pFile){
return 0;
}
/******************************* Function: fileRead**************************/
ssize_t fileRead(struct file *pFile,char __user *buffer,size_t count,loff_t *offset){
result=copy_to_user(buffer,recvBuffer,count);
if (result<0) {
//只有加了换行符之后才能立刻在控制台输出
printk(KERN_INFO "Read buffer from device failed with error code:%d\n",result);
return result;
}
return 0;
}
/****************************** Function: fileWrite ***********************/
ssize_t fileWrite(struct file *pFile,const char __user *buffer,size_t count,loff_t *offset){
if (count>=RECV_SIZE) {
printk_deferred(KERN_ALERT "Write to device data quantity (%d Bytes) is more than recieve buffer size (%d Bytes).\n",count,RECV_SIZE);
return 0;
}
printk(KERN_ALERT "Write length:%ld\n",count);
result=copy_from_user(recvBuffer,buffer,count);
if (result<0) {
printk(KERN_INFO "Write to device failed with error code:%d\n",result);
return result;
}
return 0;
}
/******************************** Function: fileClose ***********************/
int fileClose(struct inode *node,struct file *pFile){
return 0;
}
/****************************** Function: startDriver **********************/
static int __init startDriver(void){
//初始化nfhop
recvBuffer=kmalloc(RECV_SIZE,GFP_KERNEL);
//申请设备号
result=alloc_chrdev_region(&deviceNo,0,MINOR_COUNT,DEVICE_NAME);
if (result<0) {
printk(KERN_INFO "Allocate character device number failed!\n");
return result;
}
printk(KERN_INFO "Allocate device suceeded! Master: %d, Slave:%d\n",MAJOR(deviceNo),MINOR(deviceNo));
//对设备与文件操作进行绑定
cdev_init(&device,&fop);
//对设备与dev_t进行绑定
result=cdev_add(&device,deviceNo,MINOR_COUNT);
if (result<0) {
//注册字符设备
unregister_chrdev_region(deviceNo,MINOR_COUNT);
printk(KERN_INFO "Add device to system failed! Unregister Master: %d, Slave:%d\n",MAJOR(deviceNo),MINOR(deviceNo));
return result;
}
//注册网络钩子进行丢包操作
//获得当前网卡设备,这里的名称可以通过ifconfig获得,此处为enp8s0
nd=dev_get_by_name(current->nsproxy->net_ns, "enp8s0"); //current->nsproxy->net_ns用&init_net代替也是可以的
printk(KERN_INFO "Get net device %s in kernel.\n",nd->name);
//配置钩子
nfhop.hook=filterSocket;
nfhop.pf=PF_INET;
nfhop.hooknum=NF_INET_PRE_ROUTING,
nfhop.priority=NF_IP_PRI_FIRST;
nfhop.dev=nd;
//注册网络钩子
nf_register_net_hook(current->nsproxy->net_ns,&nfhop);
printk(KERN_INFO "the driver %s is started.\n",__FUNCTION__);
return 0;
}
/******************************* Function: exitDriver **************************/
static void __exit exitDriver(void) {
nf_unregister_net_hook(current->nsproxy->net_ns,&nfhop);
//释放堆上的内存防止泄漏
if (recvBuffer!=NULL) {
kfree(recvBuffer);
}
//删除设备
cdev_del(&device);
//回收设备号
unregister_chrdev_region(deviceNo,MINOR_COUNT);
printk(KERN_INFO "the driver %s exited.\n",__FUNCTION__);
}
/**************************** 例行公事 *******************************************/
module_init(startDriver);
module_exit(exitDriver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MOU MOU MOU");
Makefile
ifneq ($(KERNELRELEASE),)
obj-m +=driver.o
else
KDIR = /lib/modules/$(shell uname -r)/build
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif
clean:
rm -rf *.o *.ko *.mod
rm -rf .temp.versions
rm *.order
rm -f .driver.o.cmd
rm -f .driver.ko.cmd
rm -f .driver.mod.o.cmd
rm -f driver.mod.c