/* * Interface MIB architecture support for Solaris */ #include #include #include #include "if-mib/ifTable/ifTable_constants.h" #include "kernel_sunos5.h" #include "mibII/mibII_common.h" #include #include #include "if-mib/data_access/interface.h" #include "interface_private.h" #include #include #include #include netsnmp_feature_child_of(interface_arch_set_admin_status, interface_all); static int _set_ip_flags_v4(netsnmp_interface_entry *, mib2_ifEntry_t *); static int _match_ifname_v4addr(void *ifname, void *ipaddr); static int _get_v4addr(mib2_ifEntry_t *ife, mib2_ipAddrEntry_t *e); static int _set_ip_flags_v6(netsnmp_interface_entry *, mib2_ifEntry_t *); #ifdef SOLARIS_HAVE_IPV6_MIB_SUPPORT static int _get_v6addr(mib2_ifEntry_t *ife, mib2_ipv6AddrEntry_t *ipv6e); static int _match_ifname_v6addr(void *ifname, void *ipaddr); #endif void netsnmp_arch_interface_init(void) { init_kernel_sunos5(); } /* * find the ifIndex for an interface name * * @retval 0 : no index found * @retval >0: ifIndex for interface */ oid netsnmp_arch_interface_index_find(const char *name) { #if defined(HAVE_IF_NAMETOINDEX) return if_nametoindex(name); #else /* use GIFINDEX */ return solaris2_if_nametoindex(name, strlen(name)); #endif /* defined(HAVE_IF_NAMETOINDEX) */ } /* * @retval 0 success * @retval -1 no container specified * @retval -2 could not create entry (probably malloc) */ int netsnmp_arch_interface_container_load(netsnmp_container* container, u_int l_flags) { netsnmp_interface_entry *entry = NULL; mib2_ifEntry_t ife; int rc; req_e req = GET_FIRST; int error = 0; DEBUGMSGTL(("access:interface:container:arch", "load (flags %u)\n", l_flags)); if (container == NULL) { snmp_log(LOG_ERR, "no container specified/found for interface\n"); return -1; } while ((rc = getMibstat(MIB_INTERFACES, &ife, sizeof(ife), req, &Get_everything, NULL)) == 0) { req = GET_NEXT; DEBUGMSGTL(("access:interface:container:arch", "processing '%s'\n", ife.ifDescr.o_bytes)); entry = netsnmp_access_interface_entry_create(ife.ifDescr.o_bytes, ife.ifIndex); if (entry == NULL) { error = 1; break; } entry->ns_flags = 0; if (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP4_ONLY && _set_ip_flags_v4(entry, &ife) == 0) { netsnmp_access_interface_entry_free(entry); continue; } else if (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP6_ONLY && _set_ip_flags_v6(entry, &ife) == 0) { netsnmp_access_interface_entry_free(entry); continue; } else { (void) _set_ip_flags_v4(entry, &ife); (void) _set_ip_flags_v6(entry, &ife); } /* * collect the information needed by IF-MIB */ entry->paddr = (char*)malloc(ife.ifPhysAddress.o_length); if (entry->paddr == NULL) { netsnmp_access_interface_entry_free(entry); error = 1; break; } entry->paddr_len = ife.ifPhysAddress.o_length; (void)memcpy(entry->paddr, ife.ifPhysAddress.o_bytes, ife.ifPhysAddress.o_length); entry->type = ife.ifType; entry->mtu = ife.ifMtu; entry->speed = ife.ifSpeed; entry->speed_high = entry->speed / 1000000; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_SPEED; entry->oper_status = ife.ifOperStatus; entry->admin_status = ife.ifAdminStatus; if (ife.flags & IFF_PROMISC) entry->promiscuous = 1; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_ACTIVE; /* * Interface Stats. */ if (! (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_NO_STATS)) { entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_BYTES | NETSNMP_INTERFACE_FLAGS_HAS_DROPS | NETSNMP_INTERFACE_FLAGS_HAS_MCAST_PKTS; if (ife.ifHCInOctets > 0 || ife.ifHCOutOctets > 0) { /* * We make the assumption that if we have * a 64-bit Octet counter, then the other * counters are 64-bit as well. */ DEBUGMSGTL(("access:interface:container:arch", "interface '%s' have 64-bit stat counters\n", entry->name)); entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_BYTES | NETSNMP_INTERFACE_FLAGS_HAS_HIGH_PACKETS; /* in stats */ entry->stats.ibytes.low = ife.ifHCInOctets & 0xffffffff; entry->stats.ibytes.high = ife.ifHCInOctets >> 32; entry->stats.iucast.low = ife.ifHCInUcastPkts & 0xffffffff; entry->stats.iucast.high = ife.ifHCInUcastPkts >> 32; entry->stats.imcast.low = ife.ifHCInMulticastPkts & 0xffffffff; entry->stats.imcast.high = ife.ifHCInMulticastPkts >> 32; entry->stats.ibcast.low = ife.ifHCInBroadcastPkts & 0xffffffff; entry->stats.ibcast.high = ife.ifHCInBroadcastPkts >> 32; /* out stats */ entry->stats.obytes.low = ife.ifHCOutOctets & 0xffffffff; entry->stats.obytes.high = ife.ifHCOutOctets >> 32; entry->stats.oucast.low = ife.ifHCOutUcastPkts & 0xffffffff; entry->stats.oucast.high = ife.ifHCOutUcastPkts >> 32; entry->stats.omcast.low = ife.ifHCOutMulticastPkts & 0xffffffff; entry->stats.omcast.high = ife.ifHCOutMulticastPkts >> 32; entry->stats.obcast.low = ife.ifHCOutBroadcastPkts & 0xffffffff; entry->stats.obcast.high = ife.ifHCOutBroadcastPkts >> 32; } else { DEBUGMSGTL(("access:interface:container:arch", "interface '%s' have 32-bit stat counters\n", entry->name)); /* in stats */ entry->stats.ibytes.low = ife.ifInOctets; entry->stats.iucast.low = ife.ifInUcastPkts; entry->stats.imcast.low = ife.ifHCInMulticastPkts & 0xffffffff; entry->stats.ibcast.low = ife.ifHCInBroadcastPkts & 0xffffffff; /* out stats */ entry->stats.obytes.low = ife.ifOutOctets; entry->stats.oucast.low = ife.ifOutUcastPkts; entry->stats.omcast.low = ife.ifHCOutMulticastPkts & 0xffffffff; entry->stats.obcast.low = ife.ifHCOutBroadcastPkts & 0xffffffff; } /* in stats */ entry->stats.ierrors = ife.ifInErrors; entry->stats.idiscards = ife.ifInDiscards; entry->stats.iunknown_protos = ife.ifInUnknownProtos; entry->stats.inucast = ife.ifInNUcastPkts; /* out stats */ entry->stats.oerrors = ife.ifOutErrors; entry->stats.odiscards = ife.ifOutDiscards; entry->stats.onucast = ife.ifOutNUcastPkts; entry->stats.oqlen = ife.ifOutQLen; /* other stats */ entry->stats.collisions = ife.ifCollisions; } netsnmp_access_interface_entry_overrides(entry); /* * add to container */ CONTAINER_INSERT(container, entry); } DEBUGMSGTL(("access:interface:container:arch", "rc = %d\n", rc)); if (error) { DEBUGMSGTL(("access:interface:container:arch", "error %d, free container\n", error)); netsnmp_access_interface_container_free(container, NETSNMP_ACCESS_INTERFACE_FREE_NOFLAGS); return -2; } return 0; } /** * @internal */ static int _set_ip_flags_v4(netsnmp_interface_entry *entry, mib2_ifEntry_t *ife) { mib2_ipAddrEntry_t ipv4e; if (_get_v4addr(ife, &ipv4e) > 0) { entry->reasm_max_v4 = ipv4e.ipAdEntReasmMaxSize; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_IPV4 | NETSNMP_INTERFACE_FLAGS_HAS_V4_REASMMAX; #if defined( SOLARIS_HAVE_RFC4293_SUPPORT ) entry->retransmit_v4 = ipv4e.ipAdEntRetransmitTime; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V4_RETRANSMIT; #endif return (1); } return (0); } /** * @internal */ static int _set_ip_flags_v6(netsnmp_interface_entry *entry, mib2_ifEntry_t *ife) { #ifdef SOLARIS_HAVE_IPV6_MIB_SUPPORT mib2_ipv6AddrEntry_t ipv6e; if (_get_v6addr(ife, &ipv6e) > 0) { entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_IPV6; #if defined( SOLARIS_HAVE_RFC4293_SUPPORT ) if (ipv6e.ipv6AddrIdentifierLen <= sizeof(entry->v6_if_id)) { entry->v6_if_id_len = ipv6e.ipv6AddrIdentifierLen; (void)memcpy(&entry->v6_if_id, &ipv6e.ipv6AddrIdentifier, entry->v6_if_id_len); entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V6_IFID; } entry->reasm_max_v6 = ipv6e.ipv6AddrReasmMaxSize; entry->retransmit_v6 = ipv6e.ipv6AddrRetransmitTime; entry->reachable_time = ipv6e.ipv6AddrReachableTime; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V6_REASMMAX | NETSNMP_INTERFACE_FLAGS_HAS_V6_RETRANSMIT | NETSNMP_INTERFACE_FLAGS_HAS_V6_REACHABLE; /* XXX forwarding info missing */ #else /* XXX Don't have this info, 1500 is the minimum */ entry->reasm_max_v6 = 1500; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V6_REASMMAX; /* ??? */ #endif /* SOLARIS_HAVE_RFC4293_SUPPORT */ return (1); } #endif /* SOLARIS_HAVE_IPV6_MIB_SUPPORT */ return (0); } /** * @internal */ static int _match_ifname_v4addr(void *ifname, void *ipaddr) { DeviceName *devname = &((mib2_ipAddrEntry_t *)ipaddr)->ipAdEntIfIndex; return (strncmp((char *)ifname, devname->o_bytes, devname->o_length)); } /** * @internal * * Search for address entry that belongs to the IF entry. * Returns 1 if an address was found, in which case the entry * will be stored in ipv4e. If not entry was found, 0 is returned. * */ static int _get_v4addr(mib2_ifEntry_t *ife, mib2_ipAddrEntry_t *ipv4e) { int rc; if ((rc = getMibstat(MIB_IP_ADDR, ipv4e, sizeof(*ipv4e), GET_EXACT, &_match_ifname_v4addr, &ife->ifDescr.o_bytes)) == 0) return (1); memset(ipv4e, '\0', sizeof(*ipv4e)); return (0); } #ifdef SOLARIS_HAVE_IPV6_MIB_SUPPORT /** * @internal */ static int _match_ifname_v6addr(void *ifname, void *ipaddr) { DeviceName *devname = &((mib2_ipv6AddrEntry_t*)ipaddr)->ipv6AddrIfIndex; return (strncmp((char *)ifname, devname->o_bytes, devname->o_length)); } /** * @internal * * Search for address entry that belongs to the IF entry. * Returns 1 if an address was found, in which case the entry * will be stored in ipv4e. If not entry was found, 0 is returned. * */ static int _get_v6addr(mib2_ifEntry_t *ife, mib2_ipv6AddrEntry_t *ipv6e) { int rc; if ((rc = getMibstat(MIB_IP6_ADDR, ipv6e, sizeof(*ipv6e), GET_EXACT, &_match_ifname_v6addr, &ife->ifDescr.o_bytes)) == 0) { return (1); } memset(ipv6e, '\0', sizeof(*ipv6e)); return (0); } #endif /* SOLARIS_HAVE_IPV6_MIB_SUPPORT */ #ifndef NETSNMP_FEATURE_REMOVE_INTERFACE_ARCH_SET_ADMIN_STATUS int netsnmp_arch_set_admin_status(netsnmp_interface_entry * entry, int ifAdminStatus_val) { DEBUGMSGTL(("access:interface:arch", "set_admin_status\n")); /* * XXX Not supported yet */ return (-1); } #endif /* NETSNMP_FEATURE_REMOVE_INTERFACE_ARCH_SET_ADMIN_STATUS */