diff options
-rw-r--r-- | plugins/check_ntp.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/plugins/check_ntp.c b/plugins/check_ntp.c index 2954aa8..86709a1 100644 --- a/plugins/check_ntp.c +++ b/plugins/check_ntp.c | |||
@@ -295,6 +295,82 @@ double offset_request(const char *host){ | |||
295 | return avg_offset; | 295 | return avg_offset; |
296 | } | 296 | } |
297 | 297 | ||
298 | |||
299 | /* this should behave more like ntpdate, but needs optomisations... */ | ||
300 | double offset_request_ntpdate(const char *host){ | ||
301 | int i=0, j=0, ga_result=0, num_hosts=0, *socklist=NULL; | ||
302 | ntp_message req; | ||
303 | double offset=0., avg_offset=0.; | ||
304 | struct timeval recv_time; | ||
305 | struct addrinfo *ai=NULL, *ai_tmp=NULL, hints; | ||
306 | |||
307 | /* setup hints to only return results from getaddrinfo that we'd like */ | ||
308 | memset(&hints, 0, sizeof(struct addrinfo)); | ||
309 | hints.ai_family = address_family; | ||
310 | hints.ai_protocol = IPPROTO_UDP; | ||
311 | hints.ai_socktype = SOCK_DGRAM; | ||
312 | |||
313 | /* XXX better error handling here... */ | ||
314 | ga_result = getaddrinfo(host, "123", &hints, &ai); | ||
315 | if(ga_result!=0){ | ||
316 | fprintf(stderr, "error getting address for %s: %s\n", | ||
317 | host, gai_strerror(ga_result)); | ||
318 | return -1.0; | ||
319 | } | ||
320 | |||
321 | /* count te number of returned hosts, and allocate an array of sockets */ | ||
322 | ai_tmp=ai; | ||
323 | while(ai_tmp){ | ||
324 | ai_tmp = ai_tmp->ai_next; | ||
325 | num_hosts++; | ||
326 | } | ||
327 | socklist=(int*)malloc(sizeof(int)*num_hosts); | ||
328 | if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); | ||
329 | |||
330 | /* setup each socket for writing */ | ||
331 | ai_tmp=ai; | ||
332 | for(i=0;ai_tmp;i++){ | ||
333 | socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); | ||
334 | if(socklist[i] == -1) { | ||
335 | perror(NULL); | ||
336 | die(STATE_UNKNOWN, "can not create new socket"); | ||
337 | } | ||
338 | if(connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)){ | ||
339 | die(STATE_UNKNOWN, "can't create socket connection"); | ||
340 | } | ||
341 | ai_tmp = ai_tmp->ai_next; | ||
342 | } | ||
343 | |||
344 | /* now do AVG_NUM checks to each host. this needs to be optimized | ||
345 | * two ways: | ||
346 | * - use some parellization w/poll for much faster results. currently | ||
347 | * we do send/recv, send/recv, etc, whereas we could use poll(), to | ||
348 | * determine when to read and just do a bunch of writing when we | ||
349 | * have free time. | ||
350 | * - behave like ntpdate and only take the 5 best responses. | ||
351 | */ | ||
352 | for(i=0; i<AVG_NUM; i++){ | ||
353 | if(verbose) printf("offset calculation run %d/%d\n", i+1, AVG_NUM); | ||
354 | for(j=0; j<num_hosts; j++){ | ||
355 | if(verbose) printf("peer %d: ", j); | ||
356 | setup_request(&req); | ||
357 | write(socklist[j], &req, sizeof(ntp_message)); | ||
358 | read(socklist[j], &req, sizeof(ntp_message)); | ||
359 | gettimeofday(&recv_time, NULL); | ||
360 | offset=calc_offset(&req, &recv_time); | ||
361 | if(verbose) printf("offset: %g\n", offset); | ||
362 | avg_offset+=offset; | ||
363 | } | ||
364 | avg_offset/=num_hosts; | ||
365 | } | ||
366 | avg_offset/=AVG_NUM; | ||
367 | if(verbose) printf("overall average offset: %g\n", avg_offset); | ||
368 | |||
369 | for(j=0; j<num_hosts; j++){ close(socklist[j]); } | ||
370 | freeaddrinfo(ai); | ||
371 | return avg_offset; | ||
372 | } | ||
373 | |||
298 | void | 374 | void |
299 | setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){ | 375 | setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){ |
300 | memset(p, 0, sizeof(ntp_control_message)); | 376 | memset(p, 0, sizeof(ntp_control_message)); |