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: }

Defined functions

clear defined in line 782; used 9 times
clock_filter defined in line 868; used 5 times
clock_update defined in line 655; used 3 times
decrypt defined in line 857; never used
encrypt defined in line 856; never used
initialize defined in line 762; used 2 times
poll_update defined in line 810; used 9 times
process_packet defined in line 544; used 5 times
receive defined in line 355; used 3 times
refclock_input defined in line 320; used 2 times
sanity_check defined in line 1215; used 2 times
select_clock defined in line 947; used 6 times
transmit defined in line 170; used 4 times

Defined variables

dummy_peer defined in line 142; used 3 times
peer_sw_inhibited defined in line 140; used 1 times
peer_switches defined in line 140; used 1 times
rcsid defined in line 2; never used

Defined struct's

sel_lst defined in line 950; never used

Defined macros

ACT_ERROR defined in line 365; used 12 times
ACT_PKT defined in line 368; used 7 times
ACT_RECV defined in line 366; used 6 times
ACT_XMIT defined in line 367; used 8 times
Last modified: 1995-07-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6292
Valid CSS Valid XHTML 1.0 Strict