JJJ:generic netlink例程分析
接嵌入式毕设、课设辅导、技术咨询,欢迎私信
完整代码:github代码仓链接
若想要和指定的generic netlink family通信,如:
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
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
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;648649 family = genl_family_find_byid(nlh->nlmsg_type);650 if (family == NULL)651 return -ENOENT;652653 if (!family->parallel_ops)654 genl_lock();655656 err = genl_family_rcv_msg(family, skb, nlh, extack);657658 if (!family->parallel_ops)659 genl_unlock();660661 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下面的