/* * IP MIB group implementation - ip.c * */ /* Portions of this file are subject to the following copyright(s). See * the Net-SNMP's COPYING file for more details and other copyrights * that may apply: */ /* * Portions of this file are copyrighted by: * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms specified in the COPYING file * distributed with the Net-SNMP package. */ #include #include #if defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL) #define _KERNEL 1 #define _I_DEFINED_KERNEL #endif #if HAVE_SYS_PARAM_H #include #endif #if HAVE_UNISTD_H #ifdef irix6 #define _STANDALONE 1 #endif #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_STRING_H #include #else #include #endif #include #if HAVE_SYS_SYSCTL_H #ifdef _I_DEFINED_KERNEL #undef _KERNEL #endif #include #ifdef _I_DEFINED_KERNEL #define _KERNEL 1 #endif #endif #if HAVE_SYS_SYSMP_H #include #endif #if HAVE_SYS_TCPIPSTATS_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NET_IF_H #include #endif #if HAVE_NET_IF_VAR_H #include #endif #ifdef _I_DEFINED_KERNEL #undef _KERNEL #endif #if HAVE_NETINET_IN_SYSTM_H #include #endif #if HAVE_SYS_HASHING_H #include #endif #if HAVE_NETINET_IN_VAR_H #include #endif #if HAVE_NETINET_IP_H #include #endif #if HAVE_NETINET_IP_VAR_H #include #endif #if HAVE_INET_MIB2_H #include #endif #if HAVE_SYS_STREAM_H #include #endif #if HAVE_NET_ROUTE_H #include #endif #if HAVE_SYSLOG_H #include #endif #if HAVE_SYS_IOCTL_H #include #endif #if defined(MIB_IPCOUNTER_SYMBOL) || defined(hpux11) #include #include #endif /* MIB_IPCOUNTER_SYMBOL || hpux11 */ #ifdef solaris2 #include "kernel_sunos5.h" #else #include "kernel.h" #endif #include #include #include #include #include "ip.h" #include "ipAddr.h" #include "interfaces.h" #if defined(cygwin) || defined(mingw32) #include #include #endif netsnmp_feature_require(interface_legacy); /********************* * * Kernel & interface information, * and internal forward declarations * *********************/ /********************* * * Initialisation & common implementation functions * *********************/ /********************* * * System specific implementation functions * *********************/ #if !defined (WIN32) && !defined (cygwin) #if !defined(NETSNMP_CAN_USE_SYSCTL) || !defined(IPCTL_STATS) #ifndef solaris2 #if defined(freebsd2) || defined(hpux11) || defined(linux) static void Address_Scan_Init(void); #ifdef freebsd2 static int Address_Scan_Next(short *, struct in_ifaddr *); #else #ifdef linux static struct ifconf ifc; static int Address_Scan_Next(short *, struct ifnet *); #else static int Address_Scan_Next(short *, mib_ipAdEnt *); #endif #endif #endif /* * var_ipAddrEntry(... * Arguments: * vp IN - pointer to variable entry that points here * name IN/OUT - IN/name requested, OUT/name found * length IN/OUT - length of IN/OUT oid's * exact IN - TRUE if an exact match was requested * var_len OUT - length of variable or 0 if function returned * write_method * */ u_char * var_ipAddrEntry(struct variable *vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { /* * object identifier is of form: * 1.3.6.1.2.1.4.20.1.?.A.B.C.D, where A.B.C.D is IP address. * IPADDR starts at offset 10. */ oid lowest[14]; oid current[14], *op; u_char *cp; int lowinterface = 0; #ifndef freebsd2 short interface; #endif #ifdef hpux11 static mib_ipAdEnt in_ifaddr, lowin_ifaddr; #else #if !defined(linux) && !defined(sunV3) static struct in_ifaddr in_ifaddr, lowin_ifaddr; #else static struct ifnet lowin_ifnet; #endif static struct ifnet ifnet; #endif /* hpux11 */ static in_addr_t addr_ret; /* * fill in object part of name for current (less sizeof instance part) */ memcpy((char *) current, (char *) vp->name, (int) vp->namelen * sizeof(oid)); #if !defined(freebsd2) && !defined(hpux11) && !defined(linux) Interface_Scan_Init(); #else Address_Scan_Init(); #endif for (;;) { #if !defined(freebsd2) && !defined(hpux11) && !defined(linux) if (Interface_Scan_Next(&interface, NULL, &ifnet, &in_ifaddr) == 0) break; #ifdef HAVE_STRUCT_IFNET_IF_ADDRLIST if (ifnet.if_addrlist == 0) continue; /* No address found for interface */ #endif #else /* !freebsd2 && !hpux11 */ #if defined(linux) if (Address_Scan_Next(&interface, &ifnet) == 0) break; #else if (Address_Scan_Next(&interface, &in_ifaddr) == 0) break; #endif #endif /* !freebsd2 && !hpux11 && !linux */ #ifdef hpux11 cp = (u_char *) & in_ifaddr.Addr; #elif defined(linux) || defined(sunV3) cp = (u_char *) & (((struct sockaddr_in *) &(ifnet.if_addr))-> sin_addr.s_addr); #else cp = (u_char *) & (((struct sockaddr_in *) &(in_ifaddr.ia_addr))-> sin_addr.s_addr); #endif op = current + 10; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; if (exact) { if (snmp_oid_compare(current, 14, name, *length) == 0) { memcpy((char *) lowest, (char *) current, 14 * sizeof(oid)); lowinterface = interface; #if defined(linux) || defined(sunV3) lowin_ifnet = ifnet; #else lowin_ifaddr = in_ifaddr; #endif break; /* no need to search further */ } } else { if ((snmp_oid_compare(current, 14, name, *length) > 0) && (!lowinterface || (snmp_oid_compare(current, 14, lowest, 14) < 0))) { /* * if new one is greater than input and closer to input than * previous lowest, save this one as the "next" one. */ lowinterface = interface; #if defined(linux) || defined(sunV3) lowin_ifnet = ifnet; #else lowin_ifaddr = in_ifaddr; #endif memcpy((char *) lowest, (char *) current, 14 * sizeof(oid)); } } } #if defined(linux) SNMP_FREE(ifc.ifc_buf); #endif if (!lowinterface) return (NULL); memcpy((char *) name, (char *) lowest, 14 * sizeof(oid)); *length = 14; *write_method = (WriteMethod*)0; *var_len = sizeof(long_return); switch (vp->magic) { case IPADADDR: *var_len = sizeof(addr_ret); #ifdef hpux11 addr_ret = lowin_ifaddr.Addr; return (u_char *) & addr_ret; #elif defined(linux) || defined(sunV3) return (u_char *) & ((struct sockaddr_in *) &lowin_ifnet.if_addr)-> sin_addr.s_addr; #else return (u_char *) & ((struct sockaddr_in *) &lowin_ifaddr. ia_addr)->sin_addr.s_addr; #endif case IPADIFINDEX: long_return = lowinterface; return (u_char *) & long_return; case IPADNETMASK: *var_len = sizeof(addr_ret); #ifdef hpux11 addr_ret = lowin_ifaddr.NetMask; return (u_char *) & addr_ret; #elif defined(linux) return (u_char *) & ((struct sockaddr_in *) &lowin_ifnet. ia_subnetmask)->sin_addr.s_addr; #elif !defined(sunV3) addr_ret = lowin_ifaddr.ia_subnetmask; return (u_char *) & addr_ret; #endif case IPADBCASTADDR: #ifdef hpux11 long_return = lowin_ifaddr.BcastAddr & 1; #elif defined(linux) || defined(sunV3) *var_len = sizeof(long_return); long_return = ntohl(((struct sockaddr_in *) &lowin_ifnet.ifu_broadaddr)-> sin_addr.s_addr) & 1; #elif defined(netbsd1) long_return = ((struct sockaddr_in *) &lowin_ifaddr.ia_broadaddr)->sin_addr. s_addr & 1; #else long_return = ntohl(((struct sockaddr_in *) &lowin_ifaddr.ia_broadaddr)-> sin_addr.s_addr) & 1; #endif return (u_char *) & long_return; case IPADREASMMAX: #ifdef hpux11 long_return = lowin_ifaddr.ReasmMaxSize; return (u_char *) & long_return; #elif defined(NETSNMP_NO_DUMMY_VALUES) return NULL; #else long_return = -1; return (u_char *) & long_return; #endif default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); } return NULL; } #ifdef freebsd2 static struct in_ifaddr *in_ifaddraddr = NULL; static void Address_Scan_Init(void) { int rc = auto_nlist(IFADDR_SYMBOL, (char *) &in_ifaddraddr, sizeof(in_ifaddraddr)); if (0 == rc) in_ifaddraddr = NULL; } /* * NB: Index is the number of the corresponding interface, not of the address */ static int Address_Scan_Next(Index, Retin_ifaddr) short *Index; struct in_ifaddr *Retin_ifaddr; { struct in_ifaddr in_ifaddr; struct ifnet ifnet, *ifnetaddr; /* NOTA: same name as another one */ short iindex = 1; while (in_ifaddraddr) { /* * Get the "in_ifaddr" structure */ if (!NETSNMP_KLOOKUP(in_ifaddraddr, (char *) &in_ifaddr, sizeof in_ifaddr)) { DEBUGMSGTL(("mibII/ip:Address_Scan_Next", "klookup failed\n")); return 0; } in_ifaddraddr = in_ifaddr.ia_next; if (Retin_ifaddr) *Retin_ifaddr = in_ifaddr; /* * Now, more difficult, find the index of the interface to which * this address belongs */ auto_nlist(IFNET_SYMBOL, (char *) &ifnetaddr, sizeof(ifnetaddr)); while (ifnetaddr && ifnetaddr != in_ifaddr.ia_ifp) { if (!NETSNMP_KLOOKUP(ifnetaddr, (char *) &ifnet, sizeof ifnet)) { DEBUGMSGTL(("mibII/ip:Address_Scan_Next", "klookup failed\n")); return 0; } ifnetaddr = ifnet.if_next; iindex++; } /* * XXX - might not find it? */ if (Index) *Index = iindex; return (1); /* DONE */ } return (0); /* EOF */ } #elif defined(hpux11) static int iptab_size, iptab_current; static mib_ipAdEnt *ip = (mib_ipAdEnt *) 0; static void Address_Scan_Init(void) { int fd; struct nmparms p; int val; unsigned int ulen; int ret; if (ip) free(ip); ip = (mib_ipAdEnt *) 0; iptab_size = 0; if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) { p.objid = ID_ipAddrNumEnt; p.buffer = (void *) &val; ulen = sizeof(int); p.len = &ulen; if ((ret = get_mib_info(fd, &p)) == 0) iptab_size = val; if (iptab_size > 0) { ulen = (unsigned) iptab_size *sizeof(mib_ipAdEnt); ip = (mib_ipAdEnt *) malloc(ulen); p.objid = ID_ipAddrTable; p.buffer = (void *) ip; p.len = &ulen; if ((ret = get_mib_info(fd, &p)) < 0) iptab_size = 0; } close_mib(fd); } iptab_current = 0; } /* * NB: Index is the number of the corresponding interface, not of the address */ static int Address_Scan_Next(Index, Retin_ifaddr) short *Index; mib_ipAdEnt *Retin_ifaddr; { if (iptab_current < iptab_size) { /* * copy values */ *Index = ip[iptab_current].IfIndex; *Retin_ifaddr = ip[iptab_current]; /* * increment to point to next entry */ iptab_current++; /* * return success */ return (1); } /* * return done */ return (0); } #elif defined(linux) static struct ifreq *ifr; static int ifr_counter; static void Address_Scan_Init(void) { int num_interfaces = 0; int fd; /* get info about all interfaces */ ifc.ifc_len = 0; SNMP_FREE(ifc.ifc_buf); ifr_counter = 0; do { if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { DEBUGMSGTL(("snmpd", "socket open failure in Address_Scan_Init\n")); return; } num_interfaces += 16; ifc.ifc_len = sizeof(struct ifreq) * num_interfaces; ifc.ifc_buf = (char*) realloc(ifc.ifc_buf, ifc.ifc_len); if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { ifr=NULL; close(fd); return; } close(fd); } while (ifc.ifc_len >= (sizeof(struct ifreq) * num_interfaces)); ifr = ifc.ifc_req; } /* * NB: Index is the number of the corresponding interface, not of the address */ static int Address_Scan_Next(short *Index, struct ifnet *Retifnet) { struct ifnet ifnet_store; int fd; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { DEBUGMSGTL(("snmpd", "socket open failure in Address_Scan_Next\n")); return(0); } while (ifr) { ifnet_store.if_addr = ifr->ifr_addr; if (Retifnet) { Retifnet->if_addr = ifr->ifr_addr; if (ioctl(fd, SIOCGIFBRDADDR, ifr) < 0) { memset((char *) &Retifnet->ifu_broadaddr, 0, sizeof(Retifnet->ifu_broadaddr)); } else Retifnet->ifu_broadaddr = ifr->ifr_broadaddr; ifr->ifr_addr = Retifnet->if_addr; if (ioctl(fd, SIOCGIFNETMASK, ifr) < 0) { memset((char *) &Retifnet->ia_subnetmask, 0, sizeof(Retifnet->ia_subnetmask)); } else Retifnet->ia_subnetmask = ifr->ifr_netmask; } if (Index) { ifr->ifr_addr = ifnet_store.if_addr; *Index = netsnmp_access_interface_index_find(ifr->ifr_name); } ifr++; ifr_counter+=sizeof(struct ifreq); if (ifr_counter >= ifc.ifc_len) { ifr = NULL; /* beyond the end */ } close(fd); return (1); /* DONE */ } close(fd); return (0); /* EOF */ } #endif /* freebsd,hpux11,linux */ #else /* solaris2 */ static int IP_Cmp(void *addr, void *ep) { if (((mib2_ipAddrEntry_t *) ep)->ipAdEntAddr == *(IpAddress *) addr) return (0); else return (1); } u_char * var_ipAddrEntry(struct variable * vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { /* * object identifier is of form: * 1.3.6.1.2.1.4.20.1.?.A.B.C.D, where A.B.C.D is IP address. * IPADDR starts at offset 10. */ #define IP_ADDRNAME_LENGTH 14 #define IP_ADDRINDEX_OFF 10 oid lowest[IP_ADDRNAME_LENGTH]; oid current[IP_ADDRNAME_LENGTH], *op; u_char *cp; IpAddress NextAddr; mib2_ipAddrEntry_t entry; static mib2_ipAddrEntry_t Lowentry; int Found = 0; req_e req_type; static in_addr_t addr_ret; /* * fill in object part of name for current (less sizeof instance part) */ DEBUGMSGTL(("mibII/ip", "var_ipAddrEntry: ")); DEBUGMSGOID(("mibII/ip", name, *length)); DEBUGMSG(("mibII/ip", " %d\n", exact)); memset(&Lowentry, 0, sizeof(Lowentry)); memcpy((char *) current, (char *) vp->name, (int) vp->namelen * sizeof(oid)); if (*length == IP_ADDRNAME_LENGTH) /* Assume that the input name is the lowest */ memcpy((char *) lowest, (char *) name, IP_ADDRNAME_LENGTH * sizeof(oid)); else lowest[0] = 0xff; for (NextAddr = (u_long) - 1, req_type = GET_FIRST;; NextAddr = entry.ipAdEntAddr, req_type = GET_NEXT) { if (getMibstat (MIB_IP_ADDR, &entry, sizeof(mib2_ipAddrEntry_t), req_type, &IP_Cmp, &NextAddr) != 0) break; COPY_IPADDR(cp, (u_char *) & entry.ipAdEntAddr, op, current + IP_ADDRINDEX_OFF); if (exact) { if (snmp_oid_compare (current, IP_ADDRNAME_LENGTH, name, *length) == 0) { memcpy((char *) lowest, (char *) current, IP_ADDRNAME_LENGTH * sizeof(oid)); Lowentry = entry; Found++; break; /* no need to search further */ } } else { if ((snmp_oid_compare (current, IP_ADDRNAME_LENGTH, name, *length) > 0) && (((NextAddr == (u_long) - 1)) || (snmp_oid_compare (current, IP_ADDRNAME_LENGTH, lowest, IP_ADDRNAME_LENGTH) < 0) || (snmp_oid_compare (name, *length, lowest, IP_ADDRNAME_LENGTH) == 0))) { /* * if new one is greater than input and closer to input than * previous lowest, and is not equal to it, save this one as the "next" one. */ Lowentry = entry; Found++; memcpy((char *) lowest, (char *) current, IP_ADDRNAME_LENGTH * sizeof(oid)); } } } DEBUGMSGTL(("mibII/ip", "... Found = %d\n", Found)); if (Found == 0) return (NULL); memcpy((char *) name, (char *) lowest, IP_ADDRNAME_LENGTH * sizeof(oid)); *length = IP_ADDRNAME_LENGTH; *write_method = 0; *var_len = sizeof(long_return); switch (vp->magic) { case IPADADDR: *var_len = sizeof(addr_ret); addr_ret = Lowentry.ipAdEntAddr; return (u_char *) & addr_ret; case IPADIFINDEX: Lowentry.ipAdEntIfIndex.o_bytes[Lowentry.ipAdEntIfIndex.o_length] = '\0'; long_return = netsnmp_access_interface_index_find(Lowentry. ipAdEntIfIndex.o_bytes); return (u_char *) & long_return; case IPADNETMASK: *var_len = sizeof(addr_ret); addr_ret = Lowentry.ipAdEntNetMask; return (u_char *) & addr_ret; case IPADBCASTADDR: long_return = Lowentry.ipAdEntBcastAddr; return (u_char *) & long_return; case IPADREASMMAX: long_return = Lowentry.ipAdEntReasmMaxSize; return (u_char *) & long_return; default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); } return NULL; } #endif /* solaris2 */ /********************* * * Internal implementation functions * *********************/ #else /* NETSNMP_CAN_USE_SYSCTL && IPCTL_STATS */ /* * Ideally, this would be combined with the code in interfaces.c. * Even separate, it's still better than what went before. */ struct iflist { int flags; int index; struct in_addr addr; struct in_addr mask; struct in_addr bcast; }; static struct iflist *ifs; static int nifs; static void get_iflist(void) { int naddrs, bit; static int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 }; char *cp, *ifbuf; size_t len; struct rt_msghdr *rtm; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr *sa; int flags; naddrs = 0; if (ifs) free(ifs); ifs = 0; nifs = 0; len = 0; if (sysctl(mib, 6, 0, &len, 0, 0) < 0) return; ifbuf = malloc(len); if (ifbuf == 0) return; if (sysctl(mib, 6, ifbuf, &len, 0, 0) < 0) { syslog(LOG_WARNING, "sysctl net-route-iflist: %m"); free(ifbuf); return; } loop: cp = ifbuf; while (cp < &ifbuf[len]) { int gotaddr; gotaddr = 0; rtm = (struct rt_msghdr *) cp; if (rtm->rtm_version != RTM_VERSION || rtm->rtm_type != RTM_IFINFO) { free(ifs); ifs = 0; nifs = 0; free(ifbuf); return; } ifm = (struct if_msghdr *) rtm; flags = ifm->ifm_flags; cp += ifm->ifm_msglen; rtm = (struct rt_msghdr *) cp; while (cp < &ifbuf[len] && rtm->rtm_type == RTM_NEWADDR) { ifam = (struct ifa_msghdr *) rtm; cp += sizeof(*ifam); /* * from route.c */ #define ROUND(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) for (bit = 1; bit && cp < &ifbuf[len]; bit <<= 1) { if (!(ifam->ifam_addrs & bit)) continue; sa = (struct sockaddr *) cp; cp += ROUND(sa->sa_len); /* * Netmasks are returned as bit * strings of type AF_UNSPEC. The * others are pretty ok. */ if (bit == RTA_IFA) { #define satosin(sa) ((struct sockaddr_in *)(sa)) if (ifs) { ifs[naddrs].addr = satosin(sa)->sin_addr; ifs[naddrs].index = ifam->ifam_index; ifs[naddrs].flags = flags; } gotaddr = 1; } else if (bit == RTA_NETMASK) { if (ifs) ifs[naddrs].mask = satosin(sa)->sin_addr; } else if (bit == RTA_BRD) { if (ifs) ifs[naddrs].bcast = satosin(sa)->sin_addr; } } if (gotaddr) naddrs++; cp = (char *) rtm + rtm->rtm_msglen; rtm = (struct rt_msghdr *) cp; } } if (ifs) { nifs = naddrs; free(ifbuf); return; } ifs = malloc(naddrs * sizeof(*ifs)); if (ifs == 0) { free(ifbuf); return; } naddrs = 0; goto loop; } u_char * var_ipAddrEntry(struct variable *vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { /* * object identifier is of form: * 1.3.6.1.2.1.4.20.1.?.A.B.C.D, where A.B.C.D is IP address. * IPADDR starts at offset 10. */ oid lowest[14]; oid current[14], *op; u_char *cp; int lowinterface = -1; int i; static in_addr_t addr_ret; /* * fill in object part of name for current (less sizeof instance part) */ memcpy(current, vp->name, (int) vp->namelen * sizeof(oid)); /* * Get interface table from kernel. */ get_iflist(); for (i = 0; i < nifs; i++) { op = ¤t[10]; cp = (u_char *) & ifs[i].addr; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; if (exact) { if (snmp_oid_compare(current, 14, name, *length) == 0) { memcpy(lowest, current, 14 * sizeof(oid)); lowinterface = i; break; /* no need to search further */ } } else { if ((snmp_oid_compare(current, 14, name, *length) > 0) && (lowinterface < 0 || (snmp_oid_compare(current, 14, lowest, 14) < 0))) { /* * if new one is greater than input * and closer to input than previous * lowest, save this one as the "next" * one. */ lowinterface = i; memcpy(lowest, current, 14 * sizeof(oid)); } } } if (lowinterface < 0) return NULL; i = lowinterface; memcpy(name, lowest, 14 * sizeof(oid)); *length = 14; *write_method = 0; *var_len = sizeof(long_return); switch (vp->magic) { case IPADADDR: *var_len = sizeof(addr_ret); addr_ret = ifs[i].addr.s_addr; return (u_char *) & addr_ret; case IPADIFINDEX: long_return = ifs[i].index; return (u_char *) & long_return; case IPADNETMASK: *var_len = sizeof(addr_ret); addr_ret = ifs[i].mask.s_addr; return (u_char *) & addr_ret; case IPADBCASTADDR: long_return = ntohl(ifs[i].bcast.s_addr) & 1; return (u_char *) & long_return; case IPADREASMMAX: #if NETSNMP_NO_DUMMY_VALUES return NULL; #else long_return = -1; return (u_char *) & long_return; #endif default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); } return NULL; } #endif /* NETSNMP_CAN_USE_SYSCTL && IPCTL_STATS */ #elif defined(HAVE_IPHLPAPI_H) /* WIN32 cygwin */ #include u_char * var_ipAddrEntry(struct variable *vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { /* * object identifier is of form: * 1.3.6.1.2.1.4.20.1.?.A.B.C.D, where A.B.C.D is IP address. * IPADDR starts at offset 10. */ oid lowest[14]; oid current[14], *op; u_char *cp; int lowinterface = -1; int i; PMIB_IPADDRTABLE pIpAddrTable = NULL; DWORD status = NO_ERROR; DWORD statusRetry = NO_ERROR; DWORD dwActualSize = 0; void *result = NULL; static in_addr_t addr_ret; /* * fill in object part of name for current (less sizeof instance part) */ memcpy(current, vp->name, (int) vp->namelen * sizeof(oid)); /* * Get interface table from kernel. */ status = GetIpAddrTable(pIpAddrTable, &dwActualSize, TRUE); if (status == ERROR_INSUFFICIENT_BUFFER) { pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwActualSize); if (pIpAddrTable != NULL) { statusRetry = GetIpAddrTable(pIpAddrTable, &dwActualSize, TRUE); } } if (statusRetry == NO_ERROR || status == NO_ERROR) { for (i = 0; i < (int) pIpAddrTable->dwNumEntries; ++i) { op = ¤t[10]; cp = (u_char *) & pIpAddrTable->table[i].dwAddr; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; if (exact) { if (snmp_oid_compare(current, 14, name, *length) == 0) { memcpy(lowest, current, 14 * sizeof(oid)); lowinterface = i; break; /* no need to search further */ } } else { if (snmp_oid_compare(current, 14, name, *length) > 0) { lowinterface = i; memcpy(lowest, current, 14 * sizeof(oid)); break; /* Since the table is sorted, no need to search further */ } } } } if (lowinterface < 0) goto out; i = lowinterface; memcpy(name, lowest, 14 * sizeof(oid)); *length = 14; *write_method = 0; switch (vp->magic) { case IPADADDR: *var_len = sizeof(addr_ret); addr_ret = pIpAddrTable->table[i].dwAddr; result = &addr_ret; break; case IPADIFINDEX: *var_len = sizeof(long_return); long_return = pIpAddrTable->table[i].dwIndex; result = &long_return; break; case IPADNETMASK: *var_len = sizeof(addr_ret); addr_ret = pIpAddrTable->table[i].dwMask; result = &addr_ret; break; case IPADBCASTADDR: *var_len = sizeof(long_return); long_return = pIpAddrTable->table[i].dwBCastAddr; result = &long_return; break; case IPADREASMMAX: *var_len = sizeof(long_return); long_return = pIpAddrTable->table[i].dwReasmSize; result = &long_return; break; default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); break; } out: free(pIpAddrTable); return result; } #endif /* WIN32 cygwin */