Package: nagios-plugins-basic
Version: 1.4.5-1etch1
Severity: normal
Tags: patch
problem can usually (depending on network config) be reproduced by:
check_ping -H [invalid-ipv6-address] -w 5000,100% -c 5000,100% -p 1
Debian's ping6 may produce output in the following format:
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time
2009ms
There's a corresponding pattern in check_ping.c:450:
"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss"
but the pattern in check_ping.c:448 matches first:
"%*d packets transmitted, %*d received, %d%% loss, time"
because sscanf interprets "+3" as a match for "%d". Although the rest
of the pattern doesn't match, the number of successful assignments
(and thus the return value of sscanf) is still 1.
A simple way to make sure the whole pattern matches is to add a "%n"
specifier at the end, which will assign the number of characters
matched by that point. (The same trick is used in check_http.c.)
There seems to be some confusion whether "%n" affects the return value
of sscanf, so it's safer to check the assigned number of characters.
A bug was reported a year ago to the upstream
http://sourceforge.net/tracker/index.php?func=detail&aid=1894850&group_id=29880&atid=397597
but it seems to be dead.
Patch to fix it attached.
-- System Information:
Debian Release: 4.0
APT prefers stable
APT policy: (500, 'stable')
Architecture: amd64 (x86_64)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.24-etchnhalf.1-amd64
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Versions of packages nagios-plugins-basic depends on:
ii iputils-ping 3:20020927-6 Tools to test the reachability of
ii libc6 2.3.6.ds1-13etch8 GNU C Library: Shared libraries
ii libssl0.9.8 0.9.8c-4etch4 SSL shared libraries
ii procps 1:3.2.7-3 /proc file system utilities
ii ucf 2.0020 Update Configuration File: preserv
nagios-plugins-basic recommends no packages.
-- no debconf information
--- plugins/check_ping.c~
+++ plugins/check_ping.c
@@ -424,6 +424,7 @@
{
char buf[MAX_INPUT_BUFFER];
int result = STATE_UNKNOWN;
+ int match;
if ((child_process = spopen (cmd)) == NULL)
die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
@@ -440,28 +441,29 @@
result = max_state (result, error_scan (buf, addr));
/* get the percent loss statistics */
- if(sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss",&pl)==1 ||
- sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss", &pl) == 1 ||
- sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss", &pl) == 1 ||
- sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss",&pl)==1 ||
- sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time",&pl)==1 ||
- sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time", &pl)==1 ||
- sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time", &pl)==1 ||
- sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss", &pl) == 1 ||
- sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss", &pl) == 1
+ match = 0;
+ if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
+ (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match)
)
continue;
/* get the round trip average */
else
- if(sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f",&rta)==1 ||
- sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f",&rta)==1 ||
- sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f",&rta)==1 ||
- sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f",&rta)==1 ||
- sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f",&rta)==1 ||
- sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f",&rta)==1 ||
- sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f",&rta)==1 ||
- sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms",&rta)==1)
+ if((sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
+ (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match))
continue;
}