Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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) */
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
/*
 * 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;
}
Пример #10
0
/******************************************************************************
 *                                                                            *
 * 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;
}
Пример #11
0
/*
 * 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;
}
Пример #12
0
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;
}
Пример #13
0
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
}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #16
0
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) */
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #22
0
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;
}
Пример #23
0
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;
}
Пример #24
0
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
}
Пример #25
0
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;
}
Пример #26
0
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;
}
Пример #27
0
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;
}
Пример #28
0
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;
}
Пример #29
0
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;
}
Пример #30
0
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;
}