#!/usr/bin/perl -w

# ntpc check module

# Version: $Revision: 0.10 $
# Author: Matt Selsky <selsky@columbia.edu>
# Date: $Date: 2003/01/29 01:20:03 $
#
# Copyright (c) 2002 - 2003
# The Trustees of Columbia University in the City of New York
# Academic Information Systems
# 
# License restrictions apply, see doc/license.html for details.

use strict;
use FindBin;
use lib "$FindBin::Bin/../common";
use Survivor::Check;

my %argfmt = ();

my $sc = new Survivor::Check();

$sc->GetOpt(\%argfmt, \&NtpcValidate);

my $NTPQ = $sc->Which('ntpq');

unless( defined $NTPQ ) {
    $sc->ExitError(MODEXEC_MISCONFIG, 0, "ntpq executable not found");
}

my $r = $sc->Exec(\&NtpcCheck);

exit($r);

sub NtpcValidate {
    return(MODEXEC_OK, 0, "Ntpc OK");
}

sub NtpcCheck {
    my $self = shift;
    my $host = shift;

    # Since ntpq has a default timeout of 5000 ms/server query, running 
    # in parallel is recommended so that responsive hosts will not
    # be prevented from providing data.

    #$ ntpq -p localhost
    #     remote           refid      st t when poll reach   delay   offset    disp
    #==============================================================================
    # 128.59.35.142   0.0.0.0         16 -    - 1024    0     0.00    0.000 16000.0
    #+cs.columbia.edu clepsydra.dec.c  2 u   77 1024  377     0.52    7.757    6.79
    #*sirius.ctr.colu NAVOBS1.MIT.EDU  2 u  715 1024  377     0.79    0.755    0.55
    #$ ntpq -p stevemartin
    #ntpq: read: Connection refused
    #$ ntpq -p foo         
    #***Can't find host foo
    
    open(ANSWER, "$NTPQ -p $host 2>&1 |");
    
    my $peer_count = 0;
    my $bad_peer_count = 0;
    my @bad_peers;

    # read first line
    my $x = <ANSWER>;
    $x ||= '';
    chomp $x;

    if( $x =~ /Connection refused/ ) {
	close(ANSWER);
	return(MODEXEC_PROBLEM, 0, "Connection refused");
    }
    elsif( $x =~ /Can\'t find host/ ) {
	close(ANSWER);
	return(MODEXEC_MISCONFIG, 0, "Can't resolve hostname");
    }

    # eat next line assuming host was found and reachable
    <ANSWER>;

    while( <ANSWER> ) {
	chomp;

	$peer_count++;
	
	# check the stratum
	if( (split)[2] == 16 ) {
	    $bad_peer_count++;
	    push @bad_peers, (split)[0];
	}
    }
    close(ANSWER);

    if( $bad_peer_count > 0 ) {
	foreach (@bad_peers) {
	    s/^[\+\*]//;
	}
	if( $bad_peer_count == $peer_count ) {
	    my $msg;
	    if( scalar @bad_peers > 1 ) {
		$msg = sprintf("Peers %s unreachable", join(',',@bad_peers));
	    }
	    else {
		$msg = sprintf("Peer %s unreachable", join(',',@bad_peers));
	    }
	    return(MODEXEC_PROBLEM, $bad_peer_count, $msg);
	}
	else {
	    my $msg;
	    if( scalar @bad_peers > 1 ) {
		$msg = sprintf("Peers %s unreachable", join(',',@bad_peers));
	    }
	    else {
		$msg = sprintf("Peer %s unreachable", join(',',@bad_peers));
	    }
	    return(MODEXEC_WARNING, $bad_peer_count, $msg);
	}
    }
    elsif( $peer_count < 1 ) {
	    return(MODEXEC_PROBLEM, 0, "No time peers defined");
    }
    else {
	return(MODEXEC_OK, 1, "All time peers reachable");
    }
}

exit($r);
