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 2954aa88..86709a1f 100644 --- a/plugins/check_ntp.c +++ b/plugins/check_ntp.c @@ -295,6 +295,82 @@ double offset_request(const char *host){ return avg_offset; } + +/* this should behave more like ntpdate, but needs optomisations... */ +double offset_request_ntpdate(const char *host){ + int i=0, j=0, ga_result=0, num_hosts=0, *socklist=NULL; + ntp_message req; + double offset=0., avg_offset=0.; + struct timeval recv_time; + struct addrinfo *ai=NULL, *ai_tmp=NULL, hints; + + /* setup hints to only return results from getaddrinfo that we'd like */ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = address_family; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_socktype = SOCK_DGRAM; + + /* XXX better error handling here... */ + ga_result = getaddrinfo(host, "123", &hints, &ai); + if(ga_result!=0){ + fprintf(stderr, "error getting address for %s: %s\n", + host, gai_strerror(ga_result)); + return -1.0; + } + + /* count te number of returned hosts, and allocate an array of sockets */ + ai_tmp=ai; + while(ai_tmp){ + ai_tmp = ai_tmp->ai_next; + num_hosts++; + } + socklist=(int*)malloc(sizeof(int)*num_hosts); + if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); + + /* setup each socket for writing */ + ai_tmp=ai; + for(i=0;ai_tmp;i++){ + socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); + if(socklist[i] == -1) { + perror(NULL); + die(STATE_UNKNOWN, "can not create new socket"); + } + if(connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)){ + die(STATE_UNKNOWN, "can't create socket connection"); + } + 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<AVG_NUM; i++){ + if(verbose) printf("offset calculation run %d/%d\n", i+1, AVG_NUM); + for(j=0; j<num_hosts; j++){ + if(verbose) printf("peer %d: ", j); + setup_request(&req); + write(socklist[j], &req, sizeof(ntp_message)); + read(socklist[j], &req, sizeof(ntp_message)); + gettimeofday(&recv_time, NULL); + offset=calc_offset(&req, &recv_time); + if(verbose) printf("offset: %g\n", offset); + avg_offset+=offset; + } + avg_offset/=num_hosts; + } + avg_offset/=AVG_NUM; + if(verbose) printf("overall average offset: %g\n", avg_offset); + + for(j=0; j<num_hosts; j++){ close(socklist[j]); } + freeaddrinfo(ai); + return avg_offset; +} + void setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){ memset(p, 0, sizeof(ntp_control_message)); |