| /* |
| * IP MIB group implementation - ip.c |
| * |
| */ |
| |
| #include <config.h> |
| |
| #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL) |
| #define _KERNEL 1 |
| #define _I_DEFINED_KERNEL |
| #endif |
| #if HAVE_SYS_PARAM_H |
| #include <sys/param.h> |
| #endif |
| #if HAVE_SYS_SOCKET_H |
| #include <sys/socket.h> |
| #endif |
| |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| #include <sys/types.h> |
| #if HAVE_WINSOCK_H |
| #include <winsock.h> |
| #endif |
| #if HAVE_SYS_SYSCTL_H |
| #ifdef _I_DEFINED_KERNEL |
| #undef _KERNEL |
| #endif |
| #include <sys/sysctl.h> |
| #ifdef _I_DEFINED_KERNEL |
| #define _KERNEL 1 |
| #endif |
| #endif |
| #if HAVE_SYS_SYSMP_H |
| #include <sys/sysmp.h> |
| #endif |
| #if HAVE_SYS_TCPIPSTATS_H |
| #include <sys/tcpipstats.h> |
| #endif |
| #if HAVE_NETINET_IN_H |
| #include <netinet/in.h> |
| #endif |
| #if HAVE_NET_IF_H |
| #include <net/if.h> |
| #endif |
| #if HAVE_NET_IF_VAR_H |
| #include <net/if_var.h> |
| #endif |
| #ifdef _I_DEFINED_KERNEL |
| #undef _KERNEL |
| #endif |
| #if HAVE_NETINET_IN_SYSTM_H |
| #include <netinet/in_systm.h> |
| #endif |
| #if HAVE_SYS_HASHING_H |
| #include <sys/hashing.h> |
| #endif |
| #if HAVE_NETINET_IN_VAR_H |
| #include <netinet/in_var.h> |
| #endif |
| #if HAVE_NETINET_IP_H |
| #include <netinet/ip.h> |
| #endif |
| #if HAVE_NETINET_IP_VAR_H |
| #include <netinet/ip_var.h> |
| #endif |
| #if HAVE_INET_MIB2_H |
| #include <inet/mib2.h> |
| #endif |
| #if HAVE_SYS_STREAM_H |
| #include <sys/stream.h> |
| #endif |
| #if HAVE_NET_ROUTE_H |
| #include <net/route.h> |
| #endif |
| #if HAVE_SYSLOG_H |
| #include <syslog.h> |
| #endif |
| |
| #ifdef solaris2 |
| #include "kernel_sunos5.h" |
| #else |
| #include "kernel.h" |
| #endif |
| |
| #include "mibincl.h" |
| #include "system.h" |
| #include "auto_nlist.h" |
| |
| #ifdef MIB_IPCOUNTER_SYMBOL |
| #include <sys/mib.h> |
| #include <netinet/mib_kern.h> |
| #endif /* MIB_IPCOUNTER_SYMBOL */ |
| |
| #include "ip.h" |
| #include "interfaces.h" |
| #include "sysORTable.h" |
| |
| #ifdef cygwin |
| #define WIN32 |
| #include <windows.h> |
| #endif |
| |
| /********************* |
| * |
| * Kernel & interface information, |
| * and internal forward declarations |
| * |
| *********************/ |
| |
| /********************* |
| * |
| * Initialisation & common implementation functions |
| * |
| *********************/ |
| |
| /********************* |
| * |
| * System specific implementation functions |
| * |
| *********************/ |
| |
| #ifndef WIN32 |
| |
| #if !defined(CAN_USE_SYSCTL) || !defined(IPCTL_STATS) |
| #ifndef solaris2 |
| |
| #ifdef freebsd2 |
| static void Address_Scan_Init (void); |
| static int Address_Scan_Next (short *, struct in_ifaddr *); |
| #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 |
| static struct in_ifaddr in_ifaddr; |
| #if !defined(linux) && !defined(sunV3) |
| static struct in_ifaddr lowin_ifaddr; |
| #else |
| static struct ifnet lowin_ifnet; |
| #endif |
| static struct ifnet ifnet; |
| |
| /* fill in object part of name for current (less sizeof instance part) */ |
| |
| memcpy( (char *)current,(char *)vp->name, (int)vp->namelen * sizeof(oid)); |
| |
| #ifndef freebsd2 |
| Interface_Scan_Init(); |
| #else |
| Address_Scan_Init(); |
| #endif |
| for (;;) { |
| |
| #ifndef freebsd2 |
| if (Interface_Scan_Next(&interface, NULL, &ifnet, &in_ifaddr) == 0) |
| break; |
| #ifdef STRUCT_IFNET_HAS_IF_ADDRLIST |
| if ( ifnet.if_addrlist == 0 ) |
| continue; /* No address found for interface */ |
| #endif |
| #else |
| if (Address_Scan_Next(&interface, &in_ifaddr) == 0) |
| break; |
| #endif /* freebsd2 */ |
| #if 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 (!lowinterface) return(NULL); |
| memcpy( (char *)name,(char *)lowest, 14 * sizeof(oid)); |
| *length = 14; |
| *write_method = 0; |
| *var_len = sizeof(long_return); |
| switch(vp->magic){ |
| case IPADADDR: |
| #if 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: |
| #ifndef sunV3 |
| #ifdef linux |
| return (u_char *)&((struct sockaddr_in *)&lowin_ifnet.ia_subnetmask)->sin_addr.s_addr; |
| #else |
| long_return = lowin_ifaddr.ia_subnetmask; |
| return(u_char *) &long_return; |
| #endif |
| #endif |
| case IPADBCASTADDR: |
| |
| #if defined(linux) || defined(sunV3) |
| long_return = ntohl(((struct sockaddr_in *) &lowin_ifnet.ifu_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: |
| #if NO_DUMMY_VALUES |
| return NULL; |
| #endif |
| long_return = -1; |
| return(u_char *) &long_return; |
| default: |
| DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); |
| } |
| return NULL; |
| } |
| |
| #ifdef freebsd2 |
| static struct in_ifaddr *in_ifaddraddr; |
| |
| static void |
| Address_Scan_Init (void) |
| { |
| auto_nlist(IFADDR_SYMBOL, (char *)&in_ifaddraddr, sizeof(in_ifaddraddr)); |
| } |
| |
| /* 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 |
| */ |
| klookup((unsigned long)in_ifaddraddr, (char *)&in_ifaddr, sizeof in_ifaddr); |
| 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) { |
| klookup((unsigned long)ifnetaddr, (char *)&ifnet, sizeof ifnet); |
| ifnetaddr = ifnet.if_next; |
| iindex++; |
| } |
| |
| /* XXX - might not find it? */ |
| |
| if (Index) |
| *Index = iindex; |
| |
| return(1); /* DONE */ |
| } |
| return(0); /* EOF */ |
| } |
| |
| #endif /* freebsd2 */ |
| |
| #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, Lowentry; |
| int Found = 0; |
| req_e req_type; |
| |
| /* 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)); |
| 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: |
| long_return = Lowentry.ipAdEntAddr; |
| return(u_char *) &long_return; |
| case IPADIFINDEX: |
| long_return = Interface_Index_By_Name(Lowentry.ipAdEntIfIndex.o_bytes, |
| Lowentry.ipAdEntIfIndex.o_length); |
| return(u_char *) &long_return; |
| case IPADNETMASK: |
| long_return = Lowentry.ipAdEntNetMask; |
| return(u_char *) &long_return; |
| case IPADBCASTADDR: |
| long_return = Lowentry.ipAdEntBcastAddr; |
| 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 /* 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, interface; |
| |
| /* 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: |
| long_return = ifs[i].addr.s_addr; |
| return (u_char *)&long_return; |
| |
| case IPADIFINDEX: |
| long_return = ifs[i].index; |
| return (u_char *)&long_return; |
| |
| case IPADNETMASK: |
| long_return = ifs[i].mask.s_addr; |
| return (u_char *)&long_return; |
| |
| case IPADBCASTADDR: |
| long_return = ntohl(ifs[i].bcast.s_addr) & 1; |
| return (u_char *)&long_return; |
| |
| case IPADREASMMAX: |
| #if NO_DUMMY_VALUES |
| return NULL; |
| #endif |
| long_return = -1; |
| return (u_char *)&long_return; |
| |
| default: |
| DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); |
| } |
| return NULL; |
| } |
| |
| #endif /* CAN_USE_SYSCTL && IPCTL_STATS */ |
| |
| #else /* WIN32 */ |
| #include <iphlpapi.h> |
| 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; |
| |
| /* 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){ |
| free(pIpAddrTable); |
| 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: |
| long_return = pIpAddrTable->table[i].dwAddr; |
| return (u_char *)&long_return; |
| |
| case IPADIFINDEX: |
| long_return = pIpAddrTable->table[i].dwIndex; |
| free(pIpAddrTable); |
| return (u_char *)&long_return; |
| |
| case IPADNETMASK: |
| long_return = pIpAddrTable->table[i].dwMask; |
| free(pIpAddrTable); |
| return (u_char *)&long_return; |
| |
| case IPADBCASTADDR: |
| long_return = pIpAddrTable->table[i].dwBCastAddr; |
| free(pIpAddrTable); |
| return (u_char *)&long_return; |
| |
| case IPADREASMMAX: |
| long_return = pIpAddrTable->table[i].dwReasmSize; |
| free(pIpAddrTable); |
| return (u_char *)&long_return; |
| |
| default: |
| DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipAddrEntry\n", vp->magic)); |
| } |
| return NULL; |
| } |
| #endif /* WIN32 */ |