3
** Copyright (C) 2000-2005 SIA Zabbix
5
** This program is free software; you can redistribute it and/or modify
6
** it under the terms of the GNU General Public License as published by
7
** the Free Software Foundation; either version 2 of the License, or
8
** (at your option) any later version.
10
** This program is distributed in the hope that it will be useful,
11
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
** GNU General Public License for more details.
15
** You should have received a copy of the GNU General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
#define NTP_SCALE 4294967296.0 /* 2^32, of course! */
28
#define NTP_PACKET_MIN 48 /* Without authentication */
29
#define NTP_PACKET_MAX 68 /* With authentication (ignored) */
30
#define NTP_DISP_FIELD 8 /* Offset of dispersion field */
31
#define NTP_REFERENCE 16 /* Offset of reference timestamp */
32
#define NTP_ORIGINATE 24 /* Offset of originate timestamp */
33
#define NTP_RECEIVE 32 /* Offset of receive timestamp */
34
#define NTP_TRANSMIT 40 /* Offset of transmit timestamp */
36
#define NTP_LI_FUDGE 0 /* The current 'status' */
37
#define NTP_VERSION 3 /* The current version */
38
#define NTP_VERSION_MAX 4 /* The maximum valid version */
39
#define NTP_STRATUM 15 /* The current stratum as a server */
40
#define NTP_STRATUM_MAX 15 /* The maximum valid stratum */
41
#define NTP_POLLING 8 /* The current 'polling interval' */
42
#define NTP_PRECISION 0 /* The current 'precision' - 1 sec. */
44
#define NTP_ACTIVE 1 /* NTP symmetric active request */
45
#define NTP_PASSIVE 2 /* NTP symmetric passive response */
46
#define NTP_CLIENT 3 /* NTP client request */
47
#define NTP_SERVER 4 /* NTP server response */
48
#define NTP_BROADCAST 5 /* NTP server broadcast */
50
#define NTP_INSANITY 3600.0 /* Errors beyond this are hopeless */
51
#define RESET_MIN 15 /* Minimum period between resets */
52
#define ABSCISSA 3.0 /* Scale factor for standard errors */
54
typedef struct ntp_data_s {
73
static void make_packet (ntp_data *data)
75
data->status = NTP_LI_FUDGE<<6;
76
data->stratum = NTP_STRATUM;
77
data->reference = data->dispersion = 0.0;
79
data->version = NTP_VERSION;
81
data->polling = NTP_POLLING;
82
data->precision = NTP_PRECISION;
83
data->receive = data->originate = 0.0;
84
data->current = data->transmit = zbx_current_time();
87
static void pack_ntp (unsigned char *packet, int length, ntp_data *data)
90
/* Pack the essential data into an NTP packet, bypassing struct layout and
91
endian problems. Note that it ignores fields irrelevant to SNTP. */
96
assert(length >= (NTP_TRANSMIT + 8));
98
memset(packet,0,(size_t)length);
100
packet[0] = (data->status << 6) | (data->version << 3) | data->mode;
101
packet[1] = data->stratum;
102
packet[2] = data->polling;
103
packet[3] = data->precision;
105
d = data->originate / NTP_SCALE;
106
for (i = 0; i < 8; ++i) {
107
if ((k = (int)(d *= 256.0)) >= 256) k = 255;
108
packet[NTP_ORIGINATE + i] = k;
112
d = data->receive / NTP_SCALE;
113
for (i = 0; i < 8; ++i) {
114
if ((k = (int)(d *= 256.0)) >= 256) k = 255;
115
packet[NTP_RECEIVE + i] = k;
119
d = data->transmit / NTP_SCALE;
120
for (i = 0; i < 8; ++i) {
121
if ((k = (int)(d *= 256.0)) >= 256) k = 255;
122
packet[NTP_TRANSMIT + i] = k;
127
static void unpack_ntp (ntp_data *data, unsigned char *packet, int length) {
129
/* Unpack the essential data from an NTP packet, bypassing struct layout and
130
endian problems. Note that it ignores fields irrelevant to SNTP. */
135
memset(data, 0, sizeof(ntp_data));
140
assert(length >= (NTP_TRANSMIT + 8));
142
data->current = zbx_current_time(); /* Best to come first */
143
data->status = (packet[0] >> 6);
144
data->version = (packet[0] >> 3) & 0x07;
145
data->mode = packet[0] & 0x07;
146
data->stratum = packet[1];
147
data->polling = packet[2];
148
data->precision = packet[3];
151
for (i = 0; i < 4; ++i) d = 256.0 * d + packet[NTP_DISP_FIELD + i];
152
data->dispersion = d / 65536.0;
154
for (i = 0; i < 8; ++i) d = 256.0 * d + packet[NTP_REFERENCE + i];
155
data->reference = d / NTP_SCALE;
157
for (i = 0; i < 8; ++i) d = 256.0 * d + packet[NTP_ORIGINATE + i];
158
data->originate = d / NTP_SCALE;
160
for (i = 0; i < 8; ++i) d = 256.0 * d + packet[NTP_RECEIVE + i];
161
data->receive = d / NTP_SCALE;
163
for (i = 0; i < 8; ++i) d = 256.0 * d + packet[NTP_TRANSMIT + i];
164
data->transmit = d / NTP_SCALE;
168
static void display_data (ntp_data *data) {
170
printf("sta = %d ver = %d mod = %d str = %d pol = %d dis = " ZBX_FS_DBL_EXT(6) " ref = " ZBX_FS_DBL_EXT(6) "\n",
171
data->status,data->version,data->mode,data->stratum,data->polling,
172
data->dispersion,data->reference);
173
printf("ori = " ZBX_FS_DBL_EXT(6) " rec = " ZBX_FS_DBL_EXT(6) "\n",data->originate, data->receive);
174
printf("tra = " ZBX_FS_DBL_EXT(6) " cur = " ZBX_FS_DBL_EXT(6) "\n",data->transmit, data->current);
178
int check_ntp(char *host, unsigned short port, int *value_int)
187
char packet[NTP_PACKET_MIN];
193
if( SUCCEED == (ret = zbx_tcp_connect(&s, host, port)) )
197
pack_ntp((unsigned char*)packet, sizeof(packet), &data);
199
if( SUCCEED == (ret = zbx_tcp_send_raw(&s, packet)) )
201
if( SUCCEED == (ret = zbx_tcp_recv(&s, &buf)) )
204
unpack_ntp(&data, (unsigned char *)buf, strlen(buf));
207
/* local time */ *value_int = time(NULL);
209
/* server time */ *value_int = (data.receive > 0) ? (int)(data.receive - ZBX_JAN_1970_IN_SEC) : 0;
218
zabbix_log(LOG_LEVEL_DEBUG, "NTP check error: %s", zbx_tcp_strerror());
221
return SYSINFO_RET_OK;