`
tcspecial
  • 浏览: 895642 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

netlink套接字

阅读更多

Linux下如何实现用户态与内核态的交互呢?一种是上文讲的/proc文件,还有一种是netlink套接字机制,netlink实现了用户空间与内核空间双向通信方法。

netlink用户态API与常见的socket编程一致,只是内核态要实现自定义protocol。

 

一.内核态模块

    该模块用于接收用户态信息,并发送一字符串响应。

#ifndef __KERNEL__
#define __KERNEL__
#endif  /* __KERNEL__ */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/uaccess.h>
#include <net/sock.h>
#include <net/netlink.h>  // netlink 
#include <linux/string.h>
#include <linux/ip.h>

#define NETLINK_TEST 31    // 自定义用户协议 

static struct sock *nlfd = NULL;  // 内核socket文件描述符
static char *payload = "Hello user,i'm from kernel!";

// 向用户层发送消息
static int sendNLMsg(int pid,void *msg,int len)
{
	struct sk_buff *skb;
	int size,count;
	struct nlmsghdr *nlmsgh = NULL;
	char *pos = NULL;
	int retval = 0;

	size = NLMSG_SPACE(len);               // 加消息头部长度
	skb = alloc_skb(size,GFP_KERNEL);	// 申请空间
	if(!skb)
	{
		retval = -1;
		return retval;
	}

	nlmsgh = nlmsg_put(skb,0,0,0,len,0);

	// 填充数据
	pos = NLMSG_DATA(nlmsgh);
	memset(pos,0,len);
	memcpy(pos,msg,len);

	NETLINK_CB(skb).dst_group = 0;  // 单播

	count = netlink_unicast(nlfd,skb,pid,MSG_DONTWAIT); 
	printk(KERN_ALERT "pid:%d send:%d\n",pid,count);

	return retval;
}


// 处理用户层传递的消息
static void handle_msg(struct sk_buff *_sk)
{
	struct sk_buff *skb;
	struct nlmsghdr *nlh = NULL;
	char str[100] = {};
	int pid;

 	printk("==>handle_msg\n");
 	
 	skb = skb_get(_sk);   // 引用当前_sk

 	if(skb->len >= NLMSG_SPACE(0))
 	{
 		nlh = nlmsg_hdr(skb);  	      // 获得信息头部
 		pid = nlh->nlmsg_pid;         // 获取用户进程pid

 		memcpy(str,NLMSG_DATA(nlh),100);
 		printk(KERN_ERR "recv:%s\n",str);

 		sendNLMsg(pid,payload,strlen(payload));  // 向用户层发送数据

 		kfree_skb(skb);
 	}

 	printk("<==handle_msg\n");
}

// 建立netlink套接字
int NLCreate(void)
{
        // 消息回调函数为handle_msg,注:参数1区别以往内核版本API,设为init_net
 	nlfd = netlink_kernel_create(&init_net,NETLINK_TEST,1,handle_msg,NULL,THIS_MODULE);
	if(!nlfd)
	{
		return -1;
	}

	return 0;
}

// 清除netlink套接字
int NLDestroy(void)
{
	if(nlfd)
	{
		sock_release(nlfd->sk_socket);
	}

	return 0;
}


static int __init netlink_init(void)
{
	NLCreate();

	return 0;
}


static void __exit netlink_exit(void)
{
	NLDestroy();
}

module_init(netlink_init);
module_exit(netlink_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("kettas");
MODULE_DESCRIPTION("Netlink Test Demo");
MODULE_VERSION("1.0.1");
MODULE_ALIAS("Netlink 01");

 

 

二.用户态

该应用向内核模块发送信息,并接收来自内核响应字符串。

        

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


#define NETLINK_TEST 31
#define MAX_NL_MSG_LEN 1024

typedef struct _packet_u
{
	struct nlmsghdr hdr;
	char payload[1024];
}packet_u;


static int nls;  // socket文件描述符

// 向内核发送消息
int sendtokernel(char *buf,int len,int type)
{
	struct nlmsghdr nlmsg;
	struct sockaddr_nl nldest = {};
	int size;

	nldest.nl_family	= AF_NETLINK;
	nldest.nl_pid		= 0;
	nldest.nl_groups	= 0;

	// 填充netlink消息头
	nlmsg.nlmsg_len = NLMSG_LENGTH(len);
	nlmsg.nlmsg_pid = getpid();
	nlmsg.nlmsg_flags = 0;
	nlmsg.nlmsg_type  = type;

	// 填充负载
	memcpy(NLMSG_DATA(&nlmsg),buf,len);

	// 发送
	size = sendto(nls,&nlmsg,nlmsg.nlmsg_len,0,(struct sockaddr*)&nldest,sizeof(nldest));
	return size;
}


// 接收内核消息
int recvfromkernel(void)
{
	int size = 0;

        // 方法一:调用recvfrom方法接收内核数据,注此时message结构体包含有消息体
        /*
	packet_u message;
	struct sockaddr_nl nldest = {};
	int len = sizeof(nldest);
	
	memset(&message,0,sizeof(message));

	nldest.nl_family	= AF_NETLINK;
	nldest.nl_pid		= 0;
	nldest.nl_groups	= 0;
	
	// 接收消息
	size = recvfrom(nls, 
			&message, 
			sizeof(message), 
			0, 
			(struct sockaddr*)&nldest, 
			&len);	
	printf("size:%d recv:%s\n",size,message.payload);   // NLMSG_DATA()与message.payload结果一致				
        */
	// 方法二:调用recvmsg方法
	struct sockaddr_nl nladdr;
	struct msghdr msg;
	struct iovec iov;
	struct nlmsghdr *nlhdr;

	nlhdr = (struct nlmsghdr *)malloc(MAX_NL_MSG_LEN);
	iov.iov_base = (void *)nlhdr;
	iov.iov_len = MAX_NL_MSG_LEN;
	msg.msg_name = (void *)&(nladdr);
	msg.msg_namelen = sizeof(nladdr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	size = recvmsg(nls, &msg, 0);
	printf("size:%d recv:%s\n",size,(char*)NLMSG_DATA(nlhdr));

	return size;
}

int main(int argc,char **argv)
{
	struct sockaddr_nl nlsource;
	int ret;

	// socket
	nls = socket(PF_NETLINK,SOCK_RAW,NETLINK_TEST);
	assert(nls!=-1);

	memset(&nlsource,0,sizeof(struct sockaddr_nl));
	nlsource.nl_family = AF_NETLINK;
	nlsource.nl_pid	   = getpid();
	nlsource.nl_groups = 0;

	// bind
	ret = bind(nls,(struct sockaddr*)&nlsource,sizeof(nlsource));
	assert(ret!=-1);

	// send
	char *str = "Hello kernel,i'm from user";
	sendtokernel(str,strlen(str),0);

	// recv
	recvfromkernel();

	close(nls);
	return 0;
}

 

三.测试运行

 

[scada@linux netlink]$ sudo insmod netlink_test.ko
[scada@linux netlink]$ ./netlink_u 
size:44 recv:Hello user,i'm from kernel!
[scada@linux netlink]$ dmesg
==>handle_msg
recv:Hello kernel,i'm from user
pid:40122 send:44
<==handle_msg
  

 

分享到:
评论

相关推荐

    Netlink套接字在Linux系统通信中的应用研究.pdf

    Netlink套接字在Linux系统通信中的应用研究.pdf

    netlink:软件包netlink提供对Linux netlink套接字的低级访问。 麻省理工学院许可

    网络链接 软件包netlink提供了对Linux netlink套接字的低级访问。 麻省理工学院许可。 有关netlink的工作方式的更多信息,请查看我关于博客系列。 如有任何疑问或需要指导,请在#networking频道中加入 !稳定性有关...

    Linux 用户态与内核态的交互――netlink 篇

    • 在 Linux 2.4 版以后版本的内核中,几乎全部的中断过程与用户态进程的通信都是使用 netlink 套接字实现的,例如iprote2网络管理工具,它与内核的交互就全部使用了netlink,著名的内核包过滤框架Netfilter在与用户...

    基于Netfilter的包过滤状态防火墙(C语言)

    整体架构 Web 端控制面板 使用数据库存储过滤规则表和 NAT 规则表等...使用 NETLINK 套接字和自定义的协议实现用户空间与内核空间的数据交换 4、NETFILTER 框架 使用 NETFILTER 提供的底层接口编写相关的内核驱动模块

    NetLink Sockets C++ Library:网络/套接字C ++库。-开源

    NetLink套接字:网络C ++库。 可能是最简单的套接字C ++库。 请参阅http://netlinksockets.sourceforge.net上的文档,示例和API参考。

    netlink:netlink库防锈

    组织板条箱提供了netlink套接字。 与和集成是可选的。 每个netlink协议都有一个netlink-packet-板条箱,用于提供该协议的数据包: 提供有关消息提供有关协议的消息提供有关协议的消息是所有其他netlink-packet-*包装...

    qdevicewatcher-master.zip

    一个使用Qt编写的,基于netlink套接字来实现监控usb块设备热拔插的程序,在多个操作系统下均可运行

    ip route2 源码 第二代网络工具

    net-tools通过procfs(/proc)和ioctl系统调用去访问和改变内核网络配置,而iproute2则通过netlink套接字接口与内核通讯。抛开性能而言,net-tools的用法给人的感觉是比较乱,而iproute2的用户接口相对net-tools来说...

    gnlpy:适用于python的通用netlink库

    gnlpy:PYthon中的通用NetLink netlink套接字用于作为RPC系统与各种内核子系统进行通信。 有关更多信息,请 。 您还可以在netlink.py python文件的文档中查看有关此库如何工作的详细说明。 该项目提供了通用网络链接...

    Linux-Kernal-Exploits-m-:Linux内核漏洞

    = 2.26) [Sudo] (须藤1.8.6p7-1.8.20) [由于UFO到非UFO路径切换而导致的内存损坏] [由BPF验证程序引起的内存损坏]( 之前Linux内核) [Netlink套接字子系统中的UAF – XFRM](4.13.11之前Linux内核) [Samba远程...

    linux-kernel-exploits:linux-kernel-exploits Linux平台提权伸缩集合

    = 2.26) [Sudo](Sudo 1.8.6p7-1.8.20) [由于UFO到非UFO路径切换而导致的内存损坏] [由BPF验证程序导致的内存损坏]( 之前Linux内核) [Netlink套接字子系统中的UAF – XFRM](4.13.11之前Linux内核) [Samba远程...

    Linux系统内核空间与用户空间通信的实现与分析

    多数的 Linux 内核态程序都需要和用户空间的进程交换数据,但 Linux 内核态无法对传统的 Linux 进 程间同步和通信的方法提供足够的支持。...推荐使用 netlink 套接字实现中断环境与用户态进程通信。 1

    RED HAT LINUX 6大全

    本书全面系统地介绍了Red Hat Linux 6。全书共分为五个部分,包括35章和四个附录。第一部分为Red Hat Linux的介绍和安装;第二部分为服务配置;第三部分为系统管理;第四部分为Linux编程;第五部分为附录。...

    go-libaudit:go-libaudit是用于与Linux Audit Framework通信的库

    Linux Audit Framework在内核中提供了系统调用审核,并使用netlink套接字将事件记录到用户空间中。 该库简化了希望接收审核事件的用户空间应用程序。 安装及使用 软件包文档可在上。 安装可以通过正常的go get来...

    ktf:内核测试框架-Linux内核的单元测试框架

    内核测试框架(KTF) KTF是类似于Google Test的环境,用于为内核代码... 提供了“ ktfrun”来执行测试,它通过netlink套接字与KTF内核模块通信,以查询可用的测试并触发测试执行。 KTF的设计重点是使其 易于运行的

    3snake:从新产生的进程中提取信息的工具

    使用netlink套接字监听proc事件,以获取要跟踪的候选进程。 当它收到sshd或sudo进程时,将附加ptrace并跟踪read和write系统调用,提取与基于密码的身份验证相关的字符串。 我不太喜欢后门openssh的解决方案或在目标...

    内核和用户空间通信—netlink源码

    但用户空间通过建立且协议类型为NL_IMP2的socket套接字并调用sendto,sendmsg函数发送数据时,传送到内核空间的数据由kernel_receive进行处理。该函数主要是记录用户进程的ID,用于随后发送数据的时候指定目的。 ...

    nield:网络接口事件记录守护程序-开源

    nield(网络接口事件日志记录守护程序)是一种工具,用于通过netlink套接字从内核接收通知,并生成与接口,邻居缓存(ARP,NDP),IP地址(IPv4,IPv6),路由,FIB规则,流量控制相关的日志。

    socket:程序包套接字提供了一种低级网络连接类型,该类型与Go的运行时网络轮询器集成在一起,以提供异步IO和截止日期支持。 麻省理工学院许可

    它旨在用作创建特定于操作系统的套接字包的基础,用于套接字家族,例如Linux的AF_NETLINK , AF_PACKET或AF_VSOCK 。 此软件包不应直接在最终用户应用程序中使用。 软件包套接字的任何使用都应由build标签保护,就...

    w1:Linux内核W1 Netlink客户端

    此源用作如何绑定到netlink连接器套接字,如何创建消息和解析回复的示例。 协议同时支持主命令和从命令。 主站支持设备列表,从站搜索,总线复位以及通用的w1读/写/触摸操作。 您也可以手动添加/删除从设备ID。 从...

Global site tag (gtag.js) - Google Analytics