c中linux内核3.10中从内核到用户空间的netlink多播错误

c中linux内核3.10中从内核到用户空间的netlink多播错误,c,linux,linux-kernel,C,Linux,Linux Kernel,我参考了Yd Ahhrk的以下资料来源 模块insmod正确,lsmod | less可以看到它在那里,但在尝试运行用户空间应用程序时,我发现错误: seotsockopt

我参考了Yd Ahhrk的以下资料来源

模块insmod正确,lsmod | less可以看到它在那里,但在尝试运行用户空间应用程序时,我发现错误:

seotsockopt<0

在用户空间应用程序中,它正在执行组错误:

if (setsockopt(sock, 270, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)) < 0) {
    printf("seotsockopt < 0\n");
    return -1;
}

/*
if(setsockopt(sock,270,NETLINK_添加_成员,&group,sizeof(group))<0){
printf(“setsockopt<0\n”);
返回-1;
}
*/
不会遇到运行时错误,但自MYGRP 1以来没有意义 不再使用,但如果我取消标记addr.nl_groups=MYMGRP 然后绑定将出错,未标记的setsockopt然后是setsockopt
将错误。。。。。我不知道如何处理这个案子

我有一个类似的问题,我想我可能是在使用相同或类似的示例。如果不看你所有的代码,我可以告诉你的信息不会太多。不过,我可以将我为多播工作所做的几件事传递给大家

  • 在内核和用户空间代码中将您的组定义为1
  • 完全删除setsockopt()
  • 如果看不到代码的其余部分,我无法提供更多的说明

    祝你好运

    这是我使用的代码。这应该会对你有所帮助。但是,出于安全原因,我的内核模块没有退出函数

    内核代码

    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义MY_组1
    结构sock*socket;
    结构sk_buff*套接字_buff;
    字符*日志;
    无效nl_数据_就绪(结构sock*sk,整数len)
    {
    nlmsg_free(套接字_buff);
    }
    静态无效发送给用户(字符*消息)
    {
    结构nlmsghdr*nlsk_mh;
    char*msg=消息;
    国际关系;
    socket\u buff=nlmsg\u new(256,GFP\u内核);
    nlsk_mh=nlmsg_put(socket_buff,0,0,nlmsg_DONE,strlen(msg),0);
    NETLINK\u CB(socket\u buff).pid=0;//内核pid
    NETLINK_CB(socket_buff).dst_group=MY_group;
    strcpy(nlmsg_数据(nlsk_mh),msg);
    res=nlmsg_多播(socket,socket_buff,0,MY_组,GFP_内核);
    如果(res<0)
    {
    printk(“未发送多播:res<0\n”);
    返回0;
    }
    其他的
    {
    printk(“发送的多播\n”);
    }
    }
    无效网络链接测试(字符*buf)
    {
    socket=netlink\u kernel\u create(&init\u net,netlink\u USERSOCK,MY\u GROUP,nl\u data\u ready,NULL,THIS\u模块);
    如果(!套接字){
    printk(“创建套接字时出错。\n”);
    返回-10;
    }
    其他的
    {
    printk(“\n\n已成功创建套接字\n\n”);
    }
    printk(“发送给用户的消息是:%s”,buf);
    发送给用户(buf);
    netlink_内核_释放(套接字);
    返回0;
    }
    
    用户空间代码

    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义最大负载1024/*最大负载大小*/
    #定义MY_组1
    内部主(空)
    {
    国际袜子协会;
    结构sockaddr\u nl user\u sockaddr;
    结构nlmsghdr*nl_msghdr;
    结构msghdr msghdr;
    结构iovec iov;
    char*kernel_msg;
    sock\u fd=套接字(PF\u NETLINK、sock\u RAW、NETLINK\u USERSOCK);
    
    如果(sock_fd,感谢您的友好回复,我刚才有更多信息,我遇到的问题是setsockopt添加组,如果我删除setsockopt,我不知道如何NETLINK_添加成员身份,addr.nl_groups=MYMGRP;将导致绑定错误。我没有足够的声誉来评论您的问题,但我将在这里发表评论。我在这里发表了评论。)这是我在这里使用的一篇非常好的文章/教程:它全面地解释了单播和多播。我定义了addr.nl_groups=1,这在多播中应该是这样的。谢谢你,你帮了很多忙。谢谢你的问题,我按照你的例子创建了我自己的网络链接。但是,在我的例子中,我有2个模,每个模都必须打开自己的网络链接ink套接字到用户空间。我的问题是,无论第二个加载哪个模块,它都会在netlink_kernel_create上失败。我可能缺少一些东西,您知道是否可以使用netlink_USERSOCK系列创建多个套接字吗?谢谢!
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/netlink.h>
    #include <net/netlink.h>
    #include <net/net_namespace.h>
    
    /* Protocol family, consistent in both kernel prog and user prog. */
    #define MYPROTO NETLINK_USERSOCK
    /* Multicast group, consistent in both kernel prog and user prog. */
    #define MYGRP 1
    
    static struct sock *nl_sk = NULL;
    
    static void send_to_user(void)
    {
        struct sk_buff *skb;
        struct nlmsghdr *nlh;
        char *msg = "Hello from kernel";
        int msg_size = strlen(msg) + 1;
        int res;
    
        pr_info("Creating skb.\n");
        skb = nlmsg_new(NLMSG_ALIGN(msg_size + 1), GFP_KERNEL);
        if (!skb) {
            pr_err("Allocation failure.\n");
            return;
        }
    
        nlh = nlmsg_put(skb, 0, 1, NLMSG_DONE, msg_size + 1, 0);
        strcpy(nlmsg_data(nlh), msg);
    
        pr_info("Sending skb.\n");
        res = nlmsg_multicast(nl_sk, skb, 0, MYGRP, GFP_KERNEL);
        if (res < 0)
            pr_info("nlmsg_multicast() error: %d\n", res);
        else
            pr_info("Success.\n");
    }
    
    static int __init marskernel_init(void)
    {
        pr_info("Inserting marskernel module.\n");
    
        nl_sk = netlink_kernel_create(&init_net, MYPROTO, NULL);
        if (!nl_sk) {
            pr_err("Error creating socket.\n");
            return -10;
        }
    
        send_to_user();
    
        netlink_kernel_release(nl_sk);
        return 0;
    }
    
    static void __exit marskernel_exit(void)
    {
        pr_info("Exiting marskernel module.\n");
    }
    
    module_init(marskernel_init);
    module_exit(marskernel_exit);
    
    MODULE_LICENSE("GPL");
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <linux/netlink.h>
    #include <unistd.h>
    
    /* Protocol family, consistent in both kernel prog and user prog. */
    #define MYPROTO NETLINK_USERSOCK
    /* Multicast group, consistent in both kernel prog and user prog. */
    #define MYMGRP 1
    
    int open_netlink(void)
    {
        int sock;
        struct sockaddr_nl addr;
        int group = MYMGRP;
    
        sock = socket(AF_NETLINK, SOCK_RAW, MYPROTO);
        if (sock < 0) {
            printf("sock < 0.\n");
            return sock;
        }
    
        memset((void *) &addr, 0, sizeof(addr));
        addr.nl_family = AF_NETLINK;
        addr.nl_pid = getpid();
        /* This doesn't work for some reason. See the setsockopt() below. */
        /* addr.nl_groups = MYMGRP; */
    
        if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
            printf("bind < 0.\n");
            return -1;
        }
    
        /*
         * 270 is SOL_NETLINK. See
         * http://lxr.free-electrons.com/source/include/linux/socket.h?v=4.1#L314
         * and
         * https://stackoverflow.com/questions/17732044/
         */
        /*
        if (setsockopt(sock, 270, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)) < 0) {
            printf("setsockopt < 0\n");
            return -1;
        }
        */
    
        return sock;
    }
    void read_event(int sock)
    {
        struct sockaddr_nl nladdr;
        struct msghdr msg;
        struct iovec iov;
        char buffer[65536];
        int ret;
    
        iov.iov_base = (void *) buffer;
        iov.iov_len = sizeof(buffer);
        msg.msg_name = (void *) &(nladdr);
        msg.msg_namelen = sizeof(nladdr);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
    
        printf("Ok, listening.\n");
        ret = recvmsg(sock, &msg, 0);
        if (ret < 0)
            printf("ret < 0.\n");
        else
            printf("Received message payload: %s\n", NLMSG_DATA((struct nlmsghdr *) &buffer));
    }
    
    int main(int argc, char *argv[])
    {
        int nls;
    
        nls = open_netlink();
        if (nls < 0)
            return nls;
    
        while (1)
            read_event(nls);
    
        return 0;
    }
    
    /* addr.nl_groups = MYMGRP; */
    
    /*
        if (setsockopt(sock, 270, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)) < 0) {
            printf("setsockopt < 0\n");
            return -1;
        }
    */
    
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/netlink.h>
    #include <net/netlink.h>
    #include <net/sock.h>
    #include <net/net_namespace.h>
    #include <linux/skbuff.h>
    
    #define MY_GROUP    1
    
    struct sock* socket;
    struct sk_buff* socket_buff;
    char *log;
    
    void nl_data_ready(struct sock *sk, int len)
    {
      nlmsg_free(socket_buff);
    }
    static void send_to_user(char *message)
    {
        struct nlmsghdr *nlsk_mh;                                                                         
        char* msg = message;
        int res;                                                                                            
    
        socket_buff = nlmsg_new(256, GFP_KERNEL);                                                                                                                                                                                                                                                 
        nlsk_mh = nlmsg_put(socket_buff, 0, 0, NLMSG_DONE, strlen(msg), 0);                       
        NETLINK_CB(socket_buff).pid = 0;    // kernel pid                                                   
        NETLINK_CB(socket_buff).dst_group = MY_GROUP;                                                     
        strcpy(nlmsg_data(nlsk_mh), msg);                                                                
    
        res = nlmsg_multicast(socket, socket_buff, 0, MY_GROUP, GFP_KERNEL);
    
        if(res < 0)
        {
            printk("Multicast not sent: res < 0\n");
            return 0;
        }
        else
        {
            printk("Multicast Sent\n");
        }
    
    }
    void netlink_test(char *buf)
    {
        socket = netlink_kernel_create(&init_net, NETLINK_USERSOCK, MY_GROUP, nl_data_ready, NULL, THIS_MODULE);
        if (!socket) {
            printk("Error creating socket.\n");
            return -10;
        }
        else
        {
            printk("\n\nSOCKET WAS CREATED SUCCESSFULLY\n\n");
        }
    
        printk("The message to be sent to the user is: %s", buf);
        send_to_user(buf);
    
        netlink_kernel_release(socket);
    
        return 0;
    
    
    }
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <linux/netlink.h>
    #include <unistd.h>
    #include <errno.h>
    #include <unistd.h>
    #define MAX_PAYLOAD 1024 /* maximum payload size*/
    #define MY_GROUP    1
    
    int main(void)
    {
        int sock_fd;
        struct sockaddr_nl user_sockaddr;
        struct nlmsghdr *nl_msghdr;
        struct msghdr msghdr;
        struct iovec iov;
    
        char* kernel_msg;
    
        sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
        if(sock_fd<0)
        {
            printf("Error creating socket because: %s\n", strerror(errno));
            return -1;
        }
    
    
        memset(&user_sockaddr, 0, sizeof(user_sockaddr));
        user_sockaddr.nl_family = AF_NETLINK;
        user_sockaddr.nl_pid = getpid();
        user_sockaddr.nl_groups = MY_GROUP;
    
        bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));
        while (1) {
            nl_msghdr = (struct nlmsghdr*) malloc(NLMSG_SPACE(1024));
            memset(nl_msghdr, 0, NLMSG_SPACE(1024));
    
            iov.iov_base = (void*) nl_msghdr;
            iov.iov_len = NLMSG_SPACE(1024);
    
            msghdr.msg_name = (void*) &user_sockaddr;
            msghdr.msg_namelen = sizeof(user_sockaddr);
            msghdr.msg_iov = &iov;
            msghdr.msg_iovlen = 1;
    
            printf("Waiting to receive message\n");
            recvmsg(sock_fd, &msghdr, 0);
    
            kernel_msg = (char*)NLMSG_DATA(nl_msghdr);
            printf("Kernel message: %s\n", kernel_msg); // print to android logs
        }
    
        close(sock_fd);
    }