我有一个小测试代码,用于检查来自
RTNLGRP_LINK
多播组的 eth 接口打开/关闭事件,但不幸的是,即使我拔下并重新插入网络电缆,我总是收到 RTM_NEWLINK
事件。我期望拔下电缆时会出现 RTM_DELLINK
,连接电缆时会出现 RTM_NEWLINK
。我正在使用 libnl-3.4.0 库。
任何人都可以指出我做错了什么吗?
extern "C"
{
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
#include <arpa/inet.h>
}
#include <iostream>
static int parseLink(struct nlmsghdr *hdr)
{
struct ifinfomsg *iface = (struct ifinfomsg *)nlmsg_data(hdr);
struct nlattr *attrs[IFLA_MAX + 1];
if (nlmsg_parse(hdr, sizeof(struct ifinfomsg), attrs, IFLA_MAX, nullptr) < 0)
{
std::cerr << "problem parsing Netlink response" << std::endl;
return -1;
}
if (attrs[IFLA_IFNAME] != nullptr)
{
if (hdr->nlmsg_type == RTM_NEWLINK)
{
std::cout << "Interface " << (char *)nla_data(attrs[IFLA_IFNAME]) << " added" << std::endl;
}
else if (hdr->nlmsg_type == RTM_DELLINK)
{
std::cout << "Interface " << (char *)nla_data(attrs[IFLA_IFNAME]) << " deleted" << std::endl;
}
}
return 0;
}
static int receiveNewMsg(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
int len = nlh->nlmsg_len;
while (nlmsg_ok(nlh, len))
{
if (nlh->nlmsg_type != RTM_NEWLINK && nlh->nlmsg_type != RTM_DELLINK)
{
if (nlh->nlmsg_type == NLMSG_DONE)
{
std::cout << "message complete" << std::endl;
}
nlh = nlmsg_next(nlh, &len);
continue;
}
if ((nlh->nlmsg_type == RTM_DELLINK) || (nlh->nlmsg_type == RTM_NEWLINK))
{
parseLink(nlh);
}
nlh = nlmsg_next(nlh, &len);
}
return 0;
}
int main(int argc, char const *argv[])
{
struct nl_sock *sk;
/* Allocate a new socket */
sk = nl_socket_alloc();
/*
* Notifications do not use sequence numbers, disable sequence number checking.
*/
nl_socket_disable_seq_check(sk);
/*
* Define a callback function, which will be called for each notification received
*/
nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, receiveNewMsg, nullptr);
nl_socket_modify_cb(sk, NL_CB_FINISH, NL_CB_CUSTOM, receiveNewMsg, nullptr);
/* Connect to routing netlink protocol */
nl_connect(sk, NETLINK_ROUTE);
/* Subscribe to link notifications group */
nl_socket_add_memberships(sk, RTNLGRP_LINK);
/*
* Start receiving messages. The function nl_recvmsgs_default() will block
* until one or more netlink messages (notification) are received which
* will be passed on to my_func().
*/
while (1)
nl_recvmsgs_default(sk);
return 0;
}
CMakeLists.txt编译上述代码:
cmake_minimum_required(VERSION 3.10)
project(mptcpd VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
include_directories(/usr/include/libnl3/)
file(GLOB SOURCES
*.h
*.cpp
)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} libnl-3.so)
更新: 我认为这与 libnl 库有关,所以我尝试了一个没有 libnl 库的示例,但事情是一样的。
这是我尝试过的示例:http://olegkutkov.me/2018/02/14/monitoring-linux-networking-state-using-netlink/
您可能想检查消息标志中的
IFF_RUNNING
(和 IFF_UP
)。
仅当您删除整个接口(仅可能的虚拟接口,例如 VLAN)时,才应通知链路本身已删除。换句话说,拔掉电缆并不会删除接口,您仍然应该能够通过
ip link show
看到它。