消息的接收和发送
内核代码
#include <net/genetlink.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
enum {
CTRL_ATTR_UNDE,
CTRL_ATTR_ID,
CTRL_ATTR_AUDIT,
__CTRL_ATTR_MAX_TEST,
};
#define CTRL_ATTR_MAX_TEST (__CTRL_ATTR_MAX_TEST - 1)
struct genl_family test_ctl = {
.id=1023,
.name="testnet",
.version=1,
.maxattr=CTRL_ATTR_MAX_TEST,
.netnsok = true
};
static const struct nla_policy test_ctrl_policy[CTRL_ATTR_MAX_TEST+1] =
{
[CTRL_ATTR_ID] = { .type = NLA_U16 },
[CTRL_ATTR_AUDIT] = { .type = NLA_NUL_STRING,.len = 100},
};
int test_ctl_function(struct sk_buff *skb, struct genl_info *info)
{
struct sk_buff *skbuff = NULL;
char *strmsg;
void *hdr;
int msg_size ;
printk("get process pid=%d cmd=%d pid=%d type=%d len=%d\n",info->snd_pid,info->genlhdr->cmd,info->nlhdr->nlmsg_pid,info->nlhdr->nlmsg_type,info->nlhdr->nlmsg_len);
if (info->attrs[CTRL_ATTR_AUDIT])
{
strmsg = nla_data(info->attrs[CTRL_ATTR_AUDIT]);
printk("recv message from usr is %s\n",strmsg);
}
msg_size = 2*nla_total_size(sizeof(u16))+nla_total_size(sizeof("hello client"));
skbuff = genlmsg_new(msg_size,GFP_KERNEL);
if(NULL == skbuff)
{
printk("alloc gen error\n");
goto out;
}
if(NULL == (hdr = genlmsg_put(skbuff,0,0,&test_ctl,0,100)))
{
printk("put error\n");
nlmsg_free(skb);
goto out;
}
NLA_PUT_U16(skbuff,CTRL_ATTR_ID,13); //传递类型为CTRL_ATTR_ID
NLA_PUT_STRING(skbuff, CTRL_ATTR_AUDIT, "hello client");//传递类型为CTRL_ATTR_AUDIT
NLA_PUT_U16(skbuff,CTRL_ATTR_ID,14);//传递类型为CTRL_ATTR_ID
genlmsg_end(skbuff,hdr);
//发送消息往用户
genlmsg_reply(skbuff,info);
nla_put_failure:
out:
return 0;
}
struct genl_ops test_ctl_ops={
.cmd = 100,
.doit = test_ctl_function,
.policy = test_ctrl_policy
};
static int __init testnlk_init(void)
{
if(genl_register_family(&test_ctl) != 0)
{
printk("register faimly error\n");
return -1;
}
if(genl_register_ops(&test_ctl,&test_ctl_ops) != 0)
{
printk("Register ops error\n");
goto out;
}
return 0;
out:
genl_unregister_family(&test_ctl);
return 0;
}
static void __exit testnlk_exit(void)
{
genl_unregister_ops(&test_ctl,&test_ctl_ops);
genl_unregister_family(&test_ctl);
}
module_init(testnlk_init);
module_exit(testnlk_exit);
MODULE_LICENSE("GPL");
应用层代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/genetlink.h>
struct mymsg{
struct nlmsghdr nhdr;
struct genlmsghdr genhdr;
char buffer[1024];
};
int main(int argc,char *argv[])
{
int skfd;
struct sockaddr_nl addr={0};
struct mymsg msg={0};
struct mymsg rcvmsg={0};
int ret;
struct nlattr *natr;
struct nlattr *nlar;
skfd = socket(AF_NETLINK,SOCK_RAW,NETLINK_GENERIC);
if(skfd < 0)
{
printf("socket error\n");
return -1;
}
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
if(bind(skfd,(struct sockaddr *)&addr,sizeof(addr)) < 0 )
{
printf("Bind error\n");
goto out;
}
addr.nl_family = AF_NETLINK;
addr.nl_pid = 0;
//设置消息头
msg.nhdr.nlmsg_type = 1023;
msg.nhdr.nlmsg_pid = getpid();
msg.nhdr.nlmsg_flags = NLM_F_REQUEST;
msg.nhdr.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); //nlmsghdr头长 + gennlmsg头长
msg.genhdr.cmd = 100;
msg.genhdr.version = 0x02;
natr = (struct nlattr*)(NLMSG_DATA(&msg)+GENL_HDRLEN);
natr->nla_type = CTRL_ATTR_FAMILY_NAME;
natr->nla_len = sizeof("hello world")+NLA_HDRLEN;
strcpy((char*)natr+NLA_HDRLEN,"hello world");
msg.nhdr.nlmsg_len += NLMSG_ALIGN(natr->nla_len);
//发送信息到内核
ret = sendto(skfd,(char*)&msg,msg.nhdr.nlmsg_len,0,(struct sockaddr *)&addr,sizeof(addr));
if(ret <= 0)
{
printf("send error\n");
goto out;
}
//接收来自内核的消息
ret = recv(skfd,(char *)&rcvmsg,sizeof(rcvmsg),0);
if(ret <= 0)
{
printf("Recv message is error\n");
goto out;
}
//消息解析
nlar = (struct nlattr*)(NLMSG_DATA(&rcvmsg)+GENL_HDRLEN);
printf("Recv mesage from kernel number is %d\n",*(unsigned short*)((char *)nlar+NLA_HDRLEN));
nlar = (struct nlattr*)(NLA_ALIGN(nlar->nla_len)+(char*)nlar);
printf("Recv mesage from kernel is %s\n",((char *)nlar+NLA_HDRLEN));
nlar = (struct nlattr*)(NLA_ALIGN(nlar->nla_len)+(char*)nlar);
printf("Recv mesage from kernel number2 is %d\n",*(unsigned short*)((char *)nlar+NLA_HDRLEN));
out:
close(skfd);
return 0;
}