用C网络链路套接字使用3.X linux内核 [英] Netlink Sockets in C using the 3.X linux kernel

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

问题描述

您好,我一直在努力试图让网络链路插座为 3.2 linux内核工作,但我似乎无法弄清楚如何做到这一点。我已经看了看四周为网络链路插座基础的例子,但似乎所有的,我觉得是在 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.

我试图找出是如何从一个内核模块使用网络链路插槽将信息发送到用户模式应用程序,反之亦然?

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?

任何帮助将大大AP preciated。谢谢!

Any help would be greatly appreciated. Thanks!

推荐答案

我一直在工作在内核中使用网络链路插槽以及跑进了同样的问题,你。

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

previous堆栈溢出回答为基地,我设法使它工作。 3.5〜3.6netlink_kernel_create功能改变了... ...和我在3.8。下面code应该为你工作。

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\n", __FUNCTION__);

msg_size=strlen(msg);

nlh=(struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n",(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\n");
    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\n");
}

static int __init hello_init(void) {

printk("Entering: %s\n",__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.\n");
    return -10;

}

return 0;
}

static void __exit hello_exit(void) {

printk(KERN_INFO "exiting hello module\n");
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\n");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel\n");

/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf("Received message payload: %s\n", (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,然后命令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.

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

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