From c6c8663cc7ecf25e45557769cb9c21942a7e24b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Tigeot?= <ftigeot@wolfpond.org>
Date: Tue, 13 Sep 2016 21:18:31 +0200
Subject: [PATCH] Add DragonFly support

* libs/zbxsysinfo bits originally copied from the freebsd subdirectory
---
 configure.ac                              |   4 +
 src/libs/zbxsysinfo/Makefile.am           |   1 +
 src/libs/zbxsysinfo/dragonfly/Makefile.am |  24 ++
 src/libs/zbxsysinfo/dragonfly/boottime.c  |  50 ++++
 src/libs/zbxsysinfo/dragonfly/cpu.c       | 227 +++++++++++++++
 src/libs/zbxsysinfo/dragonfly/diskio.c    | 221 ++++++++++++++
 src/libs/zbxsysinfo/dragonfly/diskspace.c | 222 ++++++++++++++
 src/libs/zbxsysinfo/dragonfly/freebsd.c   |  66 +++++
 src/libs/zbxsysinfo/dragonfly/hostname.c  |  44 +++
 src/libs/zbxsysinfo/dragonfly/inodes.c    | 108 +++++++
 src/libs/zbxsysinfo/dragonfly/kernel.c    |  78 +++++
 src/libs/zbxsysinfo/dragonfly/memory.c    | 260 +++++++++++++++++
 src/libs/zbxsysinfo/dragonfly/net.c       | 296 +++++++++++++++++++
 src/libs/zbxsysinfo/dragonfly/proc.c      | 466 ++++++++++++++++++++++++++++++
 src/libs/zbxsysinfo/dragonfly/software.c  |  40 +++
 src/libs/zbxsysinfo/dragonfly/swap.c      |  91 ++++++
 src/libs/zbxsysinfo/dragonfly/system.c    |  41 +++
 src/libs/zbxsysinfo/dragonfly/uptime.c    |  64 ++++
 18 files changed, 2303 insertions(+)
 create mode 100644 src/libs/zbxsysinfo/dragonfly/Makefile.am
 create mode 100644 src/libs/zbxsysinfo/dragonfly/boottime.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/cpu.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/diskio.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/diskspace.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/freebsd.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/hostname.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/inodes.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/kernel.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/memory.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/net.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/proc.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/software.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/swap.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/system.c
 create mode 100644 src/libs/zbxsysinfo/dragonfly/uptime.c

diff --git a/configure.ac b/configure.ac
index 3489dfd..01e138a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -926,6 +926,9 @@ osf*)
 openbsd*)
 	ARCH="openbsd"
 	;;
+dragonfly*)
+	ARCH="dragonfly"
+	;;
 *)
 	ARCH="unknown"
 	;;
@@ -1551,6 +1554,7 @@ AC_OUTPUT([
 	src/libs/zbxsysinfo/simple/Makefile
 	src/libs/zbxsysinfo/linux/Makefile
 	src/libs/zbxsysinfo/aix/Makefile
+	src/libs/zbxsysinfo/dragonfly/Makefile
 	src/libs/zbxsysinfo/freebsd/Makefile
 	src/libs/zbxsysinfo/hpux/Makefile
 	src/libs/zbxsysinfo/openbsd/Makefile
diff --git a/src/libs/zbxsysinfo/Makefile.am b/src/libs/zbxsysinfo/Makefile.am
index 17e6e8a..9d5cf8e 100644
--- a/src/libs/zbxsysinfo/Makefile.am
+++ b/src/libs/zbxsysinfo/Makefile.am
@@ -4,6 +4,7 @@ DIST_SUBDIRS = \
 	agent \
 	common \
 	aix \
+	dragonfly \
 	freebsd \
 	hpux \
 	linux \
diff --git a/src/libs/zbxsysinfo/dragonfly/Makefile.am b/src/libs/zbxsysinfo/dragonfly/Makefile.am
new file mode 100644
index 0000000..0ca5b57
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/Makefile.am
@@ -0,0 +1,24 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_LIBRARIES = libspecsysinfo.a libspechostnamesysinfo.a
+
+libspecsysinfo_a_CFLAGS = -I@top_srcdir@/src/zabbix_agent/
+
+libspecsysinfo_a_SOURCES = \
+	boottime.c \
+	cpu.c \
+	diskio.c \
+	diskspace.c \
+	freebsd.c \
+	inodes.c \
+	kernel.c \
+	memory.c \
+	net.c \
+	proc.c \
+	software.c \
+	swap.c \
+	system.c \
+	uptime.c
+
+libspechostnamesysinfo_a_SOURCES = \
+	hostname.c
diff --git a/src/libs/zbxsysinfo/dragonfly/boottime.c b/src/libs/zbxsysinfo/dragonfly/boottime.c
new file mode 100644
index 0000000..9ac04c5
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/boottime.c
@@ -0,0 +1,50 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "log.h"
+
+int	SYSTEM_BOOTTIME(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#ifdef HAVE_FUNCTION_SYSCTL_KERN_BOOTTIME
+	size_t		len;
+	int		mib[2];
+	struct timeval	boottime;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_BOOTTIME;
+
+	len = sizeof(struct timeval);
+
+	if (-1 == sysctl(mib, 2, &boottime, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, boottime.tv_sec);
+
+	return SYSINFO_RET_OK;
+#else
+	SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for \"kern.boottime\" system"
+			" parameter."));
+	return SYSINFO_RET_FAIL;
+#endif
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/cpu.c b/src/libs/zbxsysinfo/dragonfly/cpu.c
new file mode 100644
index 0000000..832dce4
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/cpu.c
@@ -0,0 +1,227 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "stats.h"
+#include "log.h"
+
+static int	get_cpu_num(int online)
+{
+#if defined(_SC_NPROCESSORS_ONLN)	/* FreeBSD 6.2 i386; FreeBSD 7.0 i386 */
+	if (1 == online)
+		return sysconf(_SC_NPROCESSORS_ONLN);
+
+	return sysconf(_SC_NPROCESSORS_CONF);
+#elif defined(HAVE_FUNCTION_SYSCTL_HW_NCPU)	/* FreeBSD 4.2 i386; FreeBSD 6.2 i386; FreeBSD 7.0 i386 */
+	size_t	len;
+	int	mib[] = {CTL_HW, HW_NCPU}, ncpu;
+
+	len = sizeof(ncpu);
+
+	if (1 == online && -1 != sysctl(mib, 2, &ncpu, &len, NULL, 0))
+		return ncpu;
+#endif
+	return -1;
+}
+
+int	SYSTEM_CPU_NUM(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*tmp;
+	int	online = 0, ncpu;
+
+	if (1 < 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, "online"))
+		online = 1;
+	else if (0 != strcmp(tmp, "max"))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	if (-1 == (ncpu = get_cpu_num(online)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, ncpu);
+
+	return SYSINFO_RET_OK;
+}
+
+int	SYSTEM_CPU_UTIL(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*tmp;
+	int	cpu_num, state, mode;
+
+	if (3 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	tmp = get_rparam(request, 0);
+
+	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all"))
+		cpu_num = ZBX_CPUNUM_ALL;
+	else if (SUCCEED != is_uint31_1(tmp, &cpu_num))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	tmp = get_rparam(request, 1);
+
+	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "user"))
+		state = ZBX_CPU_STATE_USER;
+	else if (0 == strcmp(tmp, "nice"))
+		state = ZBX_CPU_STATE_NICE;
+	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, "interrupt"))
+		state = ZBX_CPU_STATE_INTERRUPT;
+	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;
+	}
+
+	return get_cpustat(result, cpu_num, state, mode);
+}
+
+int	SYSTEM_CPU_LOAD(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*tmp;
+	int	mode, per_cpu = 1, cpu_num;
+	double	load[ZBX_AVG_COUNT], 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 (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];
+
+	if (1 == per_cpu)
+	{
+		if (0 >= (cpu_num = get_cpu_num(1)))
+		{
+			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;
+}
+
+int     SYSTEM_CPU_SWITCHES(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	u_int	v_swtch;
+	size_t	len;
+
+	len = sizeof(v_swtch);
+
+	if (0 != sysctlbyname("vm.stats.sys.v_swtch", &v_swtch, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain \"vm.stats.sys.v_swtch\" system parameter: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, v_swtch);
+
+	return SYSINFO_RET_OK;
+}
+
+int     SYSTEM_CPU_INTR(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	u_int	v_intr;
+	size_t	len;
+
+	len = sizeof(v_intr);
+
+	if (0 != sysctlbyname("vm.stats.sys.v_intr", &v_intr, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain \"vm.stats.sys.v_intr\" system parameter: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, v_intr);
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/diskio.c b/src/libs/zbxsysinfo/dragonfly/diskio.c
new file mode 100644
index 0000000..117fa71
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/diskio.c
@@ -0,0 +1,221 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "stats.h"
+#include "diskdevices.h"
+
+#define ZBX_DEV_PFX	"/dev/"
+#define ZBX_DEV_READ	0
+#define ZBX_DEV_WRITE	1
+
+static struct statinfo	*si = NULL;
+
+int	get_diskstat(const char *devname, zbx_uint64_t *dstat)
+{
+	int		i;
+	struct devstat	*ds = NULL;
+	int		ret = FAIL;
+	char		dev[DEVSTAT_NAME_LEN + 10];
+	const char	*pd;	/* pointer to device name without '/dev/' prefix, e.g. 'da0' */
+
+	assert(devname);
+
+	for (i = 0; i < ZBX_DSTAT_MAX; i++)
+		dstat[i] = (zbx_uint64_t)__UINT64_C(0);
+
+	if (NULL == si)
+	{
+		si = (struct statinfo *)zbx_malloc(si, sizeof(struct statinfo));
+		si->dinfo = (struct devinfo *)zbx_malloc(NULL, sizeof(struct devinfo));
+		memset(si->dinfo, 0, sizeof(struct devinfo));
+	}
+
+	pd = devname;
+
+	/* skip prefix ZBX_DEV_PFX, if present */
+	if ('\0' != *devname && 0 == strncmp(pd, ZBX_DEV_PFX, ZBX_CONST_STRLEN(ZBX_DEV_PFX)))
+			pd += ZBX_CONST_STRLEN(ZBX_DEV_PFX);
+
+#if DEVSTAT_USER_API_VER >= 5
+	if (-1 == devstat_getdevs(NULL, si))
+#else
+	if (-1 == getdevs(si))
+#endif
+		return FAIL;
+
+	for (i = 0; i < si->dinfo->numdevs; i++)
+	{
+		ds = &si->dinfo->devices[i];
+
+		/* empty '*devname' string means adding statistics for all disks together */
+		if ('\0' != *devname)
+		{
+			zbx_snprintf(dev, sizeof(dev), "%s%d", ds->device_name, ds->unit_number);
+			if (0 != strcmp(dev, pd))
+				continue;
+		}
+
+#if DEVSTAT_USER_API_VER >= 5
+		dstat[ZBX_DSTAT_R_OPER] += (zbx_uint64_t)ds->operations[DEVSTAT_READ];
+		dstat[ZBX_DSTAT_W_OPER] += (zbx_uint64_t)ds->operations[DEVSTAT_WRITE];
+		dstat[ZBX_DSTAT_R_BYTE] += (zbx_uint64_t)ds->bytes[DEVSTAT_READ];
+		dstat[ZBX_DSTAT_W_BYTE] += (zbx_uint64_t)ds->bytes[DEVSTAT_WRITE];
+#else
+		dstat[ZBX_DSTAT_R_OPER] += (zbx_uint64_t)ds->num_reads;
+		dstat[ZBX_DSTAT_W_OPER] += (zbx_uint64_t)ds->num_writes;
+		dstat[ZBX_DSTAT_R_BYTE] += (zbx_uint64_t)ds->bytes_read;
+		dstat[ZBX_DSTAT_W_BYTE] += (zbx_uint64_t)ds->bytes_written;
+#endif
+		ret = SUCCEED;
+
+		if ('\0' != *devname)
+			break;
+	}
+
+	return ret;
+}
+
+static int	vfs_dev_rw(AGENT_REQUEST *request, AGENT_RESULT *result, int rw)
+{
+	ZBX_SINGLE_DISKDEVICE_DATA *device;
+	char		devname[32], *tmp;
+	int		type, mode;
+	zbx_uint64_t	dstats[ZBX_DSTAT_MAX];
+	char		*pd;			/* pointer to device name without '/dev/' prefix, e.g. 'da0' */
+
+	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 == strcmp(tmp, "all"))
+		*devname = '\0';
+	else
+		strscpy(devname, tmp);
+
+	pd = devname;
+
+	if ('\0' != *pd)
+	{
+		/* skip prefix ZBX_DEV_PFX, if present */
+		if (0 == strncmp(pd, ZBX_DEV_PFX, ZBX_CONST_STRLEN(ZBX_DEV_PFX)))
+			pd += ZBX_CONST_STRLEN(ZBX_DEV_PFX);
+	}
+
+	tmp = get_rparam(request, 1);
+
+	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "bps"))	/* default parameter */
+		type = ZBX_DSTAT_TYPE_BPS;
+	else if (0 == strcmp(tmp, "ops"))
+		type = ZBX_DSTAT_TYPE_OPS;
+	else if (0 == strcmp(tmp, "bytes"))
+		type = ZBX_DSTAT_TYPE_BYTE;
+	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_BYTE || type == ZBX_DSTAT_TYPE_OPER)
+	{
+		if (2 < request->nparam)
+		{
+			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
+			return SYSINFO_RET_FAIL;
+		}
+
+		if (FAIL == get_diskstat(pd, dstats))
+		{
+			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information."));
+			return SYSINFO_RET_FAIL;
+		}
+
+		if (ZBX_DSTAT_TYPE_BYTE == type)
+			SET_UI64_RESULT(result, dstats[(ZBX_DEV_READ == rw ? ZBX_DSTAT_R_BYTE : ZBX_DSTAT_W_BYTE)]);
+		else	/* ZBX_DSTAT_TYPE_OPER */
+			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 == (device = collector_diskdevice_get(pd)))
+	{
+		if (FAIL == get_diskstat(pd, dstats))	/* validate device name */
+		{
+			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information."));
+			return SYSINFO_RET_FAIL;
+		}
+
+		if (NULL == (device = collector_diskdevice_add(pd)))
+		{
+			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot add disk device to agent collector."));
+			return SYSINFO_RET_FAIL;
+		}
+	}
+
+	if (ZBX_DSTAT_TYPE_BPS == type)	/* default parameter */
+		SET_DBL_RESULT(result, (ZBX_DEV_READ == rw ? device->r_bps[mode] : device->w_bps[mode]));
+	else if (ZBX_DSTAT_TYPE_OPS == type)
+		SET_DBL_RESULT(result, (ZBX_DEV_READ == rw ? device->r_ops[mode] : device->w_ops[mode]));
+
+	return SYSINFO_RET_OK;
+}
+
+int	VFS_DEV_READ(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	return vfs_dev_rw(request, result, ZBX_DEV_READ);
+}
+
+int	VFS_DEV_WRITE(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	return vfs_dev_rw(request, result, ZBX_DEV_WRITE);
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/diskspace.c b/src/libs/zbxsysinfo/dragonfly/diskspace.c
new file mode 100644
index 0000000..7cc7ba1
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/diskspace.c
@@ -0,0 +1,222 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "zbxjson.h"
+#include "log.h"
+
+static int	get_fs_size_stat(const char *fs, zbx_uint64_t *total, zbx_uint64_t *free,
+		zbx_uint64_t *used, double *pfree, double *pused, char **error)
+{
+#ifdef HAVE_SYS_STATVFS_H
+#	define ZBX_STATFS	statvfs
+#	define ZBX_BSIZE	f_frsize
+#else
+#	define ZBX_STATFS	statfs
+#	define ZBX_BSIZE	f_bsize
+#endif
+	struct ZBX_STATFS	s;
+
+	if (0 != ZBX_STATFS(fs, &s))
+	{
+		*error = zbx_dsprintf(NULL, "Cannot obtain filesystem information: %s", zbx_strerror(errno));
+		return SYSINFO_RET_FAIL;
+	}
+
+	/* Available space could be negative (top bit set) if we hit disk space */
+	/* reserved for non-privileged users. Treat it as 0.                    */
+	if (0 != ZBX_IS_TOP_BIT_SET(s.f_bavail))
+		s.f_bavail = 0;
+
+	if (NULL != total)
+		*total = (zbx_uint64_t)s.f_blocks * s.ZBX_BSIZE;
+
+	if (NULL != free)
+		*free = (zbx_uint64_t)s.f_bavail * s.ZBX_BSIZE;
+
+	if (NULL != used)
+		*used = (zbx_uint64_t)(s.f_blocks - s.f_bfree) * s.ZBX_BSIZE;
+
+	if (NULL != pfree)
+	{
+		if (0 != s.f_blocks - s.f_bfree + s.f_bavail)
+			*pfree = (double)(100.0 * s.f_bavail) / (s.f_blocks - s.f_bfree + s.f_bavail);
+		else
+			*pfree = 0;
+	}
+
+	if (NULL != pused)
+	{
+		if (0 != s.f_blocks - s.f_bfree + s.f_bavail)
+			*pused = 100.0 - (double)(100.0 * s.f_bavail) / (s.f_blocks - s.f_bfree + s.f_bavail);
+		else
+			*pused = 0;
+	}
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VFS_FS_USED(const char *fs, AGENT_RESULT *result)
+{
+	zbx_uint64_t	value;
+	char		*error;
+
+	if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, NULL, &value, NULL, NULL, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, value);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VFS_FS_FREE(const char *fs, AGENT_RESULT *result)
+{
+	zbx_uint64_t	value;
+	char		*error;
+
+	if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, &value, NULL, NULL, NULL, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, value);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VFS_FS_TOTAL(const char *fs, AGENT_RESULT *result)
+{
+	zbx_uint64_t	value;
+	char		*error;
+
+	if (SYSINFO_RET_OK != get_fs_size_stat(fs, &value, NULL, NULL, NULL, NULL, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, value);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VFS_FS_PFREE(const char *fs, AGENT_RESULT *result)
+{
+	double	value;
+	char	*error;
+
+	if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, NULL, NULL, &value, NULL, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_DBL_RESULT(result, value);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VFS_FS_PUSED(const char *fs, AGENT_RESULT *result)
+{
+	double	value;
+	char	*error;
+
+	if (SYSINFO_RET_OK != get_fs_size_stat(fs, NULL, NULL, NULL, NULL, &value, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_DBL_RESULT(result, value);
+
+	return SYSINFO_RET_OK;
+}
+
+int	VFS_FS_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*fsname, *mode;
+
+	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 (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))	/* default parameter */
+		return VFS_FS_TOTAL(fsname, result);
+	if (0 == strcmp(mode, "free"))
+		return VFS_FS_FREE(fsname, result);
+	if (0 == strcmp(mode, "pfree"))
+		return VFS_FS_PFREE(fsname, result);
+	if (0 == strcmp(mode, "used"))
+		return VFS_FS_USED(fsname, result);
+	if (0 == strcmp(mode, "pused"))
+		return VFS_FS_PUSED(fsname, result);
+
+	SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+
+	return SYSINFO_RET_FAIL;
+}
+
+int	VFS_FS_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	int		i, rc;
+	struct statfs	*mntbuf;
+	struct zbx_json	j;
+
+	if (0 == (rc = getmntinfo(&mntbuf, MNT_WAIT)))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
+
+	zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);
+
+	for (i = 0; i < rc; i++)
+	{
+		zbx_json_addobject(&j, NULL);
+		zbx_json_addstring(&j, "{#FSNAME}", mntbuf[i].f_mntonname, ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&j, "{#FSTYPE}", mntbuf[i].f_fstypename, ZBX_JSON_TYPE_STRING);
+		zbx_json_close(&j);
+	}
+
+	zbx_json_close(&j);
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer));
+
+	zbx_json_free(&j);
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/freebsd.c b/src/libs/zbxsysinfo/dragonfly/freebsd.c
new file mode 100644
index 0000000..732e0da
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/freebsd.c
@@ -0,0 +1,66 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+
+ZBX_METRIC	parameters_specific[] =
+/*	KEY			FLAG		FUNCTION		TEST PARAMETERS */
+{
+	{"kernel.maxfiles",	0,		KERNEL_MAXFILES,	NULL},
+	{"kernel.maxproc",	0,		KERNEL_MAXPROC,		NULL},
+
+	{"vfs.fs.size",		CF_HAVEPARAMS,	VFS_FS_SIZE,		"/,free"},
+	{"vfs.fs.inode",	CF_HAVEPARAMS,	VFS_FS_INODE,		"/,free"},
+	{"vfs.fs.discovery",	0,		VFS_FS_DISCOVERY,	NULL},
+
+	{"vfs.dev.read",	CF_HAVEPARAMS,	VFS_DEV_READ,		"da0,operations"},
+	{"vfs.dev.write",	CF_HAVEPARAMS,	VFS_DEV_WRITE,		"da0,operations"},
+
+	{"net.tcp.listen",	CF_HAVEPARAMS,	NET_TCP_LISTEN,		"80"},
+	{"net.udp.listen",	CF_HAVEPARAMS,	NET_UDP_LISTEN,		"68"},
+
+	{"net.if.in",		CF_HAVEPARAMS,	NET_IF_IN,		"lo0,bytes"},
+	{"net.if.out",		CF_HAVEPARAMS,	NET_IF_OUT,		"lo0,bytes"},
+	{"net.if.total",	CF_HAVEPARAMS,	NET_IF_TOTAL,		"lo0,bytes"},
+	{"net.if.collisions",	CF_HAVEPARAMS,	NET_IF_COLLISIONS,	"lo0"},
+	{"net.if.discovery",	0,		NET_IF_DISCOVERY,	"lo0"},
+
+	{"vm.memory.size",	CF_HAVEPARAMS,	VM_MEMORY_SIZE,		"free"},
+
+	{"proc.num",		CF_HAVEPARAMS,	PROC_NUM,		"inetd"},
+	{"proc.mem",		CF_HAVEPARAMS,	PROC_MEM,		"inetd"},
+
+	{"system.cpu.switches",	0,		SYSTEM_CPU_SWITCHES,	NULL},
+	{"system.cpu.intr",	0,		SYSTEM_CPU_INTR,	NULL},
+	{"system.cpu.util",	CF_HAVEPARAMS,	SYSTEM_CPU_UTIL,	"all,user,avg1"},
+	{"system.cpu.load",	CF_HAVEPARAMS,	SYSTEM_CPU_LOAD,	"all,avg1"},
+	{"system.cpu.num",	CF_HAVEPARAMS,	SYSTEM_CPU_NUM,		"online"},
+	{"system.cpu.discovery",0,		SYSTEM_CPU_DISCOVERY,	NULL},
+
+	{"system.uname",	0,		SYSTEM_UNAME,		NULL},
+
+	{"system.sw.arch",	0,		SYSTEM_SW_ARCH,		NULL},
+	{"system.swap.size",	CF_HAVEPARAMS,	SYSTEM_SWAP_SIZE,	"all,free"},
+
+	{"system.uptime",	0,		SYSTEM_UPTIME,		NULL},
+	{"system.boottime",	0,		SYSTEM_BOOTTIME,	NULL},
+
+	{NULL}
+};
diff --git a/src/libs/zbxsysinfo/dragonfly/hostname.c b/src/libs/zbxsysinfo/dragonfly/hostname.c
new file mode 100644
index 0000000..f1c708a
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/hostname.c
@@ -0,0 +1,44 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "sysinfo.h"
+#include "log.h"
+
+#ifdef HAVE_SYS_UTSNAME_H
+#	include <sys/utsname.h>
+#endif
+
+ZBX_METRIC	parameter_hostname =
+/*	KEY			FLAG		FUNCTION		TEST PARAMETERS */
+	{"system.hostname",     0,              SYSTEM_HOSTNAME,        NULL};
+
+int	SYSTEM_HOSTNAME(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	struct utsname	name;
+
+	if (-1 == uname(&name))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, name.nodename));
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/inodes.c b/src/libs/zbxsysinfo/dragonfly/inodes.c
new file mode 100644
index 0000000..dc12c3e
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/inodes.c
@@ -0,0 +1,108 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "log.h"
+
+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;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/kernel.c b/src/libs/zbxsysinfo/dragonfly/kernel.c
new file mode 100644
index 0000000..a47c2b1
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/kernel.c
@@ -0,0 +1,78 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "log.h"
+
+int	KERNEL_MAXFILES(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#ifdef HAVE_FUNCTION_SYSCTL_KERN_MAXFILES
+	int	mib[2];
+	size_t	len;
+	int	maxfiles;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_MAXFILES;
+
+	len = sizeof(maxfiles);
+
+	if (0 != sysctl(mib, 2, &maxfiles, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, maxfiles);
+
+	return SYSINFO_RET_OK;
+#else
+	SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for \"kern.maxfiles\" system"
+			" parameter."));
+	return SYSINFO_RET_FAIL;
+#endif
+}
+
+int	KERNEL_MAXPROC(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#ifdef HAVE_FUNCTION_SYSCTL_KERN_MAXPROC
+	int	mib[2];
+	size_t	len;
+	int	maxproc;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_MAXPROC;
+
+	len = sizeof(maxproc);
+
+	if (0 != sysctl(mib, 2, &maxproc, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, maxproc);
+
+	return SYSINFO_RET_OK;
+#else
+	SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for \"kern.maxproc\" system"
+			" parameter."));
+	return SYSINFO_RET_FAIL;
+#endif
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/memory.c b/src/libs/zbxsysinfo/dragonfly/memory.c
new file mode 100644
index 0000000..3fda8b8
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/memory.c
@@ -0,0 +1,260 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "log.h"
+
+static u_int	pagesize = 0;
+
+#define ZBX_SYSCTLBYNAME(name, value)									\
+													\
+	len = sizeof(value);										\
+	if (0 != sysctlbyname(name, &value, &len, NULL, 0))						\
+	{												\
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain \"%s\" system parameter: %s",	\
+				name, zbx_strerror(errno)));						\
+		return SYSINFO_RET_FAIL;								\
+	}
+
+static int	VM_MEMORY_TOTAL(AGENT_RESULT *result)
+{
+	unsigned long	totalbytes;
+	size_t		len;
+
+	ZBX_SYSCTLBYNAME("hw.physmem", totalbytes);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)totalbytes);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_ACTIVE(AGENT_RESULT *result)
+{
+	u_int	activepages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_active_count", activepages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)activepages * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_INACTIVE(AGENT_RESULT *result)
+{
+	u_int	inactivepages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_inactive_count", inactivepages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)inactivepages * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_WIRED(AGENT_RESULT *result)
+{
+	u_int	wiredpages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_wire_count", wiredpages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)wiredpages * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_CACHED(AGENT_RESULT *result)
+{
+	u_int	cachedpages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)cachedpages * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_FREE(AGENT_RESULT *result)
+{
+	u_int	freepages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_free_count", freepages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)freepages * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_USED(AGENT_RESULT *result)
+{
+	u_int	activepages, wiredpages, cachedpages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_active_count", activepages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_wire_count", wiredpages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)(activepages + wiredpages + cachedpages) * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_PUSED(AGENT_RESULT *result)
+{
+	u_int	activepages, wiredpages, cachedpages, totalpages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_active_count", activepages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_wire_count", wiredpages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_page_count", totalpages);
+
+	if (0 == totalpages)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_DBL_RESULT(result, (activepages + wiredpages + cachedpages) / (double)totalpages * 100);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_AVAILABLE(AGENT_RESULT *result)
+{
+	u_int	inactivepages, cachedpages, freepages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_inactive_count", inactivepages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_free_count", freepages);
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)(inactivepages + cachedpages + freepages) * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_PAVAILABLE(AGENT_RESULT *result)
+{
+	u_int	inactivepages, cachedpages, freepages, totalpages;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_inactive_count", inactivepages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_free_count", freepages);
+
+	ZBX_SYSCTLBYNAME("vm.stats.vm.v_page_count", totalpages);
+
+	if (0 == totalpages)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_DBL_RESULT(result, (inactivepages + cachedpages + freepages) / (double)totalpages * 100);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_BUFFERS(AGENT_RESULT *result)
+{
+	u_int	bufspace;
+	size_t	len;
+
+	ZBX_SYSCTLBYNAME("vfs.bufspace", bufspace);
+
+	SET_UI64_RESULT(result, bufspace);
+
+	return SYSINFO_RET_OK;
+}
+
+static int	VM_MEMORY_SHARED(AGENT_RESULT *result)
+{
+	struct vmtotal	vm;
+	size_t		len = sizeof(vm);
+	int		mib[] = {CTL_VM, VM_METER};
+
+	if (0 != sysctl(mib, 2, &vm, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, (zbx_uint64_t)(vm.t_vmshr + vm.t_rmshr) * pagesize);
+
+	return SYSINFO_RET_OK;
+}
+
+int     VM_MEMORY_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*mode;
+	int	ret;
+
+	if (1 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	if (0 == pagesize)
+	{
+		size_t	len;
+
+		ZBX_SYSCTLBYNAME("vm.stats.vm.v_page_size", pagesize);
+	}
+
+	mode = get_rparam(request, 0);
+
+	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
+		ret = VM_MEMORY_TOTAL(result);
+	else if (0 == strcmp(mode, "active"))
+		ret = VM_MEMORY_ACTIVE(result);
+	else if (0 == strcmp(mode, "inactive"))
+		ret = VM_MEMORY_INACTIVE(result);
+	else if (0 == strcmp(mode, "wired"))
+		ret = VM_MEMORY_WIRED(result);
+	else if (0 == strcmp(mode, "cached"))
+		ret = VM_MEMORY_CACHED(result);
+	else if (0 == strcmp(mode, "free"))
+		ret = VM_MEMORY_FREE(result);
+	else if (0 == strcmp(mode, "used"))
+		ret = VM_MEMORY_USED(result);
+	else if (0 == strcmp(mode, "pused"))
+		ret = VM_MEMORY_PUSED(result);
+	else if (0 == strcmp(mode, "available"))
+		ret = VM_MEMORY_AVAILABLE(result);
+	else if (0 == strcmp(mode, "pavailable"))
+		ret = VM_MEMORY_PAVAILABLE(result);
+	else if (0 == strcmp(mode, "buffers"))
+		ret = VM_MEMORY_BUFFERS(result);
+	else if (0 == strcmp(mode, "shared"))
+		ret = VM_MEMORY_SHARED(result);
+	else
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
+		ret = SYSINFO_RET_FAIL;
+	}
+
+	return ret;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/net.c b/src/libs/zbxsysinfo/dragonfly/net.c
new file mode 100644
index 0000000..eb318d5
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/net.c
@@ -0,0 +1,296 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "../common/common.h"
+#include "zbxjson.h"
+#include "log.h"
+
+static struct ifmibdata	ifmd;
+
+static int	get_ifmib_general(const char *if_name, char **error)
+{
+	int	mib[6], ifcount;
+	size_t	len;
+
+	if (NULL == if_name || '\0' == *if_name)
+	{
+		*error = zbx_strdup(NULL, "Network interface name cannot be empty.");
+		return FAIL;
+	}
+
+	mib[0] = CTL_NET;
+	mib[1] = PF_LINK;
+	mib[2] = NETLINK_GENERIC;
+	mib[3] = IFMIB_SYSTEM;
+	mib[4] = IFMIB_IFCOUNT;
+
+	len = sizeof(ifcount);
+
+	if (-1 == sysctl(mib, 5, &ifcount, &len, NULL, 0))
+	{
+		*error = zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno));
+		return FAIL;
+	}
+
+	mib[3] = IFMIB_IFDATA;
+	mib[5] = IFDATA_GENERAL;
+
+	len = sizeof(ifmd);
+
+	for (mib[4] = 1; mib[4] <= ifcount; mib[4]++)
+	{
+		if (-1 == sysctl(mib, 6, &ifmd, &len, NULL, 0))
+		{
+			if (ENOENT == errno)
+				continue;
+
+			break;
+		}
+
+		if (0 == strcmp(ifmd.ifmd_name, if_name))
+			return SUCCEED;
+	}
+
+	*error = zbx_strdup(NULL, "Cannot find information for this network interface.");
+
+	return FAIL;
+}
+
+int	NET_IF_IN(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*if_name, *mode, *error;
+
+	if (2 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	if_name = get_rparam(request, 0);
+	mode = get_rparam(request, 1);
+
+	if (FAIL == get_ifmib_general(if_name,&error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "bytes"))	/* default parameter */
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_ibytes);
+	else if (0 == strcmp(mode, "packets"))
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_ipackets);
+	else if (0 == strcmp(mode, "errors"))
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_ierrors);
+	else if (0 == strcmp(mode, "dropped"))
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_iqdrops);
+	else
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	return SYSINFO_RET_OK;
+}
+
+int	NET_IF_OUT(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*if_name, *mode, *error;
+
+	if (2 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	if_name = get_rparam(request, 0);
+	mode = get_rparam(request, 1);
+
+	if (FAIL == get_ifmib_general(if_name, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "bytes"))	/* default parameter */
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_obytes);
+	else if (0 == strcmp(mode, "packets"))
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_opackets);
+	else if (0 == strcmp(mode, "errors"))
+		SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_oerrors);
+	else
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	return SYSINFO_RET_OK;
+}
+
+int	NET_IF_TOTAL(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*if_name, *mode, *error;
+
+	if (2 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	if_name = get_rparam(request, 0);
+	mode = get_rparam(request, 1);
+
+	if (FAIL == get_ifmib_general(if_name, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "bytes"))	/* default parameter */
+		SET_UI64_RESULT(result, (zbx_uint64_t)ifmd.ifmd_data.ifi_ibytes + ifmd.ifmd_data.ifi_obytes);
+	else if (0 == strcmp(mode, "packets"))
+		SET_UI64_RESULT(result, (zbx_uint64_t)ifmd.ifmd_data.ifi_ipackets + ifmd.ifmd_data.ifi_opackets);
+	else if (0 == strcmp(mode, "errors"))
+		SET_UI64_RESULT(result, (zbx_uint64_t)ifmd.ifmd_data.ifi_ierrors + ifmd.ifmd_data.ifi_oerrors);
+	else
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	return SYSINFO_RET_OK;
+}
+
+int     NET_TCP_LISTEN(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char		*port_str, command[64];
+	unsigned short	port;
+	int		res;
+
+	if (1 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	port_str = get_rparam(request, 0);
+
+	if (NULL == port_str || SUCCEED != is_ushort(port_str, &port))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	zbx_snprintf(command, sizeof(command), "netstat -an | grep '^tcp.*\\.%hu[^.].*LISTEN' | wc -l", port);
+
+	if (SYSINFO_RET_FAIL == (res = EXECUTE_INT(command, result)))
+		return res;
+
+	if (1 < result->ui64)
+		result->ui64 = 1;
+
+	return res;
+}
+
+int     NET_UDP_LISTEN(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char		*port_str, command[64];
+	unsigned short	port;
+	int		res;
+
+	if (1 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	port_str = get_rparam(request, 0);
+
+	if (NULL == port_str || SUCCEED != is_ushort(port_str, &port))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	zbx_snprintf(command, sizeof(command), "netstat -an | grep '^udp.*\\.%hu[^.].*\\*\\.\\*' | wc -l", port);
+
+	if (SYSINFO_RET_FAIL == (res = EXECUTE_INT(command, result)))
+		return res;
+
+	if (1 < result->ui64)
+		result->ui64 = 1;
+
+	return res;
+}
+
+int     NET_IF_COLLISIONS(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char	*if_name, *error;
+
+	if (1 < request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	if_name = get_rparam(request, 0);
+
+	if (FAIL == get_ifmib_general(if_name, &error))
+	{
+		SET_MSG_RESULT(result, error);
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_collisions);
+
+	return SYSINFO_RET_OK;
+}
+
+int	NET_IF_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	int			i;
+	struct zbx_json		j;
+	struct if_nameindex	*interfaces;
+
+	if (NULL == (interfaces = if_nameindex()))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
+
+	zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);
+
+	for (i = 0; 0 != interfaces[i].if_index; i++)
+	{
+		zbx_json_addobject(&j, NULL);
+		zbx_json_addstring(&j, "{#IFNAME}", interfaces[i].if_name, ZBX_JSON_TYPE_STRING);
+		zbx_json_close(&j);
+	}
+
+	zbx_json_close(&j);
+
+	SET_STR_RESULT(result, strdup(j.buffer));
+
+	zbx_json_free(&j);
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/proc.c b/src/libs/zbxsysinfo/dragonfly/proc.c
new file mode 100644
index 0000000..58c424f
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/proc.c
@@ -0,0 +1,466 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "zbxregexp.h"
+#include "log.h"
+
+#	define ZBX_PROC_PID	kp_pid
+#	define ZBX_PROC_COMM	kp_comm
+#	define ZBX_PROC_STAT	kp_stat
+#	define ZBX_PROC_TSIZE	kp_vm_tsize
+#	define ZBX_PROC_DSIZE	kp_vm_dsize
+#	define ZBX_PROC_SSIZE	kp_vm_ssize
+#	define ZBX_PROC_RSSIZE	kp_vm_rssize
+#	define ZBX_PROC_VSIZE	kp_vm_map_size
+
+#	define ZBX_PROC_FLAG 	kp_flags
+#	define ZBX_PROC_MASK	P_INMEM
+
+static char	*get_commandline(struct kinfo_proc *proc)
+{
+	int		mib[4], i;
+	size_t		sz;
+	static char	*args = NULL;
+	static int	args_alloc = 128;
+
+	if (NULL == args)
+		args = zbx_malloc(args, args_alloc);
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	mib[2] = KERN_PROC_ARGS;
+	mib[3] = proc->ZBX_PROC_PID;
+retry:
+	sz = (size_t)args_alloc;
+	if (-1 == sysctl(mib, 4, args, &sz, NULL, 0))
+	{
+		if (errno == ENOMEM)
+		{
+			args_alloc *= 2;
+			args = zbx_realloc(args, args_alloc);
+			goto retry;
+		}
+		return NULL;
+	}
+
+	for (i = 0; i < (int)(sz - 1); i++)
+		if (args[i] == '\0')
+			args[i] = ' ';
+
+	if (sz == 0)
+		zbx_strlcpy(args, proc->ZBX_PROC_COMM, args_alloc);
+
+	return args;
+}
+
+int     PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#define ZBX_SIZE	1
+#define ZBX_RSS		2
+#define ZBX_VSIZE	3
+#define ZBX_PMEM	4
+#define ZBX_TSIZE	5
+#define ZBX_DSIZE	6
+#define ZBX_SSIZE	7
+
+	char		*procname, *proccomm, *param, *args, *mem_type = NULL;
+	int		do_task, pagesize, count, i, proccount = 0, invalid_user = 0, mem_type_code, mib[4];
+	unsigned int	mibs;
+	zbx_uint64_t	mem_size = 0, byte_value = 0;
+	double		pct_size = 0.0, pct_value = 0.0;
+	int		mem_pages;
+	size_t	sz;
+
+	struct kinfo_proc	*proc = NULL;
+	struct passwd		*usrinfo;
+
+	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)
+	{
+		errno = 0;
+
+		if (NULL == (usrinfo = getpwnam(param)))
+		{
+			if (0 != errno)
+			{
+				SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s",
+						zbx_strerror(errno)));
+				return SYSINFO_RET_FAIL;
+			}
+
+			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, "size"))
+	{
+		mem_type_code = ZBX_SIZE;		/* size of process (code + data + stack) */
+	}
+	else if (0 == strcmp(mem_type, "rss"))
+	{
+		mem_type_code = ZBX_RSS;		/* resident set size */
+	}
+	else if (0 == strcmp(mem_type, "vsize"))
+	{
+		mem_type_code = ZBX_VSIZE;		/* virtual 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, "tsize"))
+	{
+		mem_type_code = ZBX_TSIZE;		/* text size */
+	}
+	else if (0 == strcmp(mem_type, "dsize"))
+	{
+		mem_type_code = ZBX_DSIZE;		/* data size */
+	}
+	else if (0 == strcmp(mem_type, "ssize"))
+	{
+		mem_type_code = ZBX_SSIZE;		/* stack 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;
+
+	pagesize = getpagesize();
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	if (NULL != usrinfo)
+	{
+		mib[2] = KERN_PROC_UID;
+		mib[3] = usrinfo->pw_uid;
+		mibs = 4;
+	}
+	else
+	{
+		mib[2] = KERN_PROC_ALL;
+		mib[3] = 0;
+		mibs = 3;
+	}
+
+	if (ZBX_PMEM == mem_type_code)
+	{
+		sz = sizeof(mem_pages);
+
+		if (0 != sysctlbyname("hw.availpages", &mem_pages, &sz, NULL, (size_t)0))
+		{
+			SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain number of physical pages: %s",
+					zbx_strerror(errno)));
+			return SYSINFO_RET_FAIL;
+		}
+	}
+
+	sz = 0;
+	if (0 != sysctl(mib, mibs, NULL, &sz, NULL, (size_t)0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain necessary buffer size from system: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	proc = (struct kinfo_proc *)zbx_malloc(proc, sz);
+	if (0 != sysctl(mib, mibs, proc, &sz, NULL, (size_t)0))
+	{
+		zbx_free(proc);
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain process information: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	count = sz / sizeof(struct kinfo_proc);
+
+	for (i = 0; i < count; i++)
+	{
+		if (NULL != procname && '\0' != *procname && 0 != strcmp(procname, proc[i].ZBX_PROC_COMM))
+			continue;
+
+		if (NULL != proccomm && '\0' != *proccomm)
+		{
+			if (NULL == (args = get_commandline(&proc[i])))
+				continue;
+
+			if (NULL == zbx_regexp_match(args, proccomm, NULL))
+				continue;
+		}
+
+		switch (mem_type_code)
+		{
+			case ZBX_SIZE:
+				byte_value = (proc[i].ZBX_PROC_TSIZE + proc[i].ZBX_PROC_DSIZE + proc[i].ZBX_PROC_SSIZE)
+						* pagesize;
+				break;
+			case ZBX_RSS:
+				byte_value = proc[i].ZBX_PROC_RSSIZE * pagesize;
+				break;
+			case ZBX_VSIZE:
+				byte_value = proc[i].ZBX_PROC_VSIZE;
+				break;
+			case ZBX_PMEM:
+				if (0 != (proc[i].ZBX_PROC_FLAG))
+					pct_value = ((float)proc[i].ZBX_PROC_RSSIZE / mem_pages) * 100.0;
+				else
+					pct_value = 0.0;
+				break;
+			case ZBX_TSIZE:
+				byte_value = proc[i].ZBX_PROC_TSIZE * pagesize;
+				break;
+			case ZBX_DSIZE:
+				byte_value = proc[i].ZBX_PROC_DSIZE * pagesize;
+				break;
+			case ZBX_SSIZE:
+				byte_value = proc[i].ZBX_PROC_SSIZE * pagesize;
+				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;
+		}
+	}
+
+	zbx_free(proc);
+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_SIZE
+#undef ZBX_RSS
+#undef ZBX_VSIZE
+#undef ZBX_PMEM
+#undef ZBX_TSIZE
+#undef ZBX_DSIZE
+#undef ZBX_SSIZE
+}
+
+int	PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	char			*procname, *proccomm, *param, *args;
+	int			proccount = 0, invalid_user = 0, zbx_proc_stat;
+	int			count, i, proc_ok, stat_ok, comm_ok, mib[4], mibs;
+	size_t			sz;
+	struct kinfo_proc	*proc = NULL;
+	struct passwd		*usrinfo;
+
+	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_dsprintf(NULL, "Cannot obtain user information: %s",
+						zbx_strerror(errno)));
+				return SYSINFO_RET_FAIL;
+			}
+
+			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;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	if (NULL != usrinfo)
+	{
+		mib[2] = KERN_PROC_UID;
+		mib[3] = usrinfo->pw_uid;
+		mibs = 4;
+	}
+	else
+	{
+		mib[2] = KERN_PROC_ALL;
+		mib[3] = 0;
+		mibs = 3;
+	}
+
+	sz = 0;
+	if (0 != sysctl(mib, mibs, NULL, &sz, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain necessary buffer size from system: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	proc = (struct kinfo_proc *)zbx_malloc(proc, sz);
+	if (0 != sysctl(mib, mibs, proc, &sz, NULL, 0))
+	{
+		zbx_free(proc);
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain process information: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	count = sz / sizeof(struct kinfo_proc);
+
+	for (i = 0; i < count; i++)
+	{
+		proc_ok = 0;
+		stat_ok = 0;
+		comm_ok = 0;
+
+		if (NULL == procname || '\0' == *procname || 0 == strcmp(procname, proc[i].ZBX_PROC_COMM))
+			proc_ok = 1;
+
+		if (zbx_proc_stat != ZBX_PROC_STAT_ALL)
+		{
+			switch (zbx_proc_stat) {
+			case ZBX_PROC_STAT_RUN:
+				if (proc[i].ZBX_PROC_STAT == SACTIVE)
+					stat_ok = 1;
+				break;
+			case ZBX_PROC_STAT_SLEEP:
+				if (proc[i].ZBX_PROC_STAT == SACTIVE)
+					stat_ok = 1;
+				break;
+			case ZBX_PROC_STAT_ZOMB:
+				if (proc[i].ZBX_PROC_STAT == SZOMB)
+					stat_ok = 1;
+				break;
+			}
+		}
+		else
+			stat_ok = 1;
+
+		if (NULL != proccomm && '\0' != *proccomm)
+		{
+			if (NULL != (args = get_commandline(&proc[i])))
+				if (NULL != zbx_regexp_match(args, proccomm, NULL))
+					comm_ok = 1;
+		}
+		else
+			comm_ok = 1;
+
+		if (proc_ok && stat_ok && comm_ok)
+			proccount++;
+	}
+	zbx_free(proc);
+out:
+	SET_UI64_RESULT(result, proccount);
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/software.c b/src/libs/zbxsysinfo/dragonfly/software.c
new file mode 100644
index 0000000..24170fc
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/software.c
@@ -0,0 +1,40 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "sysinfo.h"
+#include "log.h"
+
+#ifdef HAVE_SYS_UTSNAME_H
+#       include <sys/utsname.h>
+#endif
+
+int	SYSTEM_SW_ARCH(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	struct utsname	name;
+
+	if (-1 == uname(&name))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, name.machine));
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/swap.c b/src/libs/zbxsysinfo/dragonfly/swap.c
new file mode 100644
index 0000000..ea70cca
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/swap.c
@@ -0,0 +1,91 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "log.h"
+
+int	SYSTEM_SWAP_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+/*
+ *  FreeBSD 7.0 i386
+ */
+#ifdef XSWDEV_VERSION	/* defined in <vm/vm_param.h> */
+	char		*swapdev, *mode;
+	int		mib[16], *mib_dev;
+	size_t		sz, mib_sz;
+	struct xswdev	xsw;
+	zbx_uint64_t	total = 0, used = 0;
+
+	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);
+
+	sz = ARRSIZE(mib);
+	if (-1 == sysctlnametomib("vm.swap_info", mib, &sz))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain \"vm.swap_info\" system parameter: %s",
+				zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	mib_sz = sz + 1;
+	mib_dev = &(mib[sz]);
+
+	*mib_dev = 0;
+	sz = sizeof(xsw);
+
+	while (-1 != sysctl(mib, mib_sz, &xsw, &sz, NULL, 0))
+	{
+		if (NULL == swapdev || '\0' == *swapdev || 0 == strcmp(swapdev, "all")	/* default parameter */
+				|| 0 == strcmp(swapdev, devname(xsw.xsw_dev, S_IFCHR)))
+		{
+			total += (zbx_uint64_t)xsw.xsw_nblks;
+			used += (zbx_uint64_t)xsw.xsw_used;
+		}
+		(*mib_dev)++;
+	}
+
+	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "free"))	/* default parameter */
+		SET_UI64_RESULT(result, (total - used) * getpagesize());
+	else if (0 == strcmp(mode, "total"))
+		SET_UI64_RESULT(result, total * getpagesize());
+	else if (0 == strcmp(mode, "used"))
+		SET_UI64_RESULT(result, used * getpagesize());
+	else if (0 == strcmp(mode, "pfree"))
+		SET_DBL_RESULT(result, total ? ((double)(total - used) * 100.0 / (double)total) : 0.0);
+	else if (0 == strcmp(mode, "pused"))
+		SET_DBL_RESULT(result, total ? ((double)used * 100.0 / (double)total) : 0.0);
+	else
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		return SYSINFO_RET_FAIL;
+	}
+
+	return SYSINFO_RET_OK;
+#else
+	SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for \"xswdev\" structure."));
+	return SYSINFO_RET_FAIL;
+#endif
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/system.c b/src/libs/zbxsysinfo/dragonfly/system.c
new file mode 100644
index 0000000..28c1b52
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/system.c
@@ -0,0 +1,41 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "sysinfo.h"
+#include "log.h"
+
+#ifdef HAVE_SYS_UTSNAME_H
+#	include <sys/utsname.h>
+#endif
+
+int	SYSTEM_UNAME(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+	struct utsname	name;
+
+	if (-1 == uname(&name))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	SET_STR_RESULT(result, zbx_dsprintf(NULL, "%s %s %s %s %s", name.sysname, name.nodename, name.release,
+			name.version, name.machine));
+
+	return SYSINFO_RET_OK;
+}
diff --git a/src/libs/zbxsysinfo/dragonfly/uptime.c b/src/libs/zbxsysinfo/dragonfly/uptime.c
new file mode 100644
index 0000000..450e60c
--- /dev/null
+++ b/src/libs/zbxsysinfo/dragonfly/uptime.c
@@ -0,0 +1,64 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2016 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "common.h"
+#include "sysinfo.h"
+#include "log.h"
+
+int	SYSTEM_UPTIME(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+#if defined(HAVE_SYSINFO_UPTIME)
+	struct sysinfo info;
+
+	if (0 == sysinfo(&info))
+	{
+		SET_UI64_RESULT(result, info.uptime);
+		return SYSINFO_RET_OK;
+	}
+	else
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+#elif defined(HAVE_FUNCTION_SYSCTL_KERN_BOOTTIME)
+	int		mib[2], now;
+	size_t		len;
+	struct timeval	uptime;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_BOOTTIME;
+
+	len = sizeof(uptime);
+
+	if (0 != sysctl(mib, 2, &uptime, &len, NULL, 0))
+	{
+		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
+		return SYSINFO_RET_FAIL;
+	}
+
+	now = time(NULL);
+
+	SET_UI64_RESULT(result, now - uptime.tv_sec);
+
+	return SYSINFO_RET_OK;
+#else
+	SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for uptime information."));
+	return SYSINFO_RET_FAIL;
+#endif
+}
-- 
2.9.2

