1: #if !defined(lint) && defined(DOSCCS) 2: static char *rcsid = "$Source: /usr/src/new/ntp/ntpd.c,v $ $Revision: 3.4.1.12 $ $Date: 95/07/1 20:35:17 $"; 3: #endif lint 4: 5: /* 6: * $Log: ntpd.c,v $ 7: * Revision 3.4.1.11 95/01/31 20:35:17 sms 8: * Fix missing initializer before calling sysctl(). 9: * 10: * Revision 3.4.1.10 95/01/27 17:20:17 sms 11: * 2.11BSD - remove SETTICKADJ from ntpd.c. This was done for several reasons: 12: * 1) tickadj does not (and never has) existed, 2) this is an old version and 13: * not going to be ported to a system with tickadj, 3) with 'securelevel' 14: * (see sysctl(3), init(8) and sysctl(8)) set to 1 or 2 /dev/{k}mem can not 15: * be written even by root. If tickadj were ever added it would need an 16: * extension to sysctl(3) to have a chance of working. 17: * 18: * Revision 3.4.1.9 89/05/18 18:30:17 louie 19: * Changes in ntpd.c for reference clock support. Also, a few diddles to 20: * accomodate the NeXT computer system that has a slightly different nlist.h 21: * 22: * Revision 3.4.1.8 89/05/03 15:16:17 louie 23: * Add code to save the value of the drift compensation register to a file every 24: * hour. Add additional configuration file directives which can specify the same 25: * information as on the command line. 26: * 27: * Revision 3.4.1.7 89/04/10 15:58:45 louie 28: * Add -l option to enable logging of clock adjust messages. 29: * 30: * Revision 3.4.1.6 89/04/07 19:09:04 louie 31: * Added NOSWAP code for Ultrix systems to lock NTP process in memory. Deleted 32: * unused variable in ntpd.c 33: * 34: * Revision 3.4.1.5 89/03/31 16:37:49 louie 35: * Add support for "trusting" directive in NTP configuration file. It allows 36: * you to specify at run time if non-configured peers will be synced to. 37: * 38: * Revision 3.4.1.4 89/03/29 12:30:46 louie 39: * peer->mode has been renamed peer->hmode. Drop PEER_FL_SYNC since the 40: * PEER_FL_CONFIG flag means much the same thing. 41: * 42: * Revision 3.4.1.3 89/03/22 18:29:41 louie 43: * patch3: Use new RCS headers. 44: * 45: * Revision 3.4.1.2 89/03/22 18:03:17 louie 46: * The peer->refid field was being htonl()'ed when it was already in network 47: * byte order. 48: * 49: * Revision 3.4.1.1 89/03/20 00:12:10 louie 50: * patch1: Diddle syslog messages a bit. Handle case of udp/ntp not being 51: * patch1: defined in /etc/services. Compute default value for tickadj if 52: * patch1: the change-kernel-tickadj flag is set, but no tickadj directive 53: * patch1: is present in the configuration file. 54: * 55: * Revision 3.4 89/03/17 18:37:11 louie 56: * Latest test release. 57: * 58: * Revision 3.3.1.1 89/03/17 18:26:32 louie 59: * 1 60: * 61: * Revision 3.3 89/03/15 14:19:56 louie 62: * New baseline for next release. 63: * 64: * Revision 3.2.1.2 89/03/15 13:59:50 louie 65: * Initialize random number generator. The ntpdc query_mode() routine has been 66: * revised to send more peers per packet, a count of the total number of peers 67: * which will be transmited, the number of packets to be transmitted, and a 68: * sequence number for each packet. There is a new version number for the 69: * ntpdc query packets, which is now symbolically defined in ntp.h 70: * 71: * Revision 3.2.1.1 89/03/10 12:27:41 louie 72: * Removed reference to HUGE, and replaced it by a suitable large number. Added 73: * some #ifdef DEBUG .. #endif around some debug code that was missing. Display 74: * patchlevel along with version. 75: * 76: * Revision 3.2 89/03/07 18:26:30 louie 77: * New version of the UNIX NTP daemon based on the 6 March 1989 draft of the 78: * new NTP protcol spec. A bunch of cosmetic changes. The peer list is 79: * now doublely linked, and a subroutine (enqueue()) replaces the ENQUEUE 80: * macro used previously. 81: * 82: * Revision 3.1.1.1 89/02/15 08:58:46 louie 83: * Bugfixes to released version. 84: * 85: * 86: * Revision 3.1 89/01/30 14:43:14 louie 87: * Second UNIX NTP test release. 88: * 89: * Revision 3.0 88/12/12 15:56:38 louie 90: * Test release of new UNIX NTP software. This version should conform to the 91: * revised NTP protocol specification. 92: * 93: */ 94: 95: #include <stdio.h> 96: #include <sys/types.h> 97: #include <sys/param.h> 98: #include <sys/uio.h> 99: #include <sys/socket.h> 100: #include <sys/time.h> 101: #include <sys/ioctl.h> 102: #include <sys/resource.h> 103: #include <sys/file.h> 104: #ifdef NOSWAP 105: #include <sys/lock.h> 106: #endif 107: 108: #include <net/if.h> 109: 110: #include <netinet/in.h> 111: #include <netinet/in_systm.h> 112: #include <netinet/ip.h> 113: #include <netinet/udp.h> 114: 115: #include <arpa/inet.h> 116: #include <netdb.h> 117: #include <strings.h> 118: #include <errno.h> 119: #include <syslog.h> 120: 121: #include "ntp.h" 122: #include "patchlevel.h" 123: 124: #define TRUE 1 125: #define FALSE 0 126: 127: struct sockaddr_in dst_sock = {AF_INET}; 128: 129: struct servent *servp; 130: struct list peer_list; 131: 132: struct itimerval it; 133: struct itimerval *itp = ⁢ 134: struct timeval tv; 135: char *prog_name; 136: 137: char *conf = NTPINITFILE; 138: char *driftcomp_file = NTPDRIFTCOMP; 139: static int drift_fd = -1; 140: 141: #ifdef DEBUG 142: int debug = 0; 143: #endif 144: 145: #ifdef NOSWAP 146: int noswap = 0; 147: #endif 148: 149: int doset = 1; 150: int ticked; 151: int selfds; 152: int trusting = 1; 153: int logstats; 154: 155: double WayTooBig = WAYTOOBIG; 156: u_long clock_watchdog; 157: 158: struct ntpdata ntpframe; 159: struct sysdata sys; 160: 161: extern int errno; 162: extern char *malloc(), *ntoa(); 163: 164: void finish(), timeout(), tock(), make_new_peer(), init_ntp(), initialize(), 165: init_kern_vars(), hourly(); 166: extern void transmit(), process_packet(), clock_update(), 167: clear(), clock_filter(), select_clock(); 168: 169: extern void init_logical_clock(); 170: 171: main(argc, argv) 172: int argc; 173: char *argv[]; 174: { 175: struct sockaddr_in *dst = &dst_sock; 176: struct ntpdata *pkt = &ntpframe; 177: fd_set readfds, tmpmask; 178: int dstlen = sizeof(struct sockaddr_in); 179: int cc; 180: register int i; 181: extern char *optarg; 182: extern int atoi(); 183: 184: #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2) 185: void incdebug(), decdebug(); 186: #endif 187: initialize(); /* call NTP protocol initialization first, 188: then allow others to override default 189: values */ 190: prog_name = argv[0]; 191: while ((cc = getopt(argc, argv, "a:c:dD:lstn")) != EOF) { 192: switch (cc) { 193: case 'a': 194: if (strcmp(optarg, "any") == 0) 195: WayTooBig = 10e15; 196: else 197: WayTooBig = atof(optarg); 198: break; 199: 200: case 'd': 201: #ifdef DEBUG 202: debug++; 203: #else 204: fprintf(stderr, "%s: not compiled with DEBUG\n", 205: prog_name); 206: #endif 207: break; 208: 209: case 'D': 210: #ifdef DEBUG 211: debug = atoi(optarg); 212: #else 213: fprintf(stderr, "%s: not compiled with DEBUG\n", 214: prog_name); 215: #endif 216: break; 217: 218: case 's': 219: doset = 0; 220: break; 221: 222: case 't': 223: fprintf(stderr, "%s: tickadj not supported\n", 224: prog_name); 225: break; 226: 227: case 'n': 228: #ifdef NOSWAP 229: noswap = 1; 230: #else 231: fprintf(stderr, "%s: not compiled for noswap\n", 232: prog_name); 233: #endif 234: break; 235: 236: case 'l': 237: logstats = 1; 238: break; 239: 240: case 'c': 241: conf = optarg; 242: break; 243: 244: default: 245: fprintf(stderr, "ntpd: -%c: unknown option\n", cc); 246: break; 247: } 248: } 249: 250: #ifdef DEBUG 251: if (!debug) { 252: #endif 253: if (fork()) 254: exit(0); 255: 256: { 257: int s; 258: for (s = getdtablesize(); s >= 0; s--) 259: (void) close(s); 260: (void) open("/", 0); 261: (void) dup2(0, 1); 262: (void) dup2(0, 2); 263: (void) setpgrp(0, getpid()); 264: s = open("/dev/tty", 2); 265: if (s >= 0) { 266: (void) ioctl(s, (u_long) TIOCNOTTY, (char *) 0); 267: (void) close(s); 268: } 269: } 270: #ifdef DEBUG 271: } 272: #endif 273: 274: #ifndef LOG_DAEMON 275: openlog("ntpd", LOG_PID); 276: #else 277: 278: #ifndef LOG_NTP 279: #define LOG_NTP LOG_DAEMON 280: #endif 281: openlog("ntpd", LOG_PID | LOG_NDELAY, LOG_NTP); 282: #ifdef DEBUG 283: if (debug) 284: setlogmask(LOG_UPTO(LOG_DEBUG)); 285: else 286: #endif /* DEBUG */ 287: setlogmask(LOG_UPTO(LOG_INFO)); 288: #endif /* LOG_DAEMON */ 289: 290: syslog(LOG_NOTICE, "%s version $Revision: 3.4.1.9 $", prog_name); 291: syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL); 292: 293: #ifdef DEBUG 294: if (debug) 295: printf("%s version $Revision: 3.4.1.9 $ patchlevel %d\n", 296: prog_name, PATCHLEVEL); 297: #endif 298: (void) setpriority(PRIO_PROCESS, 0, -10); 299: 300: #ifdef NOSWAP 301: if (noswap) 302: if (plock(PROCLOCK) != 0) { 303: syslog(LOG_ERR, "plock() failed: %m"); 304: #ifdef DEBUG 305: if (debug) 306: perror("plock() failed"); 307: #endif 308: } 309: #endif 310: 311: servp = getservbyname("ntp", "udp"); 312: if (servp == NULL) { 313: syslog(LOG_CRIT, "udp/ntp: service unknown, using default %d", 314: NTP_PORT); 315: (void) create_sockets(htons(NTP_PORT)); 316: } else 317: (void) create_sockets(servp->s_port); 318: 319: 320: peer_list.head = peer_list.tail = NULL; 321: peer_list.members = 0; 322: 323: init_ntp(conf); 324: init_kern_vars(); 325: init_logical_clock(); 326: 327: /* 328: * Attempt to open for writing the file for storing the drift comp 329: * register. File must already exist for snapshots to be taken. 330: */ 331: if ((i = open(driftcomp_file, O_WRONLY|O_CREAT, 0644)) >= 0) { 332: drift_fd = i; 333: } 334: (void) gettimeofday(&tv, (struct timezone *) 0); 335: srand(tv.tv_sec); 336: 337: FD_ZERO(&tmpmask); 338: for (i = 0; i < nintf; i++) { 339: FD_SET(addrs[i].fd, &tmpmask); 340: #ifdef DEBUG 341: if (debug>2) { 342: if (addrs[i].if_flags & IFF_BROADCAST) 343: printf("Addr %d: %s fd %d %s broadcast %s\n", 344: i, addrs[i].name, addrs[i].fd, 345: ntoa(addrs[i].sin.sin_addr), 346: ntoa(addrs[i].bcast.sin_addr)); 347: else 348: printf("Addr %d: %s fd %d %s\n", i, 349: addrs[i].name, addrs[i].fd, 350: ntoa(addrs[i].sin.sin_addr)); 351: } 352: #endif 353: } 354: 355: (void) signal(SIGINT, finish); 356: (void) signal(SIGTERM, finish); 357: (void) signal(SIGALRM, tock); 358: #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2) 359: (void) signal(SIGUSR1, incdebug); 360: (void) signal(SIGUSR2, decdebug); 361: #endif 362: itp->it_interval.tv_sec = (1<<CLOCK_ADJ); 363: itp->it_interval.tv_usec = 0; 364: itp->it_value.tv_sec = 1; 365: itp->it_value.tv_usec = 0; 366: 367: /* 368: * Find highest fd in use. This might save a few microseconds in 369: * the select system call. 370: */ 371: for (selfds = FD_SETSIZE - 1; selfds; selfds--) 372: if (FD_ISSET(selfds, &tmpmask)) 373: break; 374: #ifdef DEBUG 375: if (debug > 2) 376: printf("Highest fd in use is %d\n", selfds); 377: if (!selfds) abort(); 378: #endif 379: selfds++; 380: 381: (void) setitimer(ITIMER_REAL, itp, (struct itimerval *) 0); 382: 383: for (;;) { /* go into a finite but hopefully very long 384: * loop */ 385: int nfds; 386: 387: readfds = tmpmask; 388: nfds = select(selfds, &readfds, (fd_set *) 0, (fd_set *) 0, 389: (struct timeval *) 0); 390: (void) gettimeofday(&tv, (struct timezone *) 0); 391: 392: for(i = 0; i < nintf && nfds > 0; i++) { 393: if (!FD_ISSET(addrs[i].fd, &readfds)) 394: continue; 395: addrs[i].uses++; 396: dstlen = sizeof(struct sockaddr_in); 397: if ((cc = 398: recvfrom(addrs[i].fd, (char *) pkt, 399: sizeof(ntpframe), 0, 400: (struct sockaddr *) dst, &dstlen)) < 0) { 401: 402: if (errno != EWOULDBLOCK) { 403: syslog(LOG_NOTICE, "recvfrom: %m"); 404: #ifdef DEBUG 405: if(debug > 2) 406: perror("recvfrom"); 407: #endif 408: } 409: continue; 410: } 411: 412: if (cc < sizeof(*pkt)) { 413: #ifdef DEBUG 414: if (debug) 415: printf("Runt packet from %s\n", 416: ntoa(dst->sin_addr)); 417: #endif 418: continue; 419: } 420: 421: if (pkt->stratum == INFO_QUERY || 422: pkt->stratum == INFO_REPLY) { 423: query_mode(dst, pkt, i); 424: continue; 425: } 426: #ifdef DEBUG 427: if (debug > 3) { 428: printf("\nInput "); 429: dump_pkt(dst, pkt, NULL); 430: } 431: #endif 432: if ((pkt->status & VERSIONMASK) != NTPVERSION_1) 433: continue; 434: 435: receive(dst, pkt, &tv, i); 436: } 437: if (ticked) { 438: ticked = 0; 439: timeout(); 440: } 441: } /* end of forever loop */ 442: } 443: 444: struct ntp_peer * 445: check_peer(dst, sock) 446: struct sockaddr_in *dst; 447: int sock; 448: { 449: register struct ntp_peer *peer = peer_list.head; 450: 451: while (peer != NULL) { 452: if ((peer->src.sin_addr.s_addr == dst->sin_addr.s_addr) && 453: (peer->src.sin_port == dst->sin_port) && 454: ((peer->sock == sock) || (peer->sock == -1))) 455: return peer; 456: peer = peer->next; 457: } 458: return ((struct ntp_peer *) NULL); 459: } 460: 461: #ifdef DEBUG 462: dump_pkt(dst, pkt, peer) 463: struct sockaddr_in *dst; 464: struct ntpdata *pkt; 465: struct ntp_peer *peer; 466: { 467: struct in_addr clock_host; 468: 469: printf("Packet: [%s](%d)\n", inet_ntoa(dst->sin_addr), 470: (int) htons(dst->sin_port)); 471: printf("Leap %d, version %d, mode %d, poll %d, precision %d stratum %d", 472: (pkt->status & LEAPMASK) >> 6, (pkt->status & VERSIONMASK) >> 3, 473: pkt->status & MODEMASK, pkt->ppoll, pkt->precision, 474: pkt->stratum); 475: switch (pkt->stratum) { 476: case 0: 477: case 1: 478: printf(" (%.4s)\n", (char *)&pkt->refid); 479: break; 480: default: 481: clock_host.s_addr = (u_long) pkt->refid; 482: printf(" [%s]\n", inet_ntoa(clock_host)); 483: break; 484: } 485: printf("Synch Dist is %04x.%04x Synch Dispersion is %04x.%04x\n", 486: ntohs((u_short) pkt->distance.int_part), 487: ntohs((u_short) pkt->distance.fraction), 488: ntohs((u_short) pkt->dispersion.int_part), 489: ntohs((u_short) pkt->dispersion.fraction)); 490: printf("Reference Timestamp is %08lx.%08lx\n", 491: ntohl(pkt->reftime.int_part), 492: ntohl(pkt->reftime.fraction)); 493: printf("Originate Timestamp is %08lx.%08lx\n", 494: ntohl(pkt->org.int_part), 495: ntohl(pkt->org.fraction)); 496: printf("Receive Timestamp is %08lx.%08lx\n", 497: ntohl(pkt->rec.int_part), 498: ntohl(pkt->rec.fraction)); 499: printf("Transmit Timestamp is %08lx.%08lx\n", 500: ntohl(pkt->xmt.int_part), 501: ntohl(pkt->xmt.fraction)); 502: if(peer != NULL) 503: printf("Input Timestamp is %08lx.%08lx\n", 504: ntohl(peer->rec.int_part), 505: ntohl(peer->rec.fraction)); 506: putchar('\n'); 507: } 508: #endif 509: 510: void 511: make_new_peer(peer) 512: struct ntp_peer *peer; 513: { 514: int i; 515: 516: /* 517: * initialize peer data fields 518: */ 519: peer->src.sin_family = AF_INET; 520: peer->src.sin_port = 0; 521: peer->src.sin_addr.s_addr = 0; 522: peer->hmode = MODE_SYM_PAS; /* default: symmetric passive mode */ 523: peer->flags = 0; 524: peer->timer = 1 << NTP_MINPOLL; 525: peer->stopwatch = 0; 526: peer->hpoll = NTP_MINPOLL; 527: double_to_s_fixed(&peer->dispersion, PEER_MAXDISP); 528: peer->reach = 0; 529: peer->estoffset = 0.0; 530: peer->estdelay = 0.0; 531: peer->org.int_part = peer->org.fraction = 0; 532: peer->rec.int_part = peer->rec.fraction = 0; 533: peer->filter.samples = 0; 534: for (i = 0; i < NTP_WINDOW; i++) { 535: peer->filter.offset[i] = 0.0; 536: peer->filter.delay[i] = 0.0; 537: } 538: peer->pkt_sent = 0; 539: peer->pkt_rcvd = 0; 540: peer->pkt_dropped = 0; 541: } 542: 543: /* 544: * This procedure is called to delete a peer from our list of peers. 545: */ 546: void 547: demobilize(l, peer) 548: struct list *l; 549: struct ntp_peer *peer; 550: { 551: extern struct ntp_peer dummy_peer; 552: 553: if (peer == &dummy_peer) 554: #ifdef DEBUG 555: abort(); 556: #else 557: return; 558: #endif 559: 560: #ifdef DEBUG 561: if ((peer->next == NULL && peer->prev == NULL) || 562: l->tail == NULL || l->head == NULL) 563: abort(); 564: #endif 565: 566: /* delete only peer in list? */ 567: if (l->head == l->tail) { 568: #ifdef DEBUG 569: if (l->head != peer) abort(); 570: #endif 571: l->head = l->tail = NULL; 572: goto dropit; 573: } 574: 575: /* delete first peer? */ 576: if (l->head == peer) { 577: l->head = peer->next; 578: l->head->prev = NULL; 579: goto dropit; 580: } 581: 582: /* delete last peer? */ 583: if (l->tail == peer) { 584: l->tail = peer->prev; 585: l->tail->next = NULL; 586: goto dropit; 587: } 588: 589: /* drop peer in middle */ 590: peer->prev->next = peer->next; 591: peer->next->prev = peer->prev; 592: 593: dropit: 594: #ifdef DEBUG 595: /* just some sanity checking */ 596: if ((l->members < 0) || 597: (l->members && l->tail == NULL) || 598: (l->members == 0 && l->tail != NULL)) { 599: syslog(LOG_ERR, "List hosed (demobilize)"); 600: abort(); 601: } 602: peer->next = peer->prev = NULL; 603: #endif 604: free((char *) peer); 605: l->members--; 606: 607: return; 608: } 609: 610: enqueue(l, peer) 611: register struct list *l; 612: struct ntp_peer *peer; 613: { 614: l->members++; 615: if (l->tail == NULL) { 616: /* insertion into empty list */ 617: l->tail = l->head = peer; 618: peer->next = peer->prev = NULL; 619: return; 620: } 621: 622: /* insert at end of list */ 623: l->tail->next = peer; 624: peer->next = NULL; 625: peer->prev = l->tail; 626: l->tail = peer; 627: } 628: 629: /* XXX */ 630: /* 631: * Trivial signal handler. Assumes you have Berkeley flavored signals which 632: * re-enable themselves. 633: */ 634: void 635: tock() { 636: ticked = 1; 637: } 638: 639: void 640: timeout() 641: { 642: static int periodic = 0; 643: register struct ntp_peer *peer = peer_list.head, *next; 644: #ifndef XADJTIME2 645: extern void adj_host_clock(); 646: 647: adj_host_clock(); 648: #endif 649: /* 650: * Count down sys.hold if necessary. 651: */ 652: if (sys.hold) { 653: if (sys.hold <= (1<<CLOCK_ADJ)) 654: sys.hold = 0; 655: else 656: sys.hold -= (1<<CLOCK_ADJ); 657: } 658: /* 659: * If interval has expired blast off an NTP to that host. 660: */ 661: while (peer != NULL) { 662: #ifdef DEBUG 663: if (peer->next == NULL && peer != peer_list.tail) { 664: printf("Broken peer list\n"); 665: syslog(LOG_ERR, "Broken peer list"); 666: abort(); 667: } 668: #endif 669: next = peer->next; 670: if (peer->reach != 0 || peer->hmode != MODE_SERVER) { 671: peer->stopwatch +=(1<<CLOCK_ADJ); 672: if (peer->timer <= peer->stopwatch) { 673: transmit(peer); 674: peer->stopwatch = 0; 675: } 676: } 677: peer = next; 678: } 679: 680: periodic += (1<<CLOCK_ADJ); 681: if (periodic >= 60*60) { 682: periodic = 0; 683: hourly(); 684: } 685: 686: clock_watchdog += (1 << CLOCK_ADJ); 687: if (clock_watchdog >= NTP_MAXAGE) { 688: /* woof, woof - barking dogs bite! */ 689: sys.leap = ALARM; 690: if (clock_watchdog < NTP_MAXAGE + (1 << CLOCK_ADJ)) { 691: syslog(LOG_ERR, 692: "logical clock adjust timeout (%d seconds)", 693: NTP_MAXAGE); 694: #ifdef DEBUG 695: if (debug) 696: printf("logical clock adjust timeout (%d seconds)\n", 697: NTP_MAXAGE); 698: #endif 699: } 700: } 701: 702: #ifdef DEBUG 703: if (debug) 704: (void) fflush(stdout); 705: #endif 706: } 707: 708: 709: /* 710: * init_ntp() reads NTP daemon configuration information from disk file. 711: */ 712: void 713: init_ntp(config) 714: char *config; 715: { 716: struct sockaddr_in sin; 717: char ref_clock[5]; 718: char name[81]; 719: FILE *fp; 720: int error = FALSE, c; 721: struct ntp_peer *peer; 722: int precision; 723: int stratum; 724: int i; 725: int debuglevel; 726: int stagger = 0; 727: double j; 728: extern double drift_comp; 729: 730: bzero((char *) &sin, sizeof(sin)); 731: fp = fopen(config, "r"); 732: if (fp == NULL) { 733: fprintf(stderr,"Problem opening NTP initialization file %s\n", 734: config); 735: syslog(LOG_ERR,"Problem opening NTP initialization file %s", 736: config); 737: exit(1); 738: } 739: 740: while (fscanf(fp, "%s", name) != EOF) { /* read first word of line 741: * and compare to key words */ 742: if (strcmp(name, "maxpeers") == 0) { 743: if (fscanf(fp, "%d", &sys.maxpeers) != 1) 744: error = TRUE; 745: } else if (strcmp(name, "trusting") == 0) { 746: if (fscanf(fp, "%s", name) != 1) 747: error = TRUE; 748: else { 749: if (*name == 'Y' || *name == 'y') { 750: trusting = 1; 751: } else if (*name == 'N' || *name == 'n') { 752: trusting = 0; 753: } else 754: trusting = atoi(name); 755: } 756: } else if (strcmp(name, "logclock") == 0) { 757: if (fscanf(fp, "%s", name) != 1) 758: error = TRUE; 759: else { 760: if (*name == 'Y' || *name == 'y') { 761: logstats = 1; 762: } else if (*name == 'N' || *name == 'n') { 763: logstats = 0; 764: } else 765: logstats = atoi(name); 766: } 767: } else if (strcmp(name, "driftfile") == 0) { 768: if (fscanf(fp, "%s", name) != 1) 769: error = TRUE; 770: else { 771: if (driftcomp_file = malloc(strlen(name)+1)) 772: strcpy(driftcomp_file, name); 773: } 774: } else if (strcmp(name, "waytoobig") == 0 || 775: strcmp(name, "setthreshold") == 0) { 776: if (fscanf(fp, "%s", name) != 1) 777: error = TRUE; 778: else { 779: if (strcmp(name, "any") == 0) 780: WayTooBig = 10e15; 781: else 782: WayTooBig = atof(name); 783: } 784: } else if (strncmp(name, "debuglevel", 5) == 0) { 785: if (fscanf(fp, "%d", &debuglevel) != 1) 786: error = TRUE; 787: #ifdef DEBUG 788: else debug += debuglevel; 789: #endif 790: } else if (strcmp(name, "stratum") == 0) { 791: fprintf(stderr, "Obsolete command 'stratum'\n"); 792: error = TRUE; 793: } else if (strcmp(name, "precision") == 0) { 794: if (fscanf(fp, "%d", &precision) != 1) 795: error = TRUE; 796: else sys.precision = (char) precision; 797: #ifdef NOSWAP 798: } else if (strcmp(name, "noswap") == 0) { 799: noswap = 1; 800: #endif 801: #ifdef BROADCAST_NTP 802: } else if (strcmp(name, "broadcast") == 0) { 803: if (fscanf(fp, "%s", name) != 1) { 804: error = TRUE; 805: goto skipit; 806: } 807: for (i = 0; i < nintf; i++) 808: if (strcmp(addrs[i].name, name) == 0) 809: break; 810: if (i == nintf) { 811: syslog(LOG_ERR, "config file: %s not a known interface"); 812: error = TRUE; 813: goto skipit; 814: } 815: if ((addrs[i].if_flags & IFF_BROADCAST) == 0) { 816: syslog(LOG_ERR, "config file: %s doesn't support broadcast", name); 817: error = TRUE; 818: goto skipit; 819: } 820: if (peer = check_peer(&addrs[i].bcast, -1)) { 821: syslog(LOG_ERR, "config file: duplicate broadcast for %s", 822: name); 823: error = TRUE; 824: goto skipit; 825: } 826: peer = (struct ntp_peer *) malloc(sizeof(struct ntp_peer)); 827: if (peer == NULL) { 828: error = TRUE; 829: syslog(LOG_ERR, "No memory"); 830: goto skipit; 831: } 832: make_new_peer(peer); 833: peer->flags = PEER_FL_BCAST; 834: peer->hmode = MODE_BROADCAST; 835: peer->src = addrs[i].bcast; 836: peer->sock = i; 837: #endif /* BROADCAST_NTP */ 838: } else if ((strcmp(name, "peer") == 0) || 839: (strcmp(name, "passive") == 0) || 840: (strcmp(name, "server") == 0)) { 841: int mode = 0; 842: 843: if (strcmp(name, "peer") == 0) { 844: mode = MODE_SYM_ACT; 845: } else if (strcmp(name, "server") == 0) { 846: mode = MODE_CLIENT; 847: } else if (strcmp(name, "passive") == 0) { 848: mode = MODE_SYM_PAS; 849: } else { 850: printf("can't happen\n"); 851: abort(); 852: } 853: if (fscanf(fp, "%s", name) != 1) 854: error = TRUE; 855: #ifdef REFCLOCK 856: else if (name[0] == '/') { 857: int stratum, precision; 858: char clk_type[20]; 859: 860: if (fscanf(fp, "%4s", ref_clock) != 1) { 861: error = TRUE; 862: syslog(LOG_ERR, "reference id missing"); 863: goto skipit; 864: } 865: if (fscanf(fp, "%4d", &stratum) != 1) { 866: error = TRUE; 867: syslog(LOG_ERR, "reference stratum missing"); 868: goto skipit; 869: } 870: if (fscanf(fp, "%4d", &precision) != 1) { 871: error = TRUE; 872: syslog(LOG_ERR, "reference precision missing"); 873: goto skipit; 874: } 875: if (fscanf(fp, "%19s", clk_type) != 1) { 876: error = TRUE; 877: syslog(LOG_ERR, "reference type missing"); 878: goto skipit; 879: } 880: 881: if((i = init_clock(name, clk_type)) < 0) { 882: /* If we could not initialize clock line */ 883: #ifdef DEBUG 884: if (debug) 885: printf("Could not init reference source %s (type %s)\n", 886: name, clk_type); 887: else 888: #endif DEBUG 889: syslog(LOG_ERR, "Could not init reference source %s (type %s)", 890: name, clk_type); 891: error = TRUE; 892: goto skipit; 893: } 894: peer = (struct ntp_peer *) 895: malloc(sizeof(struct ntp_peer)); 896: if (peer == NULL) { 897: close(i); 898: error = TRUE; 899: goto skipit; 900: } 901: make_new_peer(peer); 902: ref_clock[4] = 0; 903: (void) strncpy((char *) &peer->refid, 904: ref_clock, 4); 905: peer->flags = PEER_FL_CONFIG|PEER_FL_REFCLOCK; 906: peer->hmode = MODE_SYM_ACT; 907: peer->stopwatch = stagger; 908: stagger += (1<<CLOCK_ADJ); 909: peer->flags |= PEER_FL_SYNC; 910: peer->sock = i; 911: peer->stratum = stratum; 912: peer->precision = precision; 913: clear(peer); 914: enqueue(&peer_list, peer); 915: if (debug > 1) 916: printf("Peer %s mode %d refid %.4s stratum %d precision %d\n", 917: name, 918: peer->hmode, 919: (char *)&peer->refid, 920: stratum, precision); 921: transmit(peer); /* head start for REFCLOCK */ 922: } 923: #endif REFCLOCK 924: else if (GetHostName(name, &sin) == 0) 925: syslog(LOG_ERR, "%s: unknown host", name); 926: else { 927: for (i=0; i<nintf; i++) 928: if (addrs[i].sin.sin_addr.s_addr == 929: sin.sin_addr.s_addr) 930: goto skipit; 931: 932: if (servp) 933: sin.sin_port = servp->s_port; 934: else 935: sin.sin_port = htons(NTP_PORT); 936: 937: peer = check_peer(&sin, -1); 938: if (peer == NULL) { 939: peer = (struct ntp_peer *) 940: malloc(sizeof(struct ntp_peer)); 941: if (peer == NULL) 942: error = TRUE; 943: else { 944: make_new_peer(peer); 945: peer->flags = PEER_FL_CONFIG; 946: switch (mode) { 947: case MODE_SYM_ACT: /* "peer" */ 948: peer->hmode = MODE_SYM_ACT; 949: peer->stopwatch = stagger; 950: stagger += (1<<CLOCK_ADJ); 951: peer->flags |= PEER_FL_SYNC; 952: break; 953: case MODE_CLIENT: /* "server" */ 954: peer->hmode = MODE_CLIENT; 955: peer->stopwatch = stagger; 956: stagger += (1<<CLOCK_ADJ); 957: peer->flags |= PEER_FL_SYNC; 958: break; 959: case MODE_SYM_PAS: /* "passive" */ 960: peer->hmode = MODE_SYM_PAS; 961: peer->flags |= PEER_FL_SYNC; 962: break; 963: default: 964: printf("can't happen\n"); 965: abort(); 966: } 967: peer->src = sin; 968: peer->sock = -1; 969: clear(peer); 970: enqueue(&peer_list, peer); 971: #ifdef DEBUG 972: if (debug > 1) 973: printf("Peer %s/%d af %d mode %d\n", 974: inet_ntoa(peer->src.sin_addr), 975: ntohs(peer->src.sin_port), 976: peer->src.sin_family, 977: peer->hmode); 978: #endif 979: } 980: } else { 981: syslog(LOG_WARNING, 982: "Duplicate peer %s in in config file", 983: inet_ntoa(sin)); 984: #ifdef DEBUG 985: if(debug) 986: printf("Duplicate peer %s in in config file\n", 987: inet_ntoa(sin)); 988: #endif 989: } 990: } 991: skipit:; 992: } else if( *name != '#' ) { 993: syslog(LOG_ERR, "config file: %s not recognized", name); 994: #ifdef DEBUG 995: if(debug) 996: printf("unrecognized option in config file: %s\n", name); 997: #endif 998: } 999: do 1000: c = fgetc(fp); 1001: while (c != '\n' && c != EOF); /* next line */ 1002: } /* end while */ 1003: if (error) { 1004: fprintf(stderr, "init_ntp: %s: initialization error\n", config); 1005: syslog(LOG_ERR, "init_ntp: %s: initialization error", config); 1006: 1007: exit(1); 1008: } 1009: /* 1010: * Read saved drift compensation register value. 1011: */ 1012: if ((fp = fopen(driftcomp_file, "r")) != NULL) { 1013: if (fscanf(fp, "%lf", &j) == 1 && j > -1.0 && j < 1.0) { 1014: drift_comp = j; 1015: syslog(LOG_INFO, 1016: "Drift compensation value initialized to %f", j); 1017: } else { 1018: fprintf(stderr, 1019: "init_ntp: bad drift compensation value\n"); 1020: syslog(LOG_ERR, 1021: "init_ntp: bad drift compensation value\n"); 1022: } 1023: fclose(fp); 1024: } 1025: } 1026: 1027: int kern_hz; 1028: 1029: #include <sys/sysctl.h> 1030: 1031: void 1032: init_kern_vars() { 1033: int size, mib[2]; 1034: struct clockinfo cinfo; 1035: 1036: mib[0] = CTL_KERN; 1037: mib[1] = KERN_CLOCKRATE; 1038: size = sizeof (struct clockinfo); 1039: if (sysctl(mib, 2, &cinfo, &size, NULL, 0) < 0) 1040: { 1041: syslog(LOG_ERR, "sysctl() for kern.clockrate: %m\n"); 1042: return; 1043: } 1044: kern_hz = cinfo.hz; 1045: 1046: /* 1047: * If we have successfully discovered `hz' from the kernel, then we 1048: * can set sys.precision, if it has not already been specified. If 1049: * no value of `hz' is available, then use default (-6) 1050: */ 1051: if (sys.precision == 0) { 1052: if (kern_hz <= 64) 1053: sys.precision = -6; 1054: else if (kern_hz <= 128) 1055: sys.precision = -7; 1056: else if (kern_hz <= 256) 1057: sys.precision = -8; 1058: else if (kern_hz <= 512) 1059: sys.precision = -9; 1060: else if (kern_hz <= 1024) 1061: sys.precision = -10; 1062: else sys.precision = -11; 1063: syslog(LOG_INFO, "sys.precision set to %d from sys clock of %d HZ", 1064: sys.precision, kern_hz); 1065: } 1066: } 1067: 1068: 1069: /* 1070: * Given host or net name or internet address in dot notation assign the 1071: * internet address in byte format. source is ../routed/startup.c with minor 1072: * changes to detect syntax errors. 1073: * 1074: * We now try to interpret the name as in address before we go off and bother 1075: * the domain name servers. 1076: * 1077: * Unfortunately the library routine inet_addr() does not detect mal formed 1078: * addresses that have characters or byte values > 255. 1079: */ 1080: 1081: GetHostName(name, sin) 1082: char *name; 1083: struct sockaddr_in *sin; 1084: { 1085: long HostAddr; 1086: struct hostent *hp; 1087: 1088: if ((HostAddr = inet_addr(name)) != -1) { 1089: sin->sin_addr.s_addr = (u_long) HostAddr; 1090: sin->sin_family = AF_INET; 1091: return (1); 1092: } 1093: 1094: if (hp = gethostbyname(name)) { 1095: if (hp->h_addrtype != AF_INET) 1096: return (0); 1097: bcopy((char *) hp->h_addr, (char *) &sin->sin_addr, 1098: hp->h_length); 1099: sin->sin_family = hp->h_addrtype; 1100: return (1); 1101: } 1102: return (0); 1103: } 1104: 1105: #define PKTBUF_SIZE 536 1106: 1107: /* number of clocks per packet */ 1108: #define N_NTP_PKTS \ 1109: ((PKTBUF_SIZE - sizeof(struct ntpinfo))/(sizeof(struct xclockinfo))) 1110: 1111: query_mode(dst, ntp, sock) 1112: struct sockaddr_in *dst; 1113: struct ntpdata *ntp; 1114: int sock; /* which socket packet arrived on */ 1115: { 1116: char packet[PKTBUF_SIZE]; 1117: register struct ntpinfo *nip = (struct ntpinfo *) packet; 1118: register struct ntp_peer *peer = peer_list.head; 1119: struct xclockinfo *cip; 1120: int seq = 0; 1121: int i; 1122: 1123: if (ntp->stratum != INFO_QUERY) 1124: return; 1125: nip->version = NTPDC_VERSION; 1126: nip->type = INFO_REPLY; 1127: nip->seq = 0; 1128: nip->npkts = peer_list.members/N_NTP_PKTS; 1129: if (peer_list.members % N_NTP_PKTS) 1130: nip->npkts++; 1131: nip->peers = peer_list.members; 1132: nip->count = 0; 1133: cip = (struct xclockinfo *)&nip[1]; 1134: 1135: while (peer != NULL) { 1136: cip->net_address = peer->src.sin_addr.s_addr; 1137: if (peer->sock < 0) 1138: cip->my_address = htonl(0); 1139: else 1140: cip->my_address = addrs[peer->sock].sin.sin_addr.s_addr; 1141: cip->port = peer->src.sin_port; /* already in network order */ 1142: cip->flags = htons(peer->flags); 1143: if (sys.peer == peer) 1144: cip->flags |= htons(PEER_FL_SELECTED); 1145: cip->pkt_sent = htonl(peer->pkt_sent); 1146: cip->pkt_rcvd = htonl(peer->pkt_rcvd); 1147: cip->pkt_dropped = htonl(peer->pkt_dropped); 1148: cip->timer = htonl(peer->timer); 1149: cip->leap = peer->leap; 1150: cip->stratum = peer->stratum; 1151: cip->ppoll = peer->ppoll; 1152: cip->precision = (int) peer->precision; 1153: cip->hpoll = peer->hpoll; 1154: cip->reach = htons((u_short)peer->reach & NTP_WINDOW_SHIFT_MASK); 1155: cip->estdisp = htonl((long) (peer->estdisp * 1000.0)); 1156: cip->estdelay = htonl((long) (peer->estdelay * 1000.0)); 1157: cip->estoffset = htonl((long) (peer->estoffset * 1000.0)); 1158: cip->refid = peer->refid; 1159: cip->reftime.int_part = htonl(peer->reftime.int_part); 1160: cip->reftime.fraction = htonl(peer->reftime.fraction); 1161: 1162: cip->info_filter.index = htons(peer->filter.samples); 1163: for (i = 0; i < PEER_SHIFT; i++) { 1164: cip->info_filter.offset[i] = 1165: htonl((long)(peer->filter.offset[i] * 1000.0)); 1166: cip->info_filter.delay[i] = 1167: htonl((long)(peer->filter.delay[i] * 1000.0)); 1168: } 1169: cip++; 1170: if (nip->count++ >= N_NTP_PKTS - 1) { 1171: nip->seq =seq++; 1172: if ((sendto(addrs[sock].fd, (char *) packet, 1173: sizeof(packet), 0, 1174: (struct sockaddr *) dst, 1175: sizeof(struct sockaddr_in))) < 0) { 1176: syslog(LOG_ERR, "sendto: %s %m", 1177: inet_ntoa(dst->sin_addr)); 1178: } 1179: nip->type = INFO_REPLY; 1180: nip->count = 0; 1181: cip = (struct xclockinfo *)&nip[1]; 1182: } 1183: peer = peer->next; 1184: } 1185: if (nip->count) { 1186: nip->seq = seq; 1187: if ((sendto(addrs[sock].fd, (char *) packet, sizeof(packet), 0, 1188: dst, sizeof(struct sockaddr_in))) < 0) { 1189: syslog(LOG_ERR, "sendto: %s %m", ntoa(dst->sin_addr)); 1190: } 1191: } 1192: } 1193: 1194: /* every hour, dump some useful information to the log */ 1195: void 1196: hourly() { 1197: char buf[200]; 1198: register int p = 0; 1199: static double drifts[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 }; 1200: static int drift_count = 0; 1201: extern double drift_comp, compliance; 1202: extern int peer_switches, peer_sw_inhibited; 1203: 1204: (void) sprintf(buf, "stats: dc %f comp %f peersw %d inh %d", 1205: drift_comp, compliance, peer_switches, 1206: peer_sw_inhibited); 1207: 1208: if (sys.peer == NULL) { 1209: strcat(buf, " UNSYNC"); 1210: #ifdef REFCLOCK 1211: } else if (sys.peer->flags & PEER_FL_REFCLOCK) { 1212: p = strlen(buf); 1213: (void) sprintf(buf + p, " off %f SYNC %.4s %d", 1214: sys.peer->estoffset, 1215: (char *)&sys.peer->refid, 1216: sys.peer->stratum); 1217: #endif 1218: } else { 1219: p = strlen(buf); 1220: (void) sprintf(buf + p, " off %f SYNC %s %d", 1221: sys.peer->estoffset, 1222: ntoa(sys.peer->src.sin_addr), 1223: sys.peer->stratum); 1224: } 1225: syslog(LOG_INFO, buf); 1226: #ifdef DEBUG 1227: if (debug) 1228: puts(buf); 1229: #endif 1230: /* 1231: * If the drift compensation snapshot file is open, then write 1232: * the current value to it. Since there's only one block in the 1233: * file, and no one else is reading it, we'll just keep the file 1234: * open and write to it. 1235: */ 1236: if (drift_fd >= 0) { 1237: drifts[drift_count % 5] = drift_comp; 1238: /* works out to be 70 bytes */ 1239: (void) sprintf(buf, 1240: "%12.10f %12.10f %12.10f %12.10f %12.10f %4d\n", 1241: drifts[drift_count % 5], 1242: drifts[(drift_count+4) % 5], 1243: drifts[(drift_count+3) % 5], 1244: drifts[(drift_count+2) % 5], 1245: drifts[(drift_count+1) % 5], 1246: drift_count + 1); 1247: 1248: (void) lseek(drift_fd, 0L, L_SET); 1249: if (write(drift_fd, buf, strlen(buf)) < 0) { 1250: syslog(LOG_ERR, "Error writing drift comp file: %m"); 1251: } 1252: drift_count++; 1253: } 1254: } 1255: 1256: #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2) 1257: void 1258: incdebug() 1259: { 1260: if (debug == 255) 1261: return; 1262: debug++; 1263: printf("DEBUG LEVEL %d\n", debug); 1264: #ifdef LOG_DAEMON 1265: (void) setlogmask(LOG_UPTO(LOG_DEBUG)); 1266: #endif 1267: syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug); 1268: } 1269: 1270: void 1271: decdebug() 1272: { 1273: if (debug == 0) 1274: return; 1275: debug--; 1276: printf("DEBUG LEVEL %d\n", debug); 1277: syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug); 1278: #ifdef LOG_DAEMON 1279: if (debug == 0) 1280: (void) setlogmask(LOG_UPTO(LOG_INFO)); 1281: #endif 1282: } 1283: #endif 1284: 1285: void 1286: finish(sig) 1287: int sig; 1288: { 1289: syslog(LOG_NOTICE, "terminated: (sig %d)", sig); 1290: #ifdef DEBUG 1291: if (debug) 1292: printf("ntpd terminated (sig %d)\n", sig); 1293: #endif 1294: exit(1); 1295: } 1296: 1297: #ifdef REFCLOCK 1298: struct refclock { 1299: int fd; 1300: int (*reader)(); 1301: struct refclock *next; 1302: } *refclocks = NULL; 1303: 1304: int init_clock_local(), read_clock_local(); 1305: #ifdef PSTI 1306: int init_clock_psti(), read_clock_psti(); 1307: #endif PSTI 1308: 1309: init_clock(name, type) 1310: char *name, *type; 1311: { 1312: struct refclock *r; 1313: int (*reader)(); 1314: int cfd; 1315: 1316: if (strcmp(type, "local") == 0) { 1317: reader = read_clock_local; 1318: cfd = init_clock_local(name); 1319: } 1320: #ifdef PSTI 1321: else if (strcmp(type, "psti") == 0) { 1322: reader = read_clock_psti; 1323: cfd = init_clock_psti(name); 1324: } 1325: #endif PSTI 1326: else { 1327: if (debug) printf("Unknown reference type\n"); else 1328: syslog(LOG_ERR, "Unknown reference clock type (%s)\n", type); 1329: return(-1); 1330: } 1331: if (cfd >= 0) { 1332: r = (struct refclock *)malloc(sizeof(struct refclock)); 1333: r->fd = cfd; 1334: r->reader = reader; 1335: r->next = refclocks; 1336: refclocks = r; 1337: } 1338: return(cfd); 1339: } 1340: 1341: read_clock(cfd, tvpp, otvpp) 1342: int cfd; 1343: struct timeval **tvpp, **otvpp; 1344: { 1345: struct refclock *r; 1346: 1347: for (r = refclocks; r; r = r->next) 1348: if(r->fd == cfd) 1349: return((r->reader)(cfd, tvpp, otvpp)); 1350: return(1); /* Can't happen */ 1351: } 1352: #endif