侦听PF_NETLINK套接字时获取所有链接和地址信息 [英] Get all link and address information when listenning to a PF_NETLINK socket
问题描述
我编写了一段宁静的代码,每当相关(对我)网络信息发生变化(主要是侦听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...