Code

Fixed segfault in argument processing. Thanks to Christoph Schell (#1742066)
[nagiosplug.git] / plugins / check_ntp.c
index cf63eea65c8665a1c872eb311ddbf8ab2f5462bf..28c23d84309895e7bdef7f30cd192e6e9a1f75c5 100644 (file)
@@ -138,8 +138,8 @@ typedef struct {
 #define OP_SET(x,y)   do{ x |= (y&OP_MASK); }while(0)
 #define OP_READSTAT 0x01
 #define OP_READVAR  0x02
-/* In peer status bytes, bytes 6,7,8 determine clock selection status */
-#define PEER_SEL(x) (x&0x07)
+/* In peer status bytes, bits 6,7,8 determine clock selection status */
+#define PEER_SEL(x) ((ntohs(x)>>8)&0x07)
 #define PEER_INCLUDED 0x04
 #define PEER_SYNCSOURCE 0x06
 
@@ -507,6 +507,7 @@ double jitter_request(const char *host, int *status){
        int peers_size=0, peer_offset=0;
        ntp_assoc_status_pair *peers=NULL;
        ntp_control_message req;
+       const char *getvar = "jitter";
        double rval = 0.0, jitter = -1.0;
        char *startofvalue=NULL, *nptr=NULL;
        void *tmp;
@@ -584,8 +585,10 @@ double jitter_request(const char *host, int *status){
                                 * thus reducing net traffic, guaranteeing us only a single
                                 * datagram in reply, and making intepretation much simpler
                                 */
-                               strncpy(req.data, "jitter", 6);
-                               req.count = htons(6);
+                               /* Older servers doesn't know what jitter is, so if we get an
+                                * error on the first pass we redo it with "dispersion" */
+                               strncpy(req.data, getvar, MAX_CM_SIZE-1);
+                               req.count = htons(strlen(getvar));
                                DBG(printf("sending READVAR request...\n"));
                                write(conn, &req, SIZEOF_NTPCM(req));
                                DBG(print_ntp_control_message(&req));
@@ -595,6 +598,14 @@ double jitter_request(const char *host, int *status){
                                read(conn, &req, SIZEOF_NTPCM(req));
                                DBG(print_ntp_control_message(&req));
 
+                               if(req.op&REM_ERROR && strstr(getvar, "jitter")) {
+                                       if(verbose) printf("The 'jitter' command failed (old ntp server?)\nRestarting with 'dispersion'...\n");
+                                       getvar = "dispersion";
+                                       num_selected--;
+                                       i--;
+                                       continue;
+                               }
+
                                /* get to the float value */
                                if(verbose) {
                                        printf("parsing jitter from peer %.2x: ", ntohs(peers[i].assoc));
@@ -709,7 +720,7 @@ int process_arguments(int argc, char **argv){
                usage4(_("Critical offset should be larger than warning offset"));
        }
 
-       if (ocrit < owarn){
+       if (jcrit < jwarn){
                usage4(_("Critical jitter should be larger than warning jitter"));
        }
 
@@ -720,9 +731,26 @@ int process_arguments(int argc, char **argv){
        return 0;
 }
 
+char *perfd_offset (double offset)
+{
+       return fperfdata ("offset", offset, "s",
+               TRUE, owarn,
+               TRUE, ocrit,
+               FALSE, 0, FALSE, 0);
+}
+
+char *perfd_jitter (double jitter)
+{
+       return fperfdata ("jitter", jitter, "s",
+               do_jitter, jwarn,
+               do_jitter, jcrit,
+               TRUE, 0, FALSE, 0);
+}
+
 int main(int argc, char *argv[]){
        int result, offset_result, jitter_result;
        double offset=0, jitter=0;
+       char *result_line, *perfdata_line;
 
        result=offset_result=jitter_result=STATE_UNKNOWN;
 
@@ -766,28 +794,32 @@ int main(int argc, char *argv[]){
 
        switch (result) {
                case STATE_CRITICAL :
-                       printf("NTP CRITICAL: ");
+                       asprintf(&result_line, "NTP CRITICAL:");
                        break;
                case STATE_WARNING :
-                       printf("NTP WARNING: ");
+                       asprintf(&result_line, "NTP WARNING:");
                        break;
                case STATE_OK :
-                       printf("NTP OK: ");
+                       asprintf(&result_line, "NTP OK:");
                        break;
                default :
-                       printf("NTP UNKNOWN: ");
+                       asprintf(&result_line, "NTP UNKNOWN:");
                        break;
        }
        if(offset_result==STATE_CRITICAL){
-               printf("Offset unknown|offset=unknown");
+               asprintf(&result_line, "%s %s", result_line, _("Offset unknown"));
        } else {
                if(offset_result==STATE_WARNING){
-                       printf("Unable to fully sample sync server. ");
+                       asprintf(&result_line, "%s %s", result_line, _("Unable to fully sample sync server"));
                }
-               printf("Offset %.10g secs|offset=%.10g", offset, offset);
+               asprintf(&result_line, "%s Offset %.10g secs", result_line, offset);
+               asprintf(&perfdata_line, "%s", perfd_offset(offset));
+       }
+       if (do_jitter) {
+               asprintf(&result_line, "%s, jitter=%f", result_line, jitter);
+               asprintf(&perfdata_line, "%s %s", perfdata_line,  perfd_jitter(jitter));
        }
-       if (do_jitter) printf(" jitter=%f", jitter);
-       printf("\n");
+       printf("%s|%s\n", result_line, perfdata_line);
 
        if(server_address!=NULL) free(server_address);
        return result;
@@ -808,11 +840,14 @@ void print_help(void){
        print_usage();
        printf (_(UT_HELP_VRSN));
        printf (_(UT_HOST_PORT), 'p', "123");
-       printf (_(UT_WARN_CRIT));
+       printf (" %s\n", "-w, --warning=DOUBLE");
+       printf ("    %s\n", _("Offset to result in warning status (seconds)"));
+       printf (" %s\n", "-c, --critical=DOUBLE");
+       printf ("    %s\n", _("Offset to result in critical status (seconds)"));
        printf (" %s\n", "-j, --warning=DOUBLE");
-       printf ("    %s\n", _("warning value for jitter"));
+       printf ("    %s\n", _("Warning value for jitter"));
        printf (" %s\n", "-k, --critical=DOUBLE");
-       printf ("    %s\n", _("critical value for jitter"));
+       printf ("    %s\n", _("Critical value for jitter"));
        printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
        printf (_(UT_VERBOSE));
        printf (_(UT_SUPPORT));