侦听PF_NETLINK套接字时获取所有链接和地址信息 [英] Get all link and address information when listenning to a PF_NETLINK socket

查看:340
本文介绍了侦听PF_NETLINK套接字时获取所有链接和地址信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一段宁静的代码,每当相关(对我)网络信息发生变化(主要是侦听RTM_NEWADDR,RTM_DELADDR,RTM_NEWLINK和RTM_DELLINK)时都会通知我. 每当我拔出电源,更改ip或收到任何通知时,此方法都可以正常工作. 唯一的问题是,我是第一次启动代码时,希望它能提供整个当前状态(RTM_GETLINK和RTM_GETADDR).

I've written a peace of code that notifies me whenever relevant (to me) networking information changes (mainly listenning to RTM_NEWADDR, RTM_DELADDR, RTM_NEWLINK and RTM_DELLINK. this works pretty fine, each time I unplug, change ip or whatsoever I get notified. only problem, is the first time I launch my code, I would like it to give me the whole current status (RTM_GETLINK and RTM_GETADDR).

我可以请求RTM_GETLINK或RTM_GETADDR:

I am able to request either RTM_GETLINK or RTM_GETADDR:

memset(&req, 0, sizeof(req));
req.nlmsghdr.nlmsg_len   = NLMSG_LENGTH(sizeof(struct rtgenmsg));
req.nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; /* request to dump all kernel subsystem */
req.nlmsghdr.nlmsg_type  = RTM_GETLINK;  /* link information              */
req.nlmsghdr.nlmsg_seq   = 1;
req.nlmsghdr.nlmsg_pid   = pid;
req.rtgenmsg.rtgen_family = AF_UNSPEC;

iovec.iov_base = &req;
iovec.iov_len  = req.nlmsghdr.nlmsg_len;

memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_iov     = &iovec;
msghdr.msg_iovlen  = 1;
msghdr.msg_name    = &addr;
msghdr.msg_namelen = sizeof(addr);

/*
** TODO: check for number of sent characters
**       on error display errno
*/
sendmsg(nls, &msghdr, 0);

/* do listening stuff... */

但是如果我同时要求两个:

but if I request both at the same time:

req.nlmsghdr.nlmsg_type  = RTM_GETLINK | RTM_GETADDR;

我只获得IP通知.

我应该使用两个不同的套接字,一个用于请求,另一个用于侦听,还是可以在同一个套接字中完成所有这些工作?

am I supposed to use two different sockets, on for the requests and the other one for listening, or is it possible to do all that in the same socket ?

我尝试为每个请求执行发送,并使用seq(对于第二个请求增加发送),我可以看到第二个答复只有40个字节长:(

I've tried performing a send for each request, and using seq (increasing it for the second request), I am able to see that the second reply is only 40 bytes long :(

memset(&kms.addr, 0, sizeof(kms.addr));
kms.addr.nl_family = AF_NETLINK;

/* prepare request */
memset(&req, 0, sizeof(req));
req.nlmsghdr.nlmsg_len   = NLMSG_LENGTH(sizeof(struct rtgenmsg));
req.nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP /*| NLM_F_ACK*/; /* request to dump all kernel subsystem */
req.nlmsghdr.nlmsg_type  = RTM_GETLINK;                /* link information                     */
req.nlmsghdr.nlmsg_seq   = 1;
req.nlmsghdr.nlmsg_pid   = pid;
req.rtgenmsg.rtgen_family = AF_UNSPEC;

iovec.iov_base = &req;
iovec.iov_len  = req.nlmsghdr.nlmsg_len;

memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_iov     = &iovec;
msghdr.msg_iovlen  = 1;
msghdr.msg_name    = &kms.addr;
msghdr.msg_namelen = sizeof(kms.addr);

/*
** TODO: check for number of sent characters
**       on error display errno
*/
sendmsg(kms.nls, &msghdr, 0);

memset(&req, 0, sizeof(req));
req.nlmsghdr.nlmsg_len   = NLMSG_LENGTH(sizeof(struct rtgenmsg));
req.nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP /*| NLM_F_ACK*/; /* request to dump all kernel subsystem */
req.nlmsghdr.nlmsg_type  = RTM_GETADDR;                /* link information                     */
req.nlmsghdr.nlmsg_seq   = 2;
req.nlmsghdr.nlmsg_pid   = pid;
req.rtgenmsg.rtgen_family = AF_UNSPEC;

iovec.iov_base = &req;
iovec.iov_len  = req.nlmsghdr.nlmsg_len;

memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_iov     = &iovec;
msghdr.msg_iovlen  = 1;
msghdr.msg_name    = &kms.addr;
msghdr.msg_namelen = sizeof(kms.addr);

/* do listening stuff... */

再分析一下,看来我得到了NLMSG_ERROR消息类型. 错误代码为-16 表示设备或资源繁忙".

Analyzing it a bit more, it seems I get an NLMSG_ERROR message type. with error code -16 meaning "device or ressource busy".

如果每次发送后都读取了套接字,则不会出现问题.但我宁愿能够完成我的所有请求,然后才收集所有答复...

if I read the socket after each send, I don't get the problem. but I'd rather be able do all my requests, and only then gather all the replies...

推荐答案

这是我在

(可选)内核可以发出配置通知 允许用户空间侦听更改而不是轮询的更改 频繁地.通知通常会重用现有的消息类型,并且 依靠应用程序使用单独的套接字来区别 请求和通知,但您也可以指定单独的消息 类型.

Optionally, the kernel may send out notifications for configuration changes allowing userspace to listen for changes instead of polling frequently. Notifications typically reuse an existing message type and rely on the application using a separate socket to differ between requests and notifications but you may also specify a separate message type.

但不确定这意味着什么:

but not sure what this means:

,但是您也可以指定其他消息类型.

but you may also specify a separate message type.

这篇关于侦听PF_NETLINK套接字时获取所有链接和地址信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆