diff -burN net-snmp-5.7.2.pre2-clean/agent/mibgroup/if-mib/data_access/interface_linux.c net-snmp-5.7.2.pre2-netlink/agent/mibgroup/if-mib/data_access/interface_linux.c --- net-snmp-5.7.2.pre2-clean/agent/mibgroup/if-mib/data_access/interface_linux.c 2012-07-11 21:23:25.000000000 -0500 +++ net-snmp-5.7.2.pre2-netlink/agent/mibgroup/if-mib/data_access/interface_linux.c 2012-07-31 11:25:02.000000000 -0500 @@ -69,14 +69,12 @@ #define SIOCGMIIREG 0x8948 #endif -#ifdef NETSNMP_ENABLE_IPV6 #if defined(HAVE_LINUX_RTNETLINK_H) #include -#ifdef RTMGRP_IPV6_PREFIX +#if defined(NETSNMP_ENABLE_IPV6) && defined(RTMGRP_IPV6_PREFIX) #define SUPPORT_PREFIX_FLAGS 1 -#endif /* RTMGRP_IPV6_PREFIX */ +#endif #endif /* HAVE_LINUX_RTNETLINK_H */ -#endif /* NETSNMP_ENABLE_IPV6 */ unsigned long long netsnmp_linux_interface_get_if_speed(int fd, const char *name, unsigned long long defaultspeed); @@ -104,6 +102,9 @@ int netsnmp_prefix_listen(void); #endif +#ifdef HAVE_LINUX_RTNETLINK_H +static int netsnmp_iflink_listen(void); +#endif void @@ -143,6 +144,9 @@ list_info.list_head = &prefix_head_list; netsnmp_prefix_listen(); #endif +#ifdef HAVE_LINUX_RTNETLINK_H + netsnmp_iflink_listen(); +#endif #ifdef HAVE_PCI_LOOKUP_NAME pci_access = pci_alloc(); @@ -1023,41 +1027,132 @@ } return retspeed; } -#ifdef SUPPORT_PREFIX_FLAGS -void netsnmp_prefix_process(int fd, void *data); - -/* Open netlink socket to watch new ipv6 addresses and prefixes. */ -int netsnmp_prefix_listen() +#ifdef HAVE_LINUX_RTNETLINK_H +static int netsnmp_netlink_listen(unsigned subscriptions) { - struct { - struct nlmsghdr n; - struct ifinfomsg r; - char buf[1024]; - } req; - - struct rtattr *rta; - int status; struct sockaddr_nl localaddrinfo; - unsigned groups = 0; - int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (fd < 0) { - snmp_log(LOG_ERR, "netsnmp_prefix_listen: Cannot create socket.\n"); + snmp_log(LOG_ERR, "netsnmp_netlink_listen: Cannot create socket.\n"); return -1; } memset(&localaddrinfo, 0, sizeof(struct sockaddr_nl)); - groups |= RTMGRP_IPV6_IFADDR; - groups |= RTMGRP_IPV6_PREFIX; localaddrinfo.nl_family = AF_NETLINK; - localaddrinfo.nl_groups = groups; + localaddrinfo.nl_groups = subscriptions; if (bind(fd, (struct sockaddr*)&localaddrinfo, sizeof(localaddrinfo)) < 0) { - snmp_log(LOG_ERR,"netsnmp_prefix_listen: Bind failed.\n"); + snmp_log(LOG_ERR,"netsnmp_netlink_listen: Bind failed.\n"); + close(fd); + return -1; + } + + return fd; +} + +static void netsnmp_iflink_process(int fd, void *data) { + int status; + char buf[16384]; + struct nlmsghdr *nlmp; + struct ifinfomsg *ifi; + int len, req_len, length; + + status = recv(fd, buf, sizeof(buf), 0); + if (status < 0) { + snmp_log(LOG_ERR,"netsnmp_iflink_listen: Receive failed.\n"); + return; + } + + if (status == 0){ + DEBUGMSGTL(("access:interface:iflink", "End of File\n")); + return; + } + + for (nlmp = (struct nlmsghdr *)buf; + status > sizeof(*nlmp); + status -= NLMSG_ALIGN(len), + nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len))) { + len = nlmp->nlmsg_len; + req_len = len - sizeof(*nlmp); + + if (req_len < 0 || len > status) { + snmp_log(LOG_ERR,"netsnmp_iflink_listen: Error in length\n"); + return; + } + + if (!NLMSG_OK(nlmp, status)) { + DEBUGMSGTL(("access:interface:iflink", "NLMSG not OK\n")); + return; + } + + if (nlmp->nlmsg_type == RTM_NEWLINK || + nlmp->nlmsg_type == RTM_DELLINK) { + ifi = NLMSG_DATA(nlmp); + length = nlmp->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); + + if (length < 0) { + DEBUGMSGTL(("access:interface:iflink", "wrong nlmsg length %d\n", length)); + return; + } + + /* Just request a refresh! */ + ifTable_cache_reload(); + } + } +} + +static int netsnmp_iflink_listen() +{ + struct { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + int status; + int fd = netsnmp_netlink_listen(RTNLGRP_LINK); + if (fd < 0) return -1; + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = RTM_GETLINK; + req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + req.g.rtgen_family = AF_UNSPEC; + + status = send(fd, (void*)&req, sizeof(req), 0); + if (status < 0) { + snmp_log(LOG_ERR,"netsnmp_iflink_listen: send failed\n"); + close(fd); + return -1; + } + + if (register_readfd(fd, netsnmp_iflink_process, NULL) != 0) { + snmp_log(LOG_ERR,"netsnmp_iflink_listen: error registering netlink socket\n"); close(fd); return -1; } + return 0; + +} +#endif + + +#ifdef SUPPORT_PREFIX_FLAGS +void netsnmp_prefix_process(int fd, void *data); + +/* Open netlink socket to watch new ipv6 addresses and prefixes. */ +int netsnmp_prefix_listen() { + struct { + struct nlmsghdr n; + struct ifinfomsg r; + char buf[1024]; + } req; + + struct rtattr *rta; + int status; + + int fd = netsnmp_netlink_listen(RTMGRP_IPV6_IFADDR | + RTMGRP_IPV6_PREFIX); + if (fd < 0) return -1; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); diff -burN net-snmp-5.7.2.pre2-clean/agent/mibgroup/if-mib/ifTable/ifTable_interface.c net-snmp-5.7.2.pre2-netlink/agent/mibgroup/if-mib/ifTable/ifTable_interface.c --- net-snmp-5.7.2.pre2-clean/agent/mibgroup/if-mib/ifTable/ifTable_interface.c 2012-07-11 21:23:25.000000000 -0500 +++ net-snmp-5.7.2.pre2-netlink/agent/mibgroup/if-mib/ifTable/ifTable_interface.c 2012-07-30 17:31:28.000000000 -0500 @@ -1853,6 +1853,16 @@ ***********************************************************************/ static void _container_free(netsnmp_container *container); +void +ifTable_cache_reload() +{ + DEBUGMSGTL(("ifTable:cache_reload", "triggered\n")); + if (NULL != ifTable_if_ctx.cache) { + ifTable_if_ctx.cache->valid = 0; + netsnmp_cache_check_and_reload(ifTable_if_ctx.cache); + } +} + /** * @internal */ diff -burN net-snmp-5.7.2.pre2-clean/agent/mibgroup/if-mib/ifTable/ifTable_interface.h net-snmp-5.7.2.pre2-netlink/agent/mibgroup/if-mib/ifTable/ifTable_interface.h --- net-snmp-5.7.2.pre2-clean/agent/mibgroup/if-mib/ifTable/ifTable_interface.h 2012-07-11 21:23:25.000000000 -0500 +++ net-snmp-5.7.2.pre2-netlink/agent/mibgroup/if-mib/ifTable/ifTable_interface.h 2012-07-30 17:32:41.000000000 -0500 @@ -89,6 +89,11 @@ void if_mib_container_init(void); /* + * Invalidate and reload cache. + */ + void ifTable_cache_reload(void); + + /* */ void ifTable_lastChange_set(u_long uptime);