diff --git a/frontends/php/include/classes/items/CHelpItems.php b/frontends/php/include/classes/items/CHelpItems.php index c3b6e2e4f9..d5eb34b49b 100644 --- a/frontends/php/include/classes/items/CHelpItems.php +++ b/frontends/php/include/classes/items/CHelpItems.php @@ -101,6 +101,9 @@ class CHelpItems { 'description' => _('Network interface list (includes interface type, status, IPv4 address, description). Returns text') ], [ + 'key' => 'net.if.get', + 'description' => _('Network interface data collector (includes interface type, speed, LUID, description and traffic). Returns JSON') + ],[ 'key' => 'net.if.out[if,]', 'description' => _('Outgoing traffic statistics on network interface. Returns integer') ], @@ -418,6 +421,10 @@ class CHelpItems { 'key' => 'net.if.list', 'description' => _('Network interface list (includes interface type, status, IPv4 address, description). Returns text') ], + [ + 'key' => 'net.if.get', + 'description' => _('Network interface data collector (includes interface type, speed, LUID, description and traffic). Returns JSON') + ], [ 'key' => 'net.if.out[if,]', 'description' => _('Outgoing traffic statistics on network interface. Returns integer') diff --git a/include/sysinfo.h b/include/sysinfo.h index 325b62d2dc..c8cbfc6a82 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -280,6 +280,7 @@ int SERVICE_STATE(AGENT_REQUEST *request, AGENT_RESULT *result); int SERVICES(AGENT_REQUEST *request, AGENT_RESULT *result); int PROC_INFO(AGENT_REQUEST *request, AGENT_RESULT *result); int NET_IF_LIST(AGENT_REQUEST *request, AGENT_RESULT *result); +int NET_IF_GET(AGENT_REQUEST *request, AGENT_RESULT *result); int WMI_GET(AGENT_REQUEST *request, AGENT_RESULT *result); int WMI_GETALL(AGENT_REQUEST *request, AGENT_RESULT *result); int VM_VMEMORY_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result); diff --git a/src/libs/zbxsysinfo/win32/net.c b/src/libs/zbxsysinfo/win32/net.c index cbf1786fe2..d49c219c74 100644 --- a/src/libs/zbxsysinfo/win32/net.c +++ b/src/libs/zbxsysinfo/win32/net.c @@ -260,6 +260,49 @@ static ULONG64 zbx_ifrow_get_out_discards(const zbx_ifrow_t *pIfRow) return pIfRow->ifRow->dwOutDiscards; } +static int zbx_ifrow_get_luid_index(const zbx_ifrow_t *pIfRow, ULONG64 *luid_index) +{ + int ret = FAIL; + + if (NULL != pIfRow->ifRow2) + { + *luid_index = pIfRow->ifRow2->InterfaceLuid.Info.NetLuidIndex; + ret = SUCCEED; + } + + return ret; +} + +static char *zbx_ifrow_get_utf8_alias(const zbx_ifrow_t *pIfRow) +{ + if (NULL != pIfRow->ifRow2) + return zbx_unicode_to_utf8(pIfRow->ifRow2->Alias); + else + return NULL; +} + +static DWORD zbx_ifrow_get_oper_status(const zbx_ifrow_t *pIfRow) +{ + if (NULL != pIfRow->ifRow2) + return pIfRow->ifRow2->OperStatus; + else + return pIfRow->ifRow->dwOperStatus; +} + +static ULONG64 zbx_ifrow_get_speed(const zbx_ifrow_t *pIfRow) +{ + if (NULL != pIfRow->ifRow2) + { + ULONG64 tx_speed, rx_speed; + + tx_speed = pIfRow->ifRow2->TransmitLinkSpeed; + rx_speed = pIfRow->ifRow2->ReceiveLinkSpeed; + return (tx_speed > rx_speed) ? tx_speed : rx_speed; + } + else + return pIfRow->ifRow->dwSpeed; +} + /****************************************************************************** * * * Function: zbx_ifrow_get_utf8_description * @@ -394,6 +437,73 @@ clean: return ret; } +static void zbx_json_add_netif(struct zbx_json *j, const char *name, ULONG64 in, ULONG64 out) +{ + zbx_json_addobject(j, name); + zbx_json_adduint64(j, "in", in); + zbx_json_adduint64(j, "out", out); + zbx_json_adduint64(j, "total", in + out); + zbx_json_close(j); +} + +static char *get_if_type_string(DWORD type) +{ + switch (type) + { + case IF_TYPE_OTHER: return "Other"; + case IF_TYPE_ETHERNET_CSMACD: return "Ethernet"; + case IF_TYPE_ISO88025_TOKENRING: return "Token Ring"; + case IF_TYPE_PPP: return "PPP"; + case IF_TYPE_SOFTWARE_LOOPBACK: return "Software Loopback"; + case IF_TYPE_ATM: return "ATM"; + case IF_TYPE_IEEE80211: return "IEEE 802.11 Wireless"; + case IF_TYPE_TUNNEL: return "Tunnel type encapsulation"; + case IF_TYPE_IEEE1394: return "IEEE 1394 Firewire"; + default: return "unknown"; + } +} + +static char *get_if_adminstatus_string(DWORD status) +{ + switch (status) + { + case 0: return "disabled"; + case 1: return "enabled"; + default: return "unknown"; + } +} + +static char *get_oper_status_string(const zbx_ifrow_t *pIfRow, DWORD oper_status) +{ + if (NULL != pIfRow->ifRow2) + { + switch (oper_status) + { + case IfOperStatusUp: return "up"; + case IfOperStatusDown: return "down"; + case IfOperStatusTesting: return "testing"; + case IfOperStatusUnknown: return "unknown"; + case IfOperStatusDormant: return "dormant"; + case IfOperStatusNotPresent: return "not present"; + case IfOperStatusLowerLayerDown: return "lower layer down"; + default: return "unknown"; + } + } + else + { + switch (oper_status) + { + case IF_OPER_STATUS_NON_OPERATIONAL: return "non operational"; + case IF_OPER_STATUS_UNREACHABLE: return "unreachable"; + case IF_OPER_STATUS_DISCONNECTED: return "disconnected"; + case IF_OPER_STATUS_CONNECTING: return "connecting"; + case IF_OPER_STATUS_CONNECTED: return "connected"; + case IF_OPER_STATUS_OPERATIONAL: return "operational"; + default: return "unknown"; + } + } +} + int NET_IF_IN(AGENT_REQUEST *request, AGENT_RESULT *result) { char *if_name, *mode; @@ -615,31 +725,105 @@ clean: return ret; } -static char *get_if_type_string(DWORD type) +int NET_IF_GET(AGENT_REQUEST *request, AGENT_RESULT *result) { - switch (type) + DWORD dwSize, dwRetVal, i; + int ret = SYSINFO_RET_FAIL; + + /* variables used for GetIfTable and GetIfEntry */ + MIB_IFTABLE *pIfTable = NULL; + zbx_ifrow_t ifrow = {NULL, NULL}; + + struct zbx_json j; + char *utf8_descr, *utf8_alias; + + /* Allocate memory for our pointers. */ + dwSize = sizeof(MIB_IFTABLE); + pIfTable = (MIB_IFTABLE *)zbx_malloc(pIfTable, dwSize); + + /* Before calling GetIfEntry, we call GetIfTable to make */ + /* sure there are entries to get and retrieve the interface index. */ + /* Make an initial call to GetIfTable to get the necessary size into dwSize */ + if (ERROR_INSUFFICIENT_BUFFER == GetIfTable(pIfTable, &dwSize, 0)) + pIfTable = (MIB_IFTABLE *)zbx_realloc(pIfTable, dwSize); + + /* Make a second call to GetIfTable to get the actual data we want. */ + if (NO_ERROR != (dwRetVal = GetIfTable(pIfTable, &dwSize, 0))) { - case IF_TYPE_OTHER: return "Other"; - case IF_TYPE_ETHERNET_CSMACD: return "Ethernet"; - case IF_TYPE_ISO88025_TOKENRING: return "Token Ring"; - case IF_TYPE_PPP: return "PPP"; - case IF_TYPE_SOFTWARE_LOOPBACK: return "Software Loopback"; - case IF_TYPE_ATM: return "ATM"; - case IF_TYPE_IEEE80211: return "IEEE 802.11 Wireless"; - case IF_TYPE_TUNNEL: return "Tunnel type encapsulation"; - case IF_TYPE_IEEE1394: return "IEEE 1394 Firewire"; - default: return "unknown"; + zabbix_log(LOG_LEVEL_DEBUG, "GetIfTable failed with error: %s", strerror_from_system(dwRetVal)); + SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", + strerror_from_system(dwRetVal))); + goto clean; } -} -static char *get_if_adminstatus_string(DWORD status) -{ - switch (status) + zbx_json_initarray(&j, ZBX_JSON_STAT_BUF_LEN); + + zbx_ifrow_init(&ifrow); + + for (i = 0; i < pIfTable->dwNumEntries; i++) { - case 0: return "disabled"; - case 1: return "enabled"; - default: return "unknown"; + ULONG64 luid_index; + ULONG64 in, out; + + zbx_ifrow_set_index(&ifrow, pIfTable->table[i].dwIndex); + if (NO_ERROR != (dwRetVal = zbx_ifrow_call_get_if_entry(&ifrow))) + { + zabbix_log(LOG_LEVEL_DEBUG, "zbx_ifrow_call_get_if_entry failed with error: %s", + strerror_from_system(dwRetVal)); + continue; + } + + zbx_json_addobject(&j, NULL); + + utf8_descr = zbx_ifrow_get_utf8_description(&ifrow); + zbx_json_addstring(&j, "ifname", utf8_descr, ZBX_JSON_TYPE_STRING); + + if (SUCCEED == zbx_ifrow_get_luid_index(&ifrow, &luid_index)) + zbx_json_adduint64(&j,"luid_index", luid_index); + + if (NULL != (utf8_alias = zbx_ifrow_get_utf8_alias(&ifrow))) + zbx_json_addstring(&j, "alias", utf8_alias, ZBX_JSON_TYPE_STRING); + + zbx_json_addstring(&j, "oper_status", get_oper_status_string(&ifrow, zbx_ifrow_get_oper_status(&ifrow)), + ZBX_JSON_TYPE_STRING); + zbx_json_adduint64(&j, "speed", zbx_ifrow_get_speed(&ifrow)); + zbx_json_addstring(&j, "if_type", get_if_type_string(zbx_ifrow_get_type(&ifrow)), ZBX_JSON_TYPE_STRING); + + in = zbx_ifrow_get_in_octets(&ifrow); + out = zbx_ifrow_get_out_octets(&ifrow); + zbx_json_add_netif(&j, "bytes", in, out); + + in = zbx_ifrow_get_in_ucast_pkts(&ifrow) + zbx_ifrow_get_in_nucast_pkts(&ifrow); + out = zbx_ifrow_get_out_ucast_pkts(&ifrow) + zbx_ifrow_get_out_nucast_pkts(&ifrow); + zbx_json_add_netif(&j, "packets", in, out); + + in = zbx_ifrow_get_in_errors(&ifrow); + out = zbx_ifrow_get_out_errors(&ifrow); + zbx_json_add_netif(&j, "errors", in, out); + + in = zbx_ifrow_get_in_discards(&ifrow) + zbx_ifrow_get_in_unknown_protos(&ifrow); + out = zbx_ifrow_get_out_discards(&ifrow); + zbx_json_add_netif(&j, "dropped", in, out); + + zbx_free(utf8_descr); + zbx_free(utf8_alias); + + zbx_json_close(&j); } + + zbx_ifrow_clean(&ifrow); + + zbx_json_close(&j); + + SET_STR_RESULT(result, strdup(j.buffer)); + + zbx_json_free(&j); + + ret = SYSINFO_RET_OK; +clean: + zbx_free(pIfTable); + + return ret; } int NET_IF_LIST(AGENT_REQUEST *request, AGENT_RESULT *result) diff --git a/src/libs/zbxsysinfo/win32/win32.c b/src/libs/zbxsysinfo/win32/win32.c index cc8eba08d8..af92e88e67 100644 --- a/src/libs/zbxsysinfo/win32/win32.c +++ b/src/libs/zbxsysinfo/win32/win32.c @@ -36,6 +36,7 @@ ZBX_METRIC parameters_specific[] = {"net.if.total", CF_HAVEPARAMS, NET_IF_TOTAL, "MS TCP Loopback interface,bytes"}, {"net.if.discovery", 0, NET_IF_DISCOVERY, NULL}, {"net.if.list", 0, NET_IF_LIST, NULL}, + {"net.if.get", 0, NET_IF_GET, NULL}, {"vm.memory.size", CF_HAVEPARAMS, VM_MEMORY_SIZE, "free"},