1 /* $OpenBSD: ntp.c,v 1.14 2003/05/14 18:06:21 itojun Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997 by N.M. Maclaren. All rights reserved. 5 * Copyright (c) 1996, 1997 by University of Cambridge. All rights reserved. 6 * Copyright (c) 2002 by Thorsten "mirabile" Glaser. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the author nor the university may be used to 17 * endorse or promote products derived from this software without 18 * specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/socket.h> 34 #include <sys/time.h> 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 38 #include <ctype.h> 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <float.h> 43 #include <limits.h> 44 #include <math.h> 45 #include <netdb.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <time.h> 50 #include <unistd.h> 51 52 #include "ntpleaps.h" 53 54 /* 55 * NTP definitions. Note that these assume 8-bit bytes - sigh. There 56 * is little point in parameterising everything, as it is neither 57 * feasible nor useful. It would be very useful if more fields could 58 * be defined as unspecified. The NTP packet-handling routines 59 * contain a lot of extra assumptions. 60 */ 61 62 #define JAN_1970 2208988800.0 /* 1970 - 1900 in seconds */ 63 #define NTP_SCALE 4294967296.0 /* 2^32, of course! */ 64 65 #define NTP_MODE_CLIENT 3 /* NTP client mode */ 66 #define NTP_MODE_SERVER 4 /* NTP server mode */ 67 #define NTP_VERSION 3 /* The current version */ 68 #define NTP_VERSION_MIN 1 /* The minum valid version */ 69 #define NTP_VERSION_MAX 4 /* The maximum valid version */ 70 #define NTP_STRATUM_MIN 1 /* The minum valid stratum */ 71 #define NTP_STRATUM_MAX 15 /* The maximum valid stratum */ 72 #define NTP_INSANITY 3600.0 /* Errors beyond this are hopeless */ 73 74 #define NTP_PACKET_MIN 48 /* Without authentication */ 75 #define NTP_PACKET_MAX 68 /* With authentication (ignored) */ 76 77 #define NTP_DISP_FIELD 8 /* Offset of dispersion field */ 78 #define NTP_REFERENCE 16 /* Offset of reference timestamp */ 79 #define NTP_ORIGINATE 24 /* Offset of originate timestamp */ 80 #define NTP_RECEIVE 32 /* Offset of receive timestamp */ 81 #define NTP_TRANSMIT 40 /* Offset of transmit timestamp */ 82 83 #define MAX_QUERIES 25 84 #define MAX_DELAY 15 85 86 #define MILLION_L 1000000l /* For conversion to/from timeval */ 87 #define MILLION_D 1.0e6 /* Must be equal to MILLION_L */ 88 89 struct ntp_data { 90 u_char status; 91 u_char version; 92 u_char mode; 93 u_char stratum; 94 u_char polling; 95 u_char precision; 96 double dispersion; 97 double reference; 98 double originate; 99 double receive; 100 double transmit; 101 double current; 102 }; 103 104 void ntp_client(const char *, struct timeval *, struct timeval *, int); 105 int sync_ntp(int, const struct sockaddr *, double *, double *); 106 void make_packet(struct ntp_data *); 107 int write_packet(int, const struct sockaddr *, struct ntp_data *); 108 int read_packet(int, struct ntp_data *, double *, double *, double *); 109 void pack_ntp(u_char *, int, struct ntp_data *); 110 void unpack_ntp(struct ntp_data *, u_char *, int); 111 double current_time(double); 112 void create_timeval(double, struct timeval *, struct timeval *); 113 114 int corrleaps; 115 116 void 117 ntp_client(const char *hostname, struct timeval *new, 118 struct timeval *adjust, int leapflag) 119 { 120 struct addrinfo hints, *res0, *res; 121 double offset, error; 122 int packets = 0, s, ierror; 123 124 memset(&hints, 0, sizeof(hints)); 125 hints.ai_family = PF_UNSPEC; 126 hints.ai_socktype = SOCK_DGRAM; 127 ierror = getaddrinfo(hostname, "ntp", &hints, &res0); 128 if (ierror) { 129 errx(1, "%s: %s", hostname, gai_strerror(ierror)); 130 /*NOTREACHED*/ 131 } 132 133 corrleaps = leapflag; 134 if (corrleaps) 135 ntpleaps_init(); 136 137 s = -1; 138 for (res = res0; res; res = res->ai_next) { 139 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 140 if (s < 0) 141 continue; 142 143 packets = sync_ntp(s, res->ai_addr, &offset, &error); 144 if (packets == 0) { 145 #ifdef DEBUG 146 fprintf(stderr, "try the next address\n"); 147 #endif 148 close(s); 149 s = -1; 150 continue; 151 } 152 if (error > NTP_INSANITY) { 153 /* should we try the next address instead? */ 154 errx(1, "Unable to get a reasonable time estimate"); 155 } 156 break; 157 } 158 freeaddrinfo(res0); 159 160 #ifdef DEBUG 161 fprintf(stderr,"Correction: %.6f +/- %.6f\n", offset,error); 162 #endif 163 164 create_timeval(offset, new, adjust); 165 } 166 167 int 168 sync_ntp(int fd, const struct sockaddr *peer, double *offset, double *error) 169 { 170 int attempts = 0, accepts = 0, rejects = 0; 171 int delay = MAX_DELAY; 172 double deadline; 173 double a, b, x, y; 174 double minerr = 0.1; /* Maximum ignorable variation */ 175 double dispersion = 0.0; /* The source dispersion in seconds */ 176 struct ntp_data data; 177 178 deadline = current_time(JAN_1970) + delay; 179 *offset = 0.0; 180 *error = NTP_INSANITY; 181 182 while (accepts < MAX_QUERIES && attempts < 2 * MAX_QUERIES) { 183 if (current_time(JAN_1970) > deadline) 184 errx(1, "Not enough valid responses received in time"); 185 186 make_packet(&data); 187 write_packet(fd, peer, &data); 188 189 if (read_packet(fd, &data, &x, &y, &dispersion)) { 190 if (++rejects > MAX_QUERIES) 191 errx(1, "Too many bad or lost packets"); 192 else 193 continue; 194 } else 195 ++accepts; 196 197 #ifdef DEBUG 198 fprintf(stderr,"Offset: %.6f +/- %.6f disp=%.6f\n", 199 x, y, dispersion); 200 #endif 201 202 if ((a = x - *offset) < 0.0) 203 a = -a; 204 if (accepts <= 1) 205 a = 0.0; 206 b = *error + y; 207 if (y < *error) { 208 *offset = x; 209 *error = y; 210 } 211 212 #ifdef DEBUG 213 fprintf(stderr,"Best: %.6f +/- %.6f\n", *offset, *error); 214 #endif 215 216 if (a > b) 217 errx(1, "Inconsistent times received from NTP server"); 218 219 if (*error <= minerr) 220 break; 221 } 222 223 return accepts; 224 } 225 226 /* Create an outgoing NTP packet */ 227 void 228 make_packet(struct ntp_data *data) 229 { 230 data->status = 0; 231 data->version = NTP_VERSION; 232 data->mode = NTP_MODE_CLIENT; 233 data->stratum = 0; 234 data->polling = 0; 235 data->precision = 0; 236 data->reference = data->dispersion = 0.0; 237 data->receive = data->originate = 0.0; 238 data->current = data->transmit = current_time(JAN_1970); 239 } 240 241 int 242 write_packet(int fd, const struct sockaddr *peer, struct ntp_data *data) 243 { 244 u_char transmit[NTP_PACKET_MIN]; 245 int length; 246 247 pack_ntp(transmit, NTP_PACKET_MIN, data); 248 length = sendto(fd, transmit, NTP_PACKET_MIN, 0, peer, SA_LEN(peer)); 249 if (length <= 0) { 250 warnx("Unable to send NTP packet to server"); 251 return 1; 252 } 253 254 return 0; 255 } 256 257 /* 258 * Check the packet and work out the offset and optionally the error. 259 * Note that this contains more checking than xntp does. Return 0 for 260 * success, 1 for failure. Note that it must not change its arguments 261 * if it fails. 262 */ 263 int 264 read_packet(int fd, struct ntp_data *data, double *off, double *error, 265 double *dispersion) 266 { 267 u_char receive[NTP_PACKET_MAX+1]; 268 double delay1, delay2, x, y; 269 int length, r; 270 fd_set *rfds; 271 struct timeval tv; 272 273 rfds = (fd_set *)calloc(howmany(fd + 1, NFDBITS), sizeof(fd_mask)); 274 if (!rfds) { 275 warnx("calloc() failed"); 276 return 1; 277 } 278 279 FD_SET(fd, rfds); 280 281 retry: 282 tv.tv_sec = 0; 283 tv.tv_usec = 1000000 * MAX_DELAY / MAX_QUERIES; 284 285 r = select(fd + 1, rfds, NULL, NULL, &tv); 286 if (r < 1 || !FD_ISSET(fd, rfds)) { 287 if (r < 0) { 288 if (errno == EINTR) 289 goto retry; 290 else 291 warnx("select() failed"); 292 } 293 free(rfds); 294 return 1; 295 } 296 free(rfds); 297 298 length = recvfrom(fd, receive, NTP_PACKET_MAX + 1, 0, NULL, 0); 299 if (length < 0) { 300 warnx("Unable to receive NTP packet from server"); 301 return 1; 302 } 303 304 if (length < NTP_PACKET_MIN || length > NTP_PACKET_MAX) { 305 warnx("Invalid NTP packet size, packet reject"); 306 return 1; 307 } 308 309 unpack_ntp(data, receive, length); 310 311 if (data->version < NTP_VERSION_MIN || 312 data->version > NTP_VERSION_MAX) { 313 warnx("Invalid NTP version, packet rejected"); 314 return 1; 315 } 316 317 if (data->mode != NTP_MODE_SERVER) { 318 warnx("Invalid NTP server mode, packet rejected"); 319 return 1; 320 } 321 322 /* 323 * Note that the conventions are very poorly defined in the NTP 324 * protocol, so we have to guess. Any full NTP server perpetrating 325 * completely unsynchronised packets is an abomination, anyway, so 326 * reject it. 327 */ 328 delay1 = data->transmit - data->receive; 329 delay2 = data->current - data->originate; 330 331 if (data->reference == 0.0 || 332 data->transmit == 0.0 || 333 data->receive == 0.0 || 334 (data->reference != 0.0 && data->receive < data->reference) || 335 delay1 < 0.0 || 336 delay1 > NTP_INSANITY || 337 delay2 < 0.0 || 338 delay2 > NTP_INSANITY || 339 data->dispersion > NTP_INSANITY) { 340 warnx("Incomprehensible NTP packet rejected"); 341 return 1; 342 } 343 344 if (*dispersion < data->dispersion) 345 *dispersion = data->dispersion; 346 347 x = data->receive - data->originate; 348 y = (data->transmit == 0.0 ? 0.0 : data->transmit-data->current); 349 *off = 0.5*(x+y); 350 *error = x-y; 351 x = data->current - data->originate; 352 if (0.5*x > *error) 353 *error = 0.5*x; 354 355 return 0; 356 } 357 358 /* 359 * Pack the essential data into an NTP packet, bypassing struct layout 360 * and endian problems. Note that it ignores fields irrelevant to 361 * SNTP. 362 */ 363 void 364 pack_ntp(u_char *packet, int length, struct ntp_data *data) 365 { 366 int i, k; 367 double d; 368 369 memset(packet,0, (size_t)length); 370 371 packet[0] = (data->status<<6)|(data->version<<3)|data->mode; 372 packet[1] = data->stratum; 373 packet[2] = data->polling; 374 packet[3] = data->precision; 375 376 d = data->originate/NTP_SCALE; 377 for (i = 0; i < 8; ++i) { 378 if ((k = (int)(d *= 256.0)) >= 256) k = 255; 379 packet[NTP_ORIGINATE+i] = k; 380 d -= k; 381 } 382 383 d = data->receive/NTP_SCALE; 384 for (i = 0; i < 8; ++i) { 385 if ((k = (int)(d *= 256.0)) >= 256) k = 255; 386 packet[NTP_RECEIVE+i] = k; 387 d -= k; 388 } 389 390 d = data->transmit/NTP_SCALE; 391 for (i = 0; i < 8; ++i) { 392 if ((k = (int)(d *= 256.0)) >= 256) k = 255; 393 packet[NTP_TRANSMIT+i] = k; 394 d -= k; 395 } 396 } 397 398 /* 399 * Unpack the essential data from an NTP packet, bypassing struct 400 * layout and endian problems. Note that it ignores fields irrelevant 401 * to SNTP. 402 */ 403 void 404 unpack_ntp(struct ntp_data *data, u_char *packet, int length) 405 { 406 int i; 407 double d; 408 409 data->current = current_time(JAN_1970); 410 411 data->status = (packet[0] >> 6); 412 data->version = (packet[0] >> 3)&0x07; 413 data->mode = packet[0]&0x07; 414 data->stratum = packet[1]; 415 data->polling = packet[2]; 416 data->precision = packet[3]; 417 418 for (i = 0, d = 0.0; i < 4; ++i) 419 d = 256.0*d+packet[NTP_DISP_FIELD+i]; 420 data->dispersion = d/65536.0; 421 422 for (i = 0, d = 0.0; i < 8; ++i) 423 d = 256.0*d+packet[NTP_REFERENCE+i]; 424 data->reference = d/NTP_SCALE; 425 426 for (i = 0, d = 0.0; i < 8; ++i) 427 d = 256.0*d+packet[NTP_ORIGINATE+i]; 428 data->originate = d/NTP_SCALE; 429 430 for (i = 0, d = 0.0; i < 8; ++i) 431 d = 256.0*d+packet[NTP_RECEIVE+i]; 432 data->receive = d/NTP_SCALE; 433 434 for (i = 0, d = 0.0; i < 8; ++i) 435 d = 256.0*d+packet[NTP_TRANSMIT+i]; 436 data->transmit = d/NTP_SCALE; 437 } 438 439 /* 440 * Get the current UTC time in seconds since the Epoch plus an offset 441 * (usually the time from the beginning of the century to the Epoch) 442 */ 443 double 444 current_time(double offset) 445 { 446 struct timeval current; 447 u_int64_t t; 448 449 if (gettimeofday(¤t, NULL)) 450 err(1, "Could not get local time of day"); 451 452 /* 453 * At this point, current has the current TAI time. 454 * Now subtract leap seconds to set the posix tick. 455 */ 456 457 t = SEC_TO_TAI64(current.tv_sec); 458 if (corrleaps) 459 ntpleaps_sub(&t); 460 461 return offset + TAI64_TO_SEC(t) + 1.0e-6 * current.tv_usec; 462 } 463 464 /* 465 * Change offset into current UTC time. This is portable, even if 466 * struct timeval uses an unsigned long for tv_sec. 467 */ 468 void 469 create_timeval(double difference, struct timeval *new, struct timeval *adjust) 470 { 471 struct timeval old; 472 long n; 473 474 /* Start by converting to timeval format. Note that we have to 475 * cater for negative, unsigned values. */ 476 if ((n = (long) difference) > difference) 477 --n; 478 adjust->tv_sec = n; 479 adjust->tv_usec = (long) (MILLION_D * (difference-n)); 480 errno = 0; 481 if (gettimeofday(&old, NULL)) 482 err(1, "Could not get local time of day"); 483 new->tv_sec = old.tv_sec + adjust->tv_sec; 484 new->tv_usec = (n = (long) old.tv_usec + (long) adjust->tv_usec); 485 486 if (n < 0) { 487 new->tv_usec += MILLION_L; 488 --new->tv_sec; 489 } else if (n >= MILLION_L) { 490 new->tv_usec -= MILLION_L; 491 ++new->tv_sec; 492 } 493 } 494 495 #ifdef DEBUG 496 void 497 print_packet(const struct ntp_data *data) 498 { 499 printf("status: %u\n", data->status); 500 printf("version: %u\n", data->version); 501 printf("mode: %u\n", data->mode); 502 printf("stratum: %u\n", data->stratum); 503 printf("polling: %u\n", data->polling); 504 printf("precision: %u\n", data->precision); 505 printf("dispersion: %e\n", data->dispersion); 506 printf("reference: %e\n", data->reference); 507 printf("originate: %e\n", data->originate); 508 printf("receive: %e\n", data->receive); 509 printf("transmit: %e\n", data->transmit); 510 printf("current: %e\n", data->current); 511 }; 512 #endif 513