linux netlink通信
(1)加入自己的NETLINK通信端口
?????在/usr/include/linux/netlink.h?中加入?NETLINK_TEST?20
(2)用户层代码
#include?<stdio.h>
#include?<unistd.h>
#include?<sys/types.h>
#include?<sys/socket.h>
#include?<arpa/inet.h>
#include?<string.h>
#include?<linux/netlink.h>
#define?NETLINK_TEST???????????20
??
struct?netlink_data{?
????????struct?nlmsghdr?msg;?
????????char?data[1024];?
};?
??
int?main()?
{?
????????struct?netlink_data?nldata;?
????????struct?nlmsghdr?*msg?=?&nldata.msg;?
????????int?retval;?
????????struct?sockaddr_nl?addr;?
????????char?*data?=?"hello?world!\0";?
????????int?size?=?strlen(data);?
????????//创建socket
????????int?fd?=?socket(PF_NETLINK,SOCK_RAW,NETLINK_TEST);?
????????if(fd<0)
????????{
????????????printf("socket?error");
????????????return?0;
????????}
????????//设置netlink消息头部信息
????????memset(&nldata,?'\0',?sizeof(nldata));?
????????msg->nlmsg_len?=?NLMSG_LENGTH(size);?//表示数据长度size+消息头部长度
????????msg->nlmsg_type?=?0;?
????????msg->nlmsg_flags?=?0;?
????????msg->nlmsg_seq?=?0;?
????????//设置接收信息的地址
????????addr.nl_family?=?AF_NETLINK;?
????????addr.nl_pid?=?0;?
????????addr.nl_groups?=?0;?
????????//拷贝信息到消息头后面
????????memcpy(NLMSG_DATA(msg),?data,?size);?
????????//发送消息
????????retval?=?sendto(fd,?&nldata,?msg->nlmsg_len,?0,?
????????????????????????(struct?sockaddr*)&addr,?sizeof(addr));?
??
????????close(fd);?
????????return?0;?
}?
(3)内核层代码
#include?<linux/module.h>
#include?<linux/init.h>
#include?<net/sock.h>
#include?<linux/netlink.h>
#include?<linux/inet.h>
#include?<linux/skbuff.h>
#define?NETLINK_TEST?20
struct?sock?*nl_sk?=?NULL;
void?test(struct?sk_buff?*__skb)
{
??????struct?sk_buff?*skb;
??????struct?nlmsghdr?*nlh;
??????//获取对skb的引用指针
??????skb=skb_get(__skb);
??????if(skb->len<NLMSG_SPACE(0))
??????{
???????????goto?free;
??????}
??????nlh=(struct?nlmsghdr?*)skb->data;
??????printk("msg:%s\n",(char?*)NLMSG_DATA(nlh));
free:
??????kfree_skb(skb);
}
static?int?__init?netlink_init(void)
{
?????//创建内核sock
?????nl_sk=netlink_kernel_create(&init_net,NETLINK_TEST,0,test,NULL,THIS_MODULE);
?????if(!nl_sk)
?????{
?????????printk("netlink:can?not?create");
?????????return?0;
?????}
?????else
?????{
????? printk("netlink:create?success!");
????????return?1;
?????}
}
static?void?__exit?netlink_exit(void)
{
?????if(nl_sk)
?????{
???????????//回收内核sock
???????????netlink_kernel_release(nl_sk);
?????}
}
MODULE_LICENSE("GPL");
module_init(netlink_init);
module_exit(netlink_exit);
(4)常用结构
struct?sockaddr_nl
{
????????sa_family_t?????nl_family;??????/*?AF_NETLINK???*/
????????unsigned?short??nl_pad;?????????/*?zero?????????*/
????????__u32???????????nl_pid;?????????/*?port?ID??????*/
????????__u32???????????nl_groups;??????/*?multicast?groups?mask?*/
};
struct?nlmsghdr
{
????????__u32???????????nlmsg_len;??????/*?Length?of?message?including?header?*/
????????__u16???????????nlmsg_type;?????/*?Message?content?*/
????????__u16???????????nlmsg_flags;????/*?Additional?flags?*/
????????__u32???????????nlmsg_seq;??????/*?Sequence?number?*/
????????__u32???????????nlmsg_pid;??????/*?Sending?process?port?ID?*/
};
(5)nlmsghdr常用宏
#define?NLMSG_HDRLEN??((int)?NLMSG_ALIGN(sizeof(struct?nlmsghdr)))//获取头部大小
#define?NLMSG_LENGTH(len)?((len)+NLMSG_ALIGN(NLMSG_HDRLEN))//获取头部+信息大小
#define?NLMSG_SPACE(len)?NLMSG_ALIGN(NLMSG_LENGTH(len))?//获取分配空间大小
#define?NLMSG_DATA(nlh)??((void*)(((char*)nlh)?+?NLMSG_LENGTH(0)))?//获取数据开始位置
<!--EndFragment-->