int SYSTEM_CPU_LOAD(AGENT_REQUEST *request, AGENT_RESULT *result) { char *tmp; double value; int per_cpu = 1, cpu_num; #if defined(HAVE_GETLOADAVG) int mode; double load[ZBX_AVG_COUNT]; #elif defined(HAVE_KSTAT_H) char *key, *error; int load; #endif if (2 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } tmp = get_rparam(request, 0); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all")) per_cpu = 0; else if (0 != strcmp(tmp, "percpu")) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } #if defined(HAVE_GETLOADAVG) tmp = get_rparam(request, 1); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1")) mode = ZBX_AVG1; else if (0 == strcmp(tmp, "avg5")) mode = ZBX_AVG5; else if (0 == strcmp(tmp, "avg15")) mode = ZBX_AVG15; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } if (mode >= getloadavg(load, 3)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain load average: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } value = load[mode]; #elif defined(HAVE_KSTAT_H) tmp = get_rparam(request, 1); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1")) key = "avenrun_1min"; else if (0 == strcmp(tmp, "avg5")) key = "avenrun_5min"; else if (0 == strcmp(tmp, "avg15")) key = "avenrun_15min"; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } if (FAIL == get_kstat_system_misc(key, &load, &error)) { SET_MSG_RESULT(result, error); return SYSINFO_RET_FAIL; } value = (double)load / FSCALE; #else SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for CPU load information.")); return SYSINFO_RET_FAIL; #endif if (1 == per_cpu) { if (0 >= (cpu_num = sysconf(_SC_NPROCESSORS_ONLN))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs.")); return SYSINFO_RET_FAIL; } value /= cpu_num; } SET_DBL_RESULT(result, value); return SYSINFO_RET_OK; }
static int vfs_dev_rw(AGENT_REQUEST *request, AGENT_RESULT *result, int rw) { ZBX_SINGLE_DISKDEVICE_DATA *device; char *devname, *tmp, kernel_devname[MAX_STRING_LEN]; int type, mode; zbx_uint64_t dstats[ZBX_DSTAT_MAX]; if (3 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } devname = get_rparam(request, 0); tmp = get_rparam(request, 1); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "sps")) /* default parameter */ type = ZBX_DSTAT_TYPE_SPS; else if (0 == strcmp(tmp, "ops")) type = ZBX_DSTAT_TYPE_OPS; else if (0 == strcmp(tmp, "sectors")) type = ZBX_DSTAT_TYPE_SECT; else if (0 == strcmp(tmp, "operations")) type = ZBX_DSTAT_TYPE_OPER; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } if (type == ZBX_DSTAT_TYPE_SECT || type == ZBX_DSTAT_TYPE_OPER) { if (request->nparam > 2) { /* Mode is supported only if type is in: operations, sectors. */ SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters.")); return SYSINFO_RET_FAIL; } if (SUCCEED != get_diskstat(devname, dstats)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information.")); return SYSINFO_RET_FAIL; } if (ZBX_DSTAT_TYPE_SECT == type) SET_UI64_RESULT(result, dstats[(ZBX_DEV_READ == rw ? ZBX_DSTAT_R_SECT : ZBX_DSTAT_W_SECT)]); else SET_UI64_RESULT(result, dstats[(ZBX_DEV_READ == rw ? ZBX_DSTAT_R_OPER : ZBX_DSTAT_W_OPER)]); return SYSINFO_RET_OK; } tmp = get_rparam(request, 2); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1")) /* default parameter */ mode = ZBX_AVG1; else if (0 == strcmp(tmp, "avg5")) mode = ZBX_AVG5; else if (0 == strcmp(tmp, "avg15")) mode = ZBX_AVG15; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } if (NULL == collector) { /* CPU statistics collector and (optionally) disk statistics collector is started only when Zabbix */ /* agentd is running as a daemon. When Zabbix agent or agentd is started with "-p" or "-t" parameter */ /* the collectors are not available and keys "vfs.dev.read", "vfs.dev.write" with some parameters */ /* (e.g. sps, ops) are not supported. */ SET_MSG_RESULT(result, zbx_strdup(NULL, "This item is available only in daemon mode when collectors are" " started.")); return SYSINFO_RET_FAIL; } if (NULL == devname || '\0' == *devname || 0 == strcmp(devname, "all")) { *kernel_devname = '\0'; } else if (SUCCEED != get_kernel_devname(devname, kernel_devname, sizeof(kernel_devname))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain device name used internally by the kernel.")); return SYSINFO_RET_FAIL; } if (NULL == (device = collector_diskdevice_get(kernel_devname))) { if (SUCCEED != get_diskstat(kernel_devname, dstats)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information.")); return SYSINFO_RET_FAIL; } if (NULL == (device = collector_diskdevice_add(kernel_devname))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot add disk device to agent collector.")); return SYSINFO_RET_FAIL; } } if (ZBX_DSTAT_TYPE_SPS == type) SET_DBL_RESULT(result, (ZBX_DEV_READ == rw ? device->r_sps[mode] : device->w_sps[mode])); else SET_DBL_RESULT(result, (ZBX_DEV_READ == rw ? device->r_ops[mode] : device->w_ops[mode])); return SYSINFO_RET_OK; }
int SYSTEM_HW_MACADDR(AGENT_REQUEST *request, AGENT_RESULT *result) { size_t offset; int ret = SYSINFO_RET_FAIL, s, i, show_names; char *format, *p, *regex, address[MAX_STRING_LEN], buffer[MAX_STRING_LEN]; struct ifreq *ifr; struct ifconf ifc; zbx_vector_str_t addresses; if (2 < request->nparam) return ret; regex = get_rparam(request, 0); format = get_rparam(request, 1); if (NULL == format || '\0' == *format || 0 == strcmp(format, "full")) show_names = 1; /* show interface names */ else if (0 == strcmp(format, "short")) show_names = 0; else return ret; if (-1 == (s = socket(AF_INET, SOCK_DGRAM, 0))) return ret; /* get the interface list */ ifc.ifc_len = sizeof(buffer); ifc.ifc_buf = buffer; if (-1 == ioctl(s, SIOCGIFCONF, &ifc)) goto close; ifr = ifc.ifc_req; ret = SYSINFO_RET_OK; zbx_vector_str_create(&addresses); zbx_vector_str_reserve(&addresses, 8); /* go through the list */ for (i = ifc.ifc_len / sizeof(struct ifreq); 0 < i--; ifr++) { if (NULL != regex && '\0' != *regex && NULL == zbx_regexp_match(ifr->ifr_name, regex, NULL)) continue; if (-1 != ioctl(s, SIOCGIFFLAGS, ifr) && /* get the interface */ 0 == (ifr->ifr_flags & IFF_LOOPBACK) && /* skip loopback interface */ -1 != ioctl(s, SIOCGIFHWADDR, ifr)) /* get the MAC address */ { offset = 0; if (1 == show_names) offset += zbx_snprintf(address + offset, sizeof(address) - offset, "[%s ", ifr->ifr_name); zbx_snprintf(address + offset, sizeof(address) - offset, "%.2hx:%.2hx:%.2hx:%.2hx:%.2hx:%.2hx", (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[0], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[1], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[2], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[3], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[4], (unsigned short int)(unsigned char)ifr->ifr_hwaddr.sa_data[5]); if (0 == show_names && FAIL != zbx_vector_str_search(&addresses, address, ZBX_DEFAULT_STR_COMPARE_FUNC)) continue; zbx_vector_str_append(&addresses, zbx_strdup(NULL, address)); } } offset = 0; if (0 != addresses.values_num) { zbx_vector_str_sort(&addresses, ZBX_DEFAULT_STR_COMPARE_FUNC); for (i = 0; i < addresses.values_num; i++) { if (1 == show_names && NULL != (p = strchr(addresses.values[i], ' '))) *p = ']'; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s, ", addresses.values[i]); zbx_free(addresses.values[i]); } offset -= 2; } buffer[offset] = '\0'; if (SYSINFO_RET_OK == ret) SET_STR_RESULT(result, zbx_strdup(NULL, buffer)); zbx_vector_str_destroy(&addresses); close: close(s); return ret; }
int check_vcenter_vm_vfs_fs_size(AGENT_REQUEST *request, const char *username, const char *password, AGENT_RESULT *result) { zbx_vmware_service_t *service; zbx_vmware_vm_t *vm; char *url, *uuid, *fsname, *mode, *value = NULL, xpath[MAX_STRING_LEN]; zbx_uint64_t value_total, value_free; int ret = SYSINFO_RET_FAIL; if (3 > request->nparam || request->nparam > 4) return SYSINFO_RET_FAIL; url = get_rparam(request, 0); uuid = get_rparam(request, 1); fsname = get_rparam(request, 2); mode = get_rparam(request, 3); if ('\0' == *uuid) return SYSINFO_RET_FAIL; zbx_vmware_lock(); if (NULL == (service = get_vmware_service(url, username, password, result, &ret))) goto unlock; if (NULL == (vm = service_vm_get(service, uuid))) goto unlock; zbx_snprintf(xpath, sizeof(xpath), ZBX_XPATH_LN2("disk", "diskPath") "[.='%s']/.." ZBX_XPATH_LN("capacity"), fsname); if (NULL == (value = zbx_xml_read_value(vm->details, xpath))) goto unlock; if (SUCCEED != is_uint64(value, &value_total)) goto unlock; zbx_free(value); zbx_snprintf(xpath, sizeof(xpath), ZBX_XPATH_LN2("disk", "diskPath") "[.='%s']/.." ZBX_XPATH_LN("freeSpace"), fsname); if (NULL == (value = zbx_xml_read_value(vm->details, xpath))) goto unlock; if (SUCCEED != is_uint64(value, &value_free)) goto unlock; ret = SYSINFO_RET_OK; if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) SET_UI64_RESULT(result, value_total); else if (0 == strcmp(mode, "free")) SET_UI64_RESULT(result, value_free); else if (0 == strcmp(mode, "used")) SET_UI64_RESULT(result, value_total - value_free); else if (0 == strcmp(mode, "pfree")) SET_DBL_RESULT(result, (0 != value_total ? (double)(100.0 * value_free) / value_total : 0)); else if (0 == strcmp(mode, "pused")) SET_DBL_RESULT(result, 100.0 - (0 != value_total ? (double)(100.0 * value_free) / value_total : 0)); else ret = SYSINFO_RET_FAIL; unlock: zbx_free(value); zbx_vmware_unlock(); return ret; }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; int zbx_proc_stat; zbx_uint64_t proccount = 0; if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { errno = 0; if (NULL == (usrinfo = getpwnam(param))) { if (0 == errno) SET_MSG_RESULT(result, zbx_strdup(NULL, "Specified user does not exist.")); else SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = ZBX_PROC_STAT_ALL; else if (0 == strcmp(param, "run")) zbx_proc_stat = ZBX_PROC_STAT_RUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = ZBX_PROC_STAT_SLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = ZBX_PROC_STAT_ZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (FAIL == check_procstate(&psinfo, zbx_proc_stat)) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; proccount++; } closedir(dir); if (-1 != fd) close(fd); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer) { #if defined(HAVE_RES_QUERY) || defined(_WINDOWS) size_t offset = 0; int res, type, retrans, retry, use_tcp, i, ret = SYSINFO_RET_FAIL, ip_type = AF_INET; char *ip, zone[MAX_STRING_LEN], buffer[MAX_STRING_LEN], *zone_str, *param, tmp[MAX_STRING_LEN]; struct in_addr inaddr; struct in6_addr in6addr; #ifndef _WINDOWS #if defined(HAVE_RES_NINIT) && !defined(_AIX) /* It seems that on some AIX systems with no updates installed res_ninit() can */ /* corrupt stack (see ZBX-14559). Use res_init() on AIX. */ struct __res_state res_state_local; #else /* thread-unsafe resolver API */ int saved_retrans, saved_retry, saved_nscount = 0; unsigned long saved_options; struct sockaddr_in saved_ns; # if defined(HAVE_RES_U_EXT) /* thread-unsafe resolver API /Linux/ */ int save_nssocks, saved_nscount6; # endif #endif #if defined(HAVE_RES_EXT_EXT) /* AIX */ union res_sockaddr_union saved_ns6; #elif defined(HAVE_RES_U_EXT_EXT) /* BSD */ struct sockaddr_in6 saved_ns6; #else struct sockaddr_in6 *saved_ns6; #endif struct sockaddr_in6 sockaddrin6; struct addrinfo hint, *hres = NULL; #endif typedef struct { const char *name; int type; } resolv_querytype_t; static const resolv_querytype_t qt[] = { {"ANY", T_ANY}, {"A", T_A}, {"AAAA", T_AAAA}, {"NS", T_NS}, {"MD", T_MD}, {"MF", T_MF}, {"CNAME", T_CNAME}, {"SOA", T_SOA}, {"MB", T_MB}, {"MG", T_MG}, {"MR", T_MR}, {"NULL", T_NULL}, #ifndef _WINDOWS {"WKS", T_WKS}, #endif {"PTR", T_PTR}, {"HINFO", T_HINFO}, {"MINFO", T_MINFO}, {"MX", T_MX}, {"TXT", T_TXT}, {"SRV", T_SRV}, {NULL} }; #ifdef _WINDOWS PDNS_RECORD pQueryResults, pDnsRecord; wchar_t *wzone; char tmp2[MAX_STRING_LEN]; DWORD options; #else char *name; unsigned char *msg_end, *msg_ptr, *p; int num_answers, num_query, q_type, q_class, q_len, value, c, n; struct servent *s; HEADER *hp; struct protoent *pr; #if PACKETSZ > 1024 unsigned char buf[PACKETSZ]; #else unsigned char buf[1024]; #endif typedef union { HEADER h; #if defined(NS_PACKETSZ) unsigned char buffer[NS_PACKETSZ]; #elif defined(PACKETSZ) unsigned char buffer[PACKETSZ]; #else unsigned char buffer[512]; #endif } answer_t; answer_t answer; #endif /* _WINDOWS */ zbx_vector_str_t answers; *buffer = '\0'; if (6 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } ip = get_rparam(request, 0); zone_str = get_rparam(request, 1); #ifndef _WINDOWS memset(&hint, '\0', sizeof(hint)); hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; if (NULL != ip && '\0' != *ip && 0 == getaddrinfo(ip, NULL, &hint, &hres) && AF_INET6 == hres->ai_family) ip_type = hres->ai_family; if (NULL != hres) freeaddrinfo(hres); #endif if (NULL == zone_str || '\0' == *zone_str) strscpy(zone, "zabbix.com"); else strscpy(zone, zone_str); param = get_rparam(request, 2); if (NULL == param || '\0' == *param) type = T_SOA; else { for (i = 0; NULL != qt[i].name; i++) { if (0 == strcasecmp(qt[i].name, param)) { type = qt[i].type; break; } } if (NULL == qt[i].name) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } } param = get_rparam(request, 3); if (NULL == param || '\0' == *param) retrans = 1; else if (SUCCEED != is_uint31(param, &retrans) || 0 == retrans) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter.")); return SYSINFO_RET_FAIL; } param = get_rparam(request, 4); if (NULL == param || '\0' == *param) retry = 2; else if (SUCCEED != is_uint31(param, &retry) || 0 == retry) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter.")); return SYSINFO_RET_FAIL; } param = get_rparam(request, 5); if (NULL == param || '\0' == *param || 0 == strcmp(param, "udp")) use_tcp = 0; else if (0 == strcmp(param, "tcp")) use_tcp = 1; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid sixth parameter.")); return SYSINFO_RET_FAIL; } #ifdef _WINDOWS options = DNS_QUERY_STANDARD | DNS_QUERY_BYPASS_CACHE; if (0 != use_tcp) options |= DNS_QUERY_USE_TCP_ONLY; wzone = zbx_utf8_to_unicode(zone); res = DnsQuery(wzone, type, options, NULL, &pQueryResults, NULL); zbx_free(wzone); if (1 == short_answer) { SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1); ret = SYSINFO_RET_OK; goto clean_dns; } if (DNS_RCODE_NOERROR != res) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot perform DNS query: [%d]", res)); return SYSINFO_RET_FAIL; } pDnsRecord = pQueryResults; zbx_vector_str_create(&answers); while (NULL != pDnsRecord) { if (DnsSectionAnswer != pDnsRecord->Flags.S.Section) { pDnsRecord = pDnsRecord->pNext; continue; } if (NULL == pDnsRecord->pName) goto clean; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp))); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(pDnsRecord->wType)); switch (pDnsRecord->wType) { case T_A: inaddr.s_addr = pDnsRecord->Data.A.IpAddress; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; case T_AAAA: memcpy(&in6addr.s6_addr, &(pDnsRecord->Data.AAAA.Ip6Address), sizeof(in6addr.s6_addr)); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp))); break; case T_NS: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp))); break; case T_MD: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp))); break; case T_MF: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp))); break; case T_CNAME: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp))); break; case T_SOA: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu", zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)), pDnsRecord->Data.SOA.dwSerialNo, pDnsRecord->Data.SOA.dwRefresh, pDnsRecord->Data.SOA.dwRetry, pDnsRecord->Data.SOA.dwExpire, pDnsRecord->Data.SOA.dwDefaultTtl); break; case T_MB: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp))); break; case T_MG: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp))); break; case T_MR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp))); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu", pDnsRecord->Data.Null.dwByteCount); break; case T_PTR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp))); break; case T_HINFO: for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"", zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp))); break; case T_MINFO: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2))); break; case T_MX: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s", pDnsRecord->Data.MX.wPreference, zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp))); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ", zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp))); if (0 < i) offset -= 1; /* remove the trailing space */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s", pDnsRecord->Data.SRV.wPriority, pDnsRecord->Data.SRV.wWeight, pDnsRecord->Data.SRV.wPort, zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp))); break; default: break; } zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); pDnsRecord = pDnsRecord->pNext; zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer)); offset = 0; *buffer = '\0'; } #else /* not _WINDOWS */ #if defined(HAVE_RES_NINIT) && !defined(_AIX) memset(&res_state_local, 0, sizeof(res_state_local)); if (-1 == res_ninit(&res_state_local)) /* initialize always, settings might have changed */ #else if (-1 == res_init()) /* initialize always, settings might have changed */ #endif { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize DNS subsystem: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } #if defined(HAVE_RES_NINIT) && !defined(_AIX) if (-1 == (res = res_nmkquery(&res_state_local, QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)))) #else if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)))) #endif { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot create DNS query: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } if (NULL != ip && '\0' != *ip && AF_INET == ip_type) { if (0 == inet_aton(ip, &inaddr)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IP address.")); return SYSINFO_RET_FAIL; } #if defined(HAVE_RES_NINIT) && !defined(_AIX) res_state_local.nsaddr_list[0].sin_addr = inaddr; res_state_local.nsaddr_list[0].sin_family = AF_INET; res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); res_state_local.nscount = 1; #else /* thread-unsafe resolver API */ memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in)); saved_nscount = _res.nscount; _res.nsaddr_list[0].sin_addr = inaddr; _res.nsaddr_list[0].sin_family = AF_INET; _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); _res.nscount = 1; #endif } else if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type) { if (0 == inet_pton(ip_type, ip, &in6addr)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IPv6 address.")); return SYSINFO_RET_FAIL; } memset(&sockaddrin6, '\0', sizeof(sockaddrin6)); #if defined(HAVE_RES_SIN6_LEN) sockaddrin6.sin6_len = sizeof(sockaddrin6); #endif sockaddrin6.sin6_family = AF_INET6; sockaddrin6.sin6_addr = in6addr; sockaddrin6.sin6_port = htons(ZBX_DEFAULT_DNS_PORT); #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) memset(&res_state_local.nsaddr_list[0], '\0', sizeof(res_state_local.nsaddr_list[0])); # ifdef HAVE_RES_U_EXT /* Linux */ saved_ns6 = res_state_local._u._ext.nsaddrs[0]; res_state_local._u._ext.nsaddrs[0] = &sockaddrin6; res_state_local._u._ext.nssocks[0] = -1; res_state_local._u._ext.nscount6 = 1; /* CentOS */ # elif HAVE_RES_U_EXT_EXT /* BSD */ if (NULL != res_state_local._u._ext.ext) memcpy(res_state_local._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6)); res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); # endif res_state_local.nscount = 1; #else memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in)); saved_nscount = _res.nscount; # if defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT) || defined(HAVE_RES_EXT_EXT) memset(&_res.nsaddr_list[0], '\0', sizeof(_res.nsaddr_list[0])); _res.nscount = 1; # endif # if defined(HAVE_RES_U_EXT) /* thread-unsafe resolver API /Linux/ */ saved_nscount6 = _res._u._ext.nscount6; saved_ns6 = _res._u._ext.nsaddrs[0]; save_nssocks = _res._u._ext.nssocks[0]; _res._u._ext.nsaddrs[0] = &sockaddrin6; _res._u._ext.nssocks[0] = -1; _res._u._ext.nscount6 = 1; # elif defined(HAVE_RES_U_EXT_EXT) /* thread-unsafe resolver API /BSD/ */ memcpy(&saved_ns6, _res._u._ext.ext, sizeof(saved_ns6)); _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); if (NULL != _res._u._ext.ext) memcpy(_res._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6)); # elif defined(HAVE_RES_EXT_EXT) /* thread-unsafe resolver API /AIX/ */ memcpy(&saved_ns6, &(_res._ext.ext.nsaddrs[0]), sizeof(saved_ns6)); memcpy(&_res._ext.ext.nsaddrs[0], &sockaddrin6, sizeof(sockaddrin6)); # endif /* #if defined(HAVE_RES_U_EXT) */ #endif /* #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) */ } #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) if (0 != use_tcp) res_state_local.options |= RES_USEVC; res_state_local.retrans = retrans; res_state_local.retry = retry; res = res_nsend(&res_state_local, buf, res, answer.buffer, sizeof(answer.buffer)); # ifdef HAVE_RES_U_EXT /* Linux */ if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type) res_state_local._u._ext.nsaddrs[0] = saved_ns6; # endif # ifdef HAVE_RES_NDESTROY res_ndestroy(&res_state_local); # else res_nclose(&res_state_local); # endif #else /* thread-unsafe resolver API */ saved_options = _res.options; saved_retrans = _res.retrans; saved_retry = _res.retry; if (0 != use_tcp) _res.options |= RES_USEVC; _res.retrans = retrans; _res.retry = retry; res = res_send(buf, res, answer.buffer, sizeof(answer.buffer)); _res.options = saved_options; _res.retrans = saved_retrans; _res.retry = saved_retry; if (NULL != ip && '\0' != *ip) { if (AF_INET6 == ip_type) { # if defined(HAVE_RES_U_EXT) /* Linux */ _res._u._ext.nsaddrs[0] = saved_ns6; _res._u._ext.nssocks[0] = save_nssocks; _res._u._ext.nscount6 = saved_nscount6; # elif defined(HAVE_RES_U_EXT_EXT) /* BSD */ if (NULL != _res._u._ext.ext) memcpy(_res._u._ext.ext, &saved_ns6, sizeof(saved_ns6)); # elif defined(HAVE_RES_EXT_EXT) /* AIX */ memcpy(&_res._ext.ext.nsaddrs[0], &saved_ns6, sizeof(saved_ns6)); # endif } memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in)); _res.nscount = saved_nscount; } #endif hp = (HEADER *)answer.buffer; if (1 == short_answer) { SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1); return SYSINFO_RET_OK; } if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query.")); return SYSINFO_RET_FAIL; } msg_end = answer.buffer + res; num_answers = ntohs(answer.h.ancount); num_query = ntohs(answer.h.qdcount); msg_ptr = answer.buffer + HFIXEDSZ; zbx_vector_str_create(&answers); /* skipping query records */ for (; 0 < num_query && msg_ptr < msg_end; num_query--) msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ; for (; 0 < num_answers && msg_ptr < msg_end; num_answers--) { if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); ret = SYSINFO_RET_FAIL; goto clean; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name); GETSHORT(q_type, msg_ptr); GETSHORT(q_class, msg_ptr); msg_ptr += INT32SZ; /* skipping TTL */ GETSHORT(q_len, msg_ptr); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type)); switch (q_type) { case T_A: switch (q_class) { case C_IN: case C_HS: memcpy(&inaddr, msg_ptr, INADDRSZ); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; default: ; } msg_ptr += q_len; break; case T_AAAA: switch (q_class) { case C_IN: case C_HS: memcpy(&in6addr, msg_ptr, IN6ADDRSZ); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp))); break; default: ; } msg_ptr += q_len; break; case T_NS: case T_CNAME: case T_MB: case T_MD: case T_MF: case T_MG: case T_MR: case T_PTR: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_MX: GETSHORT(value, msg_ptr); /* preference */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* exchange */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_SOA: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* source host */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* administrator */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); GETLONG(value, msg_ptr); /* serial number */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* refresh time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* retry time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* expire time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* minimum TTL */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len); msg_ptr += q_len; break; case T_WKS: if (INT32SZ + 1 > q_len) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } p = msg_ptr + q_len; memcpy(&inaddr, msg_ptr, INADDRSZ); msg_ptr += INT32SZ; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); if (NULL != (pr = getprotobynumber(*msg_ptr))) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr); msg_ptr++; n = 0; while (msg_ptr < p) { c = *msg_ptr++; do { if (0 != (c & 0200)) { s = getservbyport((int)htons(n), pr ? pr->p_name : NULL); if (NULL != s) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n); } c <<= 1; } while (0 != (++n & 07)); } break; case T_HINFO: p = msg_ptr + q_len; c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } if (msg_ptr < p) { c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } } break; case T_MINFO: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox responsible for mailing lists */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox for error messages */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); p = msg_ptr + q_len; while (msg_ptr < p) { for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++); } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: GETSHORT(value, msg_ptr); /* priority */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* weight */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* port */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* target */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; default: msg_ptr += q_len; break; } zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer)); offset = 0; *buffer = '\0'; } #endif /* _WINDOWS */ zbx_vector_str_sort(&answers, ZBX_DEFAULT_STR_COMPARE_FUNC); for (i = 0; i < answers.values_num; i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s", answers.values[i]); if (0 != offset) buffer[--offset] = '\0'; SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer)); ret = SYSINFO_RET_OK; clean: zbx_vector_str_clear_ext(&answers, zbx_str_free); zbx_vector_str_destroy(&answers); #ifdef _WINDOWS clean_dns: if (DNS_RCODE_NOERROR == res) DnsRecordListFree(pQueryResults, DnsFreeRecordList); #endif return ret; #else /* both HAVE_RES_QUERY and _WINDOWS not defined */ return SYSINFO_RET_FAIL; #endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */ }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char *procname, *proccomm, *param; double memsize = -1; int pgsize = getpagesize(); int proccount = 0, do_task; pid_t curr_pid = getpid(); if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information.")); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) /* default parameter */ do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { strscpy(filename, "/proc/"); zbx_strlcat(filename, entries->d_name, MAX_STRING_LEN); if (0 == zbx_stat(filename, &buf)) { proc = open(filename, O_RDONLY); if (-1 == proc) goto lbl_skip_procces; if (-1 == ioctl(proc, PIOCPSINFO, &psinfo)) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc.mem[zabbix_agentd]. */ if (psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if (NULL != procname && '\0' != *procname) if (0 == strcmp(procname, psinfo.pr_fname)) goto lbl_skip_procces; if (NULL != usrinfo) if (usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if (NULL != proccomm && '\0' != *proccomm) if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) goto lbl_skip_procces; proccount++; if (0 > memsize) /* first initialization */ { memsize = (double)(psinfo.pr_rssize * pgsize); } else { if (ZBX_DO_MAX == do_task) memsize = MAX(memsize, (double)(psinfo.pr_rssize * pgsize)); else if (ZBX_DO_MIN == do_task) memsize = MIN(memsize, (double)(psinfo.pr_rssize * pgsize)); else /* SUM */ memsize += (double)(psinfo.pr_rssize * pgsize); } lbl_skip_procces: if (-1 != proc) close(proc); } } closedir(dir); if (0 > memsize) { /* incorrect process name */ memsize = 0; } if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0 : memsize / (double)proccount); else SET_UI64_RESULT(result, memsize); return SYSINFO_RET_OK; }
int SYSTEM_LOCALTIME(AGENT_REQUEST *request, AGENT_RESULT *result) { char *type, buf[32]; struct tm *tm; size_t offset; int gmtoff, ms; unsigned short h, m; #ifdef _WINDOWS struct _timeb tv; #else struct timeval tv; struct timezone tz; #endif if (1 < request->nparam) return SYSINFO_RET_FAIL; type = get_rparam(request, 0); if (NULL == type || '\0' == *type || 0 == strcmp(type, "utc")) { SET_UI64_RESULT(result, time(NULL)); } else if (0 == strcmp(type, "local")) { #ifdef _WINDOWS _ftime(&tv); tm = localtime(&tv.time); ms = tv.millitm; #else gettimeofday(&tv, &tz); tm = localtime(&tv.tv_sec); ms = (int)(tv.tv_usec / 1000); #endif offset = zbx_snprintf(buf, sizeof(buf), "%04d-%02d-%02d,%02d:%02d:%02d.%03d,", 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, ms); /* timezone offset */ #if defined(HAVE_TM_TM_GMTOFF) gmtoff = tm->tm_gmtoff; #else gmtoff = -timezone; #endif #ifdef _WINDOWS if (0 < tm->tm_isdst) /* daylight saving time */ gmtoff += SEC_PER_HOUR; /* assume DST is one hour */ #endif h = (unsigned short)(abs(gmtoff) / SEC_PER_HOUR); m = (unsigned short)((abs(gmtoff) - h * SEC_PER_HOUR) / SEC_PER_MIN); if (0 <= gmtoff) offset += zbx_snprintf(buf + offset, sizeof(buf) - offset, "+"); else offset += zbx_snprintf(buf + offset, sizeof(buf) - offset, "-"); offset += zbx_snprintf(buf + offset, sizeof(buf) - offset, "%02d:%02d", (int)h, (int)m); SET_STR_RESULT(result, strdup(buf)); } else return SYSINFO_RET_FAIL; return SYSINFO_RET_OK; }
/* * build_activity_clause takes agent request parameters for an item key which * targets the pg_stat_actity table and creates an SQL clause to filter * results. * * This function should be reused for all items which query the pg_stat_activity * table. * * request is the agent request containing the user parameters. * buf is the character buffer to which the clause is written. * params is a pointer to a PGparams type which stores query parameters. * has_clause determines if the the clause starts with "WITH" or "AND". * * Returns non-zero on success. */ static int build_activity_clause(const AGENT_REQUEST *request, char *buf, PGparams *params, int has_clause) { const char *__function_name = "build_activity_clause"; // Function name for log file int i = 0; char *param = NULL; char *clause = (0 < has_clause ? PG_AND : PG_WHERE); int pgi = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); // iterate over the available parameters for(i = 0; i < 4; i++) { param = get_rparam(request, PARAM_FIRST + i); if(!strisnull(param)) { switch(i) { case 0: // <database> *params = param_append(*params, param); if(is_oid(param)) zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s datid = $%i", clause, ++pgi); else zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s datname = $%i", clause, ++pgi); break; case 1: // <user> *params = param_append(*params, param); if(is_oid(param)) zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s usesysid = $%i", clause, ++pgi); else zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s usename = $%i", clause, ++pgi); break; case 2: // <client> *params = param_append(*params, param); if(is_valid_ip(param)) zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s client_addr = $%i::inet", clause, ++pgi); else // requires v9.1+ zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s client_hostname = $%i", clause, ++pgi); break; case 3: // <waiting> if(0 == strncmp("true\0", param, 5)) { zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s waiting = TRUE", clause); } else if(0 == strncmp("false\0", param, 6)) { zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s waiting = FALSE", clause); } else { zabbix_log(LOG_LEVEL_ERR, "Unsupported parameter value: \"%s\" in %s", param, request->key); return 0; } break; } buf += strlen(buf); clause = PG_AND; } } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return 1; }
/****************************************************************************** * * * Function: get_value_aggregate * * * * Purpose: retrieve data from Zabbix server (aggregate items) * * * * Parameters: item - item we are interested in * * * * Return value: SUCCEED - data successfully retrieved and stored in result * * and result_str (as string) * * NOTSUPPORTED - requested item is not supported * * * * Author: Alexei Vladishev * * * ******************************************************************************/ int get_value_aggregate(DC_ITEM *item, AGENT_RESULT *result) { const char *__function_name = "get_value_aggregate"; AGENT_REQUEST request; int ret = NOTSUPPORTED; const char *tmp, *groups, *itemkey, *funcp = NULL; int grp_func, item_func, params_num; zabbix_log(LOG_LEVEL_DEBUG, "In %s() key:'%s'", __function_name, item->key_orig); init_request(&request); if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Value type must be Numeric for aggregate items")); goto out; } if (SUCCEED != parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; } if (0 == strcmp(get_rkey(&request), "grpmin")) { grp_func = ZBX_VALUE_FUNC_MIN; } else if (0 == strcmp(get_rkey(&request), "grpavg")) { grp_func = ZBX_VALUE_FUNC_AVG; } else if (0 == strcmp(get_rkey(&request), "grpmax")) { grp_func = ZBX_VALUE_FUNC_MAX; } else if (0 == strcmp(get_rkey(&request), "grpsum")) { grp_func = ZBX_VALUE_FUNC_SUM; } else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key.")); goto out; } params_num = get_rparams_num(&request); if (3 > params_num || params_num > 4) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters.")); goto out; } groups = get_rparam(&request, 0); itemkey = get_rparam(&request, 1); tmp = get_rparam(&request, 2); if (0 == strcmp(tmp, "min")) item_func = ZBX_VALUE_FUNC_MIN; else if (0 == strcmp(tmp, "avg")) item_func = ZBX_VALUE_FUNC_AVG; else if (0 == strcmp(tmp, "max")) item_func = ZBX_VALUE_FUNC_MAX; else if (0 == strcmp(tmp, "sum")) item_func = ZBX_VALUE_FUNC_SUM; else if (0 == strcmp(tmp, "count")) item_func = ZBX_VALUE_FUNC_COUNT; else if (0 == strcmp(tmp, "last")) item_func = ZBX_VALUE_FUNC_LAST; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); goto out; } if (4 == params_num) { funcp = get_rparam(&request, 3); } else if (3 == params_num && ZBX_VALUE_FUNC_LAST != item_func) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters.")); goto out; } if (SUCCEED != evaluate_aggregate(item, result, grp_func, groups, itemkey, item_func, funcp)) goto out; ret = SUCCEED; out: free_request(&request); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/* * Custom key pg.table.children.discovery * * Returns all known child tables for the specified parent table * * Parameter [0-4]: <host,port,db,user,passwd> * * Parameter[table]: Parent table * * Returns: * { * "data":[ * { * "{#OID}":"12345", * "{#SCHEMA}":"public", * "{#TABLE}":"MyTable"}]} */ int PG_TABLE_CHILDREN_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result) { int ret = SYSINFO_RET_FAIL; // Request result code const char *__function_name = "PG_TABLE_CHILDREN_DISCOVERY"; // Function name for log file struct zbx_json j; // JSON response for discovery rule PGconn *conn = NULL; PGresult *res = NULL; char *tablename = NULL; char query[MAX_STRING_LEN]; int i = 0, count = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); // Parse parameters tablename = get_rparam(request, PARAM_FIRST); if(NULL == tablename || '\0' == *tablename) { zabbix_log(LOG_LEVEL_ERR, "No table name specified in %s()", __function_name); goto out; } // Build query zbx_snprintf(query, sizeof(query), PGSQL_DISCOVER_TABLE_CHILDREN, tablename); // Connect to PostreSQL if(NULL == (conn = pg_connect(request))) goto out; // Execute a query res = PQexec(conn, query); if(PQresultStatus(res) != PGRES_TUPLES_OK) { zabbix_log(LOG_LEVEL_ERR, "Failed to execute PostgreSQL query in %s() with: %s", __function_name, PQresultErrorMessage(res)); goto out; } if(0 == (count = PQntuples(res))) { zabbix_log(LOG_LEVEL_DEBUG, "No results returned for query \"%s\" in %s()", query, __function_name); } // Create JSON array of discovered objects zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); for(i = 0; i < count; i++) { zbx_json_addobject(&j, NULL); zbx_json_addstring(&j, "{#OID}", PQgetvalue(res, i, 0), ZBX_JSON_TYPE_STRING); zbx_json_addstring(&j, "{#TABLE}", PQgetvalue(res, i, 1), ZBX_JSON_TYPE_STRING); zbx_json_addstring(&j, "{#SCHEMA}", PQgetvalue(res, i, 2), ZBX_JSON_TYPE_STRING); zbx_json_close(&j); } // Finalize JSON response zbx_json_close(&j); SET_STR_RESULT(result, strdup(j.buffer)); zbx_json_free(&j); ret = SYSINFO_RET_OK; out: PQclear(res); PQfinish(conn); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return ret; }
int SYSTEM_HOSTNAME(AGENT_REQUEST *request, AGENT_RESULT *result) { DWORD dwSize = 256; wchar_t computerName[256]; char *type, buffer[256]; int netbios, rc; WSADATA sockInfo; if (1 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } type = get_rparam(request, 0); if (NULL == type || '\0' == *type || 0 == strcmp(type, "netbios")) netbios = 1; else if (0 == strcmp(type, "host")) netbios = 0; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } if (1 == netbios) { /* Buffer size is chosen large enough to contain any DNS name, not just MAX_COMPUTERNAME_LENGTH + 1 */ /* characters. MAX_COMPUTERNAME_LENGTH is usually less than 32, but it varies among systems, so we */ /* cannot use the constant in a precompiled Windows agent, which is expected to work on any system. */ if (0 == GetComputerName(computerName, &dwSize)) { zabbix_log(LOG_LEVEL_ERR, "GetComputerName() failed: %s", strerror_from_system(GetLastError())); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain computer name: %s", strerror_from_system(GetLastError()))); return SYSINFO_RET_FAIL; } SET_STR_RESULT(result, zbx_unicode_to_utf8(computerName)); } else { if (0 != (rc = WSAStartup(MAKEWORD(2, 2), &sockInfo))) { zabbix_log(LOG_LEVEL_ERR, "WSAStartup() failed: %s", strerror_from_system(rc)); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize Winsock DLL: %s", strerror_from_system(rc))); return SYSINFO_RET_FAIL; } else if (SUCCEED != gethostname(buffer, sizeof(buffer))) { zabbix_log(LOG_LEVEL_ERR, "gethostname() failed: %s", strerror_from_system(WSAGetLastError())); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain host name: %s", strerror_from_system(WSAGetLastError()))); return SYSINFO_RET_FAIL; } SET_STR_RESULT(result, zbx_strdup(NULL, buffer)); } return SYSINFO_RET_OK; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { #define ZBX_VSIZE 0 #define ZBX_RSS 1 #define ZBX_PMEM 2 #define ZBX_SIZE 3 #define ZBX_DSIZE 4 #define ZBX_TSIZE 5 #define ZBX_SDSIZE 6 #define ZBX_DRSS 7 #define ZBX_TRSS 8 /* The pi_???_l2psize fields are described as: log2 of a proc's ??? pg sz */ /* Basically it's bits per page, so define 12 bits (4kb) for earlier AIX */ /* versions that do not support those fields. */ #ifdef _AIX61 # define ZBX_L2PSIZE(field) field #else # define ZBX_L2PSIZE(field) 12 #endif char *param, *procname, *proccomm, *mem_type = NULL; struct passwd *usrinfo; struct procentry64 procentry; pid_t pid = 0; int do_task, mem_type_code, proccount = 0, invalid_user = 0; zbx_uint64_t mem_size = 0, byte_value = 0; double pct_size = 0.0, pct_value = 0.0; if (5 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) invalid_user = 1; } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); mem_type = get_rparam(request, 4); if (NULL == mem_type || '\0' == *mem_type || 0 == strcmp(mem_type, "vsize")) { mem_type_code = ZBX_VSIZE; /* virtual memory size */ } else if (0 == strcmp(mem_type, "rss")) { mem_type_code = ZBX_RSS; /* resident set size */ } else if (0 == strcmp(mem_type, "pmem")) { mem_type_code = ZBX_PMEM; /* percentage of real memory used by process */ } else if (0 == strcmp(mem_type, "size")) { mem_type_code = ZBX_SIZE; /* size of process (code + data) */ } else if (0 == strcmp(mem_type, "dsize")) { mem_type_code = ZBX_DSIZE; /* data size */ } else if (0 == strcmp(mem_type, "tsize")) { mem_type_code = ZBX_TSIZE; /* text size */ } else if (0 == strcmp(mem_type, "sdsize")) { mem_type_code = ZBX_SDSIZE; /* data size from shared library */ } else if (0 == strcmp(mem_type, "drss")) { mem_type_code = ZBX_DRSS; /* data resident set size */ } else if (0 == strcmp(mem_type, "trss")) { mem_type_code = ZBX_TRSS; /* text resident set size */ } else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter.")); return SYSINFO_RET_FAIL; } if (1 == invalid_user) /* handle 0 for non-existent user after all parameters have been parsed and validated */ goto out; while (0 < getprocs64(&procentry, (int)sizeof(struct procentry64), NULL, 0, &pid, 1)) { if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, procentry.pi_comm)) continue; if (NULL != usrinfo && usrinfo->pw_uid != procentry.pi_uid) continue; if (NULL != proccomm && '\0' != *proccomm && SUCCEED != check_procargs(&procentry, proccomm)) continue; switch (mem_type_code) { case ZBX_VSIZE: /* historically default proc.mem[] on AIX */ byte_value = (zbx_uint64_t)procentry.pi_size << 12; /* number of pages to bytes */ break; case ZBX_RSS: /* try to be compatible with "ps -o rssize" */ byte_value = ((zbx_uint64_t)procentry.pi_drss << ZBX_L2PSIZE(procentry.pi_data_l2psize)) + ((zbx_uint64_t)procentry.pi_trss << ZBX_L2PSIZE(procentry.pi_text_l2psize)); break; case ZBX_PMEM: /* try to be compatible with "ps -o pmem" */ pct_value = procentry.pi_prm; break; case ZBX_SIZE: /* try to be compatible with "ps gvw" SIZE column */ byte_value = (zbx_uint64_t)procentry.pi_dvm << ZBX_L2PSIZE(procentry.pi_data_l2psize); break; case ZBX_DSIZE: byte_value = procentry.pi_dsize; break; case ZBX_TSIZE: /* try to be compatible with "ps gvw" TSIZ column */ byte_value = procentry.pi_tsize; break; case ZBX_SDSIZE: byte_value = procentry.pi_sdsize; break; case ZBX_DRSS: byte_value = (zbx_uint64_t)procentry.pi_drss << ZBX_L2PSIZE(procentry.pi_data_l2psize); break; case ZBX_TRSS: byte_value = (zbx_uint64_t)procentry.pi_trss << ZBX_L2PSIZE(procentry.pi_text_l2psize); break; } if (ZBX_PMEM != mem_type_code) { if (0 != proccount++) { if (ZBX_DO_MAX == do_task) mem_size = MAX(mem_size, byte_value); else if (ZBX_DO_MIN == do_task) mem_size = MIN(mem_size, byte_value); else mem_size += byte_value; } else mem_size = byte_value; } else { if (0 != proccount++) { if (ZBX_DO_MAX == do_task) pct_size = MAX(pct_size, pct_value); else if (ZBX_DO_MIN == do_task) pct_size = MIN(pct_size, pct_value); else pct_size += pct_value; } else pct_size = pct_value; } } out: if (ZBX_PMEM != mem_type_code) { if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0.0 : (double)mem_size / (double)proccount); else SET_UI64_RESULT(result, mem_size); } else { if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0.0 : pct_size / (double)proccount); else SET_DBL_RESULT(result, pct_size); } return SYSINFO_RET_OK; #undef ZBX_L2PSIZE #undef ZBX_SIZE #undef ZBX_RSS #undef ZBX_VSIZE #undef ZBX_PMEM #undef ZBX_TSIZE #undef ZBX_DSIZE #undef ZBX_SDSIZE #undef ZBX_DRSS #undef ZBX_TRSS }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { char *param, *procname, *proccomm; struct passwd *usrinfo; struct procentry64 procentry; pid_t pid = 0; int proccount = 0, invalid_user = 0, zbx_proc_stat; if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) invalid_user = 1; } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = ZBX_PROC_STAT_ALL; else if (0 == strcmp(param, "run")) zbx_proc_stat = ZBX_PROC_STAT_RUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = ZBX_PROC_STAT_SLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = ZBX_PROC_STAT_ZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (1 == invalid_user) /* handle 0 for non-existent user after all parameters have been parsed and validated */ goto out; while (0 < getprocs64(&procentry, (int)sizeof(struct procentry64), NULL, 0, &pid, 1)) { if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, procentry.pi_comm)) continue; if (NULL != usrinfo && usrinfo->pw_uid != procentry.pi_uid) continue; if (SUCCEED != check_procstate(&procentry, zbx_proc_stat)) continue; if (NULL != proccomm && '\0' != *proccomm && SUCCEED != check_procargs(&procentry, proccomm)) continue; proccount++; } out: SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) { int sts; char *metric[] = { request->key + strlen(ZBX_PCP_METRIC_PREFIX) }; char *inst; pmID pmid[1]; pmDesc desc[1]; pmResult *rp; pmAtomValue atom; int iid = 0; int i; /* Parameter is the instance. */ switch(request->nparam) { case 0: inst = NULL; break; case 1: inst = get_rparam(request, 0); break; default: SET_MSG_RESULT(result, strdup("Extraneous instance specification.")); return SYSINFO_RET_FAIL; break; } /* Preparations and sanity checks. */ sts = pmLookupName(1, metric, pmid); if (sts < 0) return SYSINFO_RET_FAIL; sts = pmLookupDesc(pmid[0], desc); if (sts < 0) return SYSINFO_RET_FAIL; if (inst != NULL && desc[0].indom == PM_INDOM_NULL) { SET_MSG_RESULT(result, strdup("Extraneous instance specification.")); return SYSINFO_RET_FAIL; } if ((inst == NULL && desc[0].indom != PM_INDOM_NULL) || (request->nparam == 1 && !strlen(inst))) { SET_MSG_RESULT(result, strdup("Missing instance specification.")); return SYSINFO_RET_FAIL; } if (desc[0].indom != PM_INDOM_NULL) { iid = pmLookupInDom(desc[0].indom, inst); if (iid < 0) { SET_MSG_RESULT(result, strdup("Instance not available.")); return SYSINFO_RET_FAIL; } } /* Fetch the metric values. */ sts = pmFetch(1, pmid, &rp); if (sts < 0) return SYSINFO_RET_FAIL; if (rp->vset[0]->numval < 1) { pmFreeResult(rp); SET_MSG_RESULT(result, strdup("No value available.")); return SYSINFO_RET_FAIL; } /* Locate the correct instance. */ for (i = 0; desc[0].indom != PM_INDOM_NULL && i < rp->vset[0]->numval; i++) { if (rp->vset[0]->vlist[i].inst == iid) { break; } } if (i == rp->vset[0]->numval) { pmFreeResult(rp); return SYSINFO_RET_FAIL; } /* Extract the wanted value. */ sts = pmExtractValue(rp->vset[0]->valfmt, &rp->vset[0]->vlist[i], desc[0].type, &atom, desc[0].type); pmFreeResult(rp); if (sts < 0) return SYSINFO_RET_FAIL; /* Hand it to the caller. */ switch(desc[0].type) { case PM_TYPE_32: SET_UI64_RESULT(result, atom.l); break; case PM_TYPE_U32: SET_UI64_RESULT(result, atom.ul); break; case PM_TYPE_64: SET_UI64_RESULT(result, atom.ll); break; case PM_TYPE_U64: SET_UI64_RESULT(result, atom.ull); break; case PM_TYPE_FLOAT: SET_DBL_RESULT(result, atom.f); break; case PM_TYPE_DOUBLE: SET_DBL_RESULT(result, atom.d); break; case PM_TYPE_STRING: SET_STR_RESULT(result, strdup(atom.cp)); break; default: SET_MSG_RESULT(result, strdup("Unsupported metric value type.")); return SYSINFO_RET_FAIL; break; } /* Success. */ return SYSINFO_RET_OK; }
static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer) { #if defined(HAVE_RES_QUERY) || defined(_WINDOWS) size_t offset = 0; int res, type, retrans, retry, i, ret = SYSINFO_RET_FAIL; char *ip, zone[MAX_STRING_LEN], buffer[MAX_STRING_LEN], *zone_str, *param; struct in_addr inaddr; #ifndef _WINDOWS int saved_nscount, saved_retrans, saved_retry; struct sockaddr_in saved_ns; #endif typedef struct { char *name; int type; } resolv_querytype_t; static const resolv_querytype_t qt[] = { {"ANY", T_ANY}, {"A", T_A}, {"NS", T_NS}, {"MD", T_MD}, {"MF", T_MF}, {"CNAME", T_CNAME}, {"SOA", T_SOA}, {"MB", T_MB}, {"MG", T_MG}, {"MR", T_MR}, {"NULL", T_NULL}, #ifndef _WINDOWS {"WKS", T_WKS}, #endif {"PTR", T_PTR}, {"HINFO", T_HINFO}, {"MINFO", T_MINFO}, {"MX", T_MX}, {"TXT", T_TXT}, {"SRV", T_SRV}, {NULL} }; #ifdef _WINDOWS PDNS_RECORD pQueryResults, pDnsRecord; wchar_t *wzone; char tmp2[MAX_STRING_LEN], tmp[MAX_STRING_LEN]; #else char *name; unsigned char *msg_end, *msg_ptr, *p; int num_answers, num_query, q_type, q_class, q_len, value, c, n; struct servent *s; HEADER *hp; struct protoent *pr; #if PACKETSZ > 1024 unsigned char buf[PACKETSZ]; #else unsigned char buf[1024]; #endif typedef union { HEADER h; #if defined(NS_PACKETSZ) unsigned char buffer[NS_PACKETSZ]; #elif defined(PACKETSZ) unsigned char buffer[PACKETSZ]; #else unsigned char buffer[512]; #endif } answer_t; answer_t answer; #endif /* _WINDOWS */ *buffer = '\0'; if (5 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } ip = get_rparam(request, 0); zone_str = get_rparam(request, 1); if (NULL == zone_str || '\0' == *zone_str) strscpy(zone, "zabbix.com"); else strscpy(zone, zone_str); param = get_rparam(request, 2); if (NULL == param || '\0' == *param) type = T_SOA; else { for (i = 0; NULL != qt[i].name; i++) { if (0 == strcasecmp(qt[i].name, param)) { type = qt[i].type; break; } } if (NULL == qt[i].name) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } } param = get_rparam(request, 3); if (NULL == param || '\0' == *param) retrans = 1; else if (SUCCEED != is_uint31(param, &retrans) || 0 == retrans) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter.")); return SYSINFO_RET_FAIL; } param = get_rparam(request, 4); if (NULL == param || '\0' == *param) retry = 2; else if (SUCCEED != is_uint31(param, &retry) || 0 == retry) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter.")); return SYSINFO_RET_FAIL; } #ifdef _WINDOWS wzone = zbx_utf8_to_unicode(zone); res = DnsQuery(wzone, type, DNS_QUERY_STANDARD, NULL, &pQueryResults, NULL); zbx_free(wzone); if (1 == short_answer) { SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1); ret = SYSINFO_RET_OK; goto clean; } if (DNS_RCODE_NOERROR != res) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot perform DNS query: [%d]", res)); return SYSINFO_RET_FAIL; } pDnsRecord = pQueryResults; while (NULL != pDnsRecord) { if (DnsSectionAnswer != pDnsRecord->Flags.S.Section) { pDnsRecord = pDnsRecord->pNext; continue; } if (NULL == pDnsRecord->pName) goto clean; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp))); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(pDnsRecord->wType)); switch (pDnsRecord->wType) { case T_A: inaddr.s_addr = pDnsRecord->Data.A.IpAddress; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; case T_NS: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp))); break; case T_MD: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp))); break; case T_MF: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp))); break; case T_CNAME: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp))); break; case T_SOA: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu", zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)), pDnsRecord->Data.SOA.dwSerialNo, pDnsRecord->Data.SOA.dwRefresh, pDnsRecord->Data.SOA.dwRetry, pDnsRecord->Data.SOA.dwExpire, pDnsRecord->Data.SOA.dwDefaultTtl); break; case T_MB: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp))); break; case T_MG: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp))); break; case T_MR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp))); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu", pDnsRecord->Data.Null.dwByteCount); break; case T_PTR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp))); break; case T_HINFO: for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"", zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp))); break; case T_MINFO: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2))); break; case T_MX: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s", pDnsRecord->Data.MX.wPreference, zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp))); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ", zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp))); if (0 < i) offset -= 1; /* remove the trailing space */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s", pDnsRecord->Data.SRV.wPriority, pDnsRecord->Data.SRV.wWeight, pDnsRecord->Data.SRV.wPort, zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp))); break; default: break; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); pDnsRecord = pDnsRecord->pNext; } #else /* not _WINDOWS */ if (-1 == res_init()) /* initialize always, settings might have changed */ { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize DNS subsystem: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot create DNS query: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } if (NULL != ip && '\0' != *ip) { if (0 == inet_aton(ip, &inaddr)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IP address.")); return SYSINFO_RET_FAIL; } memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in)); saved_nscount = _res.nscount; _res.nsaddr_list[0].sin_addr = inaddr; _res.nsaddr_list[0].sin_family = AF_INET; _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); _res.nscount = 1; } saved_retrans = _res.retrans; saved_retry = _res.retry; _res.retrans = retrans; _res.retry = retry; res = res_send(buf, res, answer.buffer, sizeof(answer.buffer)); _res.retrans = saved_retrans; _res.retry = saved_retry; if (NULL != ip && '\0' != *ip) { memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in)); _res.nscount = saved_nscount; } hp = (HEADER *)answer.buffer; if (1 == short_answer) { SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1); return SYSINFO_RET_OK; } if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query.")); return SYSINFO_RET_FAIL; } msg_end = answer.buffer + res; num_answers = ntohs(answer.h.ancount); num_query = ntohs(answer.h.qdcount); msg_ptr = answer.buffer + HFIXEDSZ; /* skipping query records */ for (; 0 < num_query && msg_ptr < msg_end; num_query--) msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ; for (; 0 < num_answers && msg_ptr < msg_end; num_answers--) { if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name); GETSHORT(q_type, msg_ptr); GETSHORT(q_class, msg_ptr); msg_ptr += INT32SZ; /* skipping TTL */ GETSHORT(q_len, msg_ptr); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type)); switch (q_type) { case T_A: switch (q_class) { case C_IN: case C_HS: memcpy(&inaddr, msg_ptr, INADDRSZ); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; default: ; } msg_ptr += q_len; break; case T_NS: case T_CNAME: case T_MB: case T_MD: case T_MF: case T_MG: case T_MR: case T_PTR: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_MX: GETSHORT(value, msg_ptr); /* preference */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* exchange */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_SOA: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* source host */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* administrator */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); GETLONG(value, msg_ptr); /* serial number */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* refresh time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* retry time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* expire time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* minimum TTL */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len); msg_ptr += q_len; break; case T_WKS: if (INT32SZ + 1 > q_len) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } p = msg_ptr + q_len; memcpy(&inaddr, msg_ptr, INADDRSZ); msg_ptr += INT32SZ; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); if (NULL != (pr = getprotobynumber(*msg_ptr))) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr); msg_ptr++; n = 0; while (msg_ptr < p) { c = *msg_ptr++; do { if (0 != (c & 0200)) { s = getservbyport((int)htons(n), pr ? pr->p_name : NULL); if (NULL != s) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n); } c <<= 1; } while (0 != (++n & 07)); } break; case T_HINFO: p = msg_ptr + q_len; c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } if (msg_ptr < p) { c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } } break; case T_MINFO: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox responsible for mailing lists */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox for error messages */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); p = msg_ptr + q_len; while (msg_ptr < p) { for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++); } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: GETSHORT(value, msg_ptr); /* priority */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* weight */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* port */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* target */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; default: msg_ptr += q_len; break; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); } #endif /* _WINDOWS */ if (0 != offset) buffer[--offset] = '\0'; SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer)); ret = SYSINFO_RET_OK; #ifdef _WINDOWS clean: if (DNS_RCODE_NOERROR == res) DnsRecordListFree(pQueryResults, DnsFreeRecordList); #endif return ret; #else /* both HAVE_RES_QUERY and _WINDOWS not defined */ return SYSINFO_RET_FAIL; #endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */ }
int SYSTEM_SWAP_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result) { MEMORYSTATUSEX ms_ex; MEMORYSTATUS ms; zbx_uint64_t real_swap_total, real_swap_avail; char *swapdev, *mode; if (2 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } swapdev = get_rparam(request, 0); mode = get_rparam(request, 1); /* only 'all' parameter supported */ if (NULL != swapdev && '\0' != *swapdev && 0 != strcmp(swapdev, "all")) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } /*************************************************************************** * * * Due to the way Windows API functions report memory metrics, * * it is impossible to accurately retrieve swap (virtual memory) * * sizes as Windows reports the total commit memory which is physical * * memory plus swap file sizes. The only resolution that could be applied * * was calculatively deducting the swap sizes knowing the page and * * physical memory sizes. * * * * While developing this solution, it was found that sometimes (in * * virtualized environments or when page file is disabled) the calculated * * swap values are outside of possible bounds. For example, the available * * swap size may appear to be larger than the total swap memory size of * * the system, or even the calculated swap sizes may result in negative * * values (in system with disabled page file). * * * * Taking these fallacious conditions into account, these calculations * * guarantee that the available swap size is never larger than the total * * available (if it is reported as such, it is lowered to the total * * as there is a higher probability of that number staying consistent * * than the other way around). In case of swap size calculations resulting * * in negative values, the corresponding values are set to 0. * * * * As the result the returned values might not be exactly accurate * * depending on the system and environment, but they ought to be close * * enough. * * * * NB: The reason why GlobalMemoryStatus[Ex] are used is their * * availability on Windows 2000 and later, as opposed to other functions * * of a similar nature (like GetPerformanceInfo) that are not supported * * on some versions of Windows. * * * ***************************************************************************/ if (NULL != zbx_GlobalMemoryStatusEx) { ms_ex.dwLength = sizeof(MEMORYSTATUSEX); zbx_GlobalMemoryStatusEx(&ms_ex); real_swap_total = ms_ex.ullTotalPageFile > ms_ex.ullTotalPhys ? ms_ex.ullTotalPageFile - ms_ex.ullTotalPhys : 0; real_swap_avail = ms_ex.ullAvailPageFile > ms_ex.ullAvailPhys ? ms_ex.ullAvailPageFile - ms_ex.ullAvailPhys : 0; } else { GlobalMemoryStatus(&ms); real_swap_total = ms.dwTotalPageFile > ms.dwTotalPhys ? ms.dwTotalPageFile - ms.dwTotalPhys : 0; real_swap_avail = ms.dwAvailPageFile > ms.dwAvailPhys ? ms.dwAvailPageFile - ms.dwAvailPhys : 0; } if (real_swap_avail > real_swap_total) real_swap_avail = real_swap_total; if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) SET_UI64_RESULT(result, real_swap_total); else if (0 == strcmp(mode, "free")) SET_UI64_RESULT(result, real_swap_avail); else if (0 == strcmp(mode, "pfree")) SET_DBL_RESULT(result, (real_swap_avail / (double)real_swap_total) * 100.0); else if (0 == strcmp(mode, "used")) SET_UI64_RESULT(result, real_swap_total - real_swap_avail); else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } return SYSINFO_RET_OK; }
int SERVICE_INFO(AGENT_REQUEST *request, AGENT_RESULT *result) { QUERY_SERVICE_CONFIG *qsc = NULL; SERVICE_DESCRIPTION *scd = NULL; SERVICE_STATUS status; SC_HANDLE h_mgr, h_srv; DWORD sz = 0; int param_type, i; char *name, *param; wchar_t *wname, service_name[MAX_STRING_LEN]; DWORD max_len_name = MAX_STRING_LEN; if (2 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } name = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL == name || '\0' == *name) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } if (NULL == param || '\0' == *param || 0 == strcmp(param, "state")) /* default second parameter */ param_type = ZBX_SRV_PARAM_STATE; else if (0 == strcmp(param, "displayname")) param_type = ZBX_SRV_PARAM_DISPLAYNAME; else if (0 == strcmp(param, "path")) param_type = ZBX_SRV_PARAM_PATH; else if (0 == strcmp(param, "user")) param_type = ZBX_SRV_PARAM_USER; else if (0 == strcmp(param, "startup")) param_type = ZBX_SRV_PARAM_STARTUP; else if (0 == strcmp(param, "description")) param_type = ZBX_SRV_PARAM_DESCRIPTION; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } if (NULL == (h_mgr = OpenSCManager(NULL, NULL, GENERIC_READ))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain system information.")); return SYSINFO_RET_FAIL; } wname = zbx_utf8_to_unicode(name); h_srv = OpenService(h_mgr, wname, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG); if (NULL == h_srv && 0 != GetServiceKeyName(h_mgr, wname, service_name, &max_len_name)) h_srv = OpenService(h_mgr, service_name, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG); zbx_free(wname); if (NULL == h_srv) { int ret; if (ZBX_SRV_PARAM_STATE == param_type) { SET_UI64_RESULT(result, 255); ret = SYSINFO_RET_OK; } else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot find the specified service.")); ret = SYSINFO_RET_FAIL; } CloseServiceHandle(h_mgr); return ret; } if (ZBX_SRV_PARAM_STATE == param_type) { if (0 != QueryServiceStatus(h_srv, &status)) { for (i = 0; i < ARRSIZE(service_states) && status.dwCurrentState != service_states[i]; i++) ; SET_UI64_RESULT(result, i); } else SET_UI64_RESULT(result, 7); } else if (ZBX_SRV_PARAM_DESCRIPTION == param_type) { QueryServiceConfig2(h_srv, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &sz); if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain service description: %s", strerror_from_system(GetLastError()))); CloseServiceHandle(h_srv); CloseServiceHandle(h_mgr); return SYSINFO_RET_FAIL; } scd = (SERVICE_DESCRIPTION *)zbx_malloc(scd, sz); if (0 == QueryServiceConfig2(h_srv, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)scd, sz, &sz)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain service description: %s", strerror_from_system(GetLastError()))); zbx_free(scd); CloseServiceHandle(h_srv); CloseServiceHandle(h_mgr); return SYSINFO_RET_FAIL; } if (NULL == scd->lpDescription) SET_TEXT_RESULT(result, zbx_strdup(NULL, "")); else SET_TEXT_RESULT(result, zbx_unicode_to_utf8(scd->lpDescription)); zbx_free(scd); } else { QueryServiceConfig(h_srv, NULL, 0, &sz); if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain service configuration: %s", strerror_from_system(GetLastError()))); CloseServiceHandle(h_srv); CloseServiceHandle(h_mgr); return SYSINFO_RET_FAIL; } qsc = (QUERY_SERVICE_CONFIG *)zbx_malloc(qsc, sz); if (0 == QueryServiceConfig(h_srv, qsc, sz, &sz)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain service configuration: %s", strerror_from_system(GetLastError()))); zbx_free(qsc); CloseServiceHandle(h_srv); CloseServiceHandle(h_mgr); return SYSINFO_RET_FAIL; } switch (param_type) { case ZBX_SRV_PARAM_DISPLAYNAME: SET_STR_RESULT(result, zbx_unicode_to_utf8(qsc->lpDisplayName)); break; case ZBX_SRV_PARAM_PATH: SET_STR_RESULT(result, zbx_unicode_to_utf8(qsc->lpBinaryPathName)); break; case ZBX_SRV_PARAM_USER: SET_STR_RESULT(result, zbx_unicode_to_utf8(qsc->lpServiceStartName)); break; case ZBX_SRV_PARAM_STARTUP: if (SERVICE_AUTO_START == qsc->dwStartType) { if (SUCCEED == check_delayed_start(h_srv)) SET_UI64_RESULT(result, 1); else SET_UI64_RESULT(result, 0); } else { for (i = 2; i < ARRSIZE(start_types) && qsc->dwStartType != start_types[i]; i++) ; SET_UI64_RESULT(result, i); } break; } zbx_free(qsc); } CloseServiceHandle(h_srv); CloseServiceHandle(h_mgr); return SYSINFO_RET_OK; }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char *procname, *proccomm, *param; int proccount = 0, zbx_proc_stat; pid_t curr_pid = getpid(); if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information.")); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = -1; else if (0 == strcmp(param, "run")) zbx_proc_stat = PR_SRUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = PR_SSLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = PR_SZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { strscpy(filename, "/proc/"); zbx_strlcat(filename, entries->d_name,MAX_STRING_LEN); if (0 == zbx_stat(filename, &buf)) { proc = open(filename, O_RDONLY); if (-1 == proc) goto lbl_skip_procces; if (-1 == ioctl(proc, PIOCPSINFO, &psinfo)) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc.num[zabbix_agentd]. */ if (psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if (NULL != procname && '\0' != *procname) if (0 != strcmp(procname, psinfo.pr_fname)) goto lbl_skip_procces; if (NULL != usrinfo) if (usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if (-1 != zbx_proc_stat) if (psinfo.pr_sname != zbx_proc_stat) goto lbl_skip_procces; if (NULL != proccomm && '\0' != *proccomm) if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) goto lbl_skip_procces; proccount++; lbl_skip_procces: if (-1 != proc) close(proc); } } closedir(dir); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
int SERVICE_STATE(AGENT_REQUEST *request, AGENT_RESULT *result) { SC_HANDLE mgr, service; char *name; wchar_t *wname; wchar_t service_name[MAX_STRING_LEN]; DWORD max_len_name = MAX_STRING_LEN; int i; SERVICE_STATUS status; if (1 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } name = get_rparam(request, 0); if (NULL == name || '\0' == *name) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } if (NULL == (mgr = OpenSCManager(NULL, NULL, GENERIC_READ))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain system information.")); return SYSINFO_RET_FAIL; } wname = zbx_utf8_to_unicode(name); service = OpenService(mgr, wname, SERVICE_QUERY_STATUS); if (NULL == service && 0 != GetServiceKeyName(mgr, wname, service_name, &max_len_name)) service = OpenService(mgr, service_name, SERVICE_QUERY_STATUS); zbx_free(wname); if (NULL == service) { SET_UI64_RESULT(result, 255); } else { if (0 != QueryServiceStatus(service, &status)) { for (i = 0; i < ARRSIZE(service_states) && status.dwCurrentState != service_states[i]; i++) ; SET_UI64_RESULT(result, i); } else SET_UI64_RESULT(result, 7); CloseServiceHandle(service); } CloseServiceHandle(mgr); return SYSINFO_RET_OK; }
int check_vcenter_vm_discovery(AGENT_REQUEST *request, const char *username, const char *password, AGENT_RESULT *result) { struct zbx_json json_data; int i, k, ret = SYSINFO_RET_FAIL; char *url, *vm_name, *hv_name; zbx_vmware_service_t *service; zbx_vmware_hv_t *hv; zbx_vmware_vm_t *vm; if (1 != request->nparam) return SYSINFO_RET_FAIL; url = get_rparam(request, 0); zbx_vmware_lock(); if (NULL == (service = get_vmware_service(url, username, password, result, &ret))) goto unlock; zbx_json_init(&json_data, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&json_data, ZBX_PROTO_TAG_DATA); for (i = 0; i < service->data->hvs.values_num; i++) { zbx_vmware_cluster_t *cluster = NULL; hv = (zbx_vmware_hv_t *)service->data->hvs.values[i]; if (NULL != hv->clusterid) cluster = cluster_get(&service->data->clusters, hv->clusterid); for (k = 0; k < hv->vms.values_num; k++) { vm = (zbx_vmware_vm_t *)hv->vms.values[k]; if (NULL == (vm_name = zbx_xml_read_value(vm->details, ZBX_XPATH_LN2("config", "name")))) continue; if (NULL == (hv_name = zbx_xml_read_value(hv->details, ZBX_XPATH_LN2("config", "name")))) { zbx_free(vm_name); continue; } zbx_json_addobject(&json_data, NULL); zbx_json_addstring(&json_data, "{#VM.UUID}", vm->uuid, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#VM.ID}", vm->id, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#VM.NAME}", vm_name, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#HV.NAME}", hv_name, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json_data, "{#CLUSTER.NAME}", (NULL != cluster ? cluster->name : ""), ZBX_JSON_TYPE_STRING); zbx_json_close(&json_data); zbx_free(hv_name); zbx_free(vm_name); } } zbx_json_close(&json_data); SET_STR_RESULT(result, zbx_strdup(NULL, json_data.buffer)); zbx_json_free(&json_data); ret = SYSINFO_RET_OK; unlock: zbx_vmware_unlock(); return ret; }
int SERVICES(AGENT_REQUEST *request, AGENT_RESULT *result) { int start_type, service_state; char *type, *state, *exclude, *buf = NULL, *utf8; SC_HANDLE h_mgr; ENUM_SERVICE_STATUS_PROCESS *ssp = NULL; DWORD sz = 0, szn, i, services, resume_handle = 0; if (3 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } type = get_rparam(request, 0); state = get_rparam(request, 1); exclude = get_rparam(request, 2); if (NULL == type || '\0' == *type || 0 == strcmp(type, "all")) /* default parameter */ start_type = ZBX_SRV_STARTTYPE_ALL; else if (0 == strcmp(type, "automatic")) start_type = ZBX_SRV_STARTTYPE_AUTOMATIC; else if (0 == strcmp(type, "manual")) start_type = ZBX_SRV_STARTTYPE_MANUAL; else if (0 == strcmp(type, "disabled")) start_type = ZBX_SRV_STARTTYPE_DISABLED; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } if (NULL == state || '\0' == *state || 0 == strcmp(state, "all")) /* default parameter */ service_state = ZBX_SRV_STATE_ALL; else if (0 == strcmp(state, "stopped")) service_state = ZBX_SRV_STATE_STOPPED; else if (0 == strcmp(state, "started")) service_state = ZBX_SRV_STATE_STARTED; else if (0 == strcmp(state, "start_pending")) service_state = ZBX_SRV_STATE_START_PENDING; else if (0 == strcmp(state, "stop_pending")) service_state = ZBX_SRV_STATE_STOP_PENDING; else if (0 == strcmp(state, "running")) service_state = ZBX_SRV_STATE_RUNNING; else if (0 == strcmp(state, "continue_pending")) service_state = ZBX_SRV_STATE_CONTINUE_PENDING; else if (0 == strcmp(state, "pause_pending")) service_state = ZBX_SRV_STATE_PAUSE_PENDING; else if (0 == strcmp(state, "paused")) service_state = ZBX_SRV_STATE_PAUSED; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } if (NULL == (h_mgr = OpenSCManager(NULL, NULL, GENERIC_READ))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain system information.")); return SYSINFO_RET_FAIL; } while (0 != EnumServicesStatusEx(h_mgr, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)ssp, sz, &szn, &services, &resume_handle, NULL) || ERROR_MORE_DATA == GetLastError()) { for (i = 0; i < services; i++) { SC_HANDLE h_srv; if (NULL == (h_srv = OpenService(h_mgr, ssp[i].lpServiceName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG))) { continue; } if (SUCCEED == check_service_starttype(h_srv, start_type)) { if (SUCCEED == check_service_state(h_srv, service_state)) { utf8 = zbx_unicode_to_utf8(ssp[i].lpServiceName); if (NULL == exclude || FAIL == str_in_list(exclude, utf8, ',')) buf = zbx_strdcatf(buf, "%s\n", utf8); zbx_free(utf8); } } CloseServiceHandle(h_srv); } if (0 == szn) break; if (NULL == ssp) { sz = szn; ssp = (ENUM_SERVICE_STATUS_PROCESS *)zbx_malloc(ssp, sz); } } zbx_free(ssp); CloseServiceHandle(h_mgr); if (NULL == buf) buf = zbx_strdup(buf, "0"); SET_STR_RESULT(result, buf); return SYSINFO_RET_OK; }
int VM_MEMORY_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result) { PERFORMANCE_INFORMATION pfi; MEMORYSTATUSEX ms_ex; MEMORYSTATUS ms; char *mode; if (1 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } mode = get_rparam(request, 0); if (NULL != mode && 0 == strcmp(mode, "cached")) { if (NULL == zbx_GetPerformanceInfo) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain system information.")); return SYSINFO_RET_FAIL; } zbx_GetPerformanceInfo(&pfi, sizeof(PERFORMANCE_INFORMATION)); SET_UI64_RESULT(result, (zbx_uint64_t)pfi.SystemCache * pfi.PageSize); return SYSINFO_RET_OK; } if (NULL != zbx_GlobalMemoryStatusEx) { ms_ex.dwLength = sizeof(MEMORYSTATUSEX); zbx_GlobalMemoryStatusEx(&ms_ex); if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) SET_UI64_RESULT(result, ms_ex.ullTotalPhys); else if (0 == strcmp(mode, "free")) SET_UI64_RESULT(result, ms_ex.ullAvailPhys); else if (0 == strcmp(mode, "used")) SET_UI64_RESULT(result, ms_ex.ullTotalPhys - ms_ex.ullAvailPhys); else if (0 == strcmp(mode, "pused") && 0 != ms_ex.ullTotalPhys) SET_DBL_RESULT(result, (ms_ex.ullTotalPhys - ms_ex.ullAvailPhys) / (double)ms_ex.ullTotalPhys * 100); else if (0 == strcmp(mode, "available")) SET_UI64_RESULT(result, ms_ex.ullAvailPhys); else if (0 == strcmp(mode, "pavailable") && 0 != ms_ex.ullTotalPhys) SET_DBL_RESULT(result, ms_ex.ullAvailPhys / (double)ms_ex.ullTotalPhys * 100); else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } } else { GlobalMemoryStatus(&ms); if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) SET_UI64_RESULT(result, ms.dwTotalPhys); else if (0 == strcmp(mode, "free")) SET_UI64_RESULT(result, ms.dwAvailPhys); else if (0 == strcmp(mode, "used")) SET_UI64_RESULT(result, ms.dwTotalPhys - ms.dwAvailPhys); else if (0 == strcmp(mode, "pused") && 0 != ms.dwTotalPhys) SET_DBL_RESULT(result, (ms.dwTotalPhys - ms.dwAvailPhys) / (double)ms.dwTotalPhys * 100); else if (0 == strcmp(mode, "available")) SET_UI64_RESULT(result, ms.dwAvailPhys); else if (0 == strcmp(mode, "pavailable") && 0 != ms.dwTotalPhys) SET_DBL_RESULT(result, ms.dwAvailPhys / (double)ms.dwTotalPhys * 100); else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } } return SYSINFO_RET_OK; }
int SYSTEM_CPU_LOAD(AGENT_REQUEST *request, AGENT_RESULT *result) { #ifdef HAVE_LIBPERFSTAT #if !defined(SBITS) # define SBITS 16 #endif char *tmp; int mode, per_cpu = 1; perfstat_cpu_total_t ps_cpu_total; double value; if (2 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } tmp = get_rparam(request, 0); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all")) per_cpu = 0; else if (0 != strcmp(tmp, "percpu")) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } tmp = get_rparam(request, 1); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1")) mode = ZBX_AVG1; else if (0 == strcmp(tmp, "avg5")) mode = ZBX_AVG5; else if (0 == strcmp(tmp, "avg15")) mode = ZBX_AVG15; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } if (-1 == perfstat_cpu_total(NULL, &ps_cpu_total, sizeof(ps_cpu_total), 1)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } value = (double)ps_cpu_total.loadavg[mode] / (1 << SBITS); if (1 == per_cpu) { if (0 >= ps_cpu_total.ncpus) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs.")); return SYSINFO_RET_FAIL; } value /= ps_cpu_total.ncpus; } SET_DBL_RESULT(result, value); return SYSINFO_RET_OK; #else SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for Perfstat API.")); return SYSINFO_RET_FAIL; #endif }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; zbx_uint64_t value = 0; int do_task; double memsize = 0; zbx_uint64_t proccount = 0; if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { errno = 0; if (NULL == (usrinfo = getpwnam(param))) { if (0 == errno) SET_MSG_RESULT(result, zbx_strdup(NULL, "Specified user does not exist.")); else SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != zbx_stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; value = psinfo.pr_size; value <<= 10; /* kB to Byte */ if (0 == proccount++) memsize = value; else { if (ZBX_DO_MAX == do_task) memsize = MAX(memsize, value); else if (ZBX_DO_MIN == do_task) memsize = MIN(memsize, value); else memsize += value; } } closedir(dir); if (-1 != fd) close(fd); if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, proccount == 0 ? 0 : memsize / proccount); else SET_UI64_RESULT(result, memsize); return SYSINFO_RET_OK; }
int SYSTEM_CPU_UTIL(AGENT_REQUEST *request, AGENT_RESULT *result) { char *tmp; int cpu_num, state, mode; if (3 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } tmp = get_rparam(request, 0); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all")) cpu_num = ZBX_CPUNUM_ALL; else if (SUCCEED != is_uint31_1(tmp, &cpu_num)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } tmp = get_rparam(request, 1); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "user")) state = ZBX_CPU_STATE_USER; else if (0 == strcmp(tmp, "system")) state = ZBX_CPU_STATE_SYSTEM; else if (0 == strcmp(tmp, "idle")) state = ZBX_CPU_STATE_IDLE; else if (0 == strcmp(tmp, "iowait")) state = ZBX_CPU_STATE_IOWAIT; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } tmp = get_rparam(request, 2); if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1")) mode = ZBX_AVG1; else if (0 == strcmp(tmp, "avg5")) mode = ZBX_AVG5; else if (0 == strcmp(tmp, "avg15")) mode = ZBX_AVG15; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } if (SYSINFO_RET_FAIL == get_cpustat(result, cpu_num, state, mode)) { if (!ISSET_MSG(result)) SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain CPU information.")); return SYSINFO_RET_FAIL; } return SYSINFO_RET_OK; }
int SYSTEM_HW_CPU(AGENT_REQUEST *request, AGENT_RESULT *result) { int ret = SYSINFO_RET_FAIL, filter, cpu, cur_cpu = -1, offset = 0; zbx_uint64_t maxfreq = FAIL, curfreq = FAIL; char line[MAX_STRING_LEN], name[MAX_STRING_LEN], tmp[MAX_STRING_LEN], buffer[MAX_BUFFER_LEN], *param; FILE *f; if (2 < request->nparam) return ret; param = get_rparam(request, 0); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) cpu = HW_CPU_ALL_CPUS; /* show all CPUs by default */ else if (FAIL == is_uint31(param, (uint32_t*)&cpu)) return ret; param = get_rparam(request, 1); if (NULL == param || '\0' == *param || 0 == strcmp(param, "full")) filter = HW_CPU_SHOW_ALL; /* show full info by default */ else if (0 == strcmp(param, "maxfreq")) filter = HW_CPU_SHOW_MAXFREQ; else if (0 == strcmp(param, "vendor")) filter = HW_CPU_SHOW_VENDOR; else if (0 == strcmp(param, "model")) filter = HW_CPU_SHOW_MODEL; else if (0 == strcmp(param, "curfreq")) filter = HW_CPU_SHOW_CURFREQ; else return ret; if (NULL == (f = fopen(HW_CPU_INFO_FILE, "r"))) return ret; *buffer = '\0'; while (NULL != fgets(line, sizeof(line), f)) { if (2 != sscanf(line, "%[^:]: %[^\n]", name, tmp)) continue; if (0 == strncmp(name, "processor", 9)) { if (-1 != cur_cpu && (HW_CPU_ALL_CPUS == cpu || cpu == cur_cpu)) /* print info about the previous cpu */ offset += print_freq(buffer + offset, sizeof(buffer) - offset, filter, cpu, maxfreq, curfreq); curfreq = FAIL; cur_cpu = atoi(tmp); if (HW_CPU_ALL_CPUS != cpu && cpu != cur_cpu) continue; if (HW_CPU_ALL_CPUS == cpu || HW_CPU_SHOW_ALL == filter) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\nprocessor %d:", cur_cpu); if ((HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_MAXFREQ == filter) && FAIL != (maxfreq = get_cpu_max_freq(cur_cpu))) { ret = SYSINFO_RET_OK; } } if (HW_CPU_ALL_CPUS != cpu && cpu != cur_cpu) continue; if (0 == strncmp(name, "vendor_id", 9) && (HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_VENDOR == filter)) { ret = SYSINFO_RET_OK; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", tmp); } else if (0 == strncmp(name, "model name", 10) && (HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_MODEL == filter)) { ret = SYSINFO_RET_OK; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", tmp); } else if (0 == strncmp(name, "cpu MHz", 7) && (HW_CPU_SHOW_ALL == filter || HW_CPU_SHOW_CURFREQ == filter)) { ret = SYSINFO_RET_OK; sscanf(tmp, ZBX_FS_UI64, &curfreq); } } zbx_fclose(f); if (SYSINFO_RET_OK == ret) { if (-1 != cur_cpu && (HW_CPU_ALL_CPUS == cpu || cpu == cur_cpu)) /* print info about the last cpu */ offset += print_freq(buffer + offset, sizeof(buffer) - offset, filter, cpu, maxfreq, curfreq); SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer + 1)); /* buf has a leading space or '\n' */ } return ret; }
int VFS_FS_INODE(AGENT_REQUEST *request, AGENT_RESULT *result) { #ifdef HAVE_SYS_STATVFS_H # define ZBX_STATFS statvfs # define ZBX_FFREE f_favail #else # define ZBX_STATFS statfs # define ZBX_FFREE f_ffree #endif char *fsname, *mode; zbx_uint64_t total; struct ZBX_STATFS s; if (2 < request->nparam) return SYSINFO_RET_FAIL; fsname = get_rparam(request, 0); mode = get_rparam(request, 1); if (NULL == fsname || '\0' == *fsname || 0 != ZBX_STATFS(fsname, &s)) return SYSINFO_RET_FAIL; if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) /* default parameter */ { SET_UI64_RESULT(result, s.f_files); } else if (0 == strcmp(mode, "free")) { SET_UI64_RESULT(result, s.ZBX_FFREE); } else if (0 == strcmp(mode, "used")) { SET_UI64_RESULT(result, s.f_files - s.f_ffree); } else if (0 == strcmp(mode, "pfree")) { total = s.f_files; #ifdef HAVE_SYS_STATVFS_H total -= s.f_ffree - s.f_favail; #endif if (0 != total) SET_DBL_RESULT(result, (double)(100.0 * s.ZBX_FFREE) / total); else return SYSINFO_RET_FAIL; } else if (0 == strcmp(mode, "pused")) { total = s.f_files; #ifdef HAVE_SYS_STATVFS_H total -= s.f_ffree - s.f_favail; #endif if (0 != total) SET_DBL_RESULT(result, 100.0 - (double)(100.0 * s.ZBX_FFREE) / total); else return SYSINFO_RET_FAIL; } else return SYSINFO_RET_FAIL; return SYSINFO_RET_OK; }
int VFS_FS_INODE(AGENT_REQUEST *request, AGENT_RESULT *result) { #ifdef HAVE_SYS_STATVFS_H # define ZBX_STATFS statvfs # define ZBX_FFREE f_favail #else # define ZBX_STATFS statfs # define ZBX_FFREE f_ffree #endif char *fsname, *mode; zbx_uint64_t total; struct ZBX_STATFS s; if (2 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } fsname = get_rparam(request, 0); mode = get_rparam(request, 1); if (NULL == fsname || '\0' == *fsname) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } if (0 != ZBX_STATFS(fsname, &s)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain filesystem information: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total")) /* default parameter */ { SET_UI64_RESULT(result, s.f_files); } else if (0 == strcmp(mode, "free")) { SET_UI64_RESULT(result, s.ZBX_FFREE); } else if (0 == strcmp(mode, "used")) { SET_UI64_RESULT(result, s.f_files - s.f_ffree); } else if (0 == strcmp(mode, "pfree")) { total = s.f_files; #ifdef HAVE_SYS_STATVFS_H total -= s.f_ffree - s.f_favail; #endif if (0 != total) SET_DBL_RESULT(result, (double)(100.0 * s.ZBX_FFREE) / total); else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero.")); return SYSINFO_RET_FAIL; } } else if (0 == strcmp(mode, "pused")) { total = s.f_files; #ifdef HAVE_SYS_STATVFS_H total -= s.f_ffree - s.f_favail; #endif if (0 != total) { SET_DBL_RESULT(result, 100.0 - (double)(100.0 * s.ZBX_FFREE) / total); } else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero.")); return SYSINFO_RET_FAIL; } } else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); return SYSINFO_RET_FAIL; } return SYSINFO_RET_OK; }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { char tmp[MAX_STRING_LEN], *procname, *proccomm, *param; DIR *dir; struct dirent *entries; struct stat buf; struct passwd *usrinfo; psinfo_t psinfo; /* In the correct procfs.h, the structure name is psinfo_t */ int fd = -1; zbx_uint64_t value = 0; int do_task; double memsize = 0; zbx_uint64_t proccount = 0; if (4 < request->nparam) return SYSINFO_RET_FAIL; procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) /* incorrect user name */ return SYSINFO_RET_FAIL; } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) do_task = DO_SUM; else if (0 == strcmp(param, "avg")) do_task = DO_AVG; else if (0 == strcmp(param, "max")) do_task = DO_MAX; else if (0 == strcmp(param, "min")) do_task = DO_MIN; else return SYSINFO_RET_FAIL; proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) return SYSINFO_RET_FAIL; while (NULL != (entries = readdir(dir))) { if (-1 != fd) { close(fd); fd = -1; } zbx_snprintf(tmp, sizeof(tmp), "/proc/%s/psinfo", entries->d_name); if (0 != stat(tmp, &buf)) continue; if (-1 == (fd = open(tmp, O_RDONLY))) continue; if (-1 == read(fd, &psinfo, sizeof(psinfo))) continue; if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, psinfo.pr_fname)) continue; if (NULL != usrinfo && usrinfo->pw_uid != psinfo.pr_uid) continue; if (NULL != proccomm && '\0' != *proccomm && NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) continue; value = psinfo.pr_size; value <<= 10; /* kB to Byte */ if (0 == proccount++) memsize = value; else { if (do_task == DO_MAX) memsize = MAX(memsize, value); else if (do_task == DO_MIN) memsize = MIN(memsize, value); else memsize += value; } } closedir(dir); if (-1 != fd) close(fd); if (do_task == DO_AVG) { SET_DBL_RESULT(result, proccount == 0 ? 0 : memsize / proccount); } else { SET_UI64_RESULT(result, memsize); } return SYSINFO_RET_OK; }