使用 3.X linux 内核的 C 语言中的 Netlink 套接字 [英] Netlink Sockets in C using the 3.X linux kernel

查看:16
本文介绍了使用 3.X linux 内核的 C 语言中的 Netlink 套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我一直在努力使 Netlink 套接字适用于 3.2 linux 内核,但我似乎不知道该怎么做.我已经四处寻找 Netlink 套接字基础知识的示例,但似乎我找到的所有示例都是针对 2.6 内核的.

Hi, I've been working on trying to get Netlink sockets to work for the 3.2 linux kernel, but I cannot seem to figure out how to do it. I have looked around for examples of the basics of Netlink sockets, but it seems all of the examples I find are for the 2.6 kernel.

我想要找到的是如何使用 Netlink 套接字将信息从内核模块发送到用户模式应用程序,反之亦然?

What I'm trying to find is how to send information from a kernel module to user mode application and vice-versa using Netlink sockets?

任何帮助将不胜感激.谢谢!

Any help would be greatly appreciated. Thanks!

推荐答案

我也一直致力于在内核中使用 Netlink 套接字,但遇到了和你一样的问题.

I've been working on using Netlink sockets in the Kernel as well and ran into the same problems as you.

使用 之前的堆栈溢出答案 作为基础,我设法让它发挥作用.在 3.5 和 3.6 之间,netlink_kernel_create"函数发生了变化……我在 3.8 上.以下代码应该适合您.

Using this previous stack overflow answer as a base, I managed to make it work. Between 3.5 and 3.6 the "netlink_kernel_create" function changed...and I'm on 3.8. The following code should work for you.

netlinkKernel.c

netlinkKernel.c

#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>


#define NETLINK_USER 31

struct sock *nl_sk = NULL;

static void hello_nl_recv_msg(struct sk_buff *skb) {

struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
char *msg="Hello from kernel";
int res;

printk(KERN_INFO "Entering: %s
", __FUNCTION__);

msg_size=strlen(msg);

nlh=(struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s
",(char*)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; /*pid of sending process */

skb_out = nlmsg_new(msg_size,0);

if(!skb_out)
{

    printk(KERN_ERR "Failed to allocate new skb
");
    return;

} 
nlh=nlmsg_put(skb_out,0,0,NLMSG_DONE,msg_size,0);  
NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */
strncpy(nlmsg_data(nlh),msg,msg_size);

res=nlmsg_unicast(nl_sk,skb_out,pid);

if(res<0)
    printk(KERN_INFO "Error while sending bak to user
");
}

static int __init hello_init(void) {

printk("Entering: %s
",__FUNCTION__);
/* This is for 3.6 kernels and above.
struct netlink_kernel_cfg cfg = {
    .input = hello_nl_recv_msg,
};

nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);*/
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg,NULL,THIS_MODULE);
if(!nl_sk)
{

    printk(KERN_ALERT "Error creating socket.
");
    return -10;

}

return 0;
}

static void __exit hello_exit(void) {

printk(KERN_INFO "exiting hello module
");
netlink_kernel_release(nl_sk);
}

module_init(hello_init); module_exit(hello_exit);

MODULE_LICENSE("GPL");

netlinkUser.c

netlinkUser.c

#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define NETLINK_USER 31

#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;

int main()
{
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0)
return -1;

memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */

bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));

memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */

nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;

strcpy(NLMSG_DATA(nlh), "Hello");

iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

printf("Sending message to kernel
");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel
");

/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf("Received message payload: %s
", (char *)NLMSG_DATA(nlh));
close(sock_fd);
}

Makefile(用于 netlinkKernel.c)

Makefile (for netlinkKernel.c)

KBUILD_CFLAGS += -w

obj-m += netlinkKernel.o

all:
    make -w -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
// Make sure the indentations before these "make" lines is a tab
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

只需运行make",然后运行gcc netlinkUser.c -o netlinkUser",然后运行sudo insmod netlinkKernel.ko",然后当您运行./netlinkUser"时,您应该看到一条消息已发送到内核模块并且用户空间应用程序收到了回复.看到内核模块打印的调试信息后,在终端中运行dmesg".

Just run "make", then "gcc netlinkUser.c -o netlinkUser", then "sudo insmod netlinkKernel.ko", then when you run "./netlinkUser" you should see that a message was sent to the kernel module and a reply was received by the user space application. Running "dmesg" in the terminal after you will see the debug messages printed by the kernel module.

如果您还有其他问题,请告诉我,我现在对自己的项目深有体会.

If you have anymore questions, let me know, I'm knee deep in this right now with my own project.

这篇关于使用 3.X linux 内核的 C 语言中的 Netlink 套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆