262以上内核中netlink使用方法.docx

上传人:b****8 文档编号:9958357 上传时间:2023-02-07 格式:DOCX 页数:12 大小:18.65KB
下载 相关 举报
262以上内核中netlink使用方法.docx_第1页
第1页 / 共12页
262以上内核中netlink使用方法.docx_第2页
第2页 / 共12页
262以上内核中netlink使用方法.docx_第3页
第3页 / 共12页
262以上内核中netlink使用方法.docx_第4页
第4页 / 共12页
262以上内核中netlink使用方法.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

262以上内核中netlink使用方法.docx

《262以上内核中netlink使用方法.docx》由会员分享,可在线阅读,更多相关《262以上内核中netlink使用方法.docx(12页珍藏版)》请在冰豆网上搜索。

262以上内核中netlink使用方法.docx

262以上内核中netlink使用方法

2.6.24以上内核中netlink使用方法

2010-02-0414:

56 5119人阅读 评论

(1) 收藏 举报

structsocket数据结构null网络协议header

 

2.6.24以上内核中netlink使用方法

测试环境:

2.6.28

Netlink在2.6内核的不同版本中发生了很大变化,具体请参考(注意其中的版本号不一定确切):

 

0.综述

以下程序基本流程如下:

运行netlink内核模块;

运行用户态程序,向内核发送连接消息,通知内核自身进程id;

内核接收用户消息,记录其进程id;

内核向用户进程id发送netlink消息;

用户接收内核发送的netlink消息。

 

1.内核部分

1.1相关的数据结构变量:

[cpp] viewplaincopy

1.44 // --------- These are for netlink --------- //  

2.45 #define NETLINK_REALNET     26  

3.46 struct sock *g_nl_sk = NULL;  

4.48 struct sockaddr_nl src_addr, dest_addr;  

5.50 struct iovec iov;  

6.52 int pid;  

7.53 struct msghdr msg;  

8.55 // ----------------------------------------- //  

 

 

[cpp] viewplaincopy

1.45 #define NETLINK_REALNET     26  

 

定义协议族。

该变量在netlink_kernel_create函数中使用。

在2.6.28内核中netlink定义了20个协议,每个协议使用唯一整数标识。

用户程序可以定义任意20个协议以外的协议,用唯一整数标识。

[cpp] viewplaincopy

1.46 struct sock *g_nl_sk = NULL;  

sock数据结构,唯一标识netlink使用的sock,与普通socket编程中sock类似。

[cpp] viewplaincopy

1.48 struct sockaddr_nl src_addr, dest_addr;  

标识netlinksock的源地址和目的地址。

[cpp] viewplaincopy

1.50 struct iovec iov;  

接收发送netlink数据使用的数据结构。

[cpp] viewplaincopy

1.53 struct msghdr msg;  

netlink消息头。

 

1.2调用过程

1.2.1创建netlinksocket

[cpp] viewplaincopy

1.g_nl_sk = netlink_kernel_create(&init_net, NETLINK_REALNET, 0, nl_data_r    eady, NULL, THIS_MODULE);  

1.2.2实现回调函数nl_data_ready

以下回调函数在netlink接收到完整的NETLINK_REALNET协议的数据包时由系统调用。

该函数接收并判断netlink消息,如果第一个字符为H,则保存该消息发出者的进程号,用以向该进程发送数据包;相同,如果为E,则清除与该进程的联系。

[cpp] viewplaincopy

1.185 void nl_data_ready(struct sk_buff *__skb)  

2.186 {  

3.187     struct sk_buff *skb;  

4.188     struct nlmsghdr *nlh;  

5.189     char str[100];  

6.190   

7.191     skb = skb_get (__skb);  

8.192   

9.193     if(skb->len >= NLMSG_SPACE(0))  

10.194     {  

11.195         nlh = nlmsg_hdr(skb);  

12.196   

13.197         memcpy(str, NLMSG_DATA(nlh), sizeof(str));  

14.198         //DbgPrint("Message received:

 %s/n", str);  

15.199   

16.200         // H stands for Hello message.  

17.201         if(str[0] == 'H')  

18.202         {  

19.203             pid = nlh->nlmsg_pid;  

20.204             u_connected = 1;  

21.205             //sendnlmsg("Hello reply.");  

22.206         }  

23.207         // E stands for Exit message  

24.208         else if(str[0] == 'E')  

25.209         {  

26.210             u_connected = 0;  

27.211             pid = 0;  

28.212         }  

29.213         kfree_skb(skb);  

30.214     }  

31.215 }  

 

[cpp] viewplaincopy

1.191 skb = skb_get (__skb);  

获取实际数据包。

该函数的参数为netlink数据包的首地址,而sk_buff为网络协议栈使用的数据结构,两者存在细微差别。

[cpp] viewplaincopy

1.195 nlh = nlmsg_hdr(skb);  

   获取netlink数据包中netlinkheader的起始地址。

[cpp] viewplaincopy

1.197 memcpy(str, NLMSG_DATA(nlh), sizeof(str));  

将netlink数据包的数据区拷贝到str中。

NLMSG_DATA(nlh)返回数据区地址。

相关宏定义参考:

[cpp] viewplaincopy

1.213 kfree_skb(skb);  

释放接收到的消息。

 

1.2.3向用户进程发送netlink消息

   以下函数的参数为netfilter捕捉到的sk_buff结构的数据包,目的是将该包通过netlink发送到用户态进程。

[cpp] viewplaincopy

1.247 void send_to_user(struct sk_buff *skb)  

2.248 {  

3.249     struct iphdr *iph;  

4.250     struct ethhdr *ehdr;  

5.251   

6.252     struct nlmsghdr *nlh;  

7.253   

8.254     struct sk_buff *nl_skb;  

9.255   

10.256     //DbgPrint("Send packages to user/n");  

11.257   

12.258     if(skb == NULL)  

13.259     {  

14.260         return ;  

15.261     }  

16.262     if(!

g_nl_sk)  

17.263     {  

18.264         return ;  

19.265     }  

20.266     if(pid == 0)  

21.267     {  

22.268         return;  

23.269     }  

24.270   

25.271     nl_skb = alloc_skb(NLMSG_SPACE(1514), GFP_ATOMIC);  

26.272     //nl_skb = alloc_skb(NLMSG_SPACE(0), GFP_ATOMIC);  

27.273     if(nl_skb == NULL)  

28.274     {  

29.275         // allocate failed.  

30.276         return;  

31.277     }  

32.278   

33.279     ehdr = eth_hdr(skb);  

34.280     iph = ip_hdr(skb);  

35.281   

36.282     nlh = nlmsg_put(nl_skb, 0, 0, 0, NLMSG_SPACE(1514) - sizeof(struct nlmsghdr), 0);  

37.283     NETLINK_CB(nl_skb).pid = 0;  

38.284   

39.285     //DbgPrint("Data length:

 %d, len=%d/n", htons(iph->tot_len) + ETH_HLEN,     NLMSG_SPACE(1514));  

40.286   

41.287     // Copy data to nlh  

42.288     memcpy(NLMSG_DATA(nlh), (char *)ehdr, htons(iph->tot_len) + ETH_HLEN);  

43.289   

44.290     netlink_unicast(g_nl_sk, nl_skb, pid, MSG_DONTWAIT);  

45.291 }  

 

[cpp] viewplaincopy

1.247 void send_to_user(struct sk_buff *skb)  

参数skb为netfilter捕捉到的数据包,不是netlink数据包。

这里作为netlink的数据传输。

[cpp] viewplaincopy

1.271 nl_skb = alloc_skb(NLMSG_SPACE(1514), GFP_ATOMIC);  

为发送数据包申请空间。

空间数据区大小为1514,即最大ethernet数据包长度。

NLMSG_SPACE(1514)返回数据区大小为1514的netlink数据包的大小。

详细参考:

[cpp] viewplaincopy

1.282 nlh = nlmsg_put(nl_skb, 0, 0, 0, NLMSG_SPACE(1514) - sizeof(struct nlmsghdr), 0);  

填充netlink数据包头。

[cpp] viewplaincopy

1.283 NETLINK_CB(nl_skb).pid = 0;  

确定发送数据包的进程号,0表示内核进程。

该处宏定义同样参考:

[cpp] viewplaincopy

1.290 netlink_unicast(g_nl_sk, nl_skb, pid, MSG_DONTWAIT);  

通过非阻塞方式发送数据包。

注意:

在发送完数据包之后,nl_skb指向的数据空间将被清空,下一次发送数据包必须重新调用alloc_skb分配空间,否则将会造成内核崩溃,必须重新启动。

 

1.2.4释放netlinksocket

使用完成netlink之后,必须要调用sock_release,否则

[cpp] viewplaincopy

1.45 #define NETLINK_REALNET     26  

指定的协议编号将不再可用。

代码如下:

[cpp] viewplaincopy

1.239 void destory_netlink(void)  

2.240 {  

3.241     if(g_nl_sk !

= NULL)  

4.242     {  

5.243         sock_release(g_nl_sk->sk_socket);  

6.244     }  

7.245 }  

 

 

2.用户态程序

2.1相关数据结构

[cpp] viewplaincopy

1.28 // ---------------- For Netlink -------------- //  

2.29 struct sockaddr_nl nl_src_addr, nl_dest_addr;  

3.30 struct nlmsghdr *nlh = NULL;  

4.31 struct iovec iov;  

5.32 int nl_fd;  

6.33 struct msghdr nl_msg;  

7.34 // ------------------------------------------- //  

 

与内核态数据结构类似,不再赘述。

 

2.2运行过程

2.2.1初始化netlink

[cpp] viewplaincopy

1.114 void init_nl()  

2.115 {  

3.116     nl_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_REALNET);  

4.117     memset(&nl_msg, 0, sizeof(nl_msg));  

5.118     memset(&nl_src_addr, 0, sizeof(nl_src_addr));  

6.119     nl_src_addr.nl_family = AF_NETLINK;  

7.120     nl_src_addr.nl_pid = getpid();  

8.121     nl_src_addr.nl_groups = 0;  

9.122       

10.123     bind(nl_fd, (struct sockaddr*)&nl_src_addr, sizeof(nl_src_addr));  

11.124     memset(&nl_dest_addr, 0, sizeof(nl_dest_addr));  

12.125     nl_dest_addr.nl_family = AF_NETLINK;  

13.126     nl_dest_addr.nl_pid = 0;   /* For Linux Kernel */  

14.127     nl_dest_addr.nl_groups = 0; /* unicast */  

15.128       

16.129     sendnlmsg("H");  

17.130       

18.131     memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));  

19.132 }    

 

[cpp] viewplaincopy

1.116 nl_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_REALNET);  

创建用户netlinksocket,与普通socket创建方法相同,协议族为PF_NETLINK,协议类型为用户自定义的NETLINK_REALNET,与内核态定义相同。

[cpp] viewplaincopy

1.117 memset(&nl_msg, 0, sizeof(nl_msg));  

清空netlink数据包。

[cpp] viewplaincopy

1.118 - 127行  

与普通socket的初始化类似,如果不熟悉可以参考有关socket编程。

需要注意的是nl_src_addr的数据结构与普通socket有些不同。

[cpp] viewplaincopy

1.129 sendnlmsg("H");  

向内核进程发送Hello消息,通知内核其进程id。

 

2.2.2向内核发送消息

以下函数创建并发送netlink消息到内核进程。

[cpp] viewplaincopy

1.36 void sendnlmsg(const char *message)  

2.37 {  

3.38     printf("Sending:

 %s/n", message);  

4.39     nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));  

5.40     nlh ->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);  

6.41     nlh -> nlmsg_pid = getpid();  

7.42     nlh -> nlmsg_flags = 0;  

8.43   

9.44     strcpy((char *)NLMSG_DATA(nlh), message);  

10.45   

11.46     iov.iov_base = (void *)nlh;  

12.47     iov.iov_len = nlh->nlmsg_len;  

13.48     nl_msg.msg_name = (void *)&nl_dest_addr;  

14.49     nl_msg.msg_namelen = sizeof(nl_dest_addr);  

15.50     nl_msg.msg_iov = &iov;  

16.51     nl_msg.msg_iovlen = 1;  

17.52   

18.53     printf("Start to send message.");  

19.54     sendmsg(nl_fd, &nl_msg, 0);  

20.55     printf("Sending finishes./n");  

21.56 }  

 

[cpp] viewplaincopy

1.39 nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));  

为netlinkheader分配存储空间,MAX_PAYLOAD由用户定义,为发送(用户)数据的最大长度。

[cpp] viewplaincopy

1.40 - 51行  

指定netlink相关的参数,准备发送消息。

[cpp] viewplaincopy

1.54 sendmsg(nl_fd, &nl_msg, 0);  

   发送netlink数据包到内核进程,与普通socket中的sendmsg消息用法相同,最后一个参数0表示非阻塞模式。

详细参考socket编程。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 哲学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1