genl 通用netlink套接字实例

#include
#include
#include
#include
 
//接收消息后的回调函数
int test_ctl_function(struct sk_buff *skb, struct genl_info *info)
{
    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);
 
    return 0;
}
 
struct genl_family test_ctl = {
    .id=0, //此family id 为0 表示动态分配
    .name="testnet",  //family name  在应用层根据此名字获得动态分配的family id
    .version=1,
};
 
struct genl_ops test_ctl_ops={
    .cmd = 100, //消息命令字 接收带此消息 会调用下面的回调函数
    .doit = test_ctl_function,//接收消息后的回调函数
};
 
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
#include
#include
#include
#include
#include
#include
#include
 
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 rcmsg={0};
    int ret;
    struct nlattr *natr;
 
    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 = GENL_ID_CTRL; //从内核获得type
    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 = CTRL_CMD_GETFAMILY;//根据family 名称获得family id
    msg.genhdr.version = 0x02;
 
    natr = (struct nlattr*)(NLMSG_DATA(&msg)+GENL_HDRLEN);
    natr->nla_type = CTRL_ATTR_FAMILY_NAME;
    natr->nla_len = sizeof("testnet")+NLA_HDRLEN;
    strcpy((char*)natr+NLA_HDRLEN,"testnet"); //此处根据这个family name获得family id
    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");
    }
 
    //接收返回的family id
    ret = recv(skfd,&rcmsg,sizeof(rcmsg),0);
    if(ret < 0)
        goto out;
 
    //错误检查
    if(!NLMSG_OK((struct nlmsghdr*)&msg,ret) || msg.nhdr.nlmsg_type == NLMSG_ERROR)
    {
        printf(" error happed\n");
        goto out;
    }
    
    //获得属性值
    natr = (struct nlattr*)(NLMSG_DATA(&rcmsg)+GENL_HDRLEN);
    natr = (struct nlattr*)(NLA_ALIGN(natr->nla_len)+(char*)natr);
    if(natr->nla_type == CTRL_ATTR_FAMILY_ID)
    {
        printf("id = %d\n",*((unsigned short *)(char*)natr+NLA_HDRLEN));
    }
    else
    {
        printf("Get id error type[%d]\n",natr->nla_type);
    }
 
out:
    close(skfd);
    return 0;
}

你可能感兴趣的:(netlink)