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
path: root/src
diff options
context:
space:
mode:
authorAndris Zeila <andris.zeila@zabbix.com>2022-02-17 11:28:39 +0300
committerAndris Zeila <andris.zeila@zabbix.com>2022-02-17 11:28:39 +0300
commit6f2d97e4bd0bb5b22ce41857967f742d7e98860b (patch)
treea60d975ac564c473c0bba3bec7b9342aa4fb910b /src
parentfbe2982527dd41559cb411377d7b09dc63cce57d (diff)
parent538e9fe6e864b0fedd51cbbf5761f1f7a26df699 (diff)
.......... [ZBX-20487] merged branch 'release/5.4' of ssh://git.zabbix.lan:7999/zbx/zabbix into feature/ZBX-20487-5.4
Diffstat (limited to 'src')
-rw-r--r--src/go/go.mod3
-rw-r--r--src/go/go.sum11
-rw-r--r--src/go/internal/agent/resultcache/diskcache.go65
-rw-r--r--src/go/pkg/version/version.go4
-rw-r--r--src/go/pkg/zbxlib/checks_darwin.go6
-rw-r--r--src/go/pkg/zbxlib/checks_linux.go6
-rw-r--r--src/go/pkg/zbxlib/checks_windows.go6
-rw-r--r--src/go/plugins/net/dns/dns.go502
-rw-r--r--src/go/plugins/net/dns/dns_nix.go (renamed from src/go/plugins/zabbix/sync/sync_nix.go)28
-rw-r--r--src/go/plugins/net/dns/dns_windows.go79
-rw-r--r--src/go/plugins/plugins_darwin.go1
-rw-r--r--src/go/plugins/plugins_linux.go2
-rw-r--r--src/go/plugins/plugins_windows.go2
-rw-r--r--src/go/plugins/smart/smart.go125
-rw-r--r--src/go/plugins/smart/smart_test.go184
-rw-r--r--src/go/plugins/smart/smartfs.go28
-rw-r--r--src/go/plugins/system/cpu/cpu.go18
-rw-r--r--src/go/plugins/system/cpu/cpu_linux.go29
-rw-r--r--src/go/plugins/system/cpu/cpu_linux_test.go136
-rw-r--r--src/go/plugins/system/cpu/cpu_windows.go9
-rw-r--r--src/go/plugins/zabbix/sync/sync.go41
-rw-r--r--src/go/plugins/zabbix/sync/sync_windows.go27
-rw-r--r--src/libs/zbxcrypto/tls.c183
-rw-r--r--src/libs/zbxdbhigh/proxy.c16
-rw-r--r--src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java4
-rw-r--r--src/zabbix_proxy/datasender/datasender.c7
-rw-r--r--src/zabbix_proxy/proxyconfig/proxyconfig.c7
27 files changed, 1230 insertions, 299 deletions
diff --git a/src/go/go.mod b/src/go/go.mod
index 5add1054209..567ebe9a064 100644
--- a/src/go/go.mod
+++ b/src/go/go.mod
@@ -20,10 +20,11 @@ require (
github.com/mattn/go-sqlite3 v1.14.8
github.com/mediocregopher/radix/v3 v3.5.0
github.com/memcachier/mc/v3 v3.0.1
+ github.com/miekg/dns v1.1.43
github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce
github.com/omeid/go-yarn v0.0.1
github.com/pkg/errors v0.9.1 // indirect
- golang.org/x/sys v0.0.0-20210104204734-6f8348627aad
+ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
diff --git a/src/go/go.sum b/src/go/go.sum
index 9837d44acc3..7267d198195 100644
--- a/src/go/go.sum
+++ b/src/go/go.sum
@@ -134,6 +134,8 @@ github.com/mediocregopher/radix/v3 v3.5.0 h1:8QHQmNh2ne9aFxTD3z63u/bkPPiOtknHoz8
github.com/mediocregopher/radix/v3 v3.5.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/memcachier/mc/v3 v3.0.1 h1:Os/fUl/8c+hc1qWgjv5hNK0JI6GxKUOuehzB/UmjLP0=
github.com/memcachier/mc/v3 v3.0.1/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug=
+github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
+github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce h1:TqjP/BTDrwN7zP9xyXVuLsMBXYMt6LLYi55PlrIcq8U=
github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:ifHPsLndGGzvgzcaXUvzmt6LxKT4pJ+uzEhtnMt+f7A=
github.com/omeid/go-yarn v0.0.1 h1:mUQExNwUrYn7tZRwQdsUuoQWHIujtjjpjb/PAtUj9dk=
@@ -185,9 +187,12 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -201,6 +206,10 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad h1:MCsdmFSdEd4UEa5TKS5JztCRHK/WtvNei1edOj5RSRo=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
diff --git a/src/go/internal/agent/resultcache/diskcache.go b/src/go/internal/agent/resultcache/diskcache.go
index fc8b4e112d6..607c7c41db3 100644
--- a/src/go/internal/agent/resultcache/diskcache.go
+++ b/src/go/internal/agent/resultcache/diskcache.go
@@ -22,6 +22,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
+ "sync"
"sync/atomic"
"time"
@@ -41,6 +42,10 @@ const (
DataLimit = 10000
)
+var (
+ cacheLock sync.Mutex
+)
+
type DiskCache struct {
*cacheData
storagePeriod int64
@@ -153,36 +158,29 @@ func (c *DiskCache) updateLogRange() (err error) {
return
}
-func (c *DiskCache) upload(u Uploader) (err error) {
- var results []*AgentData
+func (c *DiskCache) resultsGet() (results []*AgentData, maxDataId uint64, maxLogId uint64, err error) {
var result *AgentData
var rows *sql.Rows
- var maxDataId, maxLogId uint64
+
+ cacheLock.Lock()
+ defer cacheLock.Unlock()
if rows, err = c.database.Query(fmt.Sprintf("SELECT "+
"id,itemid,lastlogsize,mtime,state,value,eventsource,eventid,eventseverity,eventtimestamp,clock,ns"+
" FROM data_%d ORDER BY id LIMIT ?", c.serverID), DataLimit); err != nil {
c.Errf("cannot select from data table: %s", err.Error())
- return
+ return nil, 0, 0, err
}
-
- defer func() {
- if err != nil && (c.lastError == nil || err.Error() != c.lastError.Error()) {
- c.Warningf("cannot upload history data: %s", err)
- c.lastError = err
- }
- }()
-
for rows.Next() {
if result, err = c.resultFetch(rows); err != nil {
rows.Close()
- return
+ return nil, 0, 0, err
}
result.persistent = false
results = append(results, result)
}
if err = rows.Err(); err != nil {
- return
+ return nil, 0, 0, err
}
dataLen := len(results)
if dataLen != 0 {
@@ -192,29 +190,44 @@ func (c *DiskCache) upload(u Uploader) (err error) {
if dataLen != DataLimit {
if rows, err = c.database.Query(fmt.Sprintf("SELECT "+
"id,itemid,lastlogsize,mtime,state,value,eventsource,eventid,eventseverity,eventtimestamp,clock,ns"+
- " FROM log_%d ORDER BY id LIMIT ?", c.serverID),
- DataLimit-len(results)); err != nil {
-
+ " FROM log_%d ORDER BY id LIMIT ?", c.serverID), DataLimit-len(results)); err != nil {
c.Errf("cannot select from log table: %s", err.Error())
- return
+ return nil, 0, 0, err
}
-
for rows.Next() {
if result, err = c.resultFetch(rows); err != nil {
rows.Close()
- return
+ return nil, 0, 0, err
}
result.persistent = true
results = append(results, result)
}
if err = rows.Err(); err != nil {
- return
+ return nil, 0, 0, err
}
if len(results) != dataLen {
maxLogId = results[len(results)-1].Id
}
}
+ return results, maxDataId, maxLogId, nil
+}
+
+func (c *DiskCache) upload(u Uploader) (err error) {
+ var results []*AgentData
+ var maxDataId, maxLogId uint64
+
+ defer func() {
+ if err != nil && (c.lastError == nil || err.Error() != c.lastError.Error()) {
+ c.Warningf("cannot upload history data: %s", err)
+ c.lastError = err
+ }
+ }()
+
+ if results, maxDataId, maxLogId, err = c.resultsGet(); err != nil {
+ return
+ }
+
if len(results) == 0 {
return
}
@@ -250,6 +263,8 @@ func (c *DiskCache) upload(u Uploader) (err error) {
c.Warningf("history upload to [%s %s] is working again", u.Addr(), u.Hostname())
c.lastError = nil
}
+ cacheLock.Lock()
+ defer cacheLock.Unlock()
if maxDataId != 0 {
if _, err = c.database.Exec(fmt.Sprintf("DELETE FROM data_%d WHERE id<=?", c.serverID), maxDataId); err != nil {
return fmt.Errorf("cannot delete from data_%d: %s", c.serverID, err)
@@ -334,7 +349,11 @@ func (c *DiskCache) write(r *plugin.Result) {
var stmt *sql.Stmt
now := time.Now().Unix()
+ cacheLock.Lock()
+ defer cacheLock.Unlock()
+
if r.Persistent {
+
if c.oldestLog == 0 {
c.oldestLog = clock
}
@@ -359,6 +378,7 @@ func (c *DiskCache) write(r *plugin.Result) {
if _, err = c.database.Exec(query, now-c.storagePeriod); err != nil {
c.Errf("cannot delete old data from data_%d : %s", c.serverID, err)
}
+
c.oldestData, err = c.getOldestWriteClock(tableName("data", c.serverID))
if err != nil {
c.Errf("cannot query minimum write clock from data_%d : %s", c.serverID, err)
@@ -426,6 +446,9 @@ func (c *DiskCache) init(options *agent.AgentOptions) {
c.updateOptions(options)
var err error
+ cacheLock.Lock()
+ defer cacheLock.Unlock()
+
c.database, err = sql.Open("sqlite3", agent.Options.PersistentBufferFile)
if err != nil {
return
diff --git a/src/go/pkg/version/version.go b/src/go/pkg/version/version.go
index aa618304ebc..b219bfd722a 100644
--- a/src/go/pkg/version/version.go
+++ b/src/go/pkg/version/version.go
@@ -26,10 +26,10 @@ import (
)
const (
- ZABBIX_REVDATE = "25 January 2022"
+ ZABBIX_REVDATE = "31 January 2022"
ZABBIX_VERSION_MAJOR = 5
ZABBIX_VERSION_MINOR = 4
- ZABBIX_VERSION_PATCH = 10
+ ZABBIX_VERSION_PATCH = 11
ZABBIX_VERSION_RC = "rc1"
ZABBIX_VERSION_RC_NUM = "{ZABBIX_RC_NUM}"
ZABBIX_VERSION_REVISION = "{ZABBIX_REVISION}"
diff --git a/src/go/pkg/zbxlib/checks_darwin.go b/src/go/pkg/zbxlib/checks_darwin.go
index 83e7d8ac546..52b69a7f060 100644
--- a/src/go/pkg/zbxlib/checks_darwin.go
+++ b/src/go/pkg/zbxlib/checks_darwin.go
@@ -31,8 +31,6 @@ package zbxlib
#include "sysinfo.h"
int SYSTEM_LOCALTIME(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result);
int SYSTEM_BOOTTIME(AGENT_REQUEST *request, AGENT_RESULT *result);
int NET_TCP_LISTEN(AGENT_REQUEST *request, AGENT_RESULT *result);
int NET_TCP_PORT(AGENT_REQUEST *request, AGENT_RESULT *result);
@@ -58,10 +56,6 @@ func resolveMetric(key string) (cfunc unsafe.Pointer) {
switch key {
case "system.localtime":
return unsafe.Pointer(C.SYSTEM_LOCALTIME)
- case "net.dns":
- return unsafe.Pointer(C.NET_DNS)
- case "net.dns.record":
- return unsafe.Pointer(C.NET_DNS_RECORD)
case "system.boottime":
return unsafe.Pointer(C.SYSTEM_BOOTTIME)
case "net.tcp.listen":
diff --git a/src/go/pkg/zbxlib/checks_linux.go b/src/go/pkg/zbxlib/checks_linux.go
index ed77a2c7fd9..b1ee05ce6a4 100644
--- a/src/go/pkg/zbxlib/checks_linux.go
+++ b/src/go/pkg/zbxlib/checks_linux.go
@@ -29,8 +29,6 @@ package zbxlib
#include "module.h"
int SYSTEM_LOCALTIME(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result);
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result);
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result);
int SYSTEM_BOOTTIME(AGENT_REQUEST *request, AGENT_RESULT *result);
@@ -66,10 +64,6 @@ 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 "system.boottime":
cfunc = unsafe.Pointer(C.SYSTEM_BOOTTIME)
case "net.tcp.listen":
diff --git a/src/go/pkg/zbxlib/checks_windows.go b/src/go/pkg/zbxlib/checks_windows.go
index 0bbb90ed1c9..7fc54510f98 100644
--- a/src/go/pkg/zbxlib/checks_windows.go
+++ b/src/go/pkg/zbxlib/checks_windows.go
@@ -29,8 +29,6 @@ package zbxlib
#include "module.h"
int SYSTEM_LOCALTIME(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS(AGENT_REQUEST *request, AGENT_RESULT *result);
-int NET_DNS_RECORD(AGENT_REQUEST *request, AGENT_RESULT *result);
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result);
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result);
int SYSTEM_BOOTTIME(AGENT_REQUEST *request, AGENT_RESULT *result);
@@ -64,10 +62,6 @@ 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)
}
return
diff --git a/src/go/plugins/net/dns/dns.go b/src/go/plugins/net/dns/dns.go
new file mode 100644
index 00000000000..306b842adc0
--- /dev/null
+++ b/src/go/plugins/net/dns/dns.go
@@ -0,0 +1,502 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 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 dns
+
+import (
+ "fmt"
+ "net"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/miekg/dns"
+ "zabbix.com/pkg/plugin"
+ "zabbix.com/pkg/zbxerr"
+)
+
+const (
+ base10 = 10
+
+ tcpProtocol = "tcp"
+ udpProtocol = "udp"
+)
+
+const (
+ noneParam = iota
+ firstParam
+ secondParam
+ thirdParam
+ fourthParam
+ fifthParam
+ sixthParam
+)
+
+type options struct {
+ ip string
+ name string
+ protocol string
+ dnsType uint16
+ count int
+ timeout time.Duration
+}
+
+// Plugin -
+type Plugin struct {
+ plugin.Base
+}
+
+var impl Plugin
+
+var dnsTypes = map[string]uint16{
+ "ANY": dns.TypeANY,
+ "A": dns.TypeA,
+ "NS": dns.TypeNS,
+ "CNAME": dns.TypeCNAME,
+ "MB": dns.TypeMB,
+ "MG": dns.TypeMG,
+ "MR": dns.TypeMR,
+ "PTR": dns.TypePTR,
+ "MD": dns.TypeMD,
+ "MF": dns.TypeMF,
+ "MX": dns.TypeMX,
+ "SOA": dns.TypeSOA,
+ "NULL": dns.TypeNULL,
+ "HINFO": dns.TypeHINFO,
+ "MINFO": dns.TypeMINFO,
+ "TXT": dns.TypeTXT,
+ "AAAA": dns.TypeAAAA,
+ "SRV": dns.TypeSRV,
+}
+
+// Export -
+func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error) {
+ switch key {
+ case "net.dns":
+ return exportDns(params)
+ case "net.dns.record":
+ return exportDnsRecord(params)
+ default:
+ err = zbxerr.ErrorUnsupportedMetric
+
+ return
+ }
+}
+
+func exportDns(params []string) (result interface{}, err error) {
+ answer, err := getDNSAnswers(params)
+ if err != nil {
+ return
+ }
+
+ if len(answer) < 1 {
+ return 0, nil
+ }
+
+ return 1, nil
+}
+
+func exportDnsRecord(params []string) (result interface{}, err error) {
+ answer, err := getDNSAnswers(params)
+ if err != nil {
+ return
+ }
+
+ if len(answer) < 1 {
+ return nil, zbxerr.New("Cannot perform DNS query.")
+ }
+
+ return parseAnswers(answer), nil
+}
+
+func parseAnswers(answers []dns.RR) string {
+ var out string
+ answersNum := len(answers)
+ for i, a := range answers {
+ out += fmt.Sprintf("%-20s", strings.TrimSuffix(a.Header().Name, "."))
+ out += fmt.Sprintf(" %-8s ", dns.Type(a.Header().Rrtype).String())
+
+ switch rr := a.(type) {
+ case *dns.A:
+ out += getAString(rr)
+ case *dns.NS:
+ out += getNSString(rr)
+ case *dns.CNAME:
+ out += getCNAMEString(rr)
+ case *dns.MB:
+ out += getMBString(rr)
+ case *dns.MG:
+ out += getMGString(rr)
+ case *dns.PTR:
+ out += getPTRString(rr)
+ case *dns.MD:
+ out += getMDString(rr)
+ case *dns.MF:
+ out += getMFString(rr)
+ case *dns.MX:
+ out += getMXString(rr)
+ case *dns.SOA:
+ out += getSOAString(rr)
+ case *dns.NULL:
+ out += getNULLString(rr)
+ case *dns.HINFO:
+ out += getHINFOString(rr)
+ case *dns.MINFO:
+ out += getMINFOString(rr)
+ case *dns.TXT:
+ out += getTXTString(rr)
+ case *dns.AAAA:
+ out += getAAAAString(rr)
+ case *dns.SRV:
+ out += getSRVString(rr)
+ }
+
+ if i != answersNum - 1 {
+ out += "\n"
+ }
+ }
+
+ return out
+}
+
+func getDNSAnswers(params []string) ([]dns.RR, error) {
+ options, err := parseParamas(params)
+ if err != nil {
+ return nil, err
+ }
+
+ var resp *dns.Msg
+ for i := 1; i <= options.count; i++ {
+ resp, err = runQuery(options.ip, options.name, options.protocol, options.dnsType, options.timeout)
+ if err != nil {
+ continue
+ }
+
+ break
+ }
+
+ if err != nil {
+ return nil, zbxerr.ErrorCannotFetchData.Wrap(err)
+ }
+
+ return resp.Answer, nil
+}
+
+func getSOAString(in *dns.SOA) string {
+ return strings.TrimSuffix(in.Ns, ".") +
+ " " + strings.TrimSuffix(in.Mbox, ".") +
+ " " + strconv.FormatInt(int64(in.Serial), base10) +
+ " " + strconv.FormatInt(int64(in.Refresh), base10) +
+ " " + strconv.FormatInt(int64(in.Retry), base10) +
+ " " + strconv.FormatInt(int64(in.Expire), base10) +
+ " " + strconv.FormatInt(int64(in.Minttl), base10)
+}
+
+func getAString(in *dns.A) string {
+ if in.A == nil {
+ return "\n"
+ }
+
+ return in.A.String()
+}
+
+func getNSString(in *dns.NS) string {
+ return strings.TrimSuffix(in.Ns, ".")
+}
+
+func getCNAMEString(in *dns.CNAME) string {
+ return strings.TrimSuffix(in.Target, ".")
+}
+
+func getMBString(in *dns.MB) string {
+ return strings.TrimSuffix(in.Mb, ".")
+}
+
+func getMGString(in *dns.MG) string {
+ return strings.TrimSuffix(in.Mg, ".")
+}
+
+func getPTRString(in *dns.PTR) string {
+ return strings.TrimSuffix(in.Ptr, ".")
+}
+
+func getMDString(in *dns.MD) string {
+ return strings.TrimSuffix(in.Md, ".")
+}
+
+func getMFString(in *dns.MF) string {
+ return strings.TrimSuffix(in.Mf, ".")
+}
+
+func getMXString(in *dns.MX) string {
+ return strconv.Itoa(int(in.Preference)) +
+ " " + strings.TrimSuffix(in.Mx, ".")
+}
+
+func getNULLString(in *dns.NULL) string {
+ return strings.TrimSuffix(in.Data, ".")
+}
+
+func getHINFOString(in *dns.HINFO) string {
+ return parseTXT(in.Cpu, in.Os)
+
+}
+
+func getMINFOString(in *dns.MINFO) string {
+ return strings.TrimSuffix(in.Rmail, ".") + " " +
+ strings.TrimSuffix(in.Email, ".")
+}
+
+func getTXTString(in *dns.TXT) string {
+ return parseTXT(in.Txt...)
+}
+
+func getAAAAString(in *dns.AAAA) string {
+ if in.AAAA == nil {
+ return "\n"
+ }
+
+ return in.AAAA.String()
+}
+
+func getSRVString(in *dns.SRV) string {
+ return strconv.Itoa(int(in.Priority)) + " " +
+ strconv.Itoa(int(in.Weight)) + " " +
+ strconv.Itoa(int(in.Port)) + " " +
+ strings.TrimSuffix(in.Target, ".")
+}
+
+func parseTXT(in ...string) string {
+ var out string
+ for _, s := range in {
+ if s != "" {
+ out += "\"" + s + "\"" + " "
+ }
+ }
+
+ return strings.TrimSpace(out)
+}
+
+func parseParamas(params []string) (o options, err error) {
+ switch len(params) {
+ case sixthParam:
+ err = o.setProtocol(params[sixthParam-1])
+ if err != nil {
+ return
+ }
+
+ fallthrough
+ case fifthParam:
+ err = o.setCount(params[fifthParam-1])
+ if err != nil {
+ return
+ }
+
+ fallthrough
+ case fourthParam:
+ err = o.setTimeout(params[fourthParam-1])
+ if err != nil {
+ return
+ }
+
+ fallthrough
+ case thirdParam:
+ err = o.setDNSType(params[thirdParam-1])
+ if err != nil {
+ return
+ }
+
+ fallthrough
+ case secondParam:
+ o.name = params[secondParam-1]
+
+ fallthrough
+ case firstParam:
+ err = o.setIP(params[firstParam-1])
+ if err != nil {
+ return o, zbxerr.New(fmt.Sprintf("invalid fist parameter, %s", err.Error()))
+ }
+
+ fallthrough
+ case noneParam:
+ err = o.setDefaults()
+ if err != nil {
+ return
+ }
+ default:
+ err = zbxerr.ErrorTooManyParameters
+
+ return
+ }
+
+ return
+}
+
+func (o *options) setIP(ip string) error {
+ if ip == "" {
+ return nil
+ }
+
+ if !isValidIP(ip) {
+ return fmt.Errorf("invalid IP address, %s", ip)
+ }
+
+ o.ip = net.JoinHostPort(ip, "53")
+
+ return nil
+}
+
+func isValidIP(ip string) bool {
+ if r := net.ParseIP(ip); r == nil {
+ return false
+ }
+
+ return true
+}
+
+func (o *options) setProtocol(protocol string) error {
+ switch protocol {
+ case tcpProtocol:
+ o.protocol = tcpProtocol
+ case udpProtocol, "":
+ o.protocol = udpProtocol
+ default:
+ return zbxerr.New("invalid sixth parameter")
+ }
+
+ return nil
+}
+
+func (o *options) setCount(c string) error {
+ if c == "" {
+ return nil
+ }
+
+ count, err := strconv.Atoi(c)
+ if err != nil {
+ return zbxerr.New(fmt.Sprintf("invalid fifth parameter, %s", err.Error()))
+ }
+
+ if count <= 0 {
+ return zbxerr.New("invalid fifth parameter")
+ }
+
+ o.count = count
+
+ return nil
+}
+
+func (o *options) setTimeout(timeout string) error {
+ if timeout == "" {
+ return nil
+ }
+
+ t, err := strconv.Atoi(timeout)
+ if err != nil {
+ return zbxerr.New(fmt.Sprintf("invalid fourth parameter, %s", err.Error()))
+ }
+
+ if t <= 0 {
+ return zbxerr.New("invalid fourth parameter")
+ }
+
+ o.timeout = time.Duration(t) * time.Second
+
+ return nil
+}
+
+func (o *options) setDNSType(dnsType string) error {
+ if dnsType == "" {
+ return nil
+ }
+
+ t, ok := dnsTypes[strings.ToUpper(dnsType)]
+ if !ok {
+ return zbxerr.New(fmt.Sprintf("invalid third parameter, unknown dns type %s", dnsType))
+ }
+
+ o.dnsType = t
+
+ return nil
+}
+
+func (o *options) setDefaults() error {
+ if o.ip == "" {
+ err := o.setDefaultIP()
+ if err != nil {
+ return zbxerr.New(err.Error())
+ }
+ }
+
+ if o.name == "" {
+ o.setDefaultName()
+ }
+
+ if o.dnsType == dns.TypeNone {
+ o.dnsType = dns.TypeSOA
+ }
+
+ if o.timeout < 1 {
+ o.timeout = 1 * time.Second
+ }
+
+ if o.count < 1 {
+ o.count = 2
+ }
+
+ if o.protocol == "" {
+ o.protocol = udpProtocol
+ }
+
+ return nil
+}
+
+func (o *options) setDefaultName() {
+ o.name = "zabbix.com"
+}
+
+func runQuery(resolver, domain, net string, record uint16, timeout time.Duration) (*dns.Msg, error) {
+ c := new(dns.Client)
+ c.Net = net
+ c.DialTimeout = timeout
+ c.ReadTimeout = timeout
+ c.WriteTimeout = timeout
+
+ m := &dns.Msg{
+ MsgHdr: dns.MsgHdr{
+ CheckingDisabled: false,
+ RecursionDesired: true,
+ Opcode: dns.OpcodeQuery,
+ Rcode: dns.RcodeSuccess,
+ },
+ Question: make([]dns.Question, 1),
+ }
+
+ m.Question[0] = dns.Question{Name: dns.Fqdn(domain), Qtype: record, Qclass: dns.ClassINET}
+ r, _, err := c.Exchange(m, resolver)
+
+ return r, err
+}
+
+func init() {
+ plugin.RegisterMetrics(&impl, "DNS",
+ "net.dns", "Checks if DNS service is up.",
+ "net.dns.record", "Performs a DNS query.",
+ )
+}
diff --git a/src/go/plugins/zabbix/sync/sync_nix.go b/src/go/plugins/net/dns/dns_nix.go
index 9b6ec074977..8c617e17d34 100644
--- a/src/go/plugins/zabbix/sync/sync_nix.go
+++ b/src/go/plugins/net/dns/dns_nix.go
@@ -1,9 +1,8 @@
-//go:build !windows
// +build !windows
/*
** Zabbix
-** Copyright (C) 2001-2022 Zabbix SIA
+** Copyright (C) 2001-2021 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
@@ -20,11 +19,26 @@
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
-package zabbixsync
+package dns
-func getMetrics() []string {
- return []string{
- "net.dns", "Checks if DNS service is up.",
- "net.dns.record", "Performs DNS query.",
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+func (o *options) setDefaultIP() (err error) {
+ data, err := os.ReadFile("/etc/resolv.conf")
+ if err != nil {
+ return
+ }
+
+ s := strings.Split(string(data), "\n")
+ for _, tmp := range s {
+ if strings.HasPrefix(tmp, "nameserver") {
+ return o.setIP(strings.TrimSpace(strings.TrimPrefix(tmp, "nameserver")))
+ }
}
+
+ return fmt.Errorf("cannot find default dns nameserver")
}
diff --git a/src/go/plugins/net/dns/dns_windows.go b/src/go/plugins/net/dns/dns_windows.go
new file mode 100644
index 00000000000..baf45c3d40d
--- /dev/null
+++ b/src/go/plugins/net/dns/dns_windows.go
@@ -0,0 +1,79 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 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 dns
+
+import (
+ "strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "zabbix.com/pkg/zbxerr"
+)
+
+func (o *options) setDefaultIP() error {
+ l := uint32(20000)
+ b := make([]byte, l)
+
+ if err := windows.GetAdaptersAddresses(windows.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l); err != nil {
+ return err
+ }
+
+ var addresses []*windows.IpAdapterAddresses
+ for addr := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); addr != nil; addr = addr.Next {
+ addresses = append(addresses, addr)
+ }
+
+ resolvers := map[string]bool{}
+ for _, addr := range addresses {
+ for next := addr.FirstUnicastAddress; next != nil; next = next.Next {
+ if addr.OperStatus != windows.IfOperStatusUp {
+ continue
+ }
+
+ if next.Address.IP() != nil {
+ for dnsServer := addr.FirstDnsServerAddress; dnsServer != nil; dnsServer = dnsServer.Next {
+ ip := dnsServer.Address.IP()
+ if ip.IsMulticast() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() {
+ continue
+ }
+
+ if ip.To16() != nil && strings.HasPrefix(ip.To16().String(), "fec0:") {
+ continue
+ }
+
+ resolvers[ip.String()] = true
+ }
+
+ break
+ }
+ }
+ }
+
+ servers := []string{}
+ for server := range resolvers {
+ servers = append(servers, server)
+ }
+
+ if len(servers) < 0 {
+ return zbxerr.New("no dns server found")
+ }
+
+ return o.setIP(servers[0])
+}
diff --git a/src/go/plugins/plugins_darwin.go b/src/go/plugins/plugins_darwin.go
index 273324cdf64..fb8a166049b 100644
--- a/src/go/plugins/plugins_darwin.go
+++ b/src/go/plugins/plugins_darwin.go
@@ -39,5 +39,4 @@ import (
_ "zabbix.com/plugins/web/page"
_ "zabbix.com/plugins/zabbix/async"
_ "zabbix.com/plugins/zabbix/stats"
- _ "zabbix.com/plugins/zabbix/sync"
)
diff --git a/src/go/plugins/plugins_linux.go b/src/go/plugins/plugins_linux.go
index 33788d49989..d6d8bc9c87f 100644
--- a/src/go/plugins/plugins_linux.go
+++ b/src/go/plugins/plugins_linux.go
@@ -29,6 +29,7 @@ import (
_ "zabbix.com/plugins/mongodb"
_ "zabbix.com/plugins/mqtt"
_ "zabbix.com/plugins/mysql"
+ _ "zabbix.com/plugins/net/dns"
_ "zabbix.com/plugins/net/netif"
_ "zabbix.com/plugins/net/tcp"
_ "zabbix.com/plugins/net/udp"
@@ -55,5 +56,4 @@ import (
_ "zabbix.com/plugins/web/page"
_ "zabbix.com/plugins/zabbix/async"
_ "zabbix.com/plugins/zabbix/stats"
- _ "zabbix.com/plugins/zabbix/sync"
)
diff --git a/src/go/plugins/plugins_windows.go b/src/go/plugins/plugins_windows.go
index 0c5c15c0dc8..a7d232bcab6 100644
--- a/src/go/plugins/plugins_windows.go
+++ b/src/go/plugins/plugins_windows.go
@@ -27,6 +27,7 @@ import (
_ "zabbix.com/plugins/mongodb"
_ "zabbix.com/plugins/mqtt"
_ "zabbix.com/plugins/mysql"
+ _ "zabbix.com/plugins/net/dns"
_ "zabbix.com/plugins/net/netif"
_ "zabbix.com/plugins/net/tcp"
_ "zabbix.com/plugins/net/udp"
@@ -55,5 +56,4 @@ import (
_ "zabbix.com/plugins/windows/wmi"
_ "zabbix.com/plugins/zabbix/async"
_ "zabbix.com/plugins/zabbix/stats"
- _ "zabbix.com/plugins/zabbix/sync"
)
diff --git a/src/go/plugins/smart/smart.go b/src/go/plugins/smart/smart.go
index 48b15152511..afa7f5a5ec6 100644
--- a/src/go/plugins/smart/smart.go
+++ b/src/go/plugins/smart/smart.go
@@ -21,7 +21,6 @@ package smart
import (
"encoding/json"
- "strings"
"zabbix.com/pkg/conf"
"zabbix.com/pkg/plugin"
@@ -83,7 +82,7 @@ func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider)
for _, dev := range r.devices {
out = append(out, device{
Name: cutPrefix(dev.Info.Name),
- DeviceType: strings.ToUpper(getType(dev.Info.DevType, dev.RotationRate)),
+ DeviceType: getType(dev.Info.DevType, dev.RotationRate, dev.SmartAttributes.Table),
Model: dev.ModelName, SerialNumber: dev.SerialNumber,
})
}
@@ -127,13 +126,7 @@ func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider)
}
for _, dev := range r.devices {
- var t string
- if dev.RotationRate == 0 {
- t = "SSD"
- } else {
- t = "HDD"
- }
-
+ t := getAttributeType(dev.Info.DevType, dev.RotationRate, dev.SmartAttributes.Table)
for _, attr := range dev.SmartAttributes.Table {
out = append(
out, attribute{
@@ -169,52 +162,108 @@ func setDiskFields(deviceJsons map[string]jsonDevice) (out []interface{}, err er
}
b["disk_name"] = cutPrefix(k)
+ b["disk_type"] = getType(getTypeFromJson(b), getRateFromJson(b), getTablesFromJson(b))
- var devType string
+ out = append(out, b)
+ }
- if dev, ok := b["device"]; ok {
- s, ok := dev.(string)
- if ok {
- info := make(map[string]string)
- if err = json.Unmarshal([]byte(s), &info); err != nil {
- return out, zbxerr.ErrorCannotUnmarshalJSON.Wrap(err)
- }
+ return
+}
- devType = info["type"]
- }
+func getRateFromJson(in map[string]interface{}) (out int) {
+ if r, ok := in[rotationRateFieldName]; ok {
+ switch rate := r.(type) {
+ case int:
+ out = rate
+ case float64:
+ out = int(rate)
}
+ }
- rateInt := -1
+ return
+}
- if rate, ok := b["rotation_rate"]; ok {
- switch r := rate.(type) {
- case int:
- rateInt = r
- case float64:
- rateInt = int(r)
+func getTypeFromJson(in map[string]interface{}) (out string) {
+ if dev, ok := in[deviceFieldName]; ok {
+ m, ok := dev.(map[string]interface{})
+ if ok {
+ if t, ok := m[typeFieldName]; ok {
+ s, ok := t.(string)
+ if ok {
+ out = s
+ }
}
}
+ }
- b["disk_type"] = getType(devType, rateInt)
- out = append(out, b)
+ return
+}
+
+func getTablesFromJson(in map[string]interface{}) (out []table) {
+ attr, ok := in[ataSmartAttrFieldName]
+ if !ok {
+ return
+ }
+
+ a, ok := attr.(map[string]interface{})
+ if !ok {
+ return
+ }
+
+ tables, ok := a[ataSmartAttrTableFieldName]
+ if !ok {
+ return
+ }
+
+ tmp, ok := tables.([]interface{})
+ if !ok {
+ return
+ }
+
+ b, err := json.Marshal(tmp)
+ if err != nil {
+ return
+ }
+
+ err = json.Unmarshal(b, &out)
+ if err != nil {
+ return
}
return
}
-func getType(devType string, rate int) (out string) {
- out = "unknown"
- if devType == "nvme" {
- out = "nvme"
- } else {
- if rate == 0 {
- out = "ssd"
- } else if rate > 0 {
- out = "hdd"
+func getAttributeType(devType string, rate int, tables []table) string {
+ if devType == unknownType {
+ return unknownType
+ }
+
+ return getTypeByRateAndAttr(rate, tables)
+}
+
+func getType(devType string, rate int, tables []table) string {
+ switch devType {
+ case nvmeType:
+ return nvmeType
+ case unknownType:
+ return unknownType
+ default:
+ return getTypeByRateAndAttr(rate, tables)
+ }
+}
+
+func getTypeByRateAndAttr(rate int, tables []table) string {
+ if rate > 0 {
+ return hddType
+ }
+
+ for _, t := range tables {
+ if t.Attrname == spinUpAttrName {
+ return hddType
}
}
- return
+ return ssdType
}
func init() {
diff --git a/src/go/plugins/smart/smart_test.go b/src/go/plugins/smart/smart_test.go
index 1ca089c02d5..eb73c16c8c6 100644
--- a/src/go/plugins/smart/smart_test.go
+++ b/src/go/plugins/smart/smart_test.go
@@ -21,9 +21,18 @@ package smart
import (
"fmt"
+ "reflect"
"testing"
)
+var (
+ table1 = table{"test1", 1, 11}
+ table2 = table{"test2", 2, 22}
+ table3 = table{"test3", 3, 33}
+ table4 = table{"test4", 4, 44}
+ attrTable = table{"Spin_Up_Time", 5, 55}
+)
+
func Test_setDiskFields(t *testing.T) {
//nolint:lll
jsonSdaStr := `{"device": {"name": "/dev/sda","info_name": "/dev/sda [SAT]","type": "sat","protocol": "ATA"},"rotation_rate": 0}`
@@ -63,27 +72,192 @@ func Test_setDiskFields(t *testing.T) {
}
}
+func Test_getRateFromJson(t *testing.T) {
+ type args struct {
+ in map[string]interface{}
+ }
+ tests := []struct {
+ name string
+ args args
+ wantOut int
+ }{
+ {"rate", args{map[string]interface{}{"rotation_rate": 10}}, 10},
+ {"multiple_fields", args{map[string]interface{}{"foobar": "abc", "rotation_rate": 10}}, 10},
+ {"no_rate", args{map[string]interface{}{"foobar": "abc"}}, 0},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if gotOut := getRateFromJson(tt.args.in); gotOut != tt.wantOut {
+ t.Errorf("getRateFromJson() = %v, want %v", gotOut, tt.wantOut)
+ }
+ })
+ }
+}
+
+func Test_getTypeFromJson(t *testing.T) {
+ map1 := make(map[string]interface{})
+ map1["device"] = map[string]interface{}{"type": "sat"}
+
+ map2 := make(map[string]interface{})
+ map2["device"] = map[string]interface{}{"type": "sat", "foobar": "abc"}
+
+ map3 := make(map[string]interface{})
+ map3["device"] = map[string]interface{}{"foobar": "abc"}
+
+ type args struct {
+ in map[string]interface{}
+ }
+ tests := []struct {
+ name string
+ args args
+ wantOut string
+ }{
+ {"type", args{map1}, "sat"},
+ {"multiple_fields", args{map2}, "sat"},
+ {"no_type", args{map3}, ""},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if gotOut := getTypeFromJson(tt.args.in); gotOut != tt.wantOut {
+ t.Errorf("getTypeFromJson() = %v, want %v", gotOut, tt.wantOut)
+ }
+ })
+ }
+}
+
+func Test_getTablesFromJson(t *testing.T) {
+ map1 := make(map[string]interface{})
+ map1["table"] = []interface{}{table1, table2, attrTable}
+
+ map2 := make(map[string]interface{})
+ map2["table"] = []interface{}{table1, table2, table4}
+
+ attrTable1 := map[string]interface{}{"ata_smart_attributes": map1}
+ attrTable2 := map[string]interface{}{"ata_smart_attributes": map2}
+ attrTable3 := map[string]interface{}{"ata_smart_attributes": nil}
+ attrTable4 := map[string]interface{}{"ata_smart_attributes": []table{}}
+ attrTable5 := map[string]interface{}{"ata_smart_attributes": map[string][]table{}}
+
+ type args struct {
+ in map[string]interface{}
+ }
+ tests := []struct {
+ name string
+ args args
+ want []table
+ }{
+ {"attr_table", args{attrTable1}, []table{table1, table2, attrTable}},
+ {"no_attr_table", args{attrTable2}, []table{table1, table2, table4}},
+ {"no_table", args{attrTable3}, nil},
+ {"incorrect_table_value", args{attrTable4}, nil},
+ {"empty_map", args{attrTable5}, nil},
+ {"no_ata_attributes", args{nil}, nil},
+ {"empty_ata_attributes", args{map[string]interface{}{}}, nil},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := getTablesFromJson(tt.args.in); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("getTablesFromJson() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_getAttributeType(t *testing.T) {
+ type args struct {
+ devType string
+ rate int
+ tables []table
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {"ssd_no_tables", args{"SAT", 0, nil}, "ssd"},
+ {"ssd_tables_no_spin_up_table", args{"SAT", 0, []table{table1, table2, table4}}, "ssd"},
+ {"hdd_no_tables", args{"SAT", 12, nil}, "hdd"},
+ {"hdd_rate_spin_up_table", args{"SAT", 12, []table{table1, table2, table4, attrTable}}, "hdd"},
+ {"hdd_no_rate_spin_up_table", args{"SAT", 0, []table{table1, table2, table4, attrTable}}, "hdd"},
+ {"hdd_no_spin_up_table", args{"SAT", 12, []table{table1, table2, table4}}, "hdd"},
+ {"unknown_no_attr_table", args{"unknown", 1000, []table{table1, table2, table4}}, "unknown"},
+ {"unknown_value_table", args{"unknown", 1000, []table{table1, table2, table4, attrTable}}, "unknown"},
+ {"unknown_no_rate_no_tables", args{"unknown", 0, nil}, "unknown"},
+ {"unknown_no_rate_no_attr_table", args{"unknown", 0, []table{table1, table2, table4}}, "unknown"},
+ {"unknown_no_rate_value_table", args{"unknown", 0, []table{table1, table2, table4, attrTable}}, "unknown"},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := getAttributeType(tt.args.devType, tt.args.rate, tt.args.tables); got != tt.want {
+ t.Errorf("getAttributeType() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
func Test_getType(t *testing.T) {
type args struct {
devType string
rate int
+ tables []table
}
tests := []struct {
name string
args args
wantOut string
}{
- {"ssd", args{"SAT", 0}, "ssd"},
- {"hdd", args{"SAT", 12}, "hdd"},
- {"nvme", args{"nvme", 0}, "nvme"},
- {"unknown", args{"SAT", -1}, "unknown"},
+ {"ssd_no_tables", args{"SAT", 0, nil}, "ssd"},
+ {"ssd_tables_no_spin_up_table", args{"SAT", 0, []table{table1, table2, table4}}, "ssd"},
+ {"hdd_no_tables", args{"SAT", 12, nil}, "hdd"},
+ {"hdd_rate_spin_up_table", args{"SAT", 12, []table{table1, table2, table4, attrTable}}, "hdd"},
+ {"hdd_no_rate_spin_up_table", args{"SAT", 0, []table{table1, table2, table4, attrTable}}, "hdd"},
+ {"hdd_no_spin_up_table", args{"SAT", 12, []table{table1, table2, table4}}, "hdd"},
+ {"nvme_no_tables", args{"nvme", 1000, nil}, "nvme"},
+ {"nvme_no_attr_table", args{"nvme", 1000, []table{table1, table2, table4}}, "nvme"},
+ {"nvme_value_table", args{"nvme", 1000, []table{table1, table2, table4, attrTable}}, "nvme"},
+ {"nvme_no_rate_no_tables", args{"nvme", 0, nil}, "nvme"},
+ {"nvme_no_rate_no_attr_table", args{"nvme", 0, []table{table1, table2, table4}}, "nvme"},
+ {"nvme_no_rate_value_table", args{"nvme", 0, []table{table1, table2, table4, attrTable}}, "nvme"},
+ {"unknown_no_tables", args{"unknown", 1000, nil}, "unknown"},
+ {"unknown_no_attr_table", args{"unknown", 1000, []table{table1, table2, table4}}, "unknown"},
+ {"unknown_value_table", args{"unknown", 1000, []table{table1, table2, table4, attrTable}}, "unknown"},
+ {"unknown_no_rate_no_tables", args{"unknown", 0, nil}, "unknown"},
+ {"unknown_no_rate_no_attr_table", args{"unknown", 0, []table{table1, table2, table4}}, "unknown"},
+ {"unknown_no_rate_value_table", args{"unknown", 0, []table{table1, table2, table4, attrTable}}, "unknown"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if gotOut := getType(tt.args.devType, tt.args.rate); gotOut != tt.wantOut {
+ if gotOut := getType(tt.args.devType, tt.args.rate, tt.args.tables); gotOut != tt.wantOut {
t.Errorf("getType() = %v, want %v", gotOut, tt.wantOut)
}
})
}
}
+
+func Test_getTypeByRateAndAttr(t *testing.T) {
+ type args struct {
+ rate int
+ tables []table
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {"zero_rate_zero_spin_up", args{0, []table{table1, table2}}, "ssd"},
+ {"zero_rate_no_tables", args{0, nil}, "ssd"},
+ {"negative_rate_no_tables", args{-1000, nil}, "ssd"},
+ {"positive_rate_spin_up_table", args{12, []table{table1, table2, table3, attrTable}}, "hdd"},
+ {"positive_rate_no_tables", args{12, nil}, "hdd"},
+ {"zero_rate_spin_up_table", args{0, []table{table1, table2, table3, attrTable}}, "hdd"},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := getTypeByRateAndAttr(tt.args.rate, tt.args.tables); got != tt.want {
+ t.Errorf("getTypeByRate() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/src/go/plugins/smart/smartfs.go b/src/go/plugins/smart/smartfs.go
index 469579a3099..2942525c08f 100644
--- a/src/go/plugins/smart/smartfs.go
+++ b/src/go/plugins/smart/smartfs.go
@@ -33,9 +33,25 @@ import (
"zabbix.com/pkg/zbxerr"
)
-const supportedSmartctl = 7.1
+const (
+ supportedSmartctl = 7.1
-const satType = "sat"
+ satType = "sat"
+ nvmeType = "nvme"
+ unknownType = "unknown"
+ ssdType = "ssd"
+ hddType = "hdd"
+
+ spinUpAttrName = "Spin_Up_Time"
+
+ ataSmartAttrFieldName = "ata_smart_attributes"
+ ataSmartAttrTableFieldName = "table"
+
+ rotationRateFieldName = "rotation_rate"
+
+ deviceFieldName = "device"
+ typeFieldName = "type"
+)
var (
cpuCount int
@@ -374,7 +390,7 @@ runner:
device, err := r.plugin.executeSmartctl(fmt.Sprintf("-a %s -j ", name), false)
if err != nil {
r.plugin.Tracef(
- "stopped looking for RAID devices of %s type, err:",
+ "stopped looking for RAID devices of %s type, err: %s",
raid.rType, fmt.Errorf("failed to get RAID disk data from smartctl: %s", err.Error()),
)
@@ -384,8 +400,8 @@ runner:
var dp deviceParser
if err = json.Unmarshal(device, &dp); err != nil {
r.plugin.Tracef(
- "stopped looking for RAID devices of %s type, err:",
- raid.rType, fmt.Errorf("failed to get RAID disk data from smartctl: %s", err.Error()),
+ "stopped looking for RAID devices of %s type, err: %s",
+ raid.rType, fmt.Errorf("failed to parse RAID disk data from smartctl: %s", err.Error()),
)
continue runner
@@ -394,7 +410,7 @@ runner:
err = dp.checkErr()
if err != nil {
r.plugin.Tracef(
- "stopped looking for RAID devices of %s type, err:",
+ "stopped looking for RAID devices of %s type, err: %s",
raid.rType, fmt.Errorf("failed to get disk data from smartctl: %s", err.Error()),
)
diff --git a/src/go/plugins/system/cpu/cpu.go b/src/go/plugins/system/cpu/cpu.go
index e2eb6e9e86c..5f22df69edf 100644
--- a/src/go/plugins/system/cpu/cpu.go
+++ b/src/go/plugins/system/cpu/cpu.go
@@ -23,6 +23,8 @@ import (
"encoding/json"
"errors"
"strconv"
+
+ "zabbix.com/pkg/zbxerr"
)
const pluginName = "Cpu"
@@ -101,29 +103,21 @@ func (p *Plugin) getCpuDiscovery(params []string) (result interface{}, err error
}
func (p *Plugin) getCpuNum(params []string) (result interface{}, err error) {
- mask := cpuStatusOnline
switch len(params) {
case 1:
switch params[0] {
case "", "online":
- // default value, already initialized
+ return numCPUOnline(), nil
case "max":
- mask = cpuStatusOnline | cpuStatusOffline
+ return numCPUConf(), nil
default:
return nil, errors.New("Invalid first parameter.")
}
case 0:
+ return numCPUOnline(), nil
default:
- return nil, errors.New("Too many parameters.")
- }
-
- var num int
- for i := 1; i < len(p.cpus); i++ {
- if p.cpus[i].status&mask != 0 {
- num++
- }
+ return nil, zbxerr.ErrorTooManyParameters
}
- return num, nil
}
func periodByMode(mode string) (period historyIndex) {
diff --git a/src/go/plugins/system/cpu/cpu_linux.go b/src/go/plugins/system/cpu/cpu_linux.go
index e9eb21e8695..d52fff06fd4 100644
--- a/src/go/plugins/system/cpu/cpu_linux.go
+++ b/src/go/plugins/system/cpu/cpu_linux.go
@@ -77,11 +77,14 @@ func (p *Plugin) Collect() (err error) {
if i, err = strconv.ParseInt(fields[0][3:], 10, 32); err != nil {
return
}
- if index = int(i); index < 0 || index+1 >= len(p.cpus) {
+
+ if index = int(i); index < 0 {
p.Debugf("invalid CPU index %d", index)
continue
}
+ p.addCpu(index)
+
status = cpuStatusOnline
} else {
index = -1
@@ -112,12 +115,32 @@ func (p *Plugin) Collect() (err error) {
return nil
}
-func numCPU() int {
+func (p *Plugin) addCpu(index int) {
+ if p == nil || p.cpus == nil {
+ return
+ }
+
+ if index == 0 {
+ return
+ }
+
+ if index+1 >= len(p.cpus) {
+ for idx := p.cpus[len(p.cpus)-1].index; idx < index; idx++ {
+ p.cpus = append(p.cpus, &cpuUnit{index: idx + 1, status: cpuStatusOffline})
+ }
+ }
+}
+
+func numCPUConf() int {
return int(C.sysconf(C._SC_NPROCESSORS_CONF))
}
+func numCPUOnline() int {
+ return int(C.sysconf(C._SC_NPROCESSORS_ONLN))
+}
+
func (p *Plugin) Start() {
- p.cpus = p.newCpus(numCPU())
+ p.cpus = p.newCpus(numCPUConf())
}
func (p *Plugin) Stop() {
diff --git a/src/go/plugins/system/cpu/cpu_linux_test.go b/src/go/plugins/system/cpu/cpu_linux_test.go
new file mode 100644
index 00000000000..87d719352ca
--- /dev/null
+++ b/src/go/plugins/system/cpu/cpu_linux_test.go
@@ -0,0 +1,136 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2022 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 cpu
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestPlugin_addCpu(t *testing.T) {
+ type fields struct {
+ cpus []*cpuUnit
+ }
+ type args struct {
+ index int
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want []*cpuUnit
+ }{
+ {
+ "one_offline_cpu",
+ fields{
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ },
+ },
+ args{2},
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ {index: 2, status: cpuStatusOffline},
+ },
+ },
+ {
+ "two_offline_cpu",
+ fields{
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ },
+ },
+ args{3},
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ {index: 2, status: cpuStatusOffline},
+ {index: 3, status: cpuStatusOffline},
+ },
+ },
+ {
+ "ten_offline_cpu",
+ fields{
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ },
+ },
+ args{11},
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ {index: 2, status: cpuStatusOffline},
+ {index: 3, status: cpuStatusOffline},
+ {index: 4, status: cpuStatusOffline},
+ {index: 5, status: cpuStatusOffline},
+ {index: 6, status: cpuStatusOffline},
+ {index: 7, status: cpuStatusOffline},
+ {index: 8, status: cpuStatusOffline},
+ {index: 9, status: cpuStatusOffline},
+ {index: 10, status: cpuStatusOffline},
+ {index: 11, status: cpuStatusOffline},
+ },
+ },
+ {
+ "no_offline_cpu",
+ fields{
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ },
+ },
+ args{1},
+ []*cpuUnit{
+ {index: -1, status: cpuStatusOffline},
+ {index: 0, status: cpuStatusOffline},
+ {index: 1, status: cpuStatusOffline},
+ },
+ },
+ {
+ "empty", fields{[]*cpuUnit{}}, args{}, []*cpuUnit{},
+ },
+ {
+ "nil", fields{nil}, args{}, nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ p := &Plugin{
+ cpus: tt.fields.cpus,
+ }
+ p.addCpu(tt.args.index)
+
+ if !reflect.DeepEqual(p.cpus, tt.want) {
+ t.Errorf("addCpu() got = %v, want %v", p.cpus, tt.want)
+ }
+ })
+ }
+}
diff --git a/src/go/plugins/system/cpu/cpu_windows.go b/src/go/plugins/system/cpu/cpu_windows.go
index 0b175a17dfe..eff02894286 100644
--- a/src/go/plugins/system/cpu/cpu_windows.go
+++ b/src/go/plugins/system/cpu/cpu_windows.go
@@ -43,6 +43,15 @@ const (
defaultIndex = 60
)
+func numCPUOnline() int {
+ return numCPU()
+}
+
+func numCPUConf() int {
+ // unsupported on Windows
+ return 0
+}
+
func numCPU() (numCpu int) {
size, err := win32.GetLogicalProcessorInformationEx(win32.RelationProcessorCore, nil)
if err != nil {
diff --git a/src/go/plugins/zabbix/sync/sync.go b/src/go/plugins/zabbix/sync/sync.go
deleted file mode 100644
index dde57d8d57b..00000000000
--- a/src/go/plugins/zabbix/sync/sync.go
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-** Zabbix
-** Copyright (C) 2001-2022 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
-
-import (
- "zabbix.com/pkg/plugin"
- "zabbix.com/pkg/zbxlib"
-)
-
-// Plugin -
-type Plugin struct {
- plugin.Base
-}
-
-var impl Plugin
-
-func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error) {
- return zbxlib.ExecuteCheck(key, params)
-}
-
-func init() {
- plugin.RegisterMetrics(&impl, "ZabbixSync", getMetrics()...)
- impl.SetCapacity(1)
-}
diff --git a/src/go/plugins/zabbix/sync/sync_windows.go b/src/go/plugins/zabbix/sync/sync_windows.go
deleted file mode 100644
index 428885b1a66..00000000000
--- a/src/go/plugins/zabbix/sync/sync_windows.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-** Zabbix
-** Copyright (C) 2001-2022 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.",
- }
-}
diff --git a/src/libs/zbxcrypto/tls.c b/src/libs/zbxcrypto/tls.c
index 1230f35a04f..bf63612a84f 100644
--- a/src/libs/zbxcrypto/tls.c
+++ b/src/libs/zbxcrypto/tls.c
@@ -3498,6 +3498,66 @@ out1:
return ret;
}
#elif defined(HAVE_OPENSSL)
+static int zbx_tls_get_error(const SSL *s, int res, const char *func, size_t *error_alloc, size_t *error_offset,
+ char **error)
+{
+ int result_code;
+
+ result_code = SSL_get_error(s, res);
+
+ switch (result_code)
+ {
+ case SSL_ERROR_NONE: /* handshake successful */
+ return SUCCEED;
+ case SSL_ERROR_ZERO_RETURN:
+ zbx_snprintf_alloc(error, error_alloc, error_offset,
+ "%s() TLS connection has been closed during read", func);
+ return FAIL;
+ case SSL_ERROR_SYSCALL:
+ if (0 == ERR_peek_error())
+ {
+ if (0 == res)
+ {
+ zbx_snprintf_alloc(error, error_alloc, error_offset,
+ "%s() connection closed by peer", func);
+ }
+ else if (-1 == res)
+ {
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s()"
+ " I/O error: %s", func,
+ strerror_from_system(zbx_socket_last_error()));
+ }
+ else
+ {
+ /* "man SSL_get_error" describes only res == 0 and res == -1 for */
+ /* SSL_ERROR_SYSCALL case */
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s()"
+ " returned undocumented code %d", func, res);
+ }
+ }
+ else
+ {
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s() set"
+ " result code to SSL_ERROR_SYSCALL:", func);
+ zbx_tls_error_msg(error, error_alloc, error_offset);
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s", info_buf);
+ }
+ return FAIL;
+ case SSL_ERROR_SSL:
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s() set"
+ " result code to SSL_ERROR_SSL:", func);
+ zbx_tls_error_msg(error, error_alloc, error_offset);
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s", info_buf);
+ return FAIL;
+ default:
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s() set result code"
+ " to %d", func, result_code);
+ zbx_tls_error_msg(error, error_alloc, error_offset);
+ zbx_snprintf_alloc(error, error_alloc, error_offset, "%s", info_buf);
+ return FAIL;
+ }
+}
+
int zbx_tls_connect(zbx_socket_t *s, unsigned int tls_connect, const char *tls_arg1, const char *tls_arg2,
char **error)
{
@@ -3614,8 +3674,6 @@ int zbx_tls_connect(zbx_socket_t *s, unsigned int tls_connect, const char *tls_a
#endif
if (1 != (res = SSL_connect(s->tls_ctx->ctx)))
{
- int result_code;
-
#if defined(_WINDOWS)
if (s->timeout < zbx_time() - sec)
zbx_alarm_flag_set();
@@ -3639,59 +3697,8 @@ int zbx_tls_connect(zbx_socket_t *s, unsigned int tls_connect, const char *tls_a
}
}
- result_code = SSL_get_error(s->tls_ctx->ctx, res);
-
- switch (result_code)
- {
- case SSL_ERROR_NONE: /* handshake successful */
- break;
- case SSL_ERROR_ZERO_RETURN:
- zbx_snprintf_alloc(error, &error_alloc, &error_offset,
- "TLS connection has been closed during handshake");
- goto out;
- case SSL_ERROR_SYSCALL:
- if (0 == ERR_peek_error())
- {
- if (0 == res)
- {
- zbx_snprintf_alloc(error, &error_alloc, &error_offset,
- "connection closed by peer");
- }
- else if (-1 == res)
- {
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "SSL_connect()"
- " I/O error: %s",
- strerror_from_system(zbx_socket_last_error()));
- }
- else
- {
- /* "man SSL_get_error" describes only res == 0 and res == -1 for */
- /* SSL_ERROR_SYSCALL case */
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "SSL_connect()"
- " returned undocumented code %d", res);
- }
- }
- else
- {
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "SSL_connect() set"
- " result code to SSL_ERROR_SYSCALL:");
- zbx_tls_error_msg(error, &error_alloc, &error_offset);
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "%s", info_buf);
- }
- goto out;
- case SSL_ERROR_SSL:
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "SSL_connect() set"
- " result code to SSL_ERROR_SSL:");
- zbx_tls_error_msg(error, &error_alloc, &error_offset);
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "%s", info_buf);
- goto out;
- default:
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "SSL_connect() set result code"
- " to %d", result_code);
- zbx_tls_error_msg(error, &error_alloc, &error_offset);
- zbx_snprintf_alloc(error, &error_alloc, &error_offset, "%s", info_buf);
- goto out;
- }
+ if (FAIL == zbx_tls_get_error(s->tls_ctx->ctx, res, "SSL_connect", &error_alloc, &error_offset, error))
+ goto out;
}
if (ZBX_TCP_SEC_TLS_CERT == tls_connect)
@@ -4289,34 +4296,25 @@ out1:
ssize_t zbx_tls_write(zbx_socket_t *s, const char *buf, size_t len, char **error)
{
-#if defined(_WINDOWS)
- double sec;
-#endif
#if defined(HAVE_GNUTLS)
ssize_t res;
#elif defined(HAVE_OPENSSL)
int res;
#endif
-#if defined(_WINDOWS)
- zbx_alarm_flag_clear();
- sec = zbx_time();
-#endif
#if defined(HAVE_OPENSSL)
info_buf[0] = '\0'; /* empty buffer for zbx_openssl_info_cb() messages */
#endif
do
{
res = ZBX_TLS_WRITE(s->tls_ctx->ctx, buf, len);
-#if defined(_WINDOWS)
- if (s->timeout < zbx_time() - sec)
- zbx_alarm_flag_set();
-#endif
+#if !defined(_WINDOWS)
if (SUCCEED == zbx_alarm_timed_out())
{
*error = zbx_strdup(*error, ZBX_TLS_WRITE_FUNC_NAME "() timed out");
return ZBX_PROTO_ERROR;
}
+#endif
}
while (SUCCEED == ZBX_TLS_WANT_WRITE(res));
@@ -4331,24 +4329,12 @@ ssize_t zbx_tls_write(zbx_socket_t *s, const char *buf, size_t len, char **error
#elif defined(HAVE_OPENSSL)
if (0 >= res)
{
- int result_code;
+ size_t error_alloc = 0, error_offset = 0;
- result_code = SSL_get_error(s->tls_ctx->ctx, res);
-
- if (0 == res && SSL_ERROR_ZERO_RETURN == result_code)
- {
- *error = zbx_strdup(*error, "connection closed during write");
- }
- else
+ if (SUCCEED == zbx_tls_get_error(s->tls_ctx->ctx, res, ZBX_TLS_WRITE_FUNC_NAME, &error_alloc,
+ &error_offset, error))
{
- char *err = NULL;
- size_t error_alloc = 0, error_offset = 0;
-
- zbx_snprintf_alloc(&err, &error_alloc, &error_offset, "TLS write set result code to"
- " %d:", result_code);
- zbx_tls_error_msg(&err, &error_alloc, &error_offset);
- *error = zbx_dsprintf(*error, "%s%s", err, info_buf);
- zbx_free(err);
+ *error = zbx_strdup(*error, ZBX_TLS_WRITE_FUNC_NAME "() unexpected result code");
}
return ZBX_PROTO_ERROR;
@@ -4360,34 +4346,25 @@ ssize_t zbx_tls_write(zbx_socket_t *s, const char *buf, size_t len, char **error
ssize_t zbx_tls_read(zbx_socket_t *s, char *buf, size_t len, char **error)
{
-#if defined(_WINDOWS)
- double sec;
-#endif
#if defined(HAVE_GNUTLS)
ssize_t res;
#elif defined(HAVE_OPENSSL)
int res;
#endif
-#if defined(_WINDOWS)
- zbx_alarm_flag_clear();
- sec = zbx_time();
-#endif
#if defined(HAVE_OPENSSL)
info_buf[0] = '\0'; /* empty buffer for zbx_openssl_info_cb() messages */
#endif
do
{
res = ZBX_TLS_READ(s->tls_ctx->ctx, buf, len);
-#if defined(_WINDOWS)
- if (s->timeout < zbx_time() - sec)
- zbx_alarm_flag_set();
-#endif
+#if !defined(_WINDOWS)
if (SUCCEED == zbx_alarm_timed_out())
{
*error = zbx_strdup(*error, ZBX_TLS_READ_FUNC_NAME "() timed out");
return ZBX_PROTO_ERROR;
}
+#endif
}
while (SUCCEED == ZBX_TLS_WANT_READ(res));
@@ -4403,24 +4380,12 @@ ssize_t zbx_tls_read(zbx_socket_t *s, char *buf, size_t len, char **error)
#elif defined(HAVE_OPENSSL)
if (0 >= res)
{
- int result_code;
-
- result_code = SSL_get_error(s->tls_ctx->ctx, res);
+ size_t error_alloc = 0, error_offset = 0;
- if (0 == res && SSL_ERROR_ZERO_RETURN == result_code)
+ if (SUCCEED == zbx_tls_get_error(s->tls_ctx->ctx, res, ZBX_TLS_READ_FUNC_NAME, &error_alloc,
+ &error_offset, error))
{
- *error = zbx_strdup(*error, "connection closed during read");
- }
- else
- {
- char *err = NULL;
- size_t error_alloc = 0, error_offset = 0;
-
- zbx_snprintf_alloc(&err, &error_alloc, &error_offset, "TLS read set result code to"
- " %d:", result_code);
- zbx_tls_error_msg(&err, &error_alloc, &error_offset);
- *error = zbx_dsprintf(*error, "%s%s", err, info_buf);
- zbx_free(err);
+ *error = zbx_strdup(*error, ZBX_TLS_READ_FUNC_NAME "() unexpected result code");
}
return ZBX_PROTO_ERROR;
diff --git a/src/libs/zbxdbhigh/proxy.c b/src/libs/zbxdbhigh/proxy.c
index c84fa56f61b..8941b175cd3 100644
--- a/src/libs/zbxdbhigh/proxy.c
+++ b/src/libs/zbxdbhigh/proxy.c
@@ -3547,7 +3547,7 @@ static int process_history_data_by_itemids(zbx_socket_t *sock, zbx_client_item_v
double sec;
DC_ITEM *items;
char *error = NULL;
- zbx_uint64_t itemids[ZBX_HISTORY_VALUES_MAX];
+ zbx_uint64_t itemids[ZBX_HISTORY_VALUES_MAX], last_valueid = 0;
zbx_agent_value_t values[ZBX_HISTORY_VALUES_MAX];
zbx_timespec_t unique_shift = {0, 0};
@@ -3593,8 +3593,7 @@ static int process_history_data_by_itemids(zbx_socket_t *sock, zbx_client_item_v
total_num += read_num;
- if (NULL != session)
- session->last_valueid = values[values_num - 1].id;
+ last_valueid = values[values_num - 1].id;
DCconfig_clean_items(items, errcodes, values_num);
zbx_agent_values_clean(values, values_num);
@@ -3603,6 +3602,17 @@ static int process_history_data_by_itemids(zbx_socket_t *sock, zbx_client_item_v
break;
}
+ if (NULL != session && 0 != last_valueid)
+ {
+ if (session->last_valueid > last_valueid)
+ {
+ zabbix_log(LOG_LEVEL_WARNING, "received id:" ZBX_FS_UI64 " is less than last id:"
+ ZBX_FS_UI64, last_valueid, session->last_valueid);
+ }
+ else
+ session->last_valueid = last_valueid;
+ }
+
zbx_free(errcodes);
zbx_free(items);
diff --git a/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java b/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java
index 0fbb0080b5e..7106aa6389e 100644
--- a/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java
+++ b/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java
@@ -22,9 +22,9 @@ package com.zabbix.gateway;
class GeneralInformation
{
static final String APPLICATION_NAME = "Zabbix Java Gateway";
- static final String REVISION_DATE = "25 January 2022";
+ static final String REVISION_DATE = "31 January 2022";
static final String REVISION = "{ZABBIX_REVISION}";
- static final String VERSION = "5.4.10rc1";
+ static final String VERSION = "5.4.11rc1";
static void printVersion()
{
diff --git a/src/zabbix_proxy/datasender/datasender.c b/src/zabbix_proxy/datasender/datasender.c
index 967285f2e1f..249fb1e2f6b 100644
--- a/src/zabbix_proxy/datasender/datasender.c
+++ b/src/zabbix_proxy/datasender/datasender.c
@@ -184,9 +184,16 @@ static int proxy_data_sender(int *more, int now, int *hist_upload_state)
reserved = j.buffer_size;
zbx_json_free(&j); /* json buffer can be large, free as fast as possible */
+ update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);
+
/* retry till have a connection */
if (FAIL == connect_to_server(&sock, 600, CONFIG_PROXYDATA_FREQUENCY))
+ {
+ update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
goto clean;
+ }
+
+ update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
upload_state = put_data_to_server(&sock, &buffer, buffer_size, reserved, &error);
get_hist_upload_state(sock.buffer, hist_upload_state);
diff --git a/src/zabbix_proxy/proxyconfig/proxyconfig.c b/src/zabbix_proxy/proxyconfig/proxyconfig.c
index 1fec32183e4..8f57ce27317 100644
--- a/src/zabbix_proxy/proxyconfig/proxyconfig.c
+++ b/src/zabbix_proxy/proxyconfig/proxyconfig.c
@@ -81,8 +81,15 @@ static void process_configuration_sync(size_t *data_size)
reserved = j.buffer_size;
zbx_json_free(&j);
+ update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);
+
if (FAIL == connect_to_server(&sock, 600, CONFIG_PROXYCONFIG_RETRY)) /* retry till have a connection */
+ {
+ update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
goto out;
+ }
+
+ update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
if (SUCCEED != get_data_from_server(&sock, &buffer, buffer_size, reserved, &error))
{