Linux下使用NetLink 监听网络变化

来源:互联网 发布:淘宝优质卖家 编辑:程序博客网 时间:2024/05/13 15:55

本文来源http://blog.csdn.net/gt945/article/details/45315911

其实网上已经有类似代码,但是还是自己重新写了一遍,实践出真知


/* * NetMonitor.c * *  Created on: 2015年4月25日 *      Author: tao */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <errno.h>#include <sys/types.h>#include <asm/types.h>#include <arpa/inet.h>#include <sys/socket.h>#include <linux/netlink.h>#include <linux/rtnetlink.h>#include <linux/route.h>#define BUFLEN 20480#define t_assert(x) { \if(!(x))  {err = -__LINE__;goto error;} \}/*Ctrl + C 退出*/static volatile int keepRunning = 1;void intHandler(int dummy){keepRunning = 0;}/** * 解析RTA,并存入tb */void parse_rtattr(struct rtattr **tb, int max, struct rtattr *attr, int len){for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {if (attr->rta_type <= max) {tb[attr->rta_type] = attr;}}}/** * 显示连接信息 * 当网卡变动的时候触发这个信息,例如插/拔网线,增/减网卡设备,启用/禁用接口等. */void print_ifinfomsg(struct nlmsghdr *nh){int len;struct rtattr *tb[IFLA_MAX + 1];struct ifinfomsg *ifinfo;bzero(tb, sizeof(tb));ifinfo = NLMSG_DATA(nh);len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));parse_rtattr(tb, IFLA_MAX, IFLA_RTA (ifinfo), len);printf("%s: %s ", (nh->nlmsg_type==RTM_NEWLINK)?"NEWLINK":"DELLINK", (ifinfo->ifi_flags & IFF_UP) ? "up" : "down");if(tb[IFLA_IFNAME]) {printf("%s", RTA_DATA(tb[IFLA_IFNAME]));}printf("\n");}/** * 显示地址信息 * 当地址变动的时候触发这个信息,例如通过DHCP获取到地址后 */void print_ifaddrmsg(struct nlmsghdr *nh){int len;struct rtattr *tb[IFA_MAX + 1];struct ifaddrmsg *ifaddr;char tmp[256];bzero(tb, sizeof(tb));ifaddr = NLMSG_DATA(nh);len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifaddr));parse_rtattr(tb, IFA_MAX, IFA_RTA (ifaddr), len);printf("%s ", (nh->nlmsg_type==RTM_NEWADDR)?"NEWADDR":"DELADDR");if (tb[IFA_LABEL] != NULL) {printf("%s ", RTA_DATA(tb[IFA_LABEL]));}if (tb[IFA_ADDRESS] != NULL) {inet_ntop(ifaddr->ifa_family, RTA_DATA(tb[IFA_ADDRESS]), tmp, sizeof(tmp));printf("%s ", tmp);}printf("\n");}/** * 显示路由信息 * 当路由变动的时候触发这个信息 */void print_rtmsg(struct nlmsghdr *nh){int len;struct rtattr *tb[RTA_MAX + 1];struct rtmsg *rt;char tmp[256];bzero(tb, sizeof(tb));rt = NLMSG_DATA(nh);len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*rt));parse_rtattr(tb, RTA_MAX, RTM_RTA(rt), len);printf("%s: ", (nh->nlmsg_type==RTM_NEWROUTE)?"NEWROUT":"DELROUT");if (tb[RTA_DST] != NULL) {inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_DST]), tmp, sizeof(tmp));printf("RTA_DST %s ", tmp);}if (tb[RTA_SRC] != NULL) {inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_SRC]), tmp, sizeof(tmp));printf("RTA_SRC %s ", tmp);}if (tb[RTA_GATEWAY] != NULL) {inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_GATEWAY]), tmp, sizeof(tmp));printf("RTA_GATEWAY %s ", tmp);}printf("\n");}int main(int argc, char *argv[]){int socket_fd;int err = 0;fd_set rd_set;struct timeval timeout;int select_r;int read_r;struct sockaddr_nl sa;struct nlmsghdr *nh;int len = BUFLEN;char buff[2048];signal(SIGINT, intHandler);/*打开NetLink Socket*/socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);t_assert(socket_fd > 0);t_assert(!setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)));/*设定接收类型并绑定Socket*/bzero(&sa, sizeof(sa));sa.nl_family = AF_NETLINK;sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;t_assert(!bind(socket_fd, (struct sockaddr *) &sa, sizeof(sa)));while (keepRunning) {FD_ZERO(&rd_set);FD_SET(socket_fd, &rd_set);timeout.tv_sec = 5;timeout.tv_usec = 0;select_r = select(socket_fd + 1, &rd_set, NULL, NULL, &timeout);if (select_r < 0) {perror("select");} else if (select_r > 0) {if (FD_ISSET(socket_fd, &rd_set)) {read_r = read(socket_fd, buff, sizeof(buff));for (nh = (struct nlmsghdr *) buff; NLMSG_OK(nh, read_r); nh = NLMSG_NEXT(nh, read_r)) {switch (nh->nlmsg_type) {default:/*收到些奇怪的信息*/printf("nh->nlmsg_type = %d\n", nh->nlmsg_type);break;case NLMSG_DONE:case NLMSG_ERROR:break;case RTM_NEWLINK:case RTM_DELLINK:print_ifinfomsg(nh);break;case RTM_NEWADDR:case RTM_DELADDR:print_ifaddrmsg(nh);break;case RTM_NEWROUTE:case RTM_DELROUTE:print_rtmsg(nh);break;}}}}}close(socket_fd);error:if (err < 0) {printf("Error at line %d\nErrno=%d\n", -err, errno);}return err;}





0 0
原创粉丝点击