(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-->