JJJ:generic netlink例程分析

接嵌入式毕设、课设辅导、技术咨询,欢迎私信

完整代码:github代码仓链接

若想要和指定的generic netlink family通信,如:

c 复制代码
 994 static struct genl_family genl_ctrl __ro_after_init = { // generic netlink子协议
 995     .module = THIS_MODULE,
 996     .ops = genl_ctrl_ops,
 997     .n_ops = ARRAY_SIZE(genl_ctrl_ops),
 998     .mcgrps = genl_ctrl_groups,
 999     .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups),
1000     .id = GENL_ID_CTRL, // 0x10 分配区域最小值
1001     .name = "nlctrl",
1002     .version = 0x2,
1003     .maxattr = CTRL_ATTR_MAX, // 最多支持多少个属性
1004     .netnsok = true,
1005 };

#在自己构造的netlink数据结构中

nlmsghdr的nlmsg_type 指定为genl_family 的id即可,如指定为:GENL_ID_CTRL

发送流程:

demo_send_cmd -》sendto -》__sys_sendto -》sock_sendmsg -》 sock_sendmsg_nosec -》sock->ops->sendmsg

调用具体协议族的proto_ops的sendmsg hook,本次会调用发送方所属于的netlink协议族,netlink_sendmsg

netlink_sendmsg中,会调用:netlink_unicast

netlink_unicast中,先调用:netlink_getsockbyportid。基于源sock所属的protocol(就是socket系统调用的参数2,本流程中是NETLINK_GENERIC),在全局nl_table对应协议的表项中通过portid查找哈希表,找到目的sock。(generic netlink协议在nl_table下面的sock由genl_init -》register_pernet_subsys -》genl_pernet_init -》 netlink_kernel_create中创建并放入到nl_table对应generic netlink下面的哈希表中)

由于本流程是用户态sock向内核发送netlink数据,所以会走:netlink_unicast_kernel,此函数会直接调用目的netlink_sock的netlink_rcv hook:nlk->netlink_rcv(skb);,由于我们发送到的是netlink协议族下面generic netlink子协议的sock,所以 netlink_rcv hook为genl_rcv

c 复制代码
 664 static void genl_rcv(struct sk_buff *skb)
 665 {
 666     down_read(&cb_lock);
 667     netlink_rcv_skb(skb, &genl_rcv_msg);
 668     up_read(&cb_lock);
 669 }

接下来会调用 genl_rcv_msg 具体的接收函数 genl_rcv_msg

c 复制代码
 643 static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
 644             struct netlink_ext_ack *extack)
 645 {
 646     const struct genl_family *family;
 647     int err;
 648
 649     family = genl_family_find_byid(nlh->nlmsg_type);
 650     if (family == NULL)
 651         return -ENOENT;
 652
 653     if (!family->parallel_ops)
 654         genl_lock();
 655
 656     err = genl_family_rcv_msg(family, skb, nlh, extack);
 657
 658     if (!family->parallel_ops)
 659         genl_unlock();
 660
 661     return err;
 662 }

genl_family_rcv_msg 函数中,

首先获取 genlmsghdr 中的cmd成员,调用genl_get_cmd获取相同cmd的genl_ops。这里获取到的是genl_ctrl_ops

然后根据 nlmsghdr 的 nlmsg_flags成员是否置位了 NLM_F_DUMP,来执行 dumpit hook 还是 doit hook

中间framewaork处理的代码流程略过。直接看genl_ctrl_ops 的 doit hook,ctrl_getfamily,填充skb,并回复

诸个genl_family是属于generic netlink下面的

相关推荐
niuTaylor7 分钟前
嵌入式Linux驱动开发基础知识(三)
linux·运维·驱动开发
清源妙木真菌9 分钟前
Linux:页表详解(虚拟地址到物理地址转换过程)
linux·性能优化·内存管理
高峰聚焦10 分钟前
Linux 系统管理综合实训 —— 基于 NAT 模式的多 IP 配置、Nginx 服务部署及存储管理
linux·tcp/ip·nginx
逐光猴22 分钟前
docker 配置harbor 非https访问(http server give HTTP response to HTTPS client)
linux·docker·容器
多多*27 分钟前
2024第十五届蓝桥杯大赛软件赛省赛Java大学B组 报数游戏 类斐波那契循环数 分布式队列 食堂 最优分组 星际旅行 LITS游戏 拼十字
java·linux·stm32·单片机·嵌入式硬件·spring·eclipse
逆鱼_0441 分钟前
ARM-UART
linux·运维·arm开发
源远流长jerry1 小时前
Linux内核页表缓存(TLB)与巨型页
linux
北海屿鹿2 小时前
Linux网络:数据链路层&以太网
linux·运维·网络
开发小菜Go2 小时前
小菜Go:Ubuntu下Go语言开发环境搭建
linux·运维·ubuntu·vim
多云的夏天2 小时前
麒麟-QT-ODBC-达梦
linux·数据库·麒麟