通用netlink的基本使用(3) NETLINK_GENERIC

消息的接收和发送

内核代码

#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;
}
	

猜你喜欢

转载自blog.csdn.net/yldfree/article/details/82500438
今日推荐