linux内核用户通信netfilter

netfilter提供了nf_register_sockopt()nf_unregister_sockopt()来动态登记或取消sockopt命令字;打开一个网络socket后可以使用set/getsockopt(2)可实现用户空间与内核的通信,本质和ioctl差不多,区别在于set/getsockopt不用新建设备,直接利用系统已有的socket类型就可以进行,可用setsockopt函数向内核写数据,用getsockopt向内核读数据。


module.c:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/netfilter_ipv4.h>
#include <linux/init.h>
#include <asm/uaccess.h> 

#define SOCKET_OPS_BASE          128
#define SOCKET_OPS_SET       (SOCKET_OPS_BASE)
#define SOCKET_OPS_GET      (SOCKET_OPS_BASE)
#define SOCKET_OPS_MAX       (SOCKET_OPS_BASE + 1)

#define KMSG          "a message from kernel"
#define KMSG_LEN      sizeof("a message from kernel")

MODULE_LICENSE("GPL");

static int recv_msg(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
    
int ret = 0;
    
printk(KERN_INFO "sockopt: recv_msg()\n"); 
   
    
if (cmd == SOCKET_OPS_SET)
    
{
        
char umsg[64];
        
int len = sizeof(char)*64;
        
memset(umsg, 0, len);
        
ret = copy_from_user(umsg, user, len);
        
printk("recv_msg: umsg = %s. ret = %d\n", umsg, ret);        
    
}
    
return 0;
} 

static int send_msg(struct sock *sk, int cmd, void __user *user, int *len)
{
    
int ret = 0;
    
printk(KERN_INFO "sockopt: send_msg()\n"); 
    
if (cmd == SOCKET_OPS_GET)
    
{
        
ret = copy_to_user(user, KMSG, KMSG_LEN);
        
printk("send_msg: umsg = %s. ret = %d. success\n", KMSG, ret);    
    
}
    
return 0;
} 

static struct nf_sockopt_ops test_sockops =
{
    
.pf = PF_INET,
    
.set_optmin = SOCKET_OPS_SET,
    
.set_optmax = SOCKET_OPS_MAX,
    
.set = recv_msg,
    
.get_optmin = SOCKET_OPS_GET,
    
.get_optmax = SOCKET_OPS_MAX,
    
.get = send_msg,
    
.owner = THIS_MODULE,
}; 

static int __init init_sockopt(void)
{
    
printk(KERN_INFO "sockopt: init_sockopt()\n"); 
    
return nf_register_sockopt(&test_sockops);
} 

static void __exit fini_sockopt(void)
{
    
printk(KERN_INFO "sockopt: fini_sockopt()\n"); 
    
nf_unregister_sockopt(&test_sockops);
} 

module_init(init_sockopt); 
module_exit(fini_sockopt); 

user.c:

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <string.h>
#include <errno.h> 

#define SOCKET_OPS_BASE      128
#define SOCKET_OPS_SET       (SOCKET_OPS_BASE)
#define SOCKET_OPS_GET      (SOCKET_OPS_BASE)
#define SOCKET_OPS_MAX       (SOCKET_OPS_BASE + 1) 

#define UMSG      "a message from userspace"
#define UMSG_LEN  sizeof("a message from userspace") 

char kmsg[64]; 

int main(void)
{
    
int sockfd;
    
int len;
    
int ret; 

    
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    
if(sockfd < 0)
    
{
        
printf("can not create a socket\n");
        
return -1;
    
} 

    
/*call fun
用户名/邮箱

密码ction recv_msg()*/
    
ret = setsockopt(sockfd, IPPROTO_IP, SOCKET_OPS_SET, UMSG, UMSG_LEN);
    
printf("setsockopt: ret = %d. msg = %s\n", ret, UMSG);
    
len = sizeof(char)*64; 

    
/*call function send_msg()*/
    
ret = getsockopt(sockfd, IPPROTO_IP, SOCKET_OPS_GET, kmsg, &len);
    
printf("getsockopt: ret = %d. msg = %s\n", ret, kmsg);
    
if (ret != 0)
    
{
        
printf("getsockopt error: errno = %d, errstr = %s\n", errno, strerror(errno));
    
} 

    
close(sockfd);
    
return 0;
}

Makefile:

TARGET = test
OBJS = test.o
MDIR = drivers/misc

EXTRA_CFLAGS = -DEXPORT_SYMTAB
CURRENT = $(shell uname -r)
KDIR = /lib/modules/$(CURRENT)/build
PWD = $(shell pwd)
DEST = /lib/modules/$(CURRENT)/kernel/$(MDIR)
obj-m      := $(TARGET).o
$(TARGET)-objs :=module.o
default:
    make -C  
$(KDIR) SUBDIRS=$(PWD) modules 
    gcc -o user user.c
$(TARGET).o: $(OBJS)
    
$(LD) $(LD_RFLAG) -r -o $@ $(OBJS)
ifneq (,
$(findstring 2.4.,$(CURRENT)))
install:
    su -c "cp -v 
$(TARGET).o $(DEST) && /sbin/depmod -a"
else
install:
    su -c "cp -v 
$(TARGET).ko $(DEST) && /sbin/depmod -a"
endif

clean:
    -rm -rf *.o *.ko .
$(TARGET).ko.cmd .*.flags *.mod.c modules.order  Module.symvers .tmp_versions
    -rm -rf protocol/*.o protocol/.*.o.cmd
    -rm -rf user

-include 
$(KDIR)/Rules.make


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值