技术专栏
Linux 网口热插拔
在Linux下监控网卡的连接状态有多种方式,我想要的方式,不是以轮询方式定时查询或主动获取某个值,而是在网卡连接状态变化时我的程序能收到通知。
具体做法如下:
- 使用AF_NETLINK socket
- 绑定到RTMGRP_LINK组
- 等待接收RTM_NEWLINK和RTM_DELLINK类型的message
- 解析收到的消息中ifinfomsg结构体的ifi_flags成员是否被设置了IFF_RUNNING1. -
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
//#include <net/if.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define PRINTF(fmt, ...) printf("%s:%d: " fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define BUF_SIZE 4096
static int init(struct sockaddr_nl *psa);
static int deinit();
static int msg_req();
static int msg_loop(struct msghdr *pmh);
static void sig_handler(int sig);
static int sfd = -1;
int main (int argc, char *argv[])
{
int ret = 0;
char buf[BUF_SIZE];
struct iovec iov = {buf, sizeof(buf)};
struct sockaddr_nl sa;
struct msghdr msg = {(void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0};
ret = init(&sa);
if (!ret) {
ret = msg_req();
}
if (!ret) {
ret = msg_loop(&msg);
}
ret = deinit();
return ret;
}
static int init(struct sockaddr_nl *psa)
{
int ret = 0;
struct sigaction sigact;
sigact.sa_handler = sig_handler;
if (!ret && -1 == sigemptyset(&sigact.sa_mask)) {
PRINTF("ERROR! sigemptyset\n");
ret = -1;
}
if (!ret && -1 == sigaction(SIGINT, &sigact, NULL)) {
PRINTF("ERROR! sigaction SIGINT\n");
ret = -1;
}
if (!ret && -1 == sigaction(SIGTERM, &sigact, NULL)) {
PRINTF("ERROR! sigaction SIGTERM\n");
ret = -1;
}
if (!ret) {
sfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (-1 == sfd) {
PRINTF("ERROR! socket: %s\n", strerror(errno));
ret = -1;
}
}
memset(psa, 0, sizeof(*psa));
psa->nl_family = AF_NETLINK;
psa->nl_groups = RTMGRP_LINK;
if (!ret && bind(sfd, (struct sockaddr *)psa, sizeof(*psa))) {
PRINTF("ERROR! bind: %s\n", strerror(errno));
ret = -1;
}
if (0 != ret) {
deinit();
}
return ret;
}
static int deinit()
{
int ret = 0;
if (-1 != sfd) {
if (-1 == close(sfd)) {
PRINTF("ERROR! close: %s\n", strerror(errno));
ret = -1;
}
sfd = -1;
}
return ret;
}
static int msg_req()
{
int ret = 0;
struct {
struct nlmsghdr nh;
struct ifinfomsg ifimsg;
} req;
memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
req.nh.nlmsg_type = RTM_GETLINK;
req.ifimsg.ifi_family = AF_UNSPEC;
req.ifimsg.ifi_index = 0;
req.ifimsg.ifi_change = 0xFFFFFFFF;
if (-1 == send(sfd, &req, req.nh.nlmsg_len, 0)) {
PRINTF("ERROR! send: %s\n", strerror(errno));
ret = -1;
}
return ret;
}
static int msg_loop(struct msghdr *pmh)
{
int ret = 0;
ssize_t nread = -1;
char *buf = (char *)(pmh->msg_iov->iov_base);
struct nlmsghdr *nh;
struct ifinfomsg *ifimsg;
struct rtattr *rta;
int attrlen;
while (!ret) {
nread = recvmsg(sfd, pmh, 0);
if (-1 == nread) {
PRINTF("ERROR! recvmsg: %s\n", strerror(errno));
ret = -1;
}
for (nh = (struct nlmsghdr *)buf;
!ret && NLMSG_OK(nh, nread);
nh = NLMSG_NEXT(nh, nread)) {
if (NLMSG_DONE == nh->nlmsg_type) {
break;
}
if (NLMSG_ERROR == nh->nlmsg_type) {
PRINTF("ERROR! NLMSG_ERROR\n");
ret = -1;
}
if (!ret && (RTM_NEWLINK == nh->nlmsg_type || RTM_DELLINK == nh->nlmsg_type)) {
ifimsg = (struct ifinfomsg *)NLMSG_DATA(nh);
if (ARPHRD_LOOPBACK != ifimsg->ifi_type) {
attrlen = nh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
for (rta = IFLA_RTA(ifimsg);
RTA_OK(rta, attrlen) && rta->rta_type <= IFLA_MAX;
rta = RTA_NEXT(rta, attrlen)) {
if (IFLA_IFNAME == rta->rta_type) {
printf("%s: ", (char*)RTA_DATA(rta));
}
}
if (IFF_RUNNING & ifimsg->ifi_flags)
printf("link up\n");
else
printf("link down\n");
}
}
}
}
return ret;
}
static void sig_handler(int sig)
{
exit(deinit());
}
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包
点赞
收藏
评论
打赏
- 分享
- 举报
评论
0个
手气红包
暂无数据
相关专栏
-
浏览量:2503次2020-06-19 15:39:47
-
浏览量:4095次2021-07-30 15:02:12
-
浏览量:1167次2024-01-12 17:23:50
-
浏览量:7088次2021-05-11 17:04:57
-
浏览量:3044次2020-08-17 19:42:53
-
浏览量:2450次2017-12-13 15:52:24
-
浏览量:3158次2020-03-11 13:56:02
-
浏览量:2878次2019-01-22 17:41:52
-
浏览量:2349次2020-08-30 15:42:23
-
浏览量:2616次2018-04-26 15:20:37
-
浏览量:2661次2020-03-12 13:43:17
-
浏览量:3018次2021-06-01 09:51:47
-
浏览量:2453次2018-03-19 16:42:27
-
浏览量:2241次2018-04-08 16:50:59
-
浏览量:1892次2018-04-27 14:54:46
-
浏览量:2144次2018-04-17 17:33:29
-
浏览量:2056次2018-04-28 15:41:44
-
浏览量:1111次2024-01-12 13:47:40
-
2018-09-11 17:13:26
置顶时间设置
结束时间
删除原因
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
打赏作者
821586284
您的支持将鼓励我继续创作!
打赏金额:
¥1
¥5
¥10
¥50
¥100
支付方式:
微信支付
打赏成功!
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
审核成功
发布时间设置
发布时间:
请选择发布时间设置
是否关联周任务-专栏模块
审核失败
失败原因
请选择失败原因
备注
请输入备注