diff options
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | include/zbxicmpping.h | 8 | ||||
-rw-r--r-- | src/libs/zbxicmpping/icmpping.c | 61 |
3 files changed, 53 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog index c2bb482bb59..fe8393ff13e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ New features: A.F....... [ZBX-1357] updated American English, French, Hungarian, Italian, Japanese, Russian, Slovak and Turkish translations; thanks to Zabbix translators (Richlv) Bug fixes: +.......PS. [ZBX-7576] when pinging a broadcast address ignore responses from other addresses (wiper) ..F....... [ZBX-7632] allow to add favourite graph from disable host (Eduard) ..F....... [ZBX-7634] removed sid from trigger URL in Monitoring->Triggers (Oleg) ...GI..PS. [ZBX-5526] removed checking for PosgreSQL server version and disabled nonstandard use of escape strings in order to support versions newer than 8.1 (igors) diff --git a/include/zbxicmpping.h b/include/zbxicmpping.h index 6358962dde9..9e4ba3bf028 100644 --- a/include/zbxicmpping.h +++ b/include/zbxicmpping.h @@ -23,8 +23,12 @@ typedef struct { char *addr; - double min, avg, max; - int rcv, cnt; + double min; + double avg; + double max; + int rcv; + int cnt; + char *status; /* array of individual response statuses: 1 - valid, 0 - timeout */ } ZBX_FPING_HOST; diff --git a/src/libs/zbxicmpping/icmpping.c b/src/libs/zbxicmpping/icmpping.c index 27c1af13a9d..e8b07ff771c 100644 --- a/src/libs/zbxicmpping/icmpping.c +++ b/src/libs/zbxicmpping/icmpping.c @@ -78,12 +78,12 @@ static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int i const char *__function_name = "process_ping"; FILE *f; - char *c, *c2, params[64]; + char *c, params[64]; char filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN]; size_t offset; ZBX_FPING_HOST *host; double sec; - int i, ret = NOTSUPPORTED; + int i, ret = NOTSUPPORTED, index; #ifdef HAVE_IPV6 int family; @@ -137,7 +137,7 @@ static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int i fping_existence |= FPING6_EXISTS; #endif /* HAVE_IPV6 */ - offset = zbx_snprintf(params, sizeof(params), "-q -C%d", count); + offset = zbx_snprintf(params, sizeof(params), "-C%d", count); if (0 != interval) offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -p%d", interval); if (0 != size) @@ -258,6 +258,12 @@ static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int i } else { + for (i = 0; i < hosts_count; i++) + { + hosts[i].status = zbx_malloc(NULL, count); + memset(hosts[i].status, 0, count); + } + do { zbx_rtrim(tmp, "\n"); @@ -291,33 +297,58 @@ static int process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int i c += 3; - do + /* The were two issues with processing only the fping's final status line: */ + /* 1) pinging broadcast addresses could have resulted in responses from */ + /* different hosts, which were counted as the target host responses; */ + /* 2) there is a bug in fping (v3.8 at least) where pinging broadcast */ + /* address will result in no individual responses, but the final */ + /* status line might contain a bogus value. */ + /* Because of the above issues we must monitor the individual responses */ + /* and mark the valid ones. */ + if ('[' == *c) { - if (NULL != (c2 = strchr(c, ' '))) - *c2 = '\0'; + /* Fping appends response source address in format '[<- 10.3.0.10]' */ + /* if it does not match the target address. Ignore such responses. */ + if (NULL != strstr(c + 1, "[<-")) + continue; + + /* get the index of individual ping response */ + index = atoi(c + 1); + + if (0 > index || index >= count) + continue; + + host->status[index] = 1; + + continue; + } - if (0 != strcmp(c, "-")) + /* process status line for a host */ + index = 0; + do + { + if (1 == host->status[index]) { sec = atof(c) / 1000; /* convert ms to seconds */ - if (host->rcv == 0 || host->min > sec) + if (0 == host->rcv || host->min > sec) host->min = sec; - if (host->rcv == 0 || host->max < sec) + if (0 == host->rcv || host->max < sec) host->max = sec; host->avg = (host->avg * host->rcv + sec) / (host->rcv + 1); host->rcv++; } - - host->cnt++; - - if (NULL != c2) - *c2++ = ' '; } - while (NULL != (c = c2)); + while (++index < count && NULL != (c = strchr(c + 1, ' '))); + + host->cnt = count; ret = SUCCEED; } while (NULL != fgets(tmp, sizeof(tmp), f)); + + for (i = 0; i < hosts_count; i++) + zbx_free(hosts[i].status); } pclose(f); |