From 1b207c0b2759eaabc1162190d0df47bbe5935de3 Mon Sep 17 00:00:00 2001 From: "M. Sean Finney" Date: Wed, 12 Apr 2006 10:00:23 +0000 Subject: the offset_requests are now parallelized. still stuff needs to be done (conveniently marked with XXX), but on well behaving networks the plugin should behave more or less identical to check_ntp.pl now. git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1373 f882894a-f735-0410-b71e-b25c423dba1c --- plugins/check_ntp.c | 167 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 105 insertions(+), 62 deletions(-) diff --git a/plugins/check_ntp.c b/plugins/check_ntp.c index 86709a1f..149ca98f 100644 --- a/plugins/check_ntp.c +++ b/plugins/check_ntp.c @@ -29,6 +29,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "netutils.h" #include "utils.h" +#include static char *server_address=NULL; static int verbose=0; @@ -64,6 +65,13 @@ typedef struct { uint64_t txts; /* time at which request departed server */ } ntp_message; +/* this structure holds data about results from querying offset from a peer */ +typedef struct { + int waiting; /* we set to 1 to signal waiting for a response */ + int num_responses; /* number of successfully recieved responses */ + double offset[AVG_NUM]; /* offsets from each response */ +} ntp_server_results; + /* this structure holds everything in an ntp control message as per rfc1305 */ typedef struct { uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ @@ -271,38 +279,20 @@ void setup_request(ntp_message *p){ TVtoNTP64(t,p->txts); } +/* do everything we need to get the total average offset + * - we use a certain amount of parallelization with poll() to ensure + * we don't waste time sitting around waiting for single packets. + * - we also "manually" handle resolving host names and connecting, because + * we have to do it in a way that our lazy macros don't handle currently :( */ double offset_request(const char *host){ - int i=0, conn=-1; - ntp_message req; - double next_offset=0., avg_offset=0.; - struct timeval recv_time; - - for(i=0; iai_next; - num_hosts++; - } + /* count the number of returned hosts, and allocate stuff accordingly */ + for(ai_tmp=ai; ai_tmp!=NULL; ai_tmp=ai_tmp->ai_next){ num_hosts++; } + req=(ntp_message*)malloc(sizeof(ntp_message)*num_hosts); + if(req==NULL) die(STATE_UNKNOWN, "can not allocate ntp message array"); socklist=(int*)malloc(sizeof(int)*num_hosts); if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); + ufds=(struct pollfd*)malloc(sizeof(struct pollfd)*num_hosts); + if(ufds==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); + servers=(ntp_server_results*)malloc(sizeof(ntp_server_results)*num_hosts); + if(servers==NULL) die(STATE_UNKNOWN, "can not allocate server array"); + memset(servers, 0, sizeof(ntp_server_results)*num_hosts); - /* setup each socket for writing */ + /* setup each socket for writing, and the corresponding struct pollfd */ ai_tmp=ai; for(i=0;ai_tmp;i++){ socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); @@ -337,37 +329,88 @@ double offset_request_ntpdate(const char *host){ } if(connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)){ die(STATE_UNKNOWN, "can't create socket connection"); + } else { + ufds[i].fd=socklist[i]; + ufds[i].events=POLLIN; + ufds[i].revents=0; } ai_tmp = ai_tmp->ai_next; } - /* now do AVG_NUM checks to each host. this needs to be optimized - * two ways: - * - use some parellization w/poll for much faster results. currently - * we do send/recv, send/recv, etc, whereas we could use poll(), to - * determine when to read and just do a bunch of writing when we - * have free time. - * - behave like ntpdate and only take the 5 best responses. - */ - for(i=0; i