diff options
author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2024-10-31 15:27:01 +0100 |
---|---|---|
committer | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2024-10-31 15:27:01 +0100 |
commit | fa15fdcf5dc2d40aba2f8520108e552b73b1df2b (patch) | |
tree | d51d62db024b317091f42d9ee540da7371e9d170 /plugins/check_ntp_time.c | |
parent | 0fd0421052fed1972ecbdfdabecba5a616eaa109 (diff) | |
parent | 87eb2bef1ee2a6a42793437b2f5d63f41b1e1806 (diff) | |
download | monitoring-plugins-fa15fdc.tar.gz |
Merge branch 'master' into fix/check_ssh-variable-stuff
Diffstat (limited to 'plugins/check_ntp_time.c')
-rw-r--r-- | plugins/check_ntp_time.c | 628 |
1 files changed, 328 insertions, 300 deletions
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index b2e16556..703b69df 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c | |||
@@ -1,63 +1,63 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Monitoring check_ntp_time plugin | 3 | * Monitoring check_ntp_time plugin |
4 | * | 4 | * |
5 | * License: GPL | 5 | * License: GPL |
6 | * Copyright (c) 2006 Sean Finney <seanius@seanius.net> | 6 | * Copyright (c) 2006 Sean Finney <seanius@seanius.net> |
7 | * Copyright (c) 2006-2008 Monitoring Plugins Development Team | 7 | * Copyright (c) 2006-2024 Monitoring Plugins Development Team |
8 | * | 8 | * |
9 | * Description: | 9 | * Description: |
10 | * | 10 | * |
11 | * This file contains the check_ntp_time plugin | 11 | * This file contains the check_ntp_time plugin |
12 | * | 12 | * |
13 | * This plugin checks the clock offset between the local host and a | 13 | * This plugin checks the clock offset between the local host and a |
14 | * remote NTP server. It is independent of any commandline programs or | 14 | * remote NTP server. It is independent of any commandline programs or |
15 | * external libraries. | 15 | * external libraries. |
16 | * | 16 | * |
17 | * If you'd rather want to monitor an NTP server, please use | 17 | * If you'd rather want to monitor an NTP server, please use |
18 | * check_ntp_peer. | 18 | * check_ntp_peer. |
19 | * | 19 | * |
20 | * | 20 | * |
21 | * This program is free software: you can redistribute it and/or modify | 21 | * This program is free software: you can redistribute it and/or modify |
22 | * it under the terms of the GNU General Public License as published by | 22 | * it under the terms of the GNU General Public License as published by |
23 | * the Free Software Foundation, either version 3 of the License, or | 23 | * the Free Software Foundation, either version 3 of the License, or |
24 | * (at your option) any later version. | 24 | * (at your option) any later version. |
25 | * | 25 | * |
26 | * This program is distributed in the hope that it will be useful, | 26 | * This program is distributed in the hope that it will be useful, |
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
29 | * GNU General Public License for more details. | 29 | * GNU General Public License for more details. |
30 | * | 30 | * |
31 | * You should have received a copy of the GNU General Public License | 31 | * You should have received a copy of the GNU General Public License |
32 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 32 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
33 | * | 33 | * |
34 | * | 34 | * |
35 | *****************************************************************************/ | 35 | *****************************************************************************/ |
36 | 36 | ||
37 | const char *progname = "check_ntp_time"; | 37 | const char *progname = "check_ntp_time"; |
38 | const char *copyright = "2006-2008"; | 38 | const char *copyright = "2006-2024"; |
39 | const char *email = "devel@monitoring-plugins.org"; | 39 | const char *email = "devel@monitoring-plugins.org"; |
40 | 40 | ||
41 | #include "common.h" | 41 | #include "common.h" |
42 | #include "netutils.h" | 42 | #include "netutils.h" |
43 | #include "utils.h" | 43 | #include "utils.h" |
44 | 44 | ||
45 | static char *server_address=NULL; | 45 | static char *server_address = NULL; |
46 | static char *port="123"; | 46 | static char *port = "123"; |
47 | static int verbose=0; | 47 | static int verbose = 0; |
48 | static bool quiet = false; | 48 | static bool quiet = false; |
49 | static char *owarn="60"; | 49 | static char *owarn = "60"; |
50 | static char *ocrit="120"; | 50 | static char *ocrit = "120"; |
51 | static int time_offset=0; | 51 | static int time_offset = 0; |
52 | 52 | ||
53 | int process_arguments (int, char **); | 53 | static int process_arguments(int, char **); |
54 | thresholds *offset_thresholds = NULL; | 54 | static thresholds *offset_thresholds = NULL; |
55 | void print_help (void); | 55 | static void print_help(void); |
56 | void print_usage (void); | 56 | void print_usage(void); |
57 | 57 | ||
58 | /* number of times to perform each request to get a good average. */ | 58 | /* number of times to perform each request to get a good average. */ |
59 | #ifndef AVG_NUM | 59 | #ifndef AVG_NUM |
60 | #define AVG_NUM 4 | 60 | # define AVG_NUM 4 |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | /* max size of control message data */ | 63 | /* max size of control message data */ |
@@ -65,17 +65,17 @@ void print_usage (void); | |||
65 | 65 | ||
66 | /* this structure holds everything in an ntp request/response as per rfc1305 */ | 66 | /* this structure holds everything in an ntp request/response as per rfc1305 */ |
67 | typedef struct { | 67 | typedef struct { |
68 | uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ | 68 | uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ |
69 | uint8_t stratum; /* clock stratum */ | 69 | uint8_t stratum; /* clock stratum */ |
70 | int8_t poll; /* polling interval */ | 70 | int8_t poll; /* polling interval */ |
71 | int8_t precision; /* precision of the local clock */ | 71 | int8_t precision; /* precision of the local clock */ |
72 | int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */ | 72 | int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */ |
73 | uint32_t rtdisp; /* like above, but for max err to primary src */ | 73 | uint32_t rtdisp; /* like above, but for max err to primary src */ |
74 | uint32_t refid; /* ref clock identifier */ | 74 | uint32_t refid; /* ref clock identifier */ |
75 | uint64_t refts; /* reference timestamp. local time local clock */ | 75 | uint64_t refts; /* reference timestamp. local time local clock */ |
76 | uint64_t origts; /* time at which request departed client */ | 76 | uint64_t origts; /* time at which request departed client */ |
77 | uint64_t rxts; /* time at which request arrived at server */ | 77 | uint64_t rxts; /* time at which request arrived at server */ |
78 | uint64_t txts; /* time at which request departed server */ | 78 | uint64_t txts; /* time at which request departed server */ |
79 | } ntp_message; | 79 | } ntp_message; |
80 | 80 | ||
81 | /* this structure holds data about results from querying offset from a peer */ | 81 | /* this structure holds data about results from querying offset from a peer */ |
@@ -86,43 +86,55 @@ typedef struct { | |||
86 | double rtdelay; /* converted from the ntp_message */ | 86 | double rtdelay; /* converted from the ntp_message */ |
87 | double rtdisp; /* converted from the ntp_message */ | 87 | double rtdisp; /* converted from the ntp_message */ |
88 | double offset[AVG_NUM]; /* offsets from each response */ | 88 | double offset[AVG_NUM]; /* offsets from each response */ |
89 | uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ | 89 | uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ |
90 | } ntp_server_results; | 90 | } ntp_server_results; |
91 | 91 | ||
92 | /* bits 1,2 are the leap indicator */ | 92 | /* bits 1,2 are the leap indicator */ |
93 | #define LI_MASK 0xc0 | 93 | #define LI_MASK 0xc0 |
94 | #define LI(x) ((x&LI_MASK)>>6) | 94 | #define LI(x) ((x & LI_MASK) >> 6) |
95 | #define LI_SET(x,y) do{ x |= ((y<<6)&LI_MASK); }while(0) | 95 | #define LI_SET(x, y) \ |
96 | do { \ | ||
97 | x |= ((y << 6) & LI_MASK); \ | ||
98 | } while (0) | ||
96 | /* and these are the values of the leap indicator */ | 99 | /* and these are the values of the leap indicator */ |
97 | #define LI_NOWARNING 0x00 | 100 | #define LI_NOWARNING 0x00 |
98 | #define LI_EXTRASEC 0x01 | 101 | #define LI_EXTRASEC 0x01 |
99 | #define LI_MISSINGSEC 0x02 | 102 | #define LI_MISSINGSEC 0x02 |
100 | #define LI_ALARM 0x03 | 103 | #define LI_ALARM 0x03 |
101 | /* bits 3,4,5 are the ntp version */ | 104 | /* bits 3,4,5 are the ntp version */ |
102 | #define VN_MASK 0x38 | 105 | #define VN_MASK 0x38 |
103 | #define VN(x) ((x&VN_MASK)>>3) | 106 | #define VN(x) ((x & VN_MASK) >> 3) |
104 | #define VN_SET(x,y) do{ x |= ((y<<3)&VN_MASK); }while(0) | 107 | #define VN_SET(x, y) \ |
108 | do { \ | ||
109 | x |= ((y << 3) & VN_MASK); \ | ||
110 | } while (0) | ||
105 | #define VN_RESERVED 0x02 | 111 | #define VN_RESERVED 0x02 |
106 | /* bits 6,7,8 are the ntp mode */ | 112 | /* bits 6,7,8 are the ntp mode */ |
107 | #define MODE_MASK 0x07 | 113 | #define MODE_MASK 0x07 |
108 | #define MODE(x) (x&MODE_MASK) | 114 | #define MODE(x) (x & MODE_MASK) |
109 | #define MODE_SET(x,y) do{ x |= (y&MODE_MASK); }while(0) | 115 | #define MODE_SET(x, y) \ |
116 | do { \ | ||
117 | x |= (y & MODE_MASK); \ | ||
118 | } while (0) | ||
110 | /* here are some values */ | 119 | /* here are some values */ |
111 | #define MODE_CLIENT 0x03 | 120 | #define MODE_CLIENT 0x03 |
112 | #define MODE_CONTROLMSG 0x06 | 121 | #define MODE_CONTROLMSG 0x06 |
113 | /* In control message, bits 8-10 are R,E,M bits */ | 122 | /* In control message, bits 8-10 are R,E,M bits */ |
114 | #define REM_MASK 0xe0 | 123 | #define REM_MASK 0xe0 |
115 | #define REM_RESP 0x80 | 124 | #define REM_RESP 0x80 |
116 | #define REM_ERROR 0x40 | 125 | #define REM_ERROR 0x40 |
117 | #define REM_MORE 0x20 | 126 | #define REM_MORE 0x20 |
118 | /* In control message, bits 11 - 15 are opcode */ | 127 | /* In control message, bits 11 - 15 are opcode */ |
119 | #define OP_MASK 0x1f | 128 | #define OP_MASK 0x1f |
120 | #define OP_SET(x,y) do{ x |= (y&OP_MASK); }while(0) | 129 | #define OP_SET(x, y) \ |
130 | do { \ | ||
131 | x |= (y & OP_MASK); \ | ||
132 | } while (0) | ||
121 | #define OP_READSTAT 0x01 | 133 | #define OP_READSTAT 0x01 |
122 | #define OP_READVAR 0x02 | 134 | #define OP_READVAR 0x02 |
123 | /* In peer status bytes, bits 6,7,8 determine clock selection status */ | 135 | /* In peer status bytes, bits 6,7,8 determine clock selection status */ |
124 | #define PEER_SEL(x) ((ntohs(x)>>8)&0x07) | 136 | #define PEER_SEL(x) ((ntohs(x) >> 8) & 0x07) |
125 | #define PEER_INCLUDED 0x04 | 137 | #define PEER_INCLUDED 0x04 |
126 | #define PEER_SYNCSOURCE 0x06 | 138 | #define PEER_SYNCSOURCE 0x06 |
127 | 139 | ||
128 | /** | 140 | /** |
@@ -136,82 +148,91 @@ typedef struct { | |||
136 | 148 | ||
137 | /* macros to access the left/right 16 bits of a 32-bit ntp "fixed point" | 149 | /* macros to access the left/right 16 bits of a 32-bit ntp "fixed point" |
138 | number. note that these can be used as lvalues too */ | 150 | number. note that these can be used as lvalues too */ |
139 | #define L16(x) (((uint16_t*)&x)[0]) | 151 | #define L16(x) (((uint16_t *)&x)[0]) |
140 | #define R16(x) (((uint16_t*)&x)[1]) | 152 | #define R16(x) (((uint16_t *)&x)[1]) |
141 | /* macros to access the left/right 32 bits of a 64-bit ntp "fixed point" | 153 | /* macros to access the left/right 32 bits of a 64-bit ntp "fixed point" |
142 | number. these too can be used as lvalues */ | 154 | number. these too can be used as lvalues */ |
143 | #define L32(x) (((uint32_t*)&x)[0]) | 155 | #define L32(x) (((uint32_t *)&x)[0]) |
144 | #define R32(x) (((uint32_t*)&x)[1]) | 156 | #define R32(x) (((uint32_t *)&x)[1]) |
145 | 157 | ||
146 | /* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */ | 158 | /* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */ |
147 | #define EPOCHDIFF 0x83aa7e80UL | 159 | #define EPOCHDIFF 0x83aa7e80UL |
148 | 160 | ||
149 | /* extract a 32-bit ntp fixed point number into a double */ | 161 | /* extract a 32-bit ntp fixed point number into a double */ |
150 | #define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x))/65536.0) | 162 | #define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x)) / 65536.0) |
151 | 163 | ||
152 | /* likewise for a 64-bit ntp fp number */ | 164 | /* likewise for a 64-bit ntp fp number */ |
153 | #define NTP64asDOUBLE(n) (double)(((uint64_t)n)?\ | 165 | #define NTP64asDOUBLE(n) \ |
154 | (ntohl(L32(n))-EPOCHDIFF) + \ | 166 | (double)(((uint64_t)n) ? (ntohl(L32(n)) - EPOCHDIFF) + (.00000001 * (0.5 + (double)(ntohl(R32(n)) / 42.94967296))) : 0) |
155 | (.00000001*(0.5+(double)(ntohl(R32(n))/42.94967296))):\ | ||
156 | 0) | ||
157 | 167 | ||
158 | /* convert a struct timeval to a double */ | 168 | /* convert a struct timeval to a double */ |
159 | #define TVasDOUBLE(x) (double)(x.tv_sec+(0.000001*x.tv_usec)) | 169 | #define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec)) |
160 | 170 | ||
161 | /* convert an ntp 64-bit fp number to a struct timeval */ | 171 | /* convert an ntp 64-bit fp number to a struct timeval */ |
162 | #define NTP64toTV(n,t) \ | 172 | #define NTP64toTV(n, t) \ |
163 | do{ if(!n) t.tv_sec = t.tv_usec = 0; \ | 173 | do { \ |
164 | else { \ | 174 | if (!n) \ |
165 | t.tv_sec=ntohl(L32(n))-EPOCHDIFF; \ | 175 | t.tv_sec = t.tv_usec = 0; \ |
166 | t.tv_usec=(int)(0.5+(double)(ntohl(R32(n))/4294.967296)); \ | 176 | else { \ |
167 | } \ | 177 | t.tv_sec = ntohl(L32(n)) - EPOCHDIFF; \ |
168 | }while(0) | 178 | t.tv_usec = (int)(0.5 + (double)(ntohl(R32(n)) / 4294.967296)); \ |
179 | } \ | ||
180 | } while (0) | ||
169 | 181 | ||
170 | /* convert a struct timeval to an ntp 64-bit fp number */ | 182 | /* convert a struct timeval to an ntp 64-bit fp number */ |
171 | #define TVtoNTP64(t,n) \ | 183 | #define TVtoNTP64(t, n) \ |
172 | do{ if(!t.tv_usec && !t.tv_sec) n=0x0UL; \ | 184 | do { \ |
173 | else { \ | 185 | if (!t.tv_usec && !t.tv_sec) \ |
174 | L32(n)=htonl(t.tv_sec + EPOCHDIFF); \ | 186 | n = 0x0UL; \ |
175 | R32(n)=htonl((uint64_t)((4294.967296*t.tv_usec)+.5)); \ | 187 | else { \ |
176 | } \ | 188 | L32(n) = htonl(t.tv_sec + EPOCHDIFF); \ |
177 | } while(0) | 189 | R32(n) = htonl((uint64_t)((4294.967296 * t.tv_usec) + .5)); \ |
190 | } \ | ||
191 | } while (0) | ||
178 | 192 | ||
179 | /* NTP control message header is 12 bytes, plus any data in the data | 193 | /* NTP control message header is 12 bytes, plus any data in the data |
180 | * field, plus null padding to the nearest 32-bit boundary per rfc. | 194 | * field, plus null padding to the nearest 32-bit boundary per rfc. |
181 | */ | 195 | */ |
182 | #define SIZEOF_NTPCM(m) (12+ntohs(m.count)+((m.count)?4-(ntohs(m.count)%4):0)) | 196 | #define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((m.count) ? 4 - (ntohs(m.count) % 4) : 0)) |
183 | 197 | ||
184 | /* finally, a little helper or two for debugging: */ | 198 | /* finally, a little helper or two for debugging: */ |
185 | #define DBG(x) do{if(verbose>1){ x; }}while(0); | 199 | #define DBG(x) \ |
186 | #define PRINTSOCKADDR(x) \ | 200 | do { \ |
187 | do{ \ | 201 | if (verbose > 1) { \ |
188 | printf("%u.%u.%u.%u", (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff);\ | 202 | x; \ |
189 | }while(0); | 203 | } \ |
204 | } while (0); | ||
205 | #define PRINTSOCKADDR(x) \ | ||
206 | do { \ | ||
207 | printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \ | ||
208 | } while (0); | ||
190 | 209 | ||
191 | /* calculate the offset of the local clock */ | 210 | /* calculate the offset of the local clock */ |
192 | static inline double calc_offset(const ntp_message *m, const struct timeval *t){ | 211 | static inline double calc_offset(const ntp_message *m, const struct timeval *t) { |
193 | double client_tx, peer_rx, peer_tx, client_rx; | 212 | double client_tx = NTP64asDOUBLE(m->origts); |
194 | client_tx = NTP64asDOUBLE(m->origts); | 213 | double peer_rx = NTP64asDOUBLE(m->rxts); |
195 | peer_rx = NTP64asDOUBLE(m->rxts); | 214 | double peer_tx = NTP64asDOUBLE(m->txts); |
196 | peer_tx = NTP64asDOUBLE(m->txts); | 215 | double client_rx = TVasDOUBLE((*t)); |
197 | client_rx=TVasDOUBLE((*t)); | 216 | return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx))); |
198 | return (.5*((peer_tx-client_rx)+(peer_rx-client_tx))); | ||
199 | } | 217 | } |
200 | 218 | ||
201 | /* print out a ntp packet in human readable/debuggable format */ | 219 | /* print out a ntp packet in human readable/debuggable format */ |
202 | void print_ntp_message(const ntp_message *p){ | 220 | void print_ntp_message(const ntp_message *p) { |
203 | struct timeval ref, orig, rx, tx; | 221 | struct timeval ref; |
222 | struct timeval orig; | ||
223 | struct timeval rx; | ||
224 | struct timeval tx; | ||
204 | 225 | ||
205 | NTP64toTV(p->refts,ref); | 226 | NTP64toTV(p->refts, ref); |
206 | NTP64toTV(p->origts,orig); | 227 | NTP64toTV(p->origts, orig); |
207 | NTP64toTV(p->rxts,rx); | 228 | NTP64toTV(p->rxts, rx); |
208 | NTP64toTV(p->txts,tx); | 229 | NTP64toTV(p->txts, tx); |
209 | 230 | ||
210 | printf("packet contents:\n"); | 231 | printf("packet contents:\n"); |
211 | printf("\tflags: 0x%.2x\n", p->flags); | 232 | printf("\tflags: 0x%.2x\n", p->flags); |
212 | printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); | 233 | printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK); |
213 | printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); | 234 | printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK); |
214 | printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); | 235 | printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK); |
215 | printf("\tstratum = %d\n", p->stratum); | 236 | printf("\tstratum = %d\n", p->stratum); |
216 | printf("\tpoll = %g\n", pow(2, p->poll)); | 237 | printf("\tpoll = %g\n", pow(2, p->poll)); |
217 | printf("\tprecision = %g\n", pow(2, p->precision)); | 238 | printf("\tprecision = %g\n", pow(2, p->precision)); |
@@ -224,41 +245,42 @@ void print_ntp_message(const ntp_message *p){ | |||
224 | printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts)); | 245 | printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts)); |
225 | } | 246 | } |
226 | 247 | ||
227 | void setup_request(ntp_message *p){ | 248 | void setup_request(ntp_message *p) { |
228 | struct timeval t; | ||
229 | |||
230 | memset(p, 0, sizeof(ntp_message)); | 249 | memset(p, 0, sizeof(ntp_message)); |
231 | LI_SET(p->flags, LI_ALARM); | 250 | LI_SET(p->flags, LI_ALARM); |
232 | VN_SET(p->flags, 4); | 251 | VN_SET(p->flags, 4); |
233 | MODE_SET(p->flags, MODE_CLIENT); | 252 | MODE_SET(p->flags, MODE_CLIENT); |
234 | p->poll=4; | 253 | p->poll = 4; |
235 | p->precision=(int8_t)0xfa; | 254 | p->precision = (int8_t)0xfa; |
236 | L16(p->rtdelay)=htons(1); | 255 | L16(p->rtdelay) = htons(1); |
237 | L16(p->rtdisp)=htons(1); | 256 | L16(p->rtdisp) = htons(1); |
238 | 257 | ||
258 | struct timeval t; | ||
239 | gettimeofday(&t, NULL); | 259 | gettimeofday(&t, NULL); |
240 | TVtoNTP64(t,p->txts); | 260 | TVtoNTP64(t, p->txts); |
241 | } | 261 | } |
242 | 262 | ||
243 | /* select the "best" server from a list of servers, and return its index. | 263 | /* select the "best" server from a list of servers, and return its index. |
244 | * this is done by filtering servers based on stratum, dispersion, and | 264 | * this is done by filtering servers based on stratum, dispersion, and |
245 | * finally round-trip delay. */ | 265 | * finally round-trip delay. */ |
246 | int best_offset_server(const ntp_server_results *slist, int nservers){ | 266 | int best_offset_server(const ntp_server_results *slist, int nservers) { |
247 | int cserver=0, best_server=-1; | 267 | int best_server = -1; |
248 | 268 | ||
249 | /* for each server */ | 269 | /* for each server */ |
250 | for(cserver=0; cserver<nservers; cserver++){ | 270 | for (int cserver = 0; cserver < nservers; cserver++) { |
251 | /* We don't want any servers that fails these tests */ | 271 | /* We don't want any servers that fails these tests */ |
252 | /* Sort out servers that didn't respond or responede with a 0 stratum; | 272 | /* Sort out servers that didn't respond or responede with a 0 stratum; |
253 | * stratum 0 is for reference clocks so no NTP server should ever report | 273 | * stratum 0 is for reference clocks so no NTP server should ever report |
254 | * a stratum 0 */ | 274 | * a stratum 0 */ |
255 | if ( slist[cserver].stratum == 0){ | 275 | if (slist[cserver].stratum == 0) { |
256 | if (verbose) printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum); | 276 | if (verbose) |
277 | printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum); | ||
257 | continue; | 278 | continue; |
258 | } | 279 | } |
259 | /* Sort out servers with error flags */ | 280 | /* Sort out servers with error flags */ |
260 | if ( LI(slist[cserver].flags) == LI_ALARM ){ | 281 | if (LI(slist[cserver].flags) == LI_ALARM) { |
261 | if (verbose) printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags)); | 282 | if (verbose) |
283 | printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags)); | ||
262 | continue; | 284 | continue; |
263 | } | 285 | } |
264 | 286 | ||
@@ -272,13 +294,13 @@ int best_offset_server(const ntp_server_results *slist, int nservers){ | |||
272 | /* compare the server to the best one we've seen so far */ | 294 | /* compare the server to the best one we've seen so far */ |
273 | /* does it have an equal or better stratum? */ | 295 | /* does it have an equal or better stratum? */ |
274 | DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); | 296 | DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); |
275 | if(slist[cserver].stratum <= slist[best_server].stratum){ | 297 | if (slist[cserver].stratum <= slist[best_server].stratum) { |
276 | DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); | 298 | DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); |
277 | /* does it have an equal or better dispersion? */ | 299 | /* does it have an equal or better dispersion? */ |
278 | if(slist[cserver].rtdisp <= slist[best_server].rtdisp){ | 300 | if (slist[cserver].rtdisp <= slist[best_server].rtdisp) { |
279 | DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); | 301 | DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); |
280 | /* does it have a better rtdelay? */ | 302 | /* does it have a better rtdelay? */ |
281 | if(slist[cserver].rtdelay < slist[best_server].rtdelay){ | 303 | if (slist[cserver].rtdelay < slist[best_server].rtdelay) { |
282 | DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); | 304 | DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); |
283 | best_server = cserver; | 305 | best_server = cserver; |
284 | DBG(printf("peer %d is now our best candidate\n", best_server)); | 306 | DBG(printf("peer %d is now our best candidate\n", best_server)); |
@@ -287,13 +309,12 @@ int best_offset_server(const ntp_server_results *slist, int nservers){ | |||
287 | } | 309 | } |
288 | } | 310 | } |
289 | 311 | ||
290 | if(best_server >= 0) { | 312 | if (best_server >= 0) { |
291 | DBG(printf("best server selected: peer %d\n", best_server)); | 313 | DBG(printf("best server selected: peer %d\n", best_server)); |
292 | return best_server; | 314 | return best_server; |
293 | } else { | ||
294 | DBG(printf("no peers meeting synchronization criteria :(\n")); | ||
295 | return -1; | ||
296 | } | 315 | } |
316 | DBG(printf("no peers meeting synchronization criteria :(\n")); | ||
317 | return -1; | ||
297 | } | 318 | } |
298 | 319 | ||
299 | /* do everything we need to get the total average offset | 320 | /* do everything we need to get the total average offset |
@@ -301,178 +322,190 @@ int best_offset_server(const ntp_server_results *slist, int nservers){ | |||
301 | * we don't waste time sitting around waiting for single packets. | 322 | * we don't waste time sitting around waiting for single packets. |
302 | * - we also "manually" handle resolving host names and connecting, because | 323 | * - we also "manually" handle resolving host names and connecting, because |
303 | * we have to do it in a way that our lazy macros don't handle currently :( */ | 324 | * we have to do it in a way that our lazy macros don't handle currently :( */ |
304 | double offset_request(const char *host, int *status){ | 325 | double offset_request(const char *host, int *status) { |
305 | int i=0, j=0, ga_result=0, num_hosts=0, *socklist=NULL, respnum=0; | ||
306 | int servers_completed=0, one_read=0, servers_readable=0, best_index=-1; | ||
307 | time_t now_time=0, start_ts=0; | ||
308 | ntp_message *req=NULL; | ||
309 | double avg_offset=0.; | ||
310 | struct timeval recv_time; | ||
311 | struct addrinfo *ai=NULL, *ai_tmp=NULL, hints; | ||
312 | struct pollfd *ufds=NULL; | ||
313 | ntp_server_results *servers=NULL; | ||
314 | |||
315 | /* setup hints to only return results from getaddrinfo that we'd like */ | 326 | /* setup hints to only return results from getaddrinfo that we'd like */ |
327 | struct addrinfo hints; | ||
316 | memset(&hints, 0, sizeof(struct addrinfo)); | 328 | memset(&hints, 0, sizeof(struct addrinfo)); |
317 | hints.ai_family = address_family; | 329 | hints.ai_family = address_family; |
318 | hints.ai_protocol = IPPROTO_UDP; | 330 | hints.ai_protocol = IPPROTO_UDP; |
319 | hints.ai_socktype = SOCK_DGRAM; | 331 | hints.ai_socktype = SOCK_DGRAM; |
320 | 332 | ||
321 | /* fill in ai with the list of hosts resolved by the host name */ | 333 | /* fill in ai with the list of hosts resolved by the host name */ |
322 | ga_result = getaddrinfo(host, port, &hints, &ai); | 334 | struct addrinfo *ai = NULL; |
323 | if(ga_result!=0){ | 335 | int ga_result = getaddrinfo(host, port, &hints, &ai); |
324 | die(STATE_UNKNOWN, "error getting address for %s: %s\n", | 336 | if (ga_result != 0) { |
325 | host, gai_strerror(ga_result)); | 337 | die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); |
326 | } | 338 | } |
327 | 339 | ||
328 | /* count the number of returned hosts, and allocate stuff accordingly */ | 340 | /* count the number of returned hosts, and allocate stuff accordingly */ |
329 | for(ai_tmp=ai; ai_tmp!=NULL; ai_tmp=ai_tmp->ai_next){ num_hosts++; } | 341 | int num_hosts = 0; |
330 | req=(ntp_message*)malloc(sizeof(ntp_message)*num_hosts); | 342 | for (struct addrinfo *ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { |
331 | if(req==NULL) die(STATE_UNKNOWN, "can not allocate ntp message array"); | 343 | num_hosts++; |
332 | socklist=(int*)malloc(sizeof(int)*num_hosts); | 344 | } |
333 | if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); | 345 | |
334 | ufds=(struct pollfd*)malloc(sizeof(struct pollfd)*num_hosts); | 346 | ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); |
335 | if(ufds==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); | 347 | |
336 | servers=(ntp_server_results*)malloc(sizeof(ntp_server_results)*num_hosts); | 348 | if (req == NULL) |
337 | if(servers==NULL) die(STATE_UNKNOWN, "can not allocate server array"); | 349 | die(STATE_UNKNOWN, "can not allocate ntp message array"); |
338 | memset(servers, 0, sizeof(ntp_server_results)*num_hosts); | 350 | int *socklist = (int *)malloc(sizeof(int) * num_hosts); |
351 | |||
352 | if (socklist == NULL) | ||
353 | die(STATE_UNKNOWN, "can not allocate socket array"); | ||
354 | |||
355 | struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts); | ||
356 | if (ufds == NULL) | ||
357 | die(STATE_UNKNOWN, "can not allocate socket array"); | ||
358 | |||
359 | ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts); | ||
360 | if (servers == NULL) | ||
361 | die(STATE_UNKNOWN, "can not allocate server array"); | ||
362 | memset(servers, 0, sizeof(ntp_server_results) * num_hosts); | ||
339 | DBG(printf("Found %d peers to check\n", num_hosts)); | 363 | DBG(printf("Found %d peers to check\n", num_hosts)); |
340 | 364 | ||
341 | /* setup each socket for writing, and the corresponding struct pollfd */ | 365 | /* setup each socket for writing, and the corresponding struct pollfd */ |
342 | ai_tmp=ai; | 366 | struct addrinfo *ai_tmp = ai; |
343 | for(i=0;ai_tmp;i++){ | 367 | for (int i = 0; ai_tmp; i++) { |
344 | socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); | 368 | socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); |
345 | if(socklist[i] == -1) { | 369 | if (socklist[i] == -1) { |
346 | perror(NULL); | 370 | perror(NULL); |
347 | die(STATE_UNKNOWN, "can not create new socket"); | 371 | die(STATE_UNKNOWN, "can not create new socket"); |
348 | } | 372 | } |
349 | if(connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)){ | 373 | if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) { |
350 | /* don't die here, because it is enough if there is one server | 374 | /* don't die here, because it is enough if there is one server |
351 | answering in time. This also would break for dual ipv4/6 stacked | 375 | answering in time. This also would break for dual ipv4/6 stacked |
352 | ntp servers when the client only supports on of them. | 376 | ntp servers when the client only supports on of them. |
353 | */ | 377 | */ |
354 | DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); | 378 | DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); |
355 | } else { | 379 | } else { |
356 | ufds[i].fd=socklist[i]; | 380 | ufds[i].fd = socklist[i]; |
357 | ufds[i].events=POLLIN; | 381 | ufds[i].events = POLLIN; |
358 | ufds[i].revents=0; | 382 | ufds[i].revents = 0; |
359 | } | 383 | } |
360 | ai_tmp = ai_tmp->ai_next; | 384 | ai_tmp = ai_tmp->ai_next; |
361 | } | 385 | } |
362 | 386 | ||
363 | /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds | 387 | /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds |
364 | * have passed in order to ensure post-processing and jitter time. */ | 388 | * have passed in order to ensure post-processing and jitter time. */ |
365 | now_time=start_ts=time(NULL); | 389 | time_t start_ts = 0; |
366 | while(servers_completed<num_hosts && now_time-start_ts <= socket_timeout/2){ | 390 | time_t now_time = 0; |
391 | now_time = start_ts = time(NULL); | ||
392 | int servers_completed = 0; | ||
393 | bool one_read = false; | ||
394 | while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) { | ||
367 | /* loop through each server and find each one which hasn't | 395 | /* loop through each server and find each one which hasn't |
368 | * been touched in the past second or so and is still lacking | 396 | * been touched in the past second or so and is still lacking |
369 | * some responses. For each of these servers, send a new request, | 397 | * some responses. For each of these servers, send a new request, |
370 | * and update the "waiting" timestamp with the current time. */ | 398 | * and update the "waiting" timestamp with the current time. */ |
371 | now_time=time(NULL); | 399 | now_time = time(NULL); |
372 | 400 | ||
373 | for(i=0; i<num_hosts; i++){ | 401 | for (int i = 0; i < num_hosts; i++) { |
374 | if(servers[i].waiting<now_time && servers[i].num_responses<AVG_NUM){ | 402 | if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) { |
375 | if(verbose && servers[i].waiting != 0) printf("re-"); | 403 | if (verbose && servers[i].waiting != 0) |
376 | if(verbose) printf("sending request to peer %d\n", i); | 404 | printf("re-"); |
405 | if (verbose) | ||
406 | printf("sending request to peer %d\n", i); | ||
377 | setup_request(&req[i]); | 407 | setup_request(&req[i]); |
378 | write(socklist[i], &req[i], sizeof(ntp_message)); | 408 | write(socklist[i], &req[i], sizeof(ntp_message)); |
379 | servers[i].waiting=now_time; | 409 | servers[i].waiting = now_time; |
380 | break; | 410 | break; |
381 | } | 411 | } |
382 | } | 412 | } |
383 | 413 | ||
384 | /* quickly poll for any sockets with pending data */ | 414 | /* quickly poll for any sockets with pending data */ |
385 | servers_readable=poll(ufds, num_hosts, 100); | 415 | int servers_readable = poll(ufds, num_hosts, 100); |
386 | if(servers_readable==-1){ | 416 | if (servers_readable == -1) { |
387 | perror("polling ntp sockets"); | 417 | perror("polling ntp sockets"); |
388 | die(STATE_UNKNOWN, "communication errors"); | 418 | die(STATE_UNKNOWN, "communication errors"); |
389 | } | 419 | } |
390 | 420 | ||
391 | /* read from any sockets with pending data */ | 421 | /* read from any sockets with pending data */ |
392 | for(i=0; servers_readable && i<num_hosts; i++){ | 422 | for (int i = 0; servers_readable && i < num_hosts; i++) { |
393 | if(ufds[i].revents&POLLIN && servers[i].num_responses < AVG_NUM){ | 423 | if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) { |
394 | if(verbose) { | 424 | if (verbose) { |
395 | printf("response from peer %d: ", i); | 425 | printf("response from peer %d: ", i); |
396 | } | 426 | } |
397 | 427 | ||
398 | read(ufds[i].fd, &req[i], sizeof(ntp_message)); | 428 | read(ufds[i].fd, &req[i], sizeof(ntp_message)); |
429 | |||
430 | struct timeval recv_time; | ||
399 | gettimeofday(&recv_time, NULL); | 431 | gettimeofday(&recv_time, NULL); |
400 | DBG(print_ntp_message(&req[i])); | 432 | DBG(print_ntp_message(&req[i])); |
401 | respnum=servers[i].num_responses++; | 433 | int respnum = servers[i].num_responses++; |
402 | servers[i].offset[respnum]=calc_offset(&req[i], &recv_time)+time_offset; | 434 | servers[i].offset[respnum] = calc_offset(&req[i], &recv_time) + time_offset; |
403 | if(verbose) { | 435 | if (verbose) { |
404 | printf("offset %.10g\n", servers[i].offset[respnum]); | 436 | printf("offset %.10g\n", servers[i].offset[respnum]); |
405 | } | 437 | } |
406 | servers[i].stratum=req[i].stratum; | 438 | servers[i].stratum = req[i].stratum; |
407 | servers[i].rtdisp=NTP32asDOUBLE(req[i].rtdisp); | 439 | servers[i].rtdisp = NTP32asDOUBLE(req[i].rtdisp); |
408 | servers[i].rtdelay=NTP32asDOUBLE(req[i].rtdelay); | 440 | servers[i].rtdelay = NTP32asDOUBLE(req[i].rtdelay); |
409 | servers[i].waiting=0; | 441 | servers[i].waiting = 0; |
410 | servers[i].flags=req[i].flags; | 442 | servers[i].flags = req[i].flags; |
411 | servers_readable--; | 443 | servers_readable--; |
412 | one_read = 1; | 444 | one_read = true; |
413 | if(servers[i].num_responses==AVG_NUM) servers_completed++; | 445 | if (servers[i].num_responses == AVG_NUM) |
446 | servers_completed++; | ||
414 | } | 447 | } |
415 | } | 448 | } |
416 | /* lather, rinse, repeat. */ | 449 | /* lather, rinse, repeat. */ |
417 | } | 450 | } |
418 | 451 | ||
419 | if (one_read == 0) { | 452 | if (one_read == false) { |
420 | die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); | 453 | die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); |
421 | } | 454 | } |
422 | 455 | ||
423 | /* now, pick the best server from the list */ | 456 | /* now, pick the best server from the list */ |
424 | best_index=best_offset_server(servers, num_hosts); | 457 | double avg_offset = 0.; |
425 | if(best_index < 0){ | 458 | int best_index = best_offset_server(servers, num_hosts); |
426 | *status=STATE_UNKNOWN; | 459 | if (best_index < 0) { |
460 | *status = STATE_UNKNOWN; | ||
427 | } else { | 461 | } else { |
428 | /* finally, calculate the average offset */ | 462 | /* finally, calculate the average offset */ |
429 | for(i=0; i<servers[best_index].num_responses;i++){ | 463 | for (int i = 0; i < servers[best_index].num_responses; i++) { |
430 | avg_offset+=servers[best_index].offset[i]; | 464 | avg_offset += servers[best_index].offset[i]; |
431 | } | 465 | } |
432 | avg_offset/=servers[best_index].num_responses; | 466 | avg_offset /= servers[best_index].num_responses; |
433 | } | 467 | } |
434 | 468 | ||
435 | /* cleanup */ | 469 | /* cleanup */ |
436 | for(j=0; j<num_hosts; j++){ close(socklist[j]); } | 470 | for (int j = 0; j < num_hosts; j++) { |
471 | close(socklist[j]); | ||
472 | } | ||
437 | free(socklist); | 473 | free(socklist); |
438 | free(ufds); | 474 | free(ufds); |
439 | free(servers); | 475 | free(servers); |
440 | free(req); | 476 | free(req); |
441 | freeaddrinfo(ai); | 477 | freeaddrinfo(ai); |
442 | 478 | ||
443 | if(verbose) printf("overall average offset: %.10g\n", avg_offset); | 479 | if (verbose) |
480 | printf("overall average offset: %.10g\n", avg_offset); | ||
444 | return avg_offset; | 481 | return avg_offset; |
445 | } | 482 | } |
446 | 483 | ||
447 | int process_arguments(int argc, char **argv){ | 484 | int process_arguments(int argc, char **argv) { |
448 | int c; | 485 | static struct option longopts[] = {{"version", no_argument, 0, 'V'}, |
449 | int option=0; | 486 | {"help", no_argument, 0, 'h'}, |
450 | static struct option longopts[] = { | 487 | {"verbose", no_argument, 0, 'v'}, |
451 | {"version", no_argument, 0, 'V'}, | 488 | {"use-ipv4", no_argument, 0, '4'}, |
452 | {"help", no_argument, 0, 'h'}, | 489 | {"use-ipv6", no_argument, 0, '6'}, |
453 | {"verbose", no_argument, 0, 'v'}, | 490 | {"quiet", no_argument, 0, 'q'}, |
454 | {"use-ipv4", no_argument, 0, '4'}, | 491 | {"time-offset", optional_argument, 0, 'o'}, |
455 | {"use-ipv6", no_argument, 0, '6'}, | 492 | {"warning", required_argument, 0, 'w'}, |
456 | {"quiet", no_argument, 0, 'q'}, | 493 | {"critical", required_argument, 0, 'c'}, |
457 | {"time-offset", optional_argument, 0, 'o'}, | 494 | {"timeout", required_argument, 0, 't'}, |
458 | {"warning", required_argument, 0, 'w'}, | 495 | {"hostname", required_argument, 0, 'H'}, |
459 | {"critical", required_argument, 0, 'c'}, | 496 | {"port", required_argument, 0, 'p'}, |
460 | {"timeout", required_argument, 0, 't'}, | 497 | {0, 0, 0, 0}}; |
461 | {"hostname", required_argument, 0, 'H'}, | ||
462 | {"port", required_argument, 0, 'p'}, | ||
463 | {0, 0, 0, 0} | ||
464 | }; | ||
465 | |||
466 | 498 | ||
467 | if (argc < 2) | 499 | if (argc < 2) |
468 | usage ("\n"); | 500 | usage("\n"); |
469 | 501 | ||
470 | while (1) { | 502 | while (true) { |
471 | c = getopt_long (argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); | 503 | int option = 0; |
472 | if (c == -1 || c == EOF || c == 1) | 504 | int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); |
505 | if (option_char == -1 || option_char == EOF || option_char == 1) | ||
473 | break; | 506 | break; |
474 | 507 | ||
475 | switch (c) { | 508 | switch (option_char) { |
476 | case 'h': | 509 | case 'h': |
477 | print_help(); | 510 | print_help(); |
478 | exit(STATE_UNKNOWN); | 511 | exit(STATE_UNKNOWN); |
@@ -494,7 +527,7 @@ int process_arguments(int argc, char **argv){ | |||
494 | ocrit = optarg; | 527 | ocrit = optarg; |
495 | break; | 528 | break; |
496 | case 'H': | 529 | case 'H': |
497 | if(!is_host(optarg)) | 530 | if (!is_host(optarg)) |
498 | usage2(_("Invalid hostname/address"), optarg); | 531 | usage2(_("Invalid hostname/address"), optarg); |
499 | server_address = strdup(optarg); | 532 | server_address = strdup(optarg); |
500 | break; | 533 | break; |
@@ -502,11 +535,11 @@ int process_arguments(int argc, char **argv){ | |||
502 | port = strdup(optarg); | 535 | port = strdup(optarg); |
503 | break; | 536 | break; |
504 | case 't': | 537 | case 't': |
505 | socket_timeout=atoi(optarg); | 538 | socket_timeout = atoi(optarg); |
506 | break; | 539 | break; |
507 | case 'o': | 540 | case 'o': |
508 | time_offset=atoi(optarg); | 541 | time_offset = atoi(optarg); |
509 | break; | 542 | break; |
510 | case '4': | 543 | case '4': |
511 | address_family = AF_INET; | 544 | address_family = AF_INET; |
512 | break; | 545 | break; |
@@ -514,77 +547,74 @@ int process_arguments(int argc, char **argv){ | |||
514 | #ifdef USE_IPV6 | 547 | #ifdef USE_IPV6 |
515 | address_family = AF_INET6; | 548 | address_family = AF_INET6; |
516 | #else | 549 | #else |
517 | usage4 (_("IPv6 support not available")); | 550 | usage4(_("IPv6 support not available")); |
518 | #endif | 551 | #endif |
519 | break; | 552 | break; |
520 | case '?': | 553 | case '?': |
521 | /* print short usage statement if args not parsable */ | 554 | /* print short usage statement if args not parsable */ |
522 | usage5 (); | 555 | usage5(); |
523 | break; | 556 | break; |
524 | } | 557 | } |
525 | } | 558 | } |
526 | 559 | ||
527 | if(server_address == NULL){ | 560 | if (server_address == NULL) { |
528 | usage4(_("Hostname was not supplied")); | 561 | usage4(_("Hostname was not supplied")); |
529 | } | 562 | } |
530 | 563 | ||
531 | return 0; | 564 | return 0; |
532 | } | 565 | } |
533 | 566 | ||
534 | char *perfd_offset (double offset) { | 567 | char *perfd_offset(double offset) { |
535 | return fperfdata ("offset", offset, "s", | 568 | return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false, |
536 | true, offset_thresholds->warning->end, | 569 | 0); |
537 | true, offset_thresholds->critical->end, | ||
538 | false, 0, false, 0); | ||
539 | } | 570 | } |
540 | 571 | ||
541 | int main(int argc, char *argv[]){ | 572 | int main(int argc, char *argv[]) { |
542 | int result, offset_result; | 573 | setlocale(LC_ALL, ""); |
543 | double offset=0; | 574 | bindtextdomain(PACKAGE, LOCALEDIR); |
544 | char *result_line, *perfdata_line; | 575 | textdomain(PACKAGE); |
545 | |||
546 | setlocale (LC_ALL, ""); | ||
547 | bindtextdomain (PACKAGE, LOCALEDIR); | ||
548 | textdomain (PACKAGE); | ||
549 | |||
550 | result = offset_result = STATE_OK; | ||
551 | 576 | ||
552 | /* Parse extra opts if any */ | 577 | /* Parse extra opts if any */ |
553 | argv=np_extra_opts (&argc, argv, progname); | 578 | argv = np_extra_opts(&argc, argv, progname); |
554 | 579 | ||
555 | if (process_arguments (argc, argv) == ERROR) | 580 | if (process_arguments(argc, argv) == ERROR) |
556 | usage4 (_("Could not parse arguments")); | 581 | usage4(_("Could not parse arguments")); |
557 | 582 | ||
558 | set_thresholds(&offset_thresholds, owarn, ocrit); | 583 | set_thresholds(&offset_thresholds, owarn, ocrit); |
559 | 584 | ||
560 | /* initialize alarm signal handling */ | 585 | /* initialize alarm signal handling */ |
561 | signal (SIGALRM, socket_timeout_alarm_handler); | 586 | signal(SIGALRM, socket_timeout_alarm_handler); |
562 | 587 | ||
563 | /* set socket timeout */ | 588 | /* set socket timeout */ |
564 | alarm (socket_timeout); | 589 | alarm(socket_timeout); |
565 | 590 | ||
566 | offset = offset_request(server_address, &offset_result); | 591 | int offset_result = STATE_OK; |
592 | int result = STATE_OK; | ||
593 | double offset = offset_request(server_address, &offset_result); | ||
567 | if (offset_result == STATE_UNKNOWN) { | 594 | if (offset_result == STATE_UNKNOWN) { |
568 | result = ( (!quiet) ? STATE_UNKNOWN : STATE_CRITICAL); | 595 | result = ((!quiet) ? STATE_UNKNOWN : STATE_CRITICAL); |
569 | } else { | 596 | } else { |
570 | result = get_status(fabs(offset), offset_thresholds); | 597 | result = get_status(fabs(offset), offset_thresholds); |
571 | } | 598 | } |
572 | 599 | ||
600 | char *result_line; | ||
573 | switch (result) { | 601 | switch (result) { |
574 | case STATE_CRITICAL : | 602 | case STATE_CRITICAL: |
575 | xasprintf(&result_line, _("NTP CRITICAL:")); | 603 | xasprintf(&result_line, _("NTP CRITICAL:")); |
576 | break; | 604 | break; |
577 | case STATE_WARNING : | 605 | case STATE_WARNING: |
578 | xasprintf(&result_line, _("NTP WARNING:")); | 606 | xasprintf(&result_line, _("NTP WARNING:")); |
579 | break; | 607 | break; |
580 | case STATE_OK : | 608 | case STATE_OK: |
581 | xasprintf(&result_line, _("NTP OK:")); | 609 | xasprintf(&result_line, _("NTP OK:")); |
582 | break; | 610 | break; |
583 | default : | 611 | default: |
584 | xasprintf(&result_line, _("NTP UNKNOWN:")); | 612 | xasprintf(&result_line, _("NTP UNKNOWN:")); |
585 | break; | 613 | break; |
586 | } | 614 | } |
587 | if(offset_result == STATE_UNKNOWN){ | 615 | |
616 | char *perfdata_line; | ||
617 | if (offset_result == STATE_UNKNOWN) { | ||
588 | xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); | 618 | xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); |
589 | xasprintf(&perfdata_line, ""); | 619 | xasprintf(&perfdata_line, ""); |
590 | } else { | 620 | } else { |
@@ -593,35 +623,36 @@ int main(int argc, char *argv[]){ | |||
593 | } | 623 | } |
594 | printf("%s|%s\n", result_line, perfdata_line); | 624 | printf("%s|%s\n", result_line, perfdata_line); |
595 | 625 | ||
596 | if(server_address!=NULL) free(server_address); | 626 | if (server_address != NULL) |
627 | free(server_address); | ||
597 | return result; | 628 | return result; |
598 | } | 629 | } |
599 | 630 | ||
600 | void print_help(void){ | 631 | void print_help(void) { |
601 | print_revision(progname, NP_VERSION); | 632 | print_revision(progname, NP_VERSION); |
602 | 633 | ||
603 | printf ("Copyright (c) 2006 Sean Finney\n"); | 634 | printf("Copyright (c) 2006 Sean Finney\n"); |
604 | printf (COPYRIGHT, copyright, email); | 635 | printf(COPYRIGHT, copyright, email); |
605 | 636 | ||
606 | printf ("%s\n", _("This plugin checks the clock offset with the ntp server")); | 637 | printf("%s\n", _("This plugin checks the clock offset with the ntp server")); |
607 | 638 | ||
608 | printf ("\n\n"); | 639 | printf("\n\n"); |
609 | 640 | ||
610 | print_usage(); | 641 | print_usage(); |
611 | printf (UT_HELP_VRSN); | 642 | printf(UT_HELP_VRSN); |
612 | printf (UT_EXTRA_OPTS); | 643 | printf(UT_EXTRA_OPTS); |
613 | printf (UT_IPv46); | 644 | printf(UT_IPv46); |
614 | printf (UT_HOST_PORT, 'p', "123"); | 645 | printf(UT_HOST_PORT, 'p', "123"); |
615 | printf (" %s\n", "-q, --quiet"); | 646 | printf(" %s\n", "-q, --quiet"); |
616 | printf (" %s\n", _("Returns UNKNOWN instead of CRITICAL if offset cannot be found")); | 647 | printf(" %s\n", _("Returns UNKNOWN instead of CRITICAL if offset cannot be found")); |
617 | printf (" %s\n", "-w, --warning=THRESHOLD"); | 648 | printf(" %s\n", "-w, --warning=THRESHOLD"); |
618 | printf (" %s\n", _("Offset to result in warning status (seconds)")); | 649 | printf(" %s\n", _("Offset to result in warning status (seconds)")); |
619 | printf (" %s\n", "-c, --critical=THRESHOLD"); | 650 | printf(" %s\n", "-c, --critical=THRESHOLD"); |
620 | printf (" %s\n", _("Offset to result in critical status (seconds)")); | 651 | printf(" %s\n", _("Offset to result in critical status (seconds)")); |
621 | printf (" %s\n", "-o, --time_offset=INTEGER"); | 652 | printf(" %s\n", "-o, --time_offset=INTEGER"); |
622 | printf (" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); | 653 | printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); |
623 | printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | 654 | printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); |
624 | printf (UT_VERBOSE); | 655 | printf(UT_VERBOSE); |
625 | 656 | ||
626 | printf("\n"); | 657 | printf("\n"); |
627 | printf("%s\n", _("This plugin checks the clock offset between the local host and a")); | 658 | printf("%s\n", _("This plugin checks the clock offset between the local host and a")); |
@@ -641,13 +672,10 @@ void print_help(void){ | |||
641 | printf("%s\n", _("Examples:")); | 672 | printf("%s\n", _("Examples:")); |
642 | printf(" %s\n", ("./check_ntp_time -H ntpserv -w 0.5 -c 1")); | 673 | printf(" %s\n", ("./check_ntp_time -H ntpserv -w 0.5 -c 1")); |
643 | 674 | ||
644 | printf (UT_SUPPORT); | 675 | printf(UT_SUPPORT); |
645 | } | 676 | } |
646 | 677 | ||
647 | void | 678 | void print_usage(void) { |
648 | print_usage(void) | 679 | printf("%s\n", _("Usage:")); |
649 | { | ||
650 | printf ("%s\n", _("Usage:")); | ||
651 | printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-v verbose] [-o <time offset>]\n", progname); | 680 | printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-v verbose] [-o <time offset>]\n", progname); |
652 | } | 681 | } |
653 | |||