1: #if defined(DOSCCS) && !defined(lint) 2: static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.13 $ $Date: 95/07/01 18:25:04 $"; 3: #endif 4: 5: /* 6: * This module actually implements the the bulk of the NTP protocol processing. 7: * It contains a minimum of machine and operating system dependencies (or at 8: * least that's the idea). Setup of UDP sockets, timers, etc is done in the 9: * ntpd.c module, while arithmetic conversion routines are in ntpsubs.c 10: */ 11: 12: /* 13: * $Log: ntp_proto.c,v $ 14: * Revision 3.4.1.13 95/07/01 15: * Fix shifting 1 to 0 with "1<<sys.prec" - need "(u_long)(1L<<sys.prec)" 16: * 17: * Revision 3.4.1.12 89/05/18 18:25:04 louie 18: * Changes for reference clock feature in ntp_proto.c 19: * 20: * Revision 3.4.1.11 89/05/03 23:51:30 louie 21: * Had my head on backwards with a reversed test in the clockhopper avoidance 22: * code. Need to switch to the first selected clock when its stratum is lower 23: * than the current sys.peer. 24: * 25: * Revision 3.4.1.10 89/05/03 19:03:02 louie 26: * Stupid typo - dereferenced unused variable in select_clock() 27: * 28: * Revision 3.4.1.9 89/05/03 15:13:25 louie 29: * Add code to count number of peer switches and inhibited peer switches. Clock 30: * selection code has been updated to reflect 21 April 1989 draft of NTP spec. 31: * 32: * Revision 3.4.1.8 89/04/10 15:57:59 louie 33: * New -l option for ntpd to enable logging for clock adjust messages. Changed 34: * our idea of a bogus packet in the packet procedure to include a packet received 35: * before a poll is sent. Fix stupid bug in delay computation having to do with 36: * peer->precision. 37: * 38: * Revision 3.4.1.7 89/04/08 10:36:53 louie 39: * The syslog message for peer selection had to be moved to account for the 40: * anti-peer flapping code just installed. 41: * 42: * Revision 3.4.1.6 89/04/07 19:07:10 louie 43: * Don't clear peer.reach register in the clear() procedure. Code to prevent 44: * flapping between two peers with very similar dispersions. 45: * 46: * Revision 3.4.1.5 89/03/31 16:36:38 louie 47: * There is now a run-time option that can be specified in the configuration 48: * which specifies if we will synchronize to unconfigured hosts. Fixes to 49: * receive() logic state machine. 50: * 51: * Revision 3.4.1.4 89/03/29 12:29:10 louie 52: * The variable 'mode' in the peer structure was renamed 'hmode'. Add 53: * poll_update() calls in a few places per Mills. The receive() procedure is 54: * now table driven. The poll_update procedure only randomized the timer 55: * when the interval changes. If we lose synchronization, don't zap sys.stratum. 56: * Clean up the sanity_check() routine a bit. 57: * 58: * Revision 3.4.1.3 89/03/22 18:32:31 louie 59: * patch3: Use new RCS headers. 60: * 61: * Revision 3.4.1.2 89/03/22 18:02:22 louie 62: * Add some fiddles for BROADCAST NTP mode. In the receive procedure, set the 63: * reachability shift register of peers that are configured, even if we won't 64: * synchronized to them. Fix adjustment of delay in the process_packet() 65: * routine. Repair byteswapping problem. 66: * 67: * 68: * Revision 3.4.1.1 89/03/20 00:10:06 louie 69: * patch1: sys.refid could have garbage left if the peer we're synchronized to 70: * patch1: is lost. 71: * 72: * Revision 3.4 89/03/17 18:37:05 louie 73: * Latest test release. 74: * 75: * Revision 3.3.1.1 89/03/17 18:26:02 louie 76: * Oh my, peer->hpoll wasn't being set in peer_update! 77: * 78: * Revision 3.3 89/03/15 14:19:49 louie 79: * New baseline for next release. 80: * 81: * Revision 3.2.1.2 89/03/15 13:54:41 louie 82: * Change use of "%lf" in format strings to use "%f" instead. 83: * poll_update no longer returns a value, due to a change in the transmit 84: * procedure; it is now declared as returning void. Removed syslog 85: * message "Dropping peer ...". You still get messages for peers which 86: * were configured when reachability is lost with them. Clarification of 87: * calling poll_update on sys.peer rather than on the host whose packet 88: * we're processing when sys.peer changes. poll_update has been updated 89: * including randomizing peer.timer. 90: * 91: * Revision 3.2.1.1 89/03/10 11:30:33 louie 92: * Remove computation of peer->timer that was present due to a bug in the NTP 93: * spec. Don't set sys.precision in the NTP protocol initialization; this has 94: * bad side effects with the code that get tick from the kernel and the NTP 95: * config file scanner. 96: * 97: * Revision 3.2 89/03/07 18:24:54 louie 98: * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new 99: * NTP protocol specification. This version has a bunch of bugs fixes and 100: * new algorithms which were discussed on the NTP mailing list over the past 101: * few weeks. 102: * 103: * Revision 3.1.1.1 89/02/15 08:57:34 louie 104: * *** empty log message *** 105: * 106: * 107: * Revision 3.1 89/01/30 14:43:10 louie 108: * Second UNIX NTP test release. 109: * 110: * Revision 3.0 88/12/12 15:59:35 louie 111: * Test release of new UNIX NTP software. This version should conform to the 112: * revised NTP protocol specification. 113: * 114: */ 115: 116: #include <stdio.h> 117: #include <sys/types.h> 118: #include <sys/param.h> 119: #include <sys/uio.h> 120: #include <sys/socket.h> 121: #include <sys/time.h> 122: #include <sys/ioctl.h> 123: #include <sys/resource.h> 124: 125: #include <net/if.h> 126: 127: #include <netinet/in.h> 128: #include <netinet/in_systm.h> 129: #include <netinet/ip.h> 130: #include <netinet/udp.h> 131: 132: #include <arpa/inet.h> 133: #include <netdb.h> 134: #include <strings.h> 135: #include <errno.h> 136: #include <syslog.h> 137: 138: #include "ntp.h" 139: 140: int peer_switches, peer_sw_inhibited; 141: 142: struct ntp_peer dummy_peer; 143: extern double WayTooBig; 144: extern u_long clock_watchdog; 145: #ifdef DEBUG 146: extern int debug; 147: extern void dump_pkt(); 148: #endif 149: extern int trusting, logstats; 150: extern struct sysdata sys; 151: extern struct list peer_list; 152: extern struct ntp_peer *check_peer(); 153: extern struct servent *servp; 154: extern char *malloc(), *ntoa(); 155: extern double drift_comp, compliance; /* logical clock variables */ 156: extern double s_fixed_to_double(), ul_fixed_to_double(); 157: extern void make_new_peer(), double_to_s_fixed(), tstamp(), demobilize(); 158: 159: 160: #ifdef REFCLOCK 161: void refclock_input(); 162: #endif 163: 164: void process_packet(), clock_update(), clear(), clock_filter(), 165: receive(), select_clock(), poll_update(); 166: 167: /* 3.4. Event Processing */ 168: 169: /* 3.4.1. Transmit Procedure */ 170: void 171: transmit(peer) 172: struct ntp_peer *peer; 173: { 174: struct timeval txtv; 175: static struct ntpdata ntpframe; 176: struct ntpdata *pkt = &ntpframe; 177: int i; 178: 179: pkt->status = sys.leap | NTPVERSION_1 | peer->hmode; 180: pkt->stratum = sys.stratum; 181: pkt->ppoll = peer->hpoll; 182: pkt->precision = (char) sys.precision; 183: pkt->distance = sys.distance; 184: pkt->dispersion = sys.dispersion; 185: pkt->refid = sys.refid; 186: pkt->reftime = sys.reftime; 187: pkt->org = peer->org; 188: pkt->rec = peer->rec; 189: (void) gettimeofday(&txtv, (struct timezone *) 0); 190: #if 0 191: if (peer->flags & PEER_FL_AUTHENABLE) { 192: /* add encryption time into the timestamp */ 193: tstamp(&pkt->xmt, &txtv); 194: /* call encrypt() procedure */ 195: pkt->keyid = ???; 196: pkt->mac = ???; 197: } else { 198: pkt->mac[0] = pkt->mac[1] = 0; 199: pkt->keyid = 0; /* XXX */ 200: tstamp(&pkt->xmt, &txtv); 201: } 202: #else 203: tstamp(&pkt->xmt, &txtv); 204: #endif 205: 206: peer->xmt = pkt->xmt; 207: 208: if ((peer->flags & (PEER_FL_BCAST|PEER_FL_REFCLOCK)) == 0) { 209: /* select correct socket to send reply on */ 210: if (sendto(addrs[(peer->sock < 0 ? 0 : peer->sock)].fd, 211: (char *) pkt, sizeof(ntpframe), 212: 0, &peer->src, sizeof(peer->src)) < 0) { 213: syslog(LOG_ERR, "sendto: %s %m", 214: ntoa(peer->src.sin_addr)); 215: return; 216: } 217: #ifdef REFCLOCK 218: } else if (peer->flags & PEER_FL_REFCLOCK) { 219: /* Special version of code below, adjusted for refclocks */ 220: 221: 222: peer->pkt_sent++; 223: i = peer->reach; /* save a copy */ 224: 225: peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK; 226: 227: if (i && peer->reach == 0) { 228: syslog(LOG_INFO, "Lost reachability with %.4s", 229: (char *)&peer->refid); 230: #ifdef DEBUG 231: if (debug) 232: printf("Lost reachability with %.4s\n", 233: (char *)&peer->refid); 234: #endif 235: } 236: 237: if (peer->reach == 0) 238: clear(peer); 239: 240: if (peer->valid < 2) 241: peer->valid++; 242: else { 243: clock_filter(peer, 0.0, 0.0); /* call with invalid values */ 244: select_clock(); /* and try to reselect clock */ 245: } 246: 247: peer->timer = 1<<NTP_MINPOLL; /* poll refclocks frequently */ 248: 249: refclock_input(peer, pkt); 250: return; 251: #endif REFCLOCK 252: } else { 253: #ifdef BROADCAST_NTP 254: if (sendto(addrs[peer->sock].fd, 255: (char *) pkt, sizeof(ntpframe), 256: 0, &peer->src, sizeof(peer->src)) < 0) { 257: syslog(LOG_ERR, "bcast sendto: %s %m", 258: ntoa(peer->src.sin_addr)); 259: return; 260: } 261: #else 262: return; 263: #endif 264: } 265: 266: #ifdef DEBUG 267: if (debug > 5) { 268: printf("\nSent "); 269: dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL); 270: } 271: #endif 272: peer->pkt_sent++; 273: i = peer->reach; /* save a copy */ 274: 275: peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK; 276: 277: if ((peer->reach == 0) && 278: ((peer->flags & PEER_FL_CONFIG) == 0) && 279: (peer != &dummy_peer)) { 280: demobilize(&peer_list, peer); 281: return; 282: } 283: 284: if (i && peer->reach == 0) { 285: syslog(LOG_INFO, "Lost reachability with %s", 286: ntoa(peer->src.sin_addr)); 287: #ifdef DEBUG 288: if (debug) 289: printf("Lost reachability with %s", 290: ntoa(peer->src.sin_addr)); 291: #endif 292: } 293: 294: if (peer->reach == 0) { 295: clear(peer); 296: peer->sock = -1; /* since he fell off the end of the 297: earth, don't depend on local address 298: any longer */ 299: } 300: 301: if (peer->valid < 2) 302: peer->valid++; 303: else { 304: clock_filter(peer, 0.0, 0.0); /* call with invalid values */ 305: select_clock(); /* and try to reselect clock */ 306: if (sys.peer != NULL) 307: poll_update(sys.peer, NTP_MINPOLL); 308: } 309: 310: peer->timer = 1<<(MAX(MIN(peer->ppoll, MIN(peer->hpoll, NTP_MAXPOLL)), 311: NTP_MINPOLL)); 312: 313: if (peer->estdisp > PEER_THRESHOLD) 314: poll_update(peer, peer->hpoll - 1); 315: else 316: poll_update(peer, peer->hpoll + 1); 317: } 318: 319: #ifdef REFCLOCK 320: void 321: refclock_input(peer, pkt) 322: struct ntpdata *pkt; 323: struct ntp_peer *peer; 324: { 325: struct timeval *tvp; 326: struct timeval *otvp; 327: 328: if (read_clock(peer->sock, &tvp, &otvp)) 329: return; 330: 331: tstamp(&pkt->rec, tvp); 332: pkt->xmt = pkt->rec; 333: pkt->reftime = pkt->rec; 334: tstamp(&pkt->org, otvp); 335: peer->xmt = pkt->org; 336: pkt->refid = peer->refid; 337: pkt->status &= ~ALARM; 338: pkt->stratum = peer->stratum; 339: pkt->ppoll = 0xff; 340: pkt->precision = peer->precision; 341: double_to_s_fixed(&pkt->distance, 0.0); 342: double_to_s_fixed(&pkt->dispersion, 0.0); 343: #ifdef DEBUG 344: if (debug > 5) { 345: printf("\nFaking packet "); 346: dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL); 347: } 348: #endif 349: receive((struct sockaddr_in *)peer, pkt, otvp, -1); 350: return; 351: } 352: #endif REFCLOCK 353: 354: /* 3.4.2. Receive Procedure */ 355: void 356: receive(dst, pkt, tvp, sock) 357: struct sockaddr_in *dst; 358: struct ntpdata *pkt; 359: struct timeval *tvp; 360: int sock; 361: { 362: struct ntp_peer *peer; 363: int peer_mode; 364: 365: #define ACT_ERROR 1 366: #define ACT_RECV 2 367: #define ACT_XMIT 3 368: #define ACT_PKT 4 369: 370: static char actions[5][5] = { 371: 372: /* Sym Act Sym Pas Client Server Broadcast |Host / */ 373: /* -------- -------- -------- --------- --------- | / Peer */ 374: /* ------------ */ 375: {ACT_PKT, ACT_PKT, ACT_RECV, ACT_XMIT, ACT_XMIT}, /* Sym Act */ 376: {ACT_PKT, ACT_ERROR, ACT_RECV, ACT_ERROR, ACT_ERROR}, /* Sym Pas */ 377: {ACT_XMIT, ACT_XMIT, ACT_ERROR, ACT_XMIT, ACT_XMIT}, /* Client */ 378: {ACT_PKT, ACT_ERROR, ACT_RECV, ACT_ERROR, ACT_ERROR}, /* Server */ 379: {ACT_PKT, ACT_ERROR, ACT_RECV, ACT_ERROR, ACT_ERROR}};/* Broadcast */ 380: 381: /* if we're only going to support NTP Version 2 then this stuff 382: isn't necessary, right? */ 383: 384: if ((peer_mode = pkt->status & MODEMASK) == 0 && dst) { 385: /* packet from an older NTP implementation. Synthesize the 386: correct mode. The mapping goes like this: 387: 388: pkt source port pkt dst port Mode 389: --------------- ------------ ---- 390: NTP Port NTP Port symmetric active 391: NTP Port not NTP Port server 392: not NTP Port NTP Port client 393: not NTP Port not NTP Port <not possible> 394: 395: Now, since we only are processing packets with the 396: destination being NTP Port, it reduces to the two cases: 397: 398: pkt source port pkt dst port Mode 399: --------------- ------------ ---- 400: NTP Port NTP Port symmetric active 401: not NTP Port NTP Port client */ 402: 403: if (dst->sin_port == servp->s_port) 404: peer_mode = MODE_SYM_ACT; 405: else 406: peer_mode = MODE_CLIENT; 407: } 408: 409: if (peer_mode == MODE_CLIENT) { 410: /* 411: * Special case: Use the dummy peer item that we keep around 412: * just for this type of thing 413: */ 414: peer = &dummy_peer; 415: make_new_peer(peer); 416: peer->src = *dst; 417: peer->sock = sock; 418: peer->hmode = MODE_SYM_PAS; 419: peer->reach = 0; 420: clear(peer); 421: #ifdef REFCLOCK 422: } else if (sock == -1) { 423: /* we're begin called by refclock_input(), get peer ptr */ 424: peer = (struct ntp_peer *)dst; 425: #endif 426: } else 427: peer = check_peer(dst, sock); 428: 429: if (peer == NULL) { 430: peer = (struct ntp_peer *) malloc(sizeof(struct ntp_peer)); 431: if (peer == NULL) { 432: syslog(LOG_ERR, "peer malloc: %m"); 433: return; 434: } 435: make_new_peer(peer); 436: peer->src = *dst; 437: peer->sock = sock; /* remember which socket we heard 438: this from */ 439: peer->hmode = MODE_SYM_PAS; 440: peer->reach = 0; 441: clear(peer); 442: /* 443: * If we decide to consider any random NTP peer that might 444: * come as a peer we might sync to, then set the PEER_FL_SYNC 445: * flag in the peer structure. 446: * 447: * Alternatively, we could change the hmode to MODE_SERVER, 448: * but then the peer state wouldn't be persistant. 449: */ 450: if (trusting) 451: peer->flags |= PEER_FL_SYNC; 452: 453: enqueue(&peer_list, peer); 454: } 455: 456: /* 457: * "pre-configured" peers are initially assigned a socket index of 458: * -1, which means we don't know which interface we'll use to talk 459: * to them. Once the first reply comes back, we'll update the 460: * peer structure 461: */ 462: if (peer->sock == -1) 463: peer->sock = sock; 464: 465: #ifdef BROADCAST_NTP 466: /* 467: * Input frame matched a funny broadcast peer; these peers only 468: * exist to periodically generate broadcasts. If an input packet 469: * matched, it means that it looked like it *came* from the broadcast 470: * address. This is clearly bogus. 471: */ 472: if (peer->flags & PEER_FL_BCAST) { 473: #ifdef DEBUG 474: if (debug > 1) 475: printf("receive: input frame for broadcast peer?\n"); 476: #endif 477: return; 478: } 479: #endif /* BROADCAST_NTP */ 480: 481: #if 0 482: if ((peer->flags & PEER_FL_AUTHENABLE) && 483: pkt->mac) { 484: /* verify computed crypto-checksum */ 485: } 486: #endif 487: 488: if (peer_mode < MODE_SYM_ACT || peer_mode > MODE_BROADCAST) { 489: syslog(LOG_DEBUG, "Bogus peer_mode %d from %s", peer_mode, 490: ntoa(dst->sin_addr)); 491: #ifdef DEBUG 492: if (debug > 3) abort(); 493: #endif 494: return; 495: } 496: 497: if (peer->hmode < MODE_SYM_ACT || peer->hmode > MODE_BROADCAST) { 498: syslog(LOG_ERR, "Bogus hmode %d for peer %s", peer->hmode, 499: ntoa(peer->src.sin_addr)); 500: abort(); 501: } 502: 503: switch (actions[peer_mode - 1][peer->hmode - 1]) { 504: case ACT_RECV: 505: if (!(((peer->flags & PEER_FL_CONFIG) == 0) && 506: STRMCMP(pkt->stratum, >, sys.stratum))) { 507: peer->reach |= 1; 508: process_packet(dst, pkt, tvp, peer); 509: break; 510: } 511: /* Note fall-through */ 512: case ACT_ERROR: 513: if (((peer->flags & PEER_FL_CONFIG) == 0) && 514: (peer != &dummy_peer)) 515: demobilize(&peer_list, peer); 516: break; 517: 518: case ACT_PKT: 519: if (!(((peer->flags & PEER_FL_CONFIG) == 0) && 520: STRMCMP(pkt->stratum, >, sys.stratum))) { 521: peer->reach |= 1; 522: process_packet(dst, pkt, tvp, peer); 523: break; 524: } 525: /* Note fall-through */ 526: case ACT_XMIT: 527: process_packet(dst, pkt, tvp, peer); 528: poll_update(peer, peer->ppoll); 529: transmit(peer); 530: break; 531: 532: default: 533: abort(); 534: } 535: } 536: 537: #undef ACT_ERROR 538: #undef ACT_RECV 539: #undef ACT_XMIT 540: #undef ACT_PKT 541: 542: 543: /* 3.4.3 Packet procedure */ 544: void 545: process_packet(dst, pkt, tvp, peer) 546: struct sockaddr_in *dst; 547: struct ntpdata *pkt; 548: struct timeval *tvp; 549: struct ntp_peer *peer; 550: { 551: double t1, t2, t3, t4, offset, delay; 552: short duplicate, bogus; 553: 554: duplicate = (pkt->xmt.int_part == peer->org.int_part) && 555: (pkt->xmt.fraction == peer->org.fraction); 556: 557: bogus = ((pkt->org.int_part != peer->xmt.int_part) || 558: (pkt->org.fraction != peer->xmt.fraction)) 559: || (peer->xmt.int_part == 0); 560: 561: peer->pkt_rcvd++; 562: peer->leap = pkt->status & LEAPMASK; 563: peer->stratum = pkt->stratum; 564: peer->ppoll = pkt->ppoll; 565: peer->precision = pkt->precision; 566: peer->distance = pkt->distance; 567: peer->dispersion = pkt->dispersion; 568: peer->refid = pkt->refid; 569: peer->reftime = pkt->reftime; 570: peer->org = pkt->xmt; 571: tstamp(&peer->rec, tvp); 572: poll_update(peer, peer->hpoll); 573: 574: /* 575: * may want to do something special here for Broadcast Mode peers to 576: * allow these through 577: */ 578: if (bogus || duplicate || 579: (pkt->org.int_part == 0 && pkt->org.fraction == 0) || 580: (pkt->rec.int_part == 0 && pkt->org.fraction == 0)) { 581: peer->pkt_dropped++; 582: #ifdef DEBUG 583: if (debug > 3) 584: printf("process_packet: dropped duplicate or bogus\n"); 585: #endif 586: return; 587: } 588: 589: /* 590: * Now compute local adjusts 591: */ 592: t1 = ul_fixed_to_double(&pkt->org); 593: t2 = ul_fixed_to_double(&pkt->rec); 594: t3 = ul_fixed_to_double(&pkt->xmt); 595: t4 = ul_fixed_to_double(&peer->rec); 596: 597: /* 598: * although the delay computation looks different than the one in the 599: * specification, it is correct. Think about it. 600: */ 601: delay = (t2 - t1) - (t3 - t4); 602: offset = ((t2 - t1) + (t3 - t4)) / 2.0; 603: 604: delay += 1.0/(u_long)(1L << -sys.precision) 605: #ifndef REFCLOCK 606: + NTP_MAXSKW; 607: #else 608: + (peer->flags&PEER_FL_REFCLOCK) ? NTP_REFMAXSKW : NTP_MAXSKW; 609: #endif 610: if (peer->precision < 0 && -peer->precision < sizeof(long)*NBBY) 611: delay += 1.0/(u_long)(1L << -peer->precision); 612: 613: if (delay < 0.0) { 614: peer->pkt_dropped++; 615: return; 616: } 617: 618: #ifndef REFCLOCK 619: delay = MAX(delay, NTP_MINDIST); 620: #else 621: delay = MAX(delay, (peer->flags & PEER_FL_REFCLOCK) ? 622: NTP_REFMINDIST : NTP_MINDIST); 623: #endif 624: 625: peer->valid = 0; 626: clock_filter(peer, delay, offset); /* invoke clock filter procedure */ 627: #ifdef DEBUG 628: if (debug) { 629: printf("host: %s : %f : %f : %f : %f : %f : %lo\n", 630: dst ? ntoa(dst->sin_addr) : "refclock", 631: delay, offset, 632: peer->estdelay, peer->estoffset, peer->estdisp, 633: peer->reach); 634: } 635: #endif 636: clock_update(peer); /* call clock update procedure */ 637: } 638: 639: /* 3.4.4 Primary clock procedure */ 640: /* 641: * We don't have a primary clock. 642: * 643: * TODO: 644: * 645: * ``When a primary clock is connected to the host, it is convient to 646: * incorporate its information into the database as if the clock was 647: * represented as an ordinary peer. The clock can be polled once a 648: * minute or so and the returned timecheck used to produce a new update 649: * for the logical clock.'' 650: */ 651: 652: 653: /* 3.4.5 Clock update procedure */ 654: 655: void 656: clock_update(peer) 657: struct ntp_peer *peer; 658: { 659: double temp; 660: extern int adj_logical(); 661: 662: select_clock(); 663: if (sys.peer != NULL) 664: poll_update(sys.peer, NTP_MINPOLL); 665: 666: /* 667: * Did we just sync to this peer? 668: */ 669: if ((peer == sys.peer) && (sys.hold == 0)) { 670: char buf[200]; 671: 672: /* 673: * Update the local system variables 674: */ 675: sys.leap = peer->leap; 676: #ifndef REFCLOCK 677: sys.stratum = peer->stratum + 1; 678: sys.refid = peer->src.sin_addr.s_addr; 679: #else 680: if (peer->flags & PEER_FL_REFCLOCK) { 681: /* once we re-map the stratums so that stratum 0 is 682: better than stratum 1, some of this foolishness 683: can go away */ 684: sys.stratum = peer->stratum; 685: sys.refid = peer->refid; 686: } else { 687: sys.stratum = peer->stratum + 1; 688: sys.refid = peer->src.sin_addr.s_addr; 689: } 690: #endif 691: 692: temp = s_fixed_to_double(&peer->distance) + peer->estdelay; 693: double_to_s_fixed(&sys.distance, temp); 694: 695: temp = s_fixed_to_double(&peer->dispersion) + peer->estdisp; 696: double_to_s_fixed(&sys.dispersion, temp); 697: 698: sys.reftime = peer->rec; 699: 700: #ifdef DEBUG 701: if (debug > 3) 702: printf("clock_update: synced to peer, adj clock\n"); 703: #endif 704: 705: /* 706: * Sanity check: is computed offset insane? 707: */ 708: if (peer->estoffset > WayTooBig || 709: peer->estoffset < -WayTooBig) { 710: syslog(LOG_ERR, "Clock is too far off %f sec. [%s]", 711: peer->estoffset, ntoa(peer->src.sin_addr)); 712: #ifdef DEBUG 713: if (debug) 714: printf("Clock is too far off %f sec. [%s] (max %f)\n", 715: peer->estoffset, 716: ntoa(peer->src.sin_addr), WayTooBig); 717: #endif /*DEBUG*/ 718: return; 719: } 720: 721: clock_watchdog = 0; /* reset watchdog timer */ 722: if (adj_logical(peer->estoffset) > 0) { 723: register struct ntp_peer *p = peer_list.head; 724: /* did you know syslog only took 4 parameters? */ 725: sprintf(buf, 726: "adjust: STEP %s st %d off %f drft %f cmpl %f", 727: inet_ntoa(peer->src.sin_addr), peer->stratum, 728: peer->estoffset, drift_comp, compliance); 729: syslog(LOG_INFO, buf); 730: #ifdef DEBUG 731: if (debug) 732: printf("Clockset from %s stratum %d offset %f\n", 733: inet_ntoa(peer->src.sin_addr), 734: peer->stratum, peer->estoffset); 735: 736: #endif 737: while (p) { 738: clear(p); 739: p = p->next; 740: } 741: sys.hold = PEER_SHIFT * (1 << NTP_MINPOLL); 742: #ifdef DEBUG 743: if (debug > 3) 744: printf("clock_updates: STEP ADJ\n"); 745: #endif 746: } else { 747: if (logstats) { 748: sprintf(buf, 749: "adjust: SLEW %s st %d off %f drft %f cmpl %f", 750: inet_ntoa(peer->src.sin_addr), 751: peer->stratum, 752: peer->estoffset, drift_comp, 753: compliance); 754: syslog(LOG_INFO, buf); 755: } 756: } 757: } 758: } 759: 760: /* 3.4.6 Initialization procedure */ 761: 762: void 763: initialize() 764: { 765: sys.leap = ALARM; /* indicate unsynchronized */ 766: sys.stratum = 0; 767: sys.precision = 0; /* may be specified in the config file; 768: if not, gets set in init_kern_vars() */ 769: #if 0 /* under construction */ 770: sys.keyid = 0; 771: sys.keys = ??; 772: #endif 773: sys.distance.int_part = sys.distance.fraction = 0; 774: sys.dispersion.int_part = sys.dispersion.fraction = 0; 775: sys.refid = 0; 776: sys.reftime.int_part = sys.reftime.fraction = 0; 777: sys.hold = 0; 778: sys.peer = NULL; 779: } 780: 781: /* 3.4.7 Clear Procedure */ 782: void 783: clear(peer) 784: register struct ntp_peer *peer; 785: { 786: register int i; 787: 788: #ifdef DEBUG 789: if (debug > 3) 790: printf("clear: emptied filter for %s\n", 791: ntoa(peer->src.sin_addr)); 792: #endif 793: peer->hpoll = NTP_MINPOLL; 794: peer->estdisp = PEER_MAXDISP; 795: for (i = 0; i < NTP_WINDOW; i++) 796: peer->filter.offset[i] = 0.0; 797: peer->filter.samples = 0; /* Implementation specific */ 798: peer->valid = 0; 799: peer->org.int_part = peer->org.fraction = 0; 800: peer->rec.int_part = peer->rec.fraction = 0; 801: peer->xmt.int_part = peer->xmt.fraction = 0; 802: poll_update(peer, NTP_MINPOLL); 803: select_clock(); 804: if (sys.peer != NULL) 805: poll_update(sys.peer, NTP_MINPOLL); 806: } 807: 808: 809: /* 3.4.8 Poll Update Procedure */ 810: void 811: poll_update(peer, new_hpoll) 812: register struct ntp_peer *peer; 813: int new_hpoll; 814: { 815: int interval; 816: 817: peer->hpoll = MAX(NTP_MINPOLL, MIN(NTP_MAXPOLL, new_hpoll)); 818: 819: #if XTAL /* if crystal controlled clock */ 820: if (peer == sys.peer) 821: #endif 822: peer->hpoll = NTP_MINPOLL; 823: 824: interval = 1 << (MAX(MIN(peer->ppoll, MIN(peer->hpoll, NTP_MAXPOLL)), 825: NTP_MINPOLL)); 826: 827: #ifdef REFCLOCK 828: if (peer->flags & PEER_FL_REFCLOCK) 829: interval = 1 << NTP_MINPOLL; 830: #endif 831: if (interval == peer->timer) 832: return; 833: 834: /* only randomize when poll interval changes */ 835: if (interval < peer->timer) 836: peer->timer = interval; 837: 838: /* 839: * "Rand uses a multiplicative congruential random number gen- 840: * erator with period 2**32 to return successive pseudo-random 841: * numbers in the range from 0 to (2**31)-1" 842: */ 843: interval = (double)interval * 844: ((double)rand()/(double)((u_long)(1L<<31) - 1)); 845: 846: #ifdef DEBUG 847: if (debug > 3) 848: printf("poll_update: timer %d, poll=%d\n", peer->timer, 849: interval); 850: #endif 851: } 852: 853: 854: /* 3.4.9 Authentication Procedures */ 855: #if 0 856: encrypt() {} 857: decrypt() {} 858: #endif 859: 860: /* 4.1 Clock Filter Procedure */ 861: /* 862: * The previous incarnation of this code made the assumption that 863: * the value of PEER_FILTER was a power of two and used shifting. 864: * This version has been generalized, so that experimenting with 865: * different PEER_FILTER values should be much easier. 866: */ 867: 868: void 869: clock_filter(peer, new_delay, new_offset) 870: register struct ntp_peer *peer; 871: double new_delay, new_offset; 872: { 873: double offset[PEER_SHIFT], delay[PEER_SHIFT]; 874: register double temp, d, w; 875: register int i, j, samples; 876: 877: if (peer->filter.samples < PEER_SHIFT) 878: peer->filter.samples++; 879: /* 880: * Too bad C doesn't have a barrel shifter... 881: */ 882: for (i = PEER_SHIFT - 1; i; i--) { 883: peer->filter.offset[i] = peer->filter.offset[i - 1]; 884: peer->filter.delay[i] = peer->filter.delay[i - 1]; 885: } 886: peer->filter.offset[0] = new_offset; 887: peer->filter.delay[0] = new_delay; 888: 889: samples = 0; 890: /* 891: * Now sort the valid (non-zero delay) samples into a temporary 892: * list by delay. 893: * 894: * First, build the temp list... 895: */ 896: for (i = 0; i < peer->filter.samples; i++) { 897: if (peer->filter.delay[i] != 0.0) { 898: offset[samples] = peer->filter.offset[i]; 899: delay[samples++] = peer->filter.delay[i]; 900: } 901: } 902: /* ..and now sort it. */ 903: if (samples) { 904: for (i = 0; i < samples - 1; i++) { 905: for (j = i + 1; j < samples; j++) { 906: if (delay[i] > delay[j]) { 907: temp = delay[i]; 908: delay[i] = delay[j]; 909: delay[j] = temp; 910: temp = offset[i]; 911: offset[i] = offset[j]; 912: offset[j] = temp; 913: } 914: } 915: } 916: /* samples are now sorted by delay */ 917: 918: peer->estdelay = delay[0]; 919: peer->estoffset = offset[0]; 920: } 921: 922: temp = 0.0; 923: w = 1.0; 924: 925: for (i = 0; i < PEER_SHIFT; i++) { 926: if (i >= samples) 927: d = PEER_MAXDISP; 928: else { 929: if ((d = offset[i] - offset[0]) < 0) 930: d = -d; 931: if (d > PEER_MAXDISP) 932: d = PEER_MAXDISP; 933: } 934: temp += d * w; 935: /* compute PEER_FILTER**i as we go along */ 936: w *= PEER_FILTER; 937: } 938: peer->estdisp = temp; 939: #ifdef DEBUG 940: if (debug > 3) 941: printf("clock_filter: estdelay %f, estoffset %f, estdisp %f\n", 942: peer->estdelay, peer->estoffset, peer->estdisp); 943: #endif 944: } 945: 946: /* 4.2 Clock Select Procedure */ 947: void 948: select_clock() { 949: struct ntp_peer *ptmp, *peer = peer_list.head; 950: struct sel_lst { 951: struct ntp_peer *peer; 952: double distance; 953: double precision; 954: } sel_lst[X_NTP_CANDIDATES]; 955: int i, j, stratums, candidates; 956: int sanity_check(); 957: double falsetick(), dtmp; 958: 959: candidates = 0; 960: stratums = 0; 961: 962: while (peer != NULL && candidates < X_NTP_CANDIDATES) { 963: /* 964: * Check if this is a candidate for "sys.peer" 965: */ 966: peer->flags &= ~(PEER_FL_SANE | PEER_FL_CANDIDATE); 967: if(sanity_check(peer)) { 968: sel_lst[candidates].peer = peer; 969: sel_lst[candidates].distance = peer->estdisp + 970: s_fixed_to_double(&peer->dispersion); 971: peer->flags |= PEER_FL_SANE; 972: candidates++; 973: } 974: peer = peer->next; 975: } 976: #ifdef DEBUG 977: if (debug > 3) 978: printf("select_clock: step1 %d candidates\n", candidates); 979: #endif 980: /* 981: * If no candidates passed the sanity check, then give up. 982: */ 983: if (!candidates) { 984: if (sys.peer != NULL) { 985: syslog(LOG_INFO, "Lost NTP peer %s", 986: inet_ntoa(sys.peer->src.sin_addr)); 987: #ifdef DEBUG 988: if (debug) 989: printf("Lost NTP peer %s\n", 990: inet_ntoa(sys.peer->src.sin_addr)); 991: #endif 992: } 993: #ifdef DEBUG 994: if (debug > 3) 995: printf("select_clock: no candidates\n"); 996: #endif 997: sys.peer = NULL; 998: /* 999: * leave sys.stratum and sys.refid intact after losing 1000: * reachability to all clocks. After 24 hours, we'll 1001: * set the alarm condition if we didn't get any clock 1002: * updates. 1003: */ 1004: return; 1005: } 1006: 1007: /* 1008: * Sort the list. We assume that sanity_check() above trashed any 1009: * peers which were stratum 0, so we can safely compare stratums 1010: * below. Sort the list by stratum. Where stratums are equal, the 1011: * peer with the lowest (peer.estdisp + peer.dispersion) is preferred. 1012: */ 1013: for (i = 0; i < candidates - 1; i++) { 1014: for (j = i + 1; j < candidates; j++) { 1015: if ((sel_lst[i].peer->stratum > sel_lst[j].peer->stratum) || 1016: ((sel_lst[i].peer->stratum == sel_lst[j].peer->stratum) 1017: && (sel_lst[i].distance > sel_lst[j].distance))) { 1018: ptmp = sel_lst[i].peer; 1019: dtmp = sel_lst[i].distance; 1020: sel_lst[i].peer = sel_lst[j].peer; 1021: sel_lst[i].distance = sel_lst[j].distance; 1022: sel_lst[j].peer = ptmp; 1023: sel_lst[j].distance = dtmp; 1024: } 1025: } 1026: } 1027: 1028: #ifdef DEBUG 1029: if (debug > 3) 1030: printf("select_clock: step2 %d candidates\n", candidates); 1031: #endif 1032: 1033: /* truncate the list at NTP_MAXLIST peers */ 1034: if (candidates > NTP_MAXLIST) 1035: candidates = NTP_MAXLIST; 1036: 1037: #ifdef DEBUG 1038: if (debug > 3) 1039: printf("select_clock: step3 %d candidates\n", candidates); 1040: #endif 1041: 1042: /* truncate list where number of different strata exceeds NTP_MAXSTRA */ 1043: for (stratums = 0, i = 1; i < candidates; i++) { 1044: if (sel_lst[i - 1].peer->stratum != sel_lst[i].peer->stratum) { 1045: if (++stratums > NTP_MAXSTRA) { 1046: #ifdef DEBUG 1047: if (debug > 2) 1048: printf("select_clock: truncated to %d peers\n", i); 1049: #endif 1050: candidates = i; 1051: 1052: break; 1053: } 1054: } 1055: } 1056: #ifdef DEBUG 1057: if (debug > 3) 1058: printf("select_clock: step4 %d candidates\n", candidates); 1059: #endif 1060: /* 1061: * Kick out falsetickers 1062: */ 1063: /* now, re-sort the list by peer.stratum and peer.estdelay */ 1064: for (i = 0; i < candidates - 1; i++) { 1065: for (j = i + 1; j < candidates; j++) { 1066: if ((sel_lst[i].peer->stratum > sel_lst[j].peer->stratum) || 1067: ((sel_lst[i].peer->stratum == sel_lst[j].peer->stratum) 1068: && (sel_lst[i].peer->estdelay > 1069: sel_lst[j].peer->estdelay))) { 1070: ptmp = sel_lst[i].peer; 1071: sel_lst[i].peer = sel_lst[j].peer; 1072: sel_lst[j].peer = ptmp; 1073: } 1074: } 1075: } 1076: while (candidates > 1) { 1077: double maxdispersion = 0.0, dispersion, weight; 1078: double min_precision_thres = 10e20, precision_thres; 1079: short worst = 0; /* shut up GNU CC about unused var */ 1080: #ifdef DEBUG 1081: if (debug > 3) 1082: printf("select_clock: step5 %d candidates\n", candidates); 1083: #endif 1084: for (i = 0; i < candidates; i++) { 1085: /* compute dispersion of candidate `i' relative to the 1086: rest of the candidates */ 1087: dispersion = 0.0; 1088: weight = 1.0; 1089: sel_lst[i].peer->flags |= PEER_FL_CANDIDATE; 1090: for (j = 0; j < candidates; j++) { 1091: dtmp = sel_lst[j].peer->estoffset - 1092: sel_lst[i].peer->estoffset; 1093: if (dtmp < 0) 1094: dtmp = -dtmp; 1095: dispersion += dtmp * weight; 1096: weight *= NTP_SELECT; 1097: } 1098: /* since we just happen to have this double floating 1099: around.. */ 1100: sel_lst[i].distance = dispersion; 1101: 1102: precision_thres = NTP_MAXSKW + 1.0/(u_long)(1L<<-sys.precision); 1103: if (sel_lst[i].peer->precision < 0 && 1104: -sel_lst[i].peer->precision < sizeof(long)*NBBY) 1105: precision_thres += 1106: 1.0/(u_long)(1L<<-sel_lst[i].peer->precision); 1107: 1108: sel_lst[i].precision = precision_thres; 1109: 1110: if (dispersion >= maxdispersion) { 1111: maxdispersion = dispersion; 1112: worst = i; 1113: } 1114: if (precision_thres < min_precision_thres) { 1115: min_precision_thres = precision_thres; 1116: } 1117: #ifdef DEBUG 1118: if (debug > 4) { 1119: printf(" peer %s => disp %f prec_th %f\n", 1120: ntoa(sel_lst[i].peer->src.sin_addr), 1121: dispersion, precision_thres); 1122: } 1123: #endif 1124: } 1125: /* 1126: * Now check to see if the max dispersion is greater than 1127: * the min dispersion limit. If so, crank again, otherwise 1128: * bail out. 1129: */ 1130: if (! (maxdispersion > min_precision_thres)) { 1131: #ifdef DEBUG 1132: if (debug > 4) 1133: printf(" %d left valid\n", candidates); 1134: #endif 1135: break; 1136: } 1137: 1138: #ifdef DEBUG 1139: if (debug > 4) 1140: printf(" peer %s => TOSS\n", 1141: ntoa(sel_lst[worst].peer->src.sin_addr)); 1142: #endif 1143: /* 1144: * now, we need to trash the peer with the worst dispersion 1145: * and interate until there is only one candidate peer left. 1146: */ 1147: if (worst != candidates - 1) { 1148: sel_lst[worst].peer->flags &= ~PEER_FL_CANDIDATE; 1149: for (i = worst, j = worst + 1; j < candidates; ) 1150: sel_lst[i++].peer = sel_lst[j++].peer; 1151: } 1152: candidates--; 1153: /* one more time.. */ 1154: } 1155: #ifdef DEBUG 1156: if (debug > 3) 1157: printf("select_clock: step6 %d candidates\n", candidates); 1158: #endif 1159: 1160: /* 1161: * Check to see if current peer is on the list of candidate peers. If 1162: * don't change sys.peer. Note that if the first selected clock is 1163: * at a lower stratum, don't even bother; we're going to want to 1164: * switch to it. 1165: */ 1166: if (sys.peer != NULL && 1167: (sys.peer->stratum <= sel_lst[0].peer->stratum)) { 1168: for (i = 0; i < candidates; i++) { 1169: if (sys.peer == sel_lst[i].peer) { 1170: /* 1171: * The clock we're currently synchronized to 1172: * is among the candidate peers. Don't switch. 1173: */ 1174: if (i != 0) { 1175: /* 1176: * Count instances where the best 1177: * candidate is different from the 1178: * current clock, thus inhibiting 1179: * clockhopping. 1180: */ 1181: peer_sw_inhibited++; 1182: } 1183: return; 1184: } 1185: } 1186: } 1187: 1188: /* 1189: * The currently selected peer (if any) isn't on the candidate list. 1190: * Grab the first one and let it be. 1191: */ 1192: 1193: if (sys.peer != sel_lst[0].peer) { 1194: if (sys.peer != NULL) 1195: syslog(LOG_INFO, "clock: select peer %s stratum %d was %s stratum %d", 1196: ntoa(sel_lst[0].peer->src.sin_addr), 1197: sel_lst[0].peer->stratum, 1198: ntoa(sys.peer->src.sin_addr), sys.peer->stratum); 1199: else 1200: syslog(LOG_INFO, "clock: select peer %s stratum %d was UNSYNCED", 1201: ntoa(sel_lst[0].peer->src.sin_addr), 1202: sel_lst[0].peer->stratum); 1203: 1204: #ifdef DEBUG 1205: if (debug > 2) 1206: printf("clock: select peer %s stratum %d of %d cand\n", 1207: ntoa(sel_lst[0].peer->src.sin_addr), 1208: sel_lst[0].peer->stratum, candidates); 1209: #endif 1210: sys.peer = sel_lst[0].peer; 1211: peer_switches++; 1212: } 1213: } 1214: 1215: int 1216: sanity_check(peer) 1217: struct ntp_peer *peer; 1218: { 1219: #ifdef DEBUG 1220: if (debug > 7) 1221: printf("Checking peer %s stratum %d\n", 1222: inet_ntoa(peer->src.sin_addr), peer->stratum); 1223: #endif 1224: /* Sanity check 0. ?? */ 1225: if (!(peer->flags & PEER_FL_SYNC)) 1226: return(0); 1227: 1228: /* Sanity check 1. */ 1229: if (peer->stratum <= 0 || peer->stratum >= NTP_INFIN) 1230: return(0); 1231: 1232: /* Sanity check 2. 1233: if peer.stratum is greater than one (synchronized via NTP), 1234: peer.refid must not match peer.dstadr */ 1235: 1236: if (peer->stratum > 1) { 1237: register int i; 1238: for (i = 1; i < nintf; i++) 1239: if (addrs[i].sin.sin_addr.s_addr == peer->refid) 1240: return (0); 1241: } 1242: 1243: /* Sanity check 3. 1244: Both peer.estdelay and 1245: peer.estdisp to be less than NTP_MAXWGT, which insures that the 1246: filter register at least half full, yet avoids using data from 1247: very noisy associations or broken implementations. */ 1248: if (peer->estdisp > (float)NTP_MAXWGT || 1249: peer->estdelay > (float)NTP_MAXWGT) 1250: return(0); 1251: 1252: /* Sanity check 4. 1253: The peer clock must be synchronized... and the interval since 1254: the peer clock was last updated satisfy 1255: 1256: peer.org - peer.reftime < NTP.MAXAGE 1257: */ 1258: if (peer->leap == ALARM || 1259: (ul_fixed_to_double(&peer->org) 1260: - ul_fixed_to_double(&peer->reftime)) >= NTP_MAXAGE) 1261: return(0); 1262: 1263: #ifdef DEBUG 1264: if (debug > 7) 1265: printf("That one is certainly qualified %s\n", 1266: inet_ntoa(peer->src.sin_addr)); 1267: #endif 1268: return(1); 1269: }