Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndris Zeila <andris.zeila@zabbix.com>2020-03-11 12:03:05 +0300
committerAndris Zeila <andris.zeila@zabbix.com>2020-03-11 12:06:38 +0300
commit6516407225cb12182b608b48c25b5e6a29743884 (patch)
treededbac5bcc3b58869475972c1f895bc02320fbe1
parent279dd7ed7feff733c6da43656631d1982db08ba8 (diff)
...G...... [DEV-1434] added net.dns, net.dns.record, vfs.dir.count, vfs.dir.size metric support to agent2 on windows
* commit 'c7b3eed670171325bca880c57e2a15a0d9616c2b': .......... [DEV-1434] fixed warning of windows agent2 compilation .......... [DEV-1434] fixed zabbix_agentd compiling .......... [DEV-1434] added vfs.dir.* metric support .......... [DEV-1434] fixed windows dns metrics .......... [DEV-1434] add net.dns, net.dns.record supoprt via C code .......... [DEV-1434] moved dns metrics to separate file (cherry picked from commit 322a38b03c3217a832bef2c0186306a9bd964b2a)
-rw-r--r--build/mingw/Makefile11
-rw-r--r--build/win32/project/Makefile_agent1
-rw-r--r--include/disk.h2
-rw-r--r--src/go/pkg/zbxlib/checks_windows.go8
-rw-r--r--src/go/pkg/zbxlib/globals_windows.go5
-rw-r--r--src/go/plugins/plugins_windows.go1
-rw-r--r--src/go/plugins/zabbix/sync/sync_windows.go29
-rw-r--r--src/libs/zbxsysinfo/common/Makefile.am2
-rw-r--r--src/libs/zbxsysinfo/common/common.c1
-rw-r--r--src/libs/zbxsysinfo/common/dir.c14
-rw-r--r--src/libs/zbxsysinfo/common/dns.c913
-rw-r--r--src/libs/zbxsysinfo/common/dns.h95
-rw-r--r--src/libs/zbxsysinfo/common/net.c885
-rw-r--r--src/libs/zbxsysinfo/common/net.h69
14 files changed, 1072 insertions, 964 deletions
diff --git a/build/mingw/Makefile b/build/mingw/Makefile
index b4db3603ad3..a2450064cab 100644
--- a/build/mingw/Makefile
+++ b/build/mingw/Makefile
@@ -16,6 +16,7 @@ OBJS = \
$(OUTPUTDIR)\str.o \
$(OUTPUTDIR)\misc.o \
$(OUTPUTDIR)\fatal.o \
+ $(OUTPUTDIR)\disk.o \
$(OUTPUTDIR)\iprange.o \
$(OUTPUTDIR)\md5.o \
$(OUTPUTDIR)\sysinfo.o \
@@ -26,6 +27,8 @@ OBJS = \
$(OUTPUTDIR)\alias.o \
$(OUTPUTDIR)\algodefs.o \
$(OUTPUTDIR)\sysinfo_system.o \
+ $(OUTPUTDIR)\sysinfo_dns.o \
+ $(OUTPUTDIR)\sysinfo_dir.o \
$(OUTPUTDIR)\eventlog.o
CFLAGS := $(CFLAGS) -O2 -g -DUNICODE -DHAVE_STDINT_H=1 -I$(TOPDIR)\build\win32\include -I$(TOPDIR)\build\mingw -I$(TOPDIR)\include
@@ -95,6 +98,9 @@ $(OUTPUTDIR)\tls_version.o: $(TOPDIR)\src\libs\zbxcrypto\tls_version.c
$(OUTPUTDIR)\fatal.o: $(TOPDIR)\src\libs\zbxwin32\fatal.c
$(CC) $(CFLAGS) -c $^ -o $@
+$(OUTPUTDIR)\disk.o: $(TOPDIR)\src\libs\zbxwin32\disk.c
+ $(CC) $(CFLAGS) -c $^ -o $@
+
$(OUTPUTDIR)\threads.o: $(TOPDIR)\src\libs\zbxsys\threads.c
$(CC) $(CFLAGS) -c $^ -o $@
@@ -107,7 +113,10 @@ $(OUTPUTDIR)\sysinfo.o: $(TOPDIR)\src\libs\zbxsysinfo\sysinfo.c
$(OUTPUTDIR)\sysinfo_system.o: $(TOPDIR)\src\libs\zbxsysinfo\common\system.c
$(CC) $(CFLAGS) -c $^ -o $@
-$(OUTPUTDIR)\sysinfo_net.o: $(TOPDIR)\src\libs\zbxsysinfo\common\net.c
+$(OUTPUTDIR)\sysinfo_dns.o: $(TOPDIR)\src\libs\zbxsysinfo\common\dns.c
+ $(CC) $(CFLAGS) -c $^ -o $@
+
+$(OUTPUTDIR)\sysinfo_dir.o: $(TOPDIR)\src\libs\zbxsysinfo\common\dir.c
$(CC) $(CFLAGS) -c $^ -o $@
$(OUTPUTDIR)\vector.o: $(TOPDIR)\src\libs\zbxalgo\vector.c
diff --git a/build/win32/project/Makefile_agent b/build/win32/project/Makefile_agent
index 6d1df2f6726..03103fa7d10 100644
--- a/build/win32/project/Makefile_agent
+++ b/build/win32/project/Makefile_agent
@@ -70,6 +70,7 @@ OBJS = \
..\..\..\src\libs\zbxsysinfo\common\file.o \
..\..\..\src\libs\zbxsysinfo\common\http.o \
..\..\..\src\libs\zbxsysinfo\common\net.o \
+ ..\..\..\src\libs\zbxsysinfo\common\dns.o \
..\..\..\src\libs\zbxsysinfo\common\system.o \
..\..\..\src\libs\zbxsysinfo\common\zabbix_stats.o \
..\..\..\src\libs\zbxsysinfo\simple\ntp.o \
diff --git a/include/disk.h b/include/disk.h
index 9dace978a11..d38bca139a2 100644
--- a/include/disk.h
+++ b/include/disk.h
@@ -20,7 +20,7 @@
#ifndef ZABBIX_DISK_H
#define ZABBIX_DISK_H
-#ifndef _WINDOWS
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
# error "This module is only available for Windows OS"
#endif
diff --git a/src/go/pkg/zbxlib/checks_windows.go b/src/go/pkg/zbxlib/checks_windows.go
index 2dba57cd8eb..32d1d67c62d 100644
--- a/src/go/pkg/zbxlib/checks_windows.go
+++ b/src/go/pkg/zbxlib/checks_windows.go
@@ -69,6 +69,14 @@ func resolveMetric(key string) (cfunc unsafe.Pointer) {
switch key {
case "system.localtime":
cfunc = unsafe.Pointer(C.SYSTEM_LOCALTIME)
+ case "net.dns":
+ cfunc = unsafe.Pointer(C.NET_DNS)
+ case "net.dns.record":
+ cfunc = unsafe.Pointer(C.NET_DNS_RECORD)
+ case "vfs.dir.count":
+ cfunc = unsafe.Pointer(C.VFS_DIR_COUNT)
+ case "vfs.dir.size":
+ cfunc = unsafe.Pointer(C.VFS_DIR_SIZE)
}
return
}
diff --git a/src/go/pkg/zbxlib/globals_windows.go b/src/go/pkg/zbxlib/globals_windows.go
index 3688ad50808..677468464cf 100644
--- a/src/go/pkg/zbxlib/globals_windows.go
+++ b/src/go/pkg/zbxlib/globals_windows.go
@@ -32,6 +32,7 @@ package zbxlib
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/file.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/alias.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/fatal.o
+#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/disk.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/threads.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/iprange.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/md5.o
@@ -41,9 +42,11 @@ package zbxlib
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/algodefs.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/logfiles.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/sysinfo_system.o
+#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/sysinfo_dns.o
+#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/sysinfo_dir.o
#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/eventlog.o
#cgo openssl LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/tls_version.o
-#cgo LDFLAGS: -lpcre -lDbghelp -lpsapi -lws2_32 -lWevtapi
+#cgo LDFLAGS: -lpcre -lDbghelp -lpsapi -lws2_32 -lWevtapi -ldnsapi
#cgo openssl LDFLAGS: -lssl -lcrypto
#cgo LDFLAGS: -Wl,--end-group
diff --git a/src/go/plugins/plugins_windows.go b/src/go/plugins/plugins_windows.go
index 4a278241084..1d4c967058c 100644
--- a/src/go/plugins/plugins_windows.go
+++ b/src/go/plugins/plugins_windows.go
@@ -36,5 +36,6 @@ import (
_ "zabbix.com/plugins/windows/perfmon"
_ "zabbix.com/plugins/windows/services"
_ "zabbix.com/plugins/zabbix/async"
+ _ "zabbix.com/plugins/zabbix/sync"
_ "zabbix.com/plugins/zabbix/stats"
)
diff --git a/src/go/plugins/zabbix/sync/sync_windows.go b/src/go/plugins/zabbix/sync/sync_windows.go
new file mode 100644
index 00000000000..f534c052d36
--- /dev/null
+++ b/src/go/plugins/zabbix/sync/sync_windows.go
@@ -0,0 +1,29 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+package zabbixsync
+
+func getMetrics() []string {
+ return []string{
+ "net.dns", "Checks if DNS service is up.",
+ "net.dns.record", "Performs DNS query.",
+ "vfs.dir.count", "Directory entry count.",
+ "vfs.dir.size", "Directory size (in bytes).",
+ }
+}
diff --git a/src/libs/zbxsysinfo/common/Makefile.am b/src/libs/zbxsysinfo/common/Makefile.am
index 36eaba1ec8b..6a3654f92bb 100644
--- a/src/libs/zbxsysinfo/common/Makefile.am
+++ b/src/libs/zbxsysinfo/common/Makefile.am
@@ -11,6 +11,8 @@ libcommonsysinfo_a_SOURCES = \
cpu.h \
dir.c \
dir.h \
+ dns.c \
+ dns.h \
file.c \
file.h \
http.c \
diff --git a/src/libs/zbxsysinfo/common/common.c b/src/libs/zbxsysinfo/common/common.c
index 7588875cdd8..2b76db7b656 100644
--- a/src/libs/zbxsysinfo/common/common.c
+++ b/src/libs/zbxsysinfo/common/common.c
@@ -26,6 +26,7 @@
#include "dir.h"
#include "http.h"
#include "net.h"
+#include "dns.h"
#include "system.h"
#include "zabbix_stats.h"
#include "zbxexec.h"
diff --git a/src/libs/zbxsysinfo/common/dir.c b/src/libs/zbxsysinfo/common/dir.c
index 894f5eb603a..8aeeb90b84f 100644
--- a/src/libs/zbxsysinfo/common/dir.c
+++ b/src/libs/zbxsysinfo/common/dir.c
@@ -23,7 +23,7 @@
#include "zbxregexp.h"
#include "log.h"
-#ifdef _WINDOWS
+#if defined(_WINDOWS) || defined(__MINGW32__)
# include "disk.h"
#endif
@@ -183,7 +183,7 @@ static int prepare_common_parameters(const AGENT_REQUEST *request, AGENT_RESULT
if ('\0' != *(*dir + 1) && ':' != *(*dir + strlen(*dir) - 2))
zbx_rtrim(*dir, "/\\");
-#ifdef _WINDOWS
+#if defined(_WINDOWS) || defined(__MINGW32__)
if (0 != zbx_stat(*dir, status))
#else
if (0 != lstat(*dir, status))
@@ -422,7 +422,7 @@ static void descriptors_vector_destroy(zbx_vector_ptr_t *descriptors)
* sockets, etc.). *
* *
*****************************************************************************/
-#ifdef _WINDOWS
+#if defined(_WINDOWS) || defined(__MINGW32__)
#define DW2UI64(h,l) ((zbx_uint64_t)h << 32 | l)
#define FT2UT(ft) (time_t)(DW2UI64(ft.dwHighDateTime,ft.dwLowDateTime) / 10000000ULL - 11644473600ULL)
@@ -706,7 +706,7 @@ err1:
return ret;
}
-#else /* not _WINDOWS */
+#else /* not _WINDOWS or __MINGW32__ */
static int vfs_dir_size(AGENT_REQUEST *request, AGENT_RESULT *result)
{
char *dir = NULL;
@@ -873,8 +873,8 @@ int VFS_DIR_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
* Comments: under Widows we only support entry types "file" and "dir" *
* *
*****************************************************************************/
-#ifdef _WINDOWS
-static int vfs_dir_count(const AGENT_REQUEST *request, AGENT_RESULT *result, HANDLE timeout_event)
+#if defined(_WINDOWS) || defined(__MINGW32__)
+static int vfs_dir_count(AGENT_REQUEST *request, AGENT_RESULT *result, HANDLE timeout_event)
{
char *dir = NULL;
int types, max_depth, ret = SYSINFO_RET_FAIL;
@@ -1051,7 +1051,7 @@ err1:
return ret;
}
-#else /* not _WINDOWS */
+#else /* not _WINDOWS or __MINGW32__ */
static int vfs_dir_count(AGENT_REQUEST *request, AGENT_RESULT *result)
{
char *dir = NULL;
diff --git a/src/libs/zbxsysinfo/common/dns.c b/src/libs/zbxsysinfo/common/dns.c
new file mode 100644
index 00000000000..dd43cd386db
--- /dev/null
+++ b/src/libs/zbxsysinfo/common/dns.c
@@ -0,0 +1,913 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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 "comms.h"
+#include "log.h"
+#include "cfg.h"
+
+#include "dns.h"
+#include "zbxalgo.h"
+
+#if defined(_WINDOWS) || defined(__MINGW32__)
+# include <windns.h>
+# pragma comment(lib, "Dnsapi.lib") /* add the library for DnsQuery function */
+#endif
+
+#if defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__)
+
+static const char *decode_type(int q_type)
+{
+ static ZBX_THREAD_LOCAL char buf[16];
+
+ switch (q_type)
+ {
+ case T_A:
+ return "A"; /* address */
+ case T_AAAA:
+ return "AAAA"; /* v6 address */
+ case T_NS:
+ return "NS"; /* name server */
+ case T_MD:
+ return "MD"; /* mail destination */ /* obsolete */
+ case T_MF:
+ return "MF"; /* mail forwarder */ /* obsolete */
+ case T_CNAME:
+ return "CNAME"; /* canonical name */
+ case T_SOA:
+ return "SOA"; /* start of authority */
+ case T_MB:
+ return "MB"; /* mailbox */ /* experimental */
+ case T_MG:
+ return "MG"; /* mail group member */ /* experimental */
+ case T_MR:
+ return "MR"; /* mail rename */ /* experimental */
+ case T_NULL:
+ return "NULL"; /* null */ /* obsolete */
+ case T_WKS:
+ return "WKS"; /* well-known service */ /* obsolete */
+ case T_PTR:
+ return "PTR"; /* domain name pointer */
+ case T_HINFO:
+ return "HINFO"; /* host information */
+ case T_MINFO:
+ return "MINFO"; /* mailbox information */ /* experimental */
+ case T_MX:
+ return "MX"; /* mail exchanger */
+ case T_TXT:
+ return "TXT"; /* text */
+ case T_SRV:
+ return "SRV"; /* service locator */
+ default:
+ zbx_snprintf(buf, sizeof(buf), "T_%d", q_type);
+ return buf;
+ }
+}
+
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
+static char *get_name(unsigned char *msg, unsigned char *msg_end, unsigned char **msg_ptr)
+{
+ int res;
+ static char buffer[MAX_STRING_LEN];
+
+ if (-1 == (res = dn_expand(msg, msg_end, *msg_ptr, buffer, sizeof(buffer))))
+ return NULL;
+
+ *msg_ptr += res;
+
+ return buffer;
+}
+#endif /* !defined(_WINDOWS) && !defined(__MINGW32__)*/
+
+/* Replace zbx_inet_ntop with inet_ntop in case of drop Windows XP/W2k3 support */
+#if defined(_WINDOWS) || defined(__MINGW32__)
+const char *zbx_inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+ struct sockaddr_storage ss;
+ unsigned long s = size;
+
+ memset(&ss, '\0', sizeof(ss));
+ ss.ss_family = af;
+
+ switch(af)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
+ break;
+ default:
+ return NULL;
+ }
+
+ return (0 == WSAAddressToStringA((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s))? dst : NULL;
+}
+#endif
+#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__) */
+
+static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer)
+{
+#if defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__)
+
+ 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;
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
+#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},
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
+ {"WKS", T_WKS},
+#endif
+ {"PTR", T_PTR},
+ {"HINFO", T_HINFO},
+ {"MINFO", T_MINFO},
+ {"MX", T_MX},
+ {"TXT", T_TXT},
+ {"SRV", T_SRV},
+ {NULL}
+ };
+
+#if defined(_WINDOWS) || defined(__MINGW32__)
+ 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 /* defined(_WINDOWS) || defined(__MINGW32__) */
+ 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);
+
+#if !defined(_WINDOWS) && !defined(__MINGW32__)
+ 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;
+ }
+
+#if defined(_WINDOWS) || defined(__MINGW32__)
+ 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 /* !defined(_WINDOWS) && !defined(__MINGW32__) */
+#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 /* defined(_WINDOWS) || defined(__MINGW32__) */
+
+ 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);
+#if defined(_WINDOWS) || defined(__MINGW32__)
+clean_dns:
+ if (DNS_RCODE_NOERROR == res)
+ DnsRecordListFree(pQueryResults, DnsFreeRecordList);
+#endif
+
+ return ret;
+
+#else /* all HAVE_RES_QUERY and _WINDOWS and __MINGW32__not defined */
+
+ return SYSINFO_RET_FAIL;
+
+#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__)*/
+}
+
+int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+ return dns_query(request, result, 1);
+}
+
+int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result)
+{
+ return dns_query(request, result, 0);
+}
diff --git a/src/libs/zbxsysinfo/common/dns.h b/src/libs/zbxsysinfo/common/dns.h
new file mode 100644
index 00000000000..7d87d40b8fa
--- /dev/null
+++ b/src/libs/zbxsysinfo/common/dns.h
@@ -0,0 +1,95 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+#ifndef ZABBIX_SYSINFO_COMMON_DNS_H
+#define ZABBIX_SYSINFO_COMMON_DNS_H
+
+#include "sysinfo.h"
+
+#if defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__)
+
+# if !defined(C_IN) && !defined(_WINDOWS) && !defined(__MINGW32__)
+# define C_IN ns_c_in
+# endif
+
+/* define DNS record types to use common names on all systems, see RFC1035 standard for the types */
+# ifndef T_ANY
+# define T_ANY 255
+# endif
+# ifndef T_A
+# define T_A 1
+# endif
+# ifndef T_NS
+# define T_NS 2
+# endif
+# ifndef T_MD
+# define T_MD 3
+# endif
+# ifndef T_MF
+# define T_MF 4
+# endif
+# ifndef T_CNAME
+# define T_CNAME 5
+# endif
+# ifndef T_SOA
+# define T_SOA 6
+# endif
+# ifndef T_MB
+# define T_MB 7
+# endif
+# ifndef T_MG
+# define T_MG 8
+# endif
+# ifndef T_MR
+# define T_MR 9
+# endif
+# ifndef T_NULL
+# define T_NULL 10
+# endif
+# ifndef T_WKS
+# define T_WKS 11
+# endif
+# ifndef T_PTR
+# define T_PTR 12
+# endif
+# ifndef T_HINFO
+# define T_HINFO 13
+# endif
+# ifndef T_MINFO
+# define T_MINFO 14
+# endif
+# ifndef T_MX
+# define T_MX 15
+# endif
+# ifndef T_TXT
+# define T_TXT 16
+# endif
+# ifndef T_AAAA
+# define T_AAAA 28
+# endif
+# ifndef T_SRV
+# define T_SRV 33
+# endif
+
+#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) || defined(__MINGW32__) */
+
+int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result);
+int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result);
+
+#endif /* ZABBIX_SYSINFO_COMMON_NET_H */
diff --git a/src/libs/zbxsysinfo/common/net.c b/src/libs/zbxsysinfo/common/net.c
index c535a56c204..7d8027990f7 100644
--- a/src/libs/zbxsysinfo/common/net.c
+++ b/src/libs/zbxsysinfo/common/net.c
@@ -27,11 +27,6 @@
#include "net.h"
#include "zbxalgo.h"
-#ifdef _WINDOWS
-# include <windns.h>
-# pragma comment(lib, "Dnsapi.lib") /* add the library for DnsQuery function */
-#endif
-
int tcp_expect(const char *host, unsigned short port, int timeout, const char *request,
int (*validate_func)(const char *), const char *sendtoclose, int *value_int)
{
@@ -114,883 +109,3 @@ int NET_TCP_PORT(AGENT_REQUEST *request, AGENT_RESULT *result)
return ret;
}
-
-#if defined(HAVE_RES_QUERY) || defined(_WINDOWS)
-
-static const char *decode_type(int q_type)
-{
- static ZBX_THREAD_LOCAL char buf[16];
-
- switch (q_type)
- {
- case T_A:
- return "A"; /* address */
- case T_AAAA:
- return "AAAA"; /* v6 address */
- case T_NS:
- return "NS"; /* name server */
- case T_MD:
- return "MD"; /* mail destination */ /* obsolete */
- case T_MF:
- return "MF"; /* mail forwarder */ /* obsolete */
- case T_CNAME:
- return "CNAME"; /* canonical name */
- case T_SOA:
- return "SOA"; /* start of authority */
- case T_MB:
- return "MB"; /* mailbox */ /* experimental */
- case T_MG:
- return "MG"; /* mail group member */ /* experimental */
- case T_MR:
- return "MR"; /* mail rename */ /* experimental */
- case T_NULL:
- return "NULL"; /* null */ /* obsolete */
- case T_WKS:
- return "WKS"; /* well-known service */ /* obsolete */
- case T_PTR:
- return "PTR"; /* domain name pointer */
- case T_HINFO:
- return "HINFO"; /* host information */
- case T_MINFO:
- return "MINFO"; /* mailbox information */ /* experimental */
- case T_MX:
- return "MX"; /* mail exchanger */
- case T_TXT:
- return "TXT"; /* text */
- case T_SRV:
- return "SRV"; /* service locator */
- default:
- zbx_snprintf(buf, sizeof(buf), "T_%d", q_type);
- return buf;
- }
-}
-
-#if !defined(_WINDOWS)
-static char *get_name(unsigned char *msg, unsigned char *msg_end, unsigned char **msg_ptr)
-{
- int res;
- static char buffer[MAX_STRING_LEN];
-
- if (-1 == (res = dn_expand(msg, msg_end, *msg_ptr, buffer, sizeof(buffer))))
- return NULL;
-
- *msg_ptr += res;
-
- return buffer;
-}
-#endif /* !defined(_WINDOWS) */
-
-/* Replace zbx_inet_ntop with inet_ntop in case of drop Windows XP/W2k3 support */
-#if defined(_WINDOWS)
-const char *zbx_inet_ntop(int af, const void *src, char *dst, size_t size)
-{
- struct sockaddr_storage ss;
- unsigned long s = size;
-
- memset(&ss, '\0', sizeof(ss));
- ss.ss_family = af;
-
- switch(af)
- {
- case AF_INET:
- ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
- break;
- default:
- return NULL;
- }
-
- return (0 == WSAAddressToStringA((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s))? dst : NULL;
-}
-#endif
-#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */
-
-static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer)
-{
-#if defined(HAVE_RES_QUERY) || defined(_WINDOWS)
-
- size_t offset = 0;
- int res, type, retrans, retry, use_tcp, i, ret = SYSINFO_RET_FAIL, ip_type = AF_INET;
- char *ip, zone[MAX_STRING_LEN], buffer[MAX_STRING_LEN], *zone_str, *param,
- tmp[MAX_STRING_LEN];
- struct in_addr inaddr;
- struct in6_addr in6addr;
-#ifndef _WINDOWS
-#if defined(HAVE_RES_NINIT) && !defined(_AIX)
- /* It seems that on some AIX systems with no updates installed res_ninit() can */
- /* corrupt stack (see ZBX-14559). Use res_init() on AIX. */
- struct __res_state res_state_local;
-#else /* thread-unsafe resolver API */
- int saved_retrans, saved_retry, saved_nscount = 0;
- unsigned long saved_options;
- struct sockaddr_in saved_ns;
-# if defined(HAVE_RES_U_EXT) /* thread-unsafe resolver API /Linux/ */
- int save_nssocks, saved_nscount6;
-# endif
-#endif
-
-#if defined(HAVE_RES_EXT_EXT) /* AIX */
- union res_sockaddr_union saved_ns6;
-#elif defined(HAVE_RES_U_EXT_EXT) /* BSD */
- struct sockaddr_in6 saved_ns6;
-#else
- struct sockaddr_in6 *saved_ns6;
-#endif
- struct sockaddr_in6 sockaddrin6;
- struct addrinfo hint, *hres = NULL;
-#endif
- typedef struct
- {
- const char *name;
- int type;
- }
- resolv_querytype_t;
-
- static const resolv_querytype_t qt[] =
- {
- {"ANY", T_ANY},
- {"A", T_A},
- {"AAAA", T_AAAA},
- {"NS", T_NS},
- {"MD", T_MD},
- {"MF", T_MF},
- {"CNAME", T_CNAME},
- {"SOA", T_SOA},
- {"MB", T_MB},
- {"MG", T_MG},
- {"MR", T_MR},
- {"NULL", T_NULL},
-#ifndef _WINDOWS
- {"WKS", T_WKS},
-#endif
- {"PTR", T_PTR},
- {"HINFO", T_HINFO},
- {"MINFO", T_MINFO},
- {"MX", T_MX},
- {"TXT", T_TXT},
- {"SRV", T_SRV},
- {NULL}
- };
-
-#ifdef _WINDOWS
- PDNS_RECORD pQueryResults, pDnsRecord;
- wchar_t *wzone;
- char tmp2[MAX_STRING_LEN];
- DWORD options;
-#else
- char *name;
- unsigned char *msg_end, *msg_ptr, *p;
- int num_answers, num_query, q_type, q_class, q_len, value, c, n;
- struct servent *s;
- HEADER *hp;
- struct protoent *pr;
-#if PACKETSZ > 1024
- unsigned char buf[PACKETSZ];
-#else
- unsigned char buf[1024];
-#endif
-
- typedef union
- {
- HEADER h;
-#if defined(NS_PACKETSZ)
- unsigned char buffer[NS_PACKETSZ];
-#elif defined(PACKETSZ)
- unsigned char buffer[PACKETSZ];
-#else
- unsigned char buffer[512];
-#endif
- }
- answer_t;
-
- answer_t answer;
-#endif /* _WINDOWS */
- zbx_vector_str_t answers;
-
- *buffer = '\0';
-
- if (6 < request->nparam)
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
- return SYSINFO_RET_FAIL;
- }
-
- ip = get_rparam(request, 0);
- zone_str = get_rparam(request, 1);
-
-#ifndef _WINDOWS
- memset(&hint, '\0', sizeof(hint));
- hint.ai_family = PF_UNSPEC;
- hint.ai_flags = AI_NUMERICHOST;
-
- if (NULL != ip && '\0' != *ip && 0 == getaddrinfo(ip, NULL, &hint, &hres) && AF_INET6 == hres->ai_family)
- ip_type = hres->ai_family;
-
- if (NULL != hres)
- freeaddrinfo(hres);
-#endif
- if (NULL == zone_str || '\0' == *zone_str)
- strscpy(zone, "zabbix.com");
- else
- strscpy(zone, zone_str);
-
- param = get_rparam(request, 2);
-
- if (NULL == param || '\0' == *param)
- type = T_SOA;
- else
- {
- for (i = 0; NULL != qt[i].name; i++)
- {
- if (0 == strcasecmp(qt[i].name, param))
- {
- type = qt[i].type;
- break;
- }
- }
-
- if (NULL == qt[i].name)
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
- return SYSINFO_RET_FAIL;
- }
- }
-
- param = get_rparam(request, 3);
-
- if (NULL == param || '\0' == *param)
- retrans = 1;
- else if (SUCCEED != is_uint31(param, &retrans) || 0 == retrans)
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
- return SYSINFO_RET_FAIL;
- }
-
- param = get_rparam(request, 4);
-
- if (NULL == param || '\0' == *param)
- retry = 2;
- else if (SUCCEED != is_uint31(param, &retry) || 0 == retry)
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter."));
- return SYSINFO_RET_FAIL;
- }
-
- param = get_rparam(request, 5);
-
- if (NULL == param || '\0' == *param || 0 == strcmp(param, "udp"))
- use_tcp = 0;
- else if (0 == strcmp(param, "tcp"))
- use_tcp = 1;
- else
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid sixth parameter."));
- return SYSINFO_RET_FAIL;
- }
-
-#ifdef _WINDOWS
- options = DNS_QUERY_STANDARD | DNS_QUERY_BYPASS_CACHE;
- if (0 != use_tcp)
- options |= DNS_QUERY_USE_TCP_ONLY;
-
- wzone = zbx_utf8_to_unicode(zone);
- res = DnsQuery(wzone, type, options, NULL, &pQueryResults, NULL);
- zbx_free(wzone);
-
- if (1 == short_answer)
- {
- SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1);
- ret = SYSINFO_RET_OK;
- goto clean_dns;
- }
-
- if (DNS_RCODE_NOERROR != res)
- {
- SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot perform DNS query: [%d]", res));
- return SYSINFO_RET_FAIL;
- }
-
- pDnsRecord = pQueryResults;
- zbx_vector_str_create(&answers);
-
- while (NULL != pDnsRecord)
- {
- if (DnsSectionAnswer != pDnsRecord->Flags.S.Section)
- {
- pDnsRecord = pDnsRecord->pNext;
- continue;
- }
-
- if (NULL == pDnsRecord->pName)
- goto clean;
-
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s",
- zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp)));
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s",
- decode_type(pDnsRecord->wType));
-
- switch (pDnsRecord->wType)
- {
- case T_A:
- inaddr.s_addr = pDnsRecord->Data.A.IpAddress;
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- inet_ntoa(inaddr));
- break;
- case T_AAAA:
- memcpy(&in6addr.s6_addr, &(pDnsRecord->Data.AAAA.Ip6Address), sizeof(in6addr.s6_addr));
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp)));
- break;
- case T_NS:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_MD:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_MF:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_CNAME:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_SOA:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)),
- zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)),
- pDnsRecord->Data.SOA.dwSerialNo,
- pDnsRecord->Data.SOA.dwRefresh,
- pDnsRecord->Data.SOA.dwRetry,
- pDnsRecord->Data.SOA.dwExpire,
- pDnsRecord->Data.SOA.dwDefaultTtl);
- break;
- case T_MB:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_MG:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_MR:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_NULL:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu",
- pDnsRecord->Data.Null.dwByteCount);
- break;
- case T_PTR:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp)));
- break;
- case T_HINFO:
- for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++)
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp)));
- break;
- case T_MINFO:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)),
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2)));
- break;
- case T_MX:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s",
- pDnsRecord->Data.MX.wPreference,
- zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp)));
- break;
- case T_TXT:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");
-
- for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++)
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ",
- zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp)));
-
- if (0 < i)
- offset -= 1; /* remove the trailing space */
-
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");
-
- break;
- case T_SRV:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s",
- pDnsRecord->Data.SRV.wPriority,
- pDnsRecord->Data.SRV.wWeight,
- pDnsRecord->Data.SRV.wPort,
- zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp)));
- break;
- default:
- break;
- }
-
- zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");
-
- pDnsRecord = pDnsRecord->pNext;
- zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer));
- offset = 0;
- *buffer = '\0';
- }
-#else /* not _WINDOWS */
-#if defined(HAVE_RES_NINIT) && !defined(_AIX)
- memset(&res_state_local, 0, sizeof(res_state_local));
- if (-1 == res_ninit(&res_state_local)) /* initialize always, settings might have changed */
-#else
- if (-1 == res_init()) /* initialize always, settings might have changed */
-#endif
- {
- SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize DNS subsystem: %s", zbx_strerror(errno)));
- return SYSINFO_RET_FAIL;
- }
-
-#if defined(HAVE_RES_NINIT) && !defined(_AIX)
- if (-1 == (res = res_nmkquery(&res_state_local, QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
-#else
- if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
-#endif
- {
- SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot create DNS query: %s", zbx_strerror(errno)));
- return SYSINFO_RET_FAIL;
- }
-
- if (NULL != ip && '\0' != *ip && AF_INET == ip_type)
- {
- if (0 == inet_aton(ip, &inaddr))
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IP address."));
- return SYSINFO_RET_FAIL;
- }
-
-#if defined(HAVE_RES_NINIT) && !defined(_AIX)
- res_state_local.nsaddr_list[0].sin_addr = inaddr;
- res_state_local.nsaddr_list[0].sin_family = AF_INET;
- res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
- res_state_local.nscount = 1;
-#else /* thread-unsafe resolver API */
- memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
- saved_nscount = _res.nscount;
-
- _res.nsaddr_list[0].sin_addr = inaddr;
- _res.nsaddr_list[0].sin_family = AF_INET;
- _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
- _res.nscount = 1;
-#endif
- }
- else if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type)
- {
- if (0 == inet_pton(ip_type, ip, &in6addr))
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IPv6 address."));
- return SYSINFO_RET_FAIL;
- }
-
- memset(&sockaddrin6, '\0', sizeof(sockaddrin6));
-#if defined(HAVE_RES_SIN6_LEN)
- sockaddrin6.sin6_len = sizeof(sockaddrin6);
-#endif
- sockaddrin6.sin6_family = AF_INET6;
- sockaddrin6.sin6_addr = in6addr;
- sockaddrin6.sin6_port = htons(ZBX_DEFAULT_DNS_PORT);
-#if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT))
- memset(&res_state_local.nsaddr_list[0], '\0', sizeof(res_state_local.nsaddr_list[0]));
-# ifdef HAVE_RES_U_EXT /* Linux */
- saved_ns6 = res_state_local._u._ext.nsaddrs[0];
- res_state_local._u._ext.nsaddrs[0] = &sockaddrin6;
- res_state_local._u._ext.nssocks[0] = -1;
- res_state_local._u._ext.nscount6 = 1; /* CentOS */
-# elif HAVE_RES_U_EXT_EXT /* BSD */
- if (NULL != res_state_local._u._ext.ext)
- memcpy(res_state_local._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6));
-
- res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
-# endif
- res_state_local.nscount = 1;
-#else
- memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
- saved_nscount = _res.nscount;
-# if defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT) || defined(HAVE_RES_EXT_EXT)
- memset(&_res.nsaddr_list[0], '\0', sizeof(_res.nsaddr_list[0]));
- _res.nscount = 1;
-# endif
-# if defined(HAVE_RES_U_EXT) /* thread-unsafe resolver API /Linux/ */
- saved_nscount6 = _res._u._ext.nscount6;
- saved_ns6 = _res._u._ext.nsaddrs[0];
- save_nssocks = _res._u._ext.nssocks[0];
- _res._u._ext.nsaddrs[0] = &sockaddrin6;
- _res._u._ext.nssocks[0] = -1;
- _res._u._ext.nscount6 = 1;
-# elif defined(HAVE_RES_U_EXT_EXT) /* thread-unsafe resolver API /BSD/ */
- memcpy(&saved_ns6, _res._u._ext.ext, sizeof(saved_ns6));
- _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
-
- if (NULL != _res._u._ext.ext)
- memcpy(_res._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6));
-# elif defined(HAVE_RES_EXT_EXT) /* thread-unsafe resolver API /AIX/ */
- memcpy(&saved_ns6, &(_res._ext.ext.nsaddrs[0]), sizeof(saved_ns6));
- memcpy(&_res._ext.ext.nsaddrs[0], &sockaddrin6, sizeof(sockaddrin6));
-# endif /* #if defined(HAVE_RES_U_EXT) */
-#endif /* #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) */
- }
-
-#if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT))
- if (0 != use_tcp)
- res_state_local.options |= RES_USEVC;
-
- res_state_local.retrans = retrans;
- res_state_local.retry = retry;
-
- res = res_nsend(&res_state_local, buf, res, answer.buffer, sizeof(answer.buffer));
-
-# ifdef HAVE_RES_U_EXT /* Linux */
- if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type)
- res_state_local._u._ext.nsaddrs[0] = saved_ns6;
-# endif
-# ifdef HAVE_RES_NDESTROY
- res_ndestroy(&res_state_local);
-# else
- res_nclose(&res_state_local);
-# endif
-#else /* thread-unsafe resolver API */
- saved_options = _res.options;
- saved_retrans = _res.retrans;
- saved_retry = _res.retry;
-
- if (0 != use_tcp)
- _res.options |= RES_USEVC;
-
- _res.retrans = retrans;
- _res.retry = retry;
-
- res = res_send(buf, res, answer.buffer, sizeof(answer.buffer));
-
- _res.options = saved_options;
- _res.retrans = saved_retrans;
- _res.retry = saved_retry;
-
- if (NULL != ip && '\0' != *ip)
- {
- if (AF_INET6 == ip_type)
- {
-# if defined(HAVE_RES_U_EXT) /* Linux */
- _res._u._ext.nsaddrs[0] = saved_ns6;
- _res._u._ext.nssocks[0] = save_nssocks;
- _res._u._ext.nscount6 = saved_nscount6;
-# elif defined(HAVE_RES_U_EXT_EXT) /* BSD */
- if (NULL != _res._u._ext.ext)
- memcpy(_res._u._ext.ext, &saved_ns6, sizeof(saved_ns6));
-# elif defined(HAVE_RES_EXT_EXT) /* AIX */
- memcpy(&_res._ext.ext.nsaddrs[0], &saved_ns6, sizeof(saved_ns6));
-# endif
- }
-
- memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in));
- _res.nscount = saved_nscount;
- }
-#endif
- hp = (HEADER *)answer.buffer;
-
- if (1 == short_answer)
- {
- SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1);
- return SYSINFO_RET_OK;
- }
-
- if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res)
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query."));
- return SYSINFO_RET_FAIL;
- }
-
- msg_end = answer.buffer + res;
-
- num_answers = ntohs(answer.h.ancount);
- num_query = ntohs(answer.h.qdcount);
-
- msg_ptr = answer.buffer + HFIXEDSZ;
- zbx_vector_str_create(&answers);
-
- /* skipping query records */
- for (; 0 < num_query && msg_ptr < msg_end; num_query--)
- msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ;
-
- for (; 0 < num_answers && msg_ptr < msg_end; num_answers--)
- {
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- ret = SYSINFO_RET_FAIL;
- goto clean;
- }
-
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name);
-
- GETSHORT(q_type, msg_ptr);
- GETSHORT(q_class, msg_ptr);
- msg_ptr += INT32SZ; /* skipping TTL */
- GETSHORT(q_len, msg_ptr);
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type));
-
- switch (q_type)
- {
- case T_A:
- switch (q_class)
- {
- case C_IN:
- case C_HS:
- memcpy(&inaddr, msg_ptr, INADDRSZ);
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- inet_ntoa(inaddr));
- break;
- default:
- ;
- }
-
- msg_ptr += q_len;
-
- break;
- case T_AAAA:
- switch (q_class)
- {
- case C_IN:
- case C_HS:
- memcpy(&in6addr, msg_ptr, IN6ADDRSZ);
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
- inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp)));
- break;
- default:
- ;
- }
-
- msg_ptr += q_len;
-
- break;
- case T_NS:
- case T_CNAME:
- case T_MB:
- case T_MD:
- case T_MF:
- case T_MG:
- case T_MR:
- case T_PTR:
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
- break;
- case T_MX:
- GETSHORT(value, msg_ptr); /* preference */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* exchange */
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
-
- break;
- case T_SOA:
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* source host */
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
-
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* administrator */
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
-
- GETLONG(value, msg_ptr); /* serial number */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- GETLONG(value, msg_ptr); /* refresh time */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- GETLONG(value, msg_ptr); /* retry time */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- GETLONG(value, msg_ptr); /* expire time */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- GETLONG(value, msg_ptr); /* minimum TTL */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- break;
- case T_NULL:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len);
- msg_ptr += q_len;
- break;
- case T_WKS:
- if (INT32SZ + 1 > q_len)
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
-
- p = msg_ptr + q_len;
-
- memcpy(&inaddr, msg_ptr, INADDRSZ);
- msg_ptr += INT32SZ;
-
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr));
-
- if (NULL != (pr = getprotobynumber(*msg_ptr)))
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name);
- else
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr);
-
- msg_ptr++;
- n = 0;
-
- while (msg_ptr < p)
- {
- c = *msg_ptr++;
-
- do
- {
- if (0 != (c & 0200))
- {
- s = getservbyport((int)htons(n), pr ? pr->p_name : NULL);
-
- if (NULL != s)
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name);
- else
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n);
- }
-
- c <<= 1;
- }
- while (0 != (++n & 07));
- }
-
- break;
- case T_HINFO:
- p = msg_ptr + q_len;
- c = *msg_ptr++;
-
- if (0 != c)
- {
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
- msg_ptr += c;
- }
-
- if (msg_ptr < p)
- {
- c = *msg_ptr++;
-
- if (0 != c)
- {
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
- msg_ptr += c;
- }
- }
-
- break;
- case T_MINFO:
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox responsible for mailing lists */
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
-
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox for error messages */
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
-
- break;
- case T_TXT:
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");
- p = msg_ptr + q_len;
-
- while (msg_ptr < p)
- {
- for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--)
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++);
- }
-
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");
-
- break;
- case T_SRV:
- GETSHORT(value, msg_ptr); /* priority */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- GETSHORT(value, msg_ptr); /* weight */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- GETSHORT(value, msg_ptr); /* port */
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);
-
- if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* target */
- {
- SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
- return SYSINFO_RET_FAIL;
- }
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
-
- break;
- default:
- msg_ptr += q_len;
- break;
- }
-
- zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");
-
- zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer));
- offset = 0;
- *buffer = '\0';
- }
-#endif /* _WINDOWS */
-
- zbx_vector_str_sort(&answers, ZBX_DEFAULT_STR_COMPARE_FUNC);
-
- for (i = 0; i < answers.values_num; i++)
- offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s", answers.values[i]);
-
- if (0 != offset)
- buffer[--offset] = '\0';
-
- SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer));
- ret = SYSINFO_RET_OK;
-
-clean:
- zbx_vector_str_clear_ext(&answers, zbx_str_free);
- zbx_vector_str_destroy(&answers);
-#ifdef _WINDOWS
-clean_dns:
- if (DNS_RCODE_NOERROR == res)
- DnsRecordListFree(pQueryResults, DnsFreeRecordList);
-#endif
-
- return ret;
-
-#else /* both HAVE_RES_QUERY and _WINDOWS not defined */
-
- return SYSINFO_RET_FAIL;
-
-#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */
-}
-
-int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result)
-{
- return dns_query(request, result, 1);
-}
-
-int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result)
-{
- return dns_query(request, result, 0);
-}
diff --git a/src/libs/zbxsysinfo/common/net.h b/src/libs/zbxsysinfo/common/net.h
index 0141abf08b8..fe0f5f61e74 100644
--- a/src/libs/zbxsysinfo/common/net.h
+++ b/src/libs/zbxsysinfo/common/net.h
@@ -22,73 +22,6 @@
#include "sysinfo.h"
-#if defined(HAVE_RES_QUERY) || defined(_WINDOWS)
-
-# if !defined(C_IN) && !defined(_WINDOWS)
-# define C_IN ns_c_in
-# endif
-
-/* define DNS record types to use common names on all systems, see RFC1035 standard for the types */
-# ifndef T_ANY
-# define T_ANY 255
-# endif
-# ifndef T_A
-# define T_A 1
-# endif
-# ifndef T_NS
-# define T_NS 2
-# endif
-# ifndef T_MD
-# define T_MD 3
-# endif
-# ifndef T_MF
-# define T_MF 4
-# endif
-# ifndef T_CNAME
-# define T_CNAME 5
-# endif
-# ifndef T_SOA
-# define T_SOA 6
-# endif
-# ifndef T_MB
-# define T_MB 7
-# endif
-# ifndef T_MG
-# define T_MG 8
-# endif
-# ifndef T_MR
-# define T_MR 9
-# endif
-# ifndef T_NULL
-# define T_NULL 10
-# endif
-# ifndef T_WKS
-# define T_WKS 11
-# endif
-# ifndef T_PTR
-# define T_PTR 12
-# endif
-# ifndef T_HINFO
-# define T_HINFO 13
-# endif
-# ifndef T_MINFO
-# define T_MINFO 14
-# endif
-# ifndef T_MX
-# define T_MX 15
-# endif
-# ifndef T_TXT
-# define T_TXT 16
-# endif
-# ifndef T_AAAA
-# define T_AAAA 28
-# endif
-# ifndef T_SRV
-# define T_SRV 33
-# endif
-
-#endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */
-
extern char *CONFIG_SOURCE_IP;
#define ZBX_TCP_EXPECT_FAIL -1
@@ -98,8 +31,6 @@ extern char *CONFIG_SOURCE_IP;
int tcp_expect(const char *host, unsigned short port, int timeout, const char *request,
int(*validate_func)(const char *), const char *sendtoclose, int *value_int);
-int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result);
int NET_TCP_PORT(AGENT_REQUEST *request, AGENT_RESULT *result);
#endif /* ZABBIX_SYSINFO_COMMON_NET_H */