diff options
author | hugetoad <hugetoad@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2005-10-12 16:13:10 +0000 |
---|---|---|
committer | hugetoad <hugetoad@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2005-10-12 16:13:10 +0000 |
commit | dd91b8328832659bd0aa5ed0877ff6a00f0982d8 (patch) | |
tree | 630226480a4a8da52d303c0813adb9826e5d24a6 /src/libs | |
parent | e39cca6e9d8343d949007c23bb775d077def6489 (diff) | |
download | zabbix-dd91b8328832659bd0aa5ed0877ff6a00f0982d8.tar.gz zabbix-dd91b8328832659bd0aa5ed0877ff6a00f0982d8.tar.xz zabbix-dd91b8328832659bd0aa5ed0877ff6a00f0982d8.zip |
- added support of service.ntp[host,port] (Alexei)
git-svn-id: svn://svn.zabbix.com/trunk@2177 97f52cf1-0a1b-0410-bd0e-c28be96e8082
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/zbxsysinfo/Makefile.am | 2 | ||||
-rw-r--r-- | src/libs/zbxsysinfo/common/common.c | 5 | ||||
-rw-r--r-- | src/libs/zbxsysinfo/common/ntp.c | 315 |
3 files changed, 321 insertions, 1 deletions
diff --git a/src/libs/zbxsysinfo/Makefile.am b/src/libs/zbxsysinfo/Makefile.am index d2b67728..77981f4f 100644 --- a/src/libs/zbxsysinfo/Makefile.am +++ b/src/libs/zbxsysinfo/Makefile.am @@ -1,4 +1,4 @@ SUBDIRS=@ARCH@ libzbxsysinfo_a_LIBADD = ../zbxcommon/libzbxcommon.a ../zbxcrypto/libzbxcrypto.a -libzbxsysinfo_a_SOURCES=common/common.c common/file.c common/system.c @ARCH@/@ARCH@.c +libzbxsysinfo_a_SOURCES=common/common.c common/file.c common/ntp.c common/system.c @ARCH@/@ARCH@.c lib_LIBRARIES=libzbxsysinfo.a diff --git a/src/libs/zbxsysinfo/common/common.c b/src/libs/zbxsysinfo/common/common.c index 667ab69f..88dae787 100644 --- a/src/libs/zbxsysinfo/common/common.c +++ b/src/libs/zbxsysinfo/common/common.c @@ -1808,6 +1808,11 @@ int CHECK_SERVICE(const char *cmd, const char *service_and_ip_and_port,double * if(port == 0) port=22; result=check_ssh(ip,port,&value_int); } + else if(strcmp(service,"service.ntp") == 0) + { + if(port == 0) port=123; + result=check_ntp(ip,port,&value_int); + } #ifdef HAVE_LDAP else if(strcmp(service,"ldap") == 0) { diff --git a/src/libs/zbxsysinfo/common/ntp.c b/src/libs/zbxsysinfo/common/ntp.c new file mode 100644 index 00000000..b9547005 --- /dev/null +++ b/src/libs/zbxsysinfo/common/ntp.c @@ -0,0 +1,315 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <errno.h> +#include <time.h> + +#include "common.h" +#include "sysinfo.h" + +#define JAN_1970 2208988800.0 /* 1970 - 1900 in seconds */ +#define NTP_SCALE 4294967296.0 /* 2^32, of course! */ + +#define NTP_PACKET_MIN 48 /* Without authentication */ +#define NTP_PACKET_MAX 68 /* With authentication (ignored) */ +#define NTP_DISP_FIELD 8 /* Offset of dispersion field */ +#define NTP_REFERENCE 16 /* Offset of reference timestamp */ +#define NTP_ORIGINATE 24 /* Offset of originate timestamp */ +#define NTP_RECEIVE 32 /* Offset of receive timestamp */ +#define NTP_TRANSMIT 40 /* Offset of transmit timestamp */ + +#define NTP_LI_FUDGE 0 /* The current 'status' */ +#define NTP_VERSION 3 /* The current version */ +#define NTP_VERSION_MAX 4 /* The maximum valid version */ +#define NTP_STRATUM 15 /* The current stratum as a server */ +#define NTP_STRATUM_MAX 15 /* The maximum valid stratum */ +#define NTP_POLLING 8 /* The current 'polling interval' */ +#define NTP_PRECISION 0 /* The current 'precision' - 1 sec. */ + +#define NTP_ACTIVE 1 /* NTP symmetric active request */ +#define NTP_PASSIVE 2 /* NTP symmetric passive response */ +#define NTP_CLIENT 3 /* NTP client request */ +#define NTP_SERVER 4 /* NTP server response */ +#define NTP_BROADCAST 5 /* NTP server broadcast */ + +#define NTP_INSANITY 3600.0 /* Errors beyond this are hopeless */ +#define RESET_MIN 15 /* Minimum period between resets */ +#define ABSCISSA 3.0 /* Scale factor for standard errors */ + +typedef struct NTP_DATA { + unsigned char status, version, mode, stratum, polling, precision; + double dispersion, reference, originate, receive, transmit, current; +} ntp_data; + +double current_time (double offset) { + +/* Get the current UTC time in seconds since the Epoch plus an offset (usually +the time from the beginning of the century to the Epoch!) */ + + struct timeval current; + + errno = 0; + if (gettimeofday(¤t,NULL)) + { + exit(-1); + } + return offset+current.tv_sec+1.0e-6*current.tv_usec; +} + +void make_packet (ntp_data *data) +{ + data->status = NTP_LI_FUDGE<<6; + data->stratum = NTP_STRATUM; + data->reference = data->dispersion = 0.0; + + data->version = NTP_VERSION; + data->mode = 1; + data->polling = NTP_POLLING; + data->precision = NTP_PRECISION; + data->receive = data->originate = 0.0; + data->current = data->transmit = current_time(JAN_1970); +} + +void pack_ntp (unsigned char *packet, int length, ntp_data *data) { + +/* Pack the essential data into an NTP packet, bypassing struct layout and +endian problems. Note that it ignores fields irrelevant to SNTP. */ + + int i, k; + double d; + + memset(packet,0,(size_t)length); + packet[0] = (data->status<<6)|(data->version<<3)|data->mode; + packet[1] = data->stratum; + packet[2] = data->polling; + packet[3] = data->precision; + d = data->originate/NTP_SCALE; + for (i = 0; i < 8; ++i) { + if ((k = (int)(d *= 256.0)) >= 256) k = 255; + packet[NTP_ORIGINATE+i] = k; + d -= k; + } + d = data->receive/NTP_SCALE; + for (i = 0; i < 8; ++i) { + if ((k = (int)(d *= 256.0)) >= 256) k = 255; + packet[NTP_RECEIVE+i] = k; + d -= k; + } + d = data->transmit/NTP_SCALE; + for (i = 0; i < 8; ++i) { + if ((k = (int)(d *= 256.0)) >= 256) k = 255; + packet[NTP_TRANSMIT+i] = k; + d -= k; + } +} + +void unpack_ntp (ntp_data *data, unsigned char *packet, int length) { + +/* Unpack the essential data from an NTP packet, bypassing struct layout and +endian problems. Note that it ignores fields irrelevant to SNTP. */ + + int i; + double d; + + data->current = current_time(JAN_1970); /* Best to come first */ + data->status = (packet[0] >> 6); + data->version = (packet[0] >> 3)&0x07; + data->mode = packet[0]&0x07; + data->stratum = packet[1]; + data->polling = packet[2]; + data->precision = packet[3]; + d = 0.0; + for (i = 0; i < 4; ++i) d = 256.0*d+packet[NTP_DISP_FIELD+i]; + data->dispersion = d/65536.0; + d = 0.0; + for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_REFERENCE+i]; + data->reference = d/NTP_SCALE; + d = 0.0; + for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_ORIGINATE+i]; + data->originate = d/NTP_SCALE; + d = 0.0; + for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_RECEIVE+i]; + data->receive = d/NTP_SCALE; + d = 0.0; + for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_TRANSMIT+i]; + data->transmit = d/NTP_SCALE; +} + +/* +void display_data (ntp_data *data) { + + printf("sta=%d ver=%d mod=%d str=%d pol=%d dis=%.6f ref=%.6f\n", + data->status,data->version,data->mode,data->stratum,data->polling, + data->dispersion,data->reference); + printf("ori=%.6f rec=%.6f\n",data->originate,data->receive); + printf("tra=%.6f cur=%.6f\n",data->transmit,data->current); +} +*/ + + +time_t convert_time (double value, int *millisecs) { + +/* Convert the time to the ANSI C form. */ + + time_t result = (time_t)value; + + if ((*millisecs = (int)(1000.0*(value-result))) >= 1000) { + *millisecs = 0; + ++result; + } + return result; +} + +int format_time (char *text, int length, double offset, double error, + double drift, double drifterr) { + +/* Format the current time into a string, with the extra information as +requested. Note that the rest of the program uses the correction needed, which +is what is printed for diagnostics, but this formats the error in the local +system for display to users. So the results from this are the negation of +those printed by the verbose options. */ + + int milli, len; + time_t now; + struct tm *gmt; + static const char *months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + +/* Work out and format the current local time. Note that some semi-ANSI +systems do not set the return value from (s)printf. */ + + now = convert_time(current_time(offset),&milli); + errno = 0; + if ((gmt = localtime(&now)) == NULL) + { + printf("unable to work out local time",NULL); + return -1; + } + len = 24; + if (length <= len) + { + printf("internal error calling format_time"); + return -1; + } + + errno = 0; + printf("%.4d %s %.2d %.2d:%.2d:%.2d.%.3d\n", + gmt->tm_year+1900,months[gmt->tm_mon],gmt->tm_mday, + gmt->tm_hour,gmt->tm_min,gmt->tm_sec,milli); + + return now; +} + +int check_ntp(char *host, int port, int *value_int) +{ + int s; + int len; + char c[MAX_STRING_LEN]; + char *e; + + struct hostent *hp; + + struct sockaddr_in servaddr_in; + + struct linger ling; + + char text[50]; + + ntp_data data; + unsigned char packet[NTP_PACKET_MIN]; + + make_packet(&data); + + servaddr_in.sin_family=AF_INET; + hp=gethostbyname(host); + + if(hp==NULL) + { +/* printf("gethostbyname() failed [%s]", hstrerror(h_errno));*/ + return SYSINFO_RET_FAIL; + } + + servaddr_in.sin_addr.s_addr=((struct in_addr *)(hp->h_addr))->s_addr; + + servaddr_in.sin_port=htons(port); + + s=socket(AF_INET,SOCK_DGRAM,0); + + if(s == -1) + { +/* printf("Cannot create socket [%s]", strerror(errno));*/ + return SYSINFO_RET_FAIL; + } + + if( connect(s,(struct sockaddr *)&servaddr_in,sizeof(struct sockaddr_in)) == -1 ) + { + switch (errno) + { + case EINTR: + break; + case EHOSTUNREACH: + break; + default: + break; + } + close(s); + return SYSINFO_RET_FAIL; + } + + pack_ntp(packet,NTP_PACKET_MIN,&data); + + if( write(s,&packet,NTP_PACKET_MIN) == -1 ) + { + switch (errno) + { + case EINTR: + break; + default: + break; + } + close(s); + return SYSINFO_RET_FAIL; + } + + memset(c,0,MAX_STRING_LEN); + len=read(s,c,MAX_STRING_LEN); + + if(len == -1) + { + switch (errno) + { + case EINTR: + break; + case ECONNRESET: + break; + default: + break; + } + close(s); + return SYSINFO_RET_FAIL; + } + close(s); + + unpack_ntp(&data,c,len); + +/* display_data(&data); */ + + sprintf(text,"%d",0); + +/* format_time(text,75,offset,error,0.0,-1.0);*/ + +/* if (dispersion < data->dispersion) dispersion = data->dispersion; + x = data->receive-data->originate; + y = (data->transmit == 0.0 ? 0.0 : data->transmit-data->current); + *off = 0.5*(x+y); + *err = x-y; + x = data->current-data->originate; + if (0.5*x > *err) *err = 0.5*x; */ + + *value_int = format_time(text,75,0,0,0.0,-1.0); + + return SYSINFO_RET_OK; +} |