linux与应用层通信方式 之nf_sock_opt

本文介绍了一个用于Linux内核的模块实现,该模块通过注册特定的Socket选项来允许用户空间应用程序设置和获取内核数据。这些Socket选项包括HELLO_LISA和HELLO_MONA,演示了如何在用户空间和内核空间之间传递字符串数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//内核部分代码。大家可以COPY ipt_sockopts
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include "hello_sock_opt.h"

#include <linux/kmod.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/smp.h>
#include <linux/cpumask.h>
#include <linux/audit.h>
#include <net/sock.h>

char hello[10][20];


static int hello_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
        int ret=0;

        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
        printk("%s: len is %d \n",__func__,len);
        switch (cmd) {
        case HELLO_LISA:
                if (copy_from_user(hello[0], user,20) != 0)
                        return -EFAULT;

                break;

        case HELLO_MONA:
                if (copy_from_user(hello[1], user,20) != 0)
                        return -EFAULT;

                break;

        default:
                printk("hello_set_ctl:  unknown request %i\n", cmd);
                ret = -EINVAL;
        }

        return ret;
}

static int hello_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
        int ret=0;

        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;

        switch (cmd) {
        case HELLO_LISA:
                if (copy_to_user(user,hello[0] , 20) != 0)
                {
                        break;
                }
                break;
        case HELLO_MONA:
                if (copy_to_user(user,hello[1] , 20) != 0)
                        break;
                else
                        break;

        default:
                printk("hello_get_ctl:  unknown request %i\n", cmd);
                ret = -EINVAL;
        }

        return ret;
}
static struct nf_sockopt_ops   arpt_sockopts = {
        .pf             = PF_INET,
        .set_optmin     = HELLO_BASE_CTL,
        .set_optmax     = HELLO_SO_SET_MAX+1,
        .set            = hello_set_ctl,
        .get_optmin     = HELLO_BASE_CTL,
        .get_optmax     = HELLO_SO_SET_MAX+1,
        .get            = hello_get_ctl,
        .owner          = THIS_MODULE,
};
static int simple_init(void)
{
                int ret;

                /* Register setsockopt */
        ret = nf_register_sockopt(&arpt_sockopts);
        if (ret < 0)
        {
                printk("nf_register_sockopt error! \n");
                return -1;
        }

    printk("hello !!\n");
    return 0;
}


static void simple_cleanup(void)
{
        nf_unregister_sockopt(&arpt_sockopts);
        printk("Hello byebye\n");
}


module_init(simple_init);
module_exit(simple_cleanup);


/*
上下通信的通用头文件。

*/


#define  HELLO_BASE_CTL  102400 //在系统中这个号不能有重复的。建议最好是取较大值。
#define  HELLO_LISA      HELLO_BASE_CTL+1
#define  HELLO_MONA      HELLO_BASE_CTL+2
#define  HELLO_SO_SET_MAX  (HELLO_BASE_CTL+5)


 #include <sys/socket.h>
       #include <netinet/in.h>
       #include <netinet/ip.h> /* superset of previous */
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "hello_sock_opt.h"


int common_set_sock_opt(int id,void* msg,int len)
{
        int sock;
        int ret;
        sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
        if(sock <=0){
                printf("socket error\n");
                return -1;
        }
        ret=setsockopt(sock,0,id,msg,len);

        close(sock);
        return ret;
}
int common_get_sock_opt(int id,void* msg,int* len)
{
        int sock;
        int ret;
        sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
        if(sock <=0){
                printf("socket error\n");
                return -1;
        }
        ret=getsockopt(sock,0,id,msg,len);
        close(sock);
        return ret;
}
int __set_lisa(char* s)
{
        return common_set_sock_opt(HELLO_LISA,s,strlen(s));

}

int __get_lisa(char* s,int *len)
{
        return common_get_sock_opt(HELLO_LISA,s,len);


}


void main(int argc,char* argv[])
{
        char ret[100]={0};
        int len=0;
        int t;
        if(argc ==2){
                printf("argv : %s :%s \n",argv[0],argv[1]);
                t = __set_lisa(argv[1]);  //把参数配置到内核。
                if(t<0)
                        perror("__set_lisa:");
                __get_lisa(ret,&len);  //从内核读出信息。
                if(t<0)
                        perror("__GET_lisa:");
                else
                {
                        printf("ret %s; len %d\n",ret,len);
                }
        }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值