1 /* 2 * ntp_config.c - read and apply configuration information 3 */ 4 #ifdef HAVE_CONFIG_H 5 # include <config.h> 6 #endif 7 8 #ifdef HAVE_NETINFO 9 # include <netinfo/ni.h> 10 #endif 11 12 #include "ntpd.h" 13 #include "ntp_io.h" 14 #include "ntp_unixtime.h" 15 #include "ntp_refclock.h" 16 #include "ntp_filegen.h" 17 #include "ntp_stdlib.h" 18 #include "ntp_config.h" 19 #include "ntp_cmdargs.h" 20 21 #ifdef PUBKEY 22 # include "ntp_crypto.h" 23 #endif /* PUBKEY */ 24 25 #include <stdio.h> 26 #include <ctype.h> 27 #include <sys/param.h> 28 #include <signal.h> 29 #ifndef SIGCHLD 30 # define SIGCHLD SIGCLD 31 #endif 32 #if !defined(VMS) 33 # ifdef HAVE_SYS_WAIT_H 34 # include <sys/wait.h> 35 # endif 36 #endif /* VMS */ 37 38 #ifdef SYS_WINNT 39 # include <io.h> 40 extern HANDLE ResolverThreadHandle; 41 #endif /* SYS_WINNT */ 42 43 extern int priority_done; 44 45 /* 46 * These routines are used to read the configuration file at 47 * startup time. An entry in the file must fit on a single line. 48 * Entries are processed as multiple tokens separated by white space 49 * Lines are considered terminated when a '#' is encountered. Blank 50 * lines are ignored. 51 */ 52 53 /* 54 * We understand the following configuration entries and defaults. 55 * 56 * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ] 57 * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ] 58 * broadcast [ addr ] [ version 3 ] [ key 0 ] [ ttl 1 ] 59 * broadcastclient 60 * multicastclient [ 224.0.1.1 ] 61 * manycastclient [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ] 62 * manycastserver [ 224.0.1.1 ] 63 * broadcastdelay 0.0102 64 * restrict [ addr ] [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery 65 * driftfile file_name 66 * keys file_name 67 * publickey file_name 68 * privatekey file_name 69 * statsdir /var/NTP/ 70 * filegen peerstats [ file peerstats ] [ type day ] [ link ] 71 * clientlimit [ n ] 72 * clientperiod [ 3600 ] 73 * trustedkey [ key ] 74 * requestkey [ key] 75 * controlkey [ key ] 76 * trap [ addr ] 77 * fudge [ addr ] [ stratum ] [ refid ] ... 78 * pidfile [ ] 79 * setvar [ ] 80 * logfile logfile 81 * logconfig [+|-|=][{sync|sys|peer|clock}{{,all}{info|statistics|events|status}}]... 82 * enable auth|bclient|pll|kernel|monitor|stats 83 * disable auth|bclient|pll|kernel|monitor|stats 84 * phone ... 85 * pps device [assert|clear] [hardpps] 86 * priority high|normal 87 */ 88 89 /* 90 * Translation table - keywords to function index 91 */ 92 struct keyword { 93 const char *text; 94 int keytype; 95 }; 96 97 /* 98 * Command keywords 99 */ 100 static struct keyword keywords[] = { 101 { "authenticate", CONFIG_AUTHENTICATE }, 102 { "automax", CONFIG_AUTOMAX }, 103 { "broadcast", CONFIG_BROADCAST }, 104 { "broadcastclient", CONFIG_BROADCASTCLIENT }, 105 { "broadcastdelay", CONFIG_BDELAY }, 106 { "clientlimit", CONFIG_CLIENTLIMIT }, 107 { "clientperiod", CONFIG_CLIENTPERIOD }, 108 #ifdef PUBKEY 109 { "crypto", CONFIG_CRYPTO }, 110 #endif /* PUBKEY */ 111 { "controlkey", CONFIG_CONTROLKEY }, 112 { "disable", CONFIG_DISABLE }, 113 { "driftfile", CONFIG_DRIFTFILE }, 114 { "enable", CONFIG_ENABLE }, 115 { "filegen", CONFIG_FILEGEN }, 116 { "fudge", CONFIG_FUDGE }, 117 { "includefile", CONFIG_INCLUDEFILE }, 118 { "keys", CONFIG_KEYS }, 119 #ifdef PUBKEY 120 { "keysdir", CONFIG_KEYSDIR }, 121 #endif /* PUBKEY */ 122 { "logconfig", CONFIG_LOGCONFIG }, 123 { "logfile", CONFIG_LOGFILE }, 124 { "manycastclient", CONFIG_MANYCASTCLIENT }, 125 { "manycastserver", CONFIG_MANYCASTSERVER }, 126 { "multicastclient", CONFIG_MULTICASTCLIENT }, 127 { "peer", CONFIG_PEER }, 128 { "phone", CONFIG_PHONE }, 129 { "pidfile", CONFIG_PIDFILE }, 130 { "pps", CONFIG_PPS }, 131 { "requestkey", CONFIG_REQUESTKEY }, 132 { "restrict", CONFIG_RESTRICT }, 133 { "revoke", CONFIG_REVOKE }, 134 { "server", CONFIG_SERVER }, 135 { "setvar", CONFIG_SETVAR }, 136 { "statistics", CONFIG_STATISTICS }, 137 { "statsdir", CONFIG_STATSDIR }, 138 { "tinker", CONFIG_TINKER }, 139 { "trap", CONFIG_TRAP }, 140 { "trustedkey", CONFIG_TRUSTEDKEY }, 141 { "", CONFIG_UNKNOWN } 142 }; 143 144 /* 145 * "peer", "server", "broadcast" modifier keywords 146 */ 147 static struct keyword mod_keywords[] = { 148 { "autokey", CONF_MOD_SKEY }, 149 { "burst", CONF_MOD_BURST }, 150 { "iburst", CONF_MOD_IBURST }, 151 { "key", CONF_MOD_KEY }, 152 { "maxpoll", CONF_MOD_MAXPOLL }, 153 { "minpoll", CONF_MOD_MINPOLL }, 154 { "mode", CONF_MOD_MODE }, /* refclocks */ 155 { "noselect", CONF_MOD_NOSELECT }, 156 { "prefer", CONF_MOD_PREFER }, 157 #ifdef PUBKEY 158 { "publickey", CONF_MOD_PUBLICKEY }, 159 #endif /* PUBKEY */ 160 { "ttl", CONF_MOD_TTL }, /* NTP peers */ 161 { "version", CONF_MOD_VERSION }, 162 { "", CONFIG_UNKNOWN } 163 }; 164 165 /* 166 * "restrict" modifier keywords 167 */ 168 static struct keyword res_keywords[] = { 169 { "ignore", CONF_RES_IGNORE }, 170 { "limited", CONF_RES_LIMITED }, 171 { "kod", CONF_RES_DEMOBILIZE }, 172 { "lowpriotrap", CONF_RES_LPTRAP }, 173 { "mask", CONF_RES_MASK }, 174 { "nomodify", CONF_RES_NOMODIFY }, 175 { "nopeer", CONF_RES_NOPEER }, 176 { "noquery", CONF_RES_NOQUERY }, 177 { "noserve", CONF_RES_NOSERVE }, 178 { "notrap", CONF_RES_NOTRAP }, 179 { "notrust", CONF_RES_NOTRUST }, 180 { "ntpport", CONF_RES_NTPPORT }, 181 { "version", CONF_RES_VERSION }, 182 { "", CONFIG_UNKNOWN } 183 }; 184 185 /* 186 * "trap" modifier keywords 187 */ 188 static struct keyword trap_keywords[] = { 189 { "port", CONF_TRAP_PORT }, 190 { "interface", CONF_TRAP_INTERFACE }, 191 { "", CONFIG_UNKNOWN } 192 }; 193 194 /* 195 * "fudge" modifier keywords 196 */ 197 static struct keyword fudge_keywords[] = { 198 { "flag1", CONF_FDG_FLAG1 }, 199 { "flag2", CONF_FDG_FLAG2 }, 200 { "flag3", CONF_FDG_FLAG3 }, 201 { "flag4", CONF_FDG_FLAG4 }, 202 { "refid", CONF_FDG_REFID }, 203 { "stratum", CONF_FDG_STRATUM }, 204 { "time1", CONF_FDG_TIME1 }, 205 { "time2", CONF_FDG_TIME2 }, 206 { "", CONFIG_UNKNOWN } 207 }; 208 209 210 /* 211 * "filegen" modifier keywords 212 */ 213 static struct keyword filegen_keywords[] = { 214 { "disable", CONF_FGEN_FLAG_DISABLE }, 215 { "enable", CONF_FGEN_FLAG_ENABLE }, 216 { "file", CONF_FGEN_FILE }, 217 { "link", CONF_FGEN_FLAG_LINK }, 218 { "nolink", CONF_FGEN_FLAG_NOLINK }, 219 { "type", CONF_FGEN_TYPE }, 220 { "", CONFIG_UNKNOWN } 221 }; 222 223 /* 224 * "type" modifier keywords 225 */ 226 static struct keyword fgen_types[] = { 227 { "age", FILEGEN_AGE }, 228 { "day", FILEGEN_DAY }, 229 { "month", FILEGEN_MONTH }, 230 { "none", FILEGEN_NONE }, 231 { "pid", FILEGEN_PID }, 232 { "week", FILEGEN_WEEK }, 233 { "year", FILEGEN_YEAR }, 234 { "", CONFIG_UNKNOWN} 235 }; 236 237 /* 238 * "enable", "disable" modifier keywords 239 */ 240 static struct keyword flags_keywords[] = { 241 { "auth", PROTO_AUTHENTICATE }, 242 { "bclient", PROTO_BROADCLIENT }, 243 { "kernel", PROTO_KERNEL }, 244 { "monitor", PROTO_MONITOR }, 245 { "ntp", PROTO_NTP }, 246 { "stats", PROTO_FILEGEN }, 247 { "pps", PROTO_PPS }, 248 { "calibrate", PROTO_CAL }, 249 { "", CONFIG_UNKNOWN } 250 }; 251 252 /* 253 * "pps" modifier keywords 254 */ 255 static struct keyword pps_keywords[] = { 256 { "assert", CONF_PPS_ASSERT }, 257 { "clear", CONF_PPS_CLEAR }, 258 { "hardpps", CONF_PPS_HARDPPS }, 259 { "", CONFIG_UNKNOWN } 260 }; 261 262 /* 263 * "tinker" modifier keywords 264 */ 265 static struct keyword tinker_keywords[] = { 266 { "step", CONF_CLOCK_MAX }, 267 { "panic", CONF_CLOCK_PANIC }, 268 { "dispersion", CONF_CLOCK_PHI }, 269 { "stepout", CONF_CLOCK_MINSTEP }, 270 { "minpoll", CONF_CLOCK_MINPOLL }, 271 { "allan", CONF_CLOCK_ALLAN }, 272 { "huffpuff", CONF_CLOCK_HUFFPUFF }, 273 { "", CONFIG_UNKNOWN } 274 }; 275 276 #ifdef PUBKEY 277 /* 278 * "crypto" modifier keywords 279 */ 280 static struct keyword crypto_keywords[] = { 281 { "dh", CONF_CRYPTO_DH }, 282 { "flags", CONF_CRYPTO_FLAGS }, 283 { "leap", CONF_CRYPTO_LEAP }, 284 { "privatekey", CONF_CRYPTO_PRIVATEKEY }, 285 { "publickey", CONF_CRYPTO_PUBLICKEY }, 286 { "", CONFIG_UNKNOWN } 287 }; 288 #endif /* PUBKEY */ 289 290 /* 291 * "logconfig" building blocks 292 */ 293 struct masks { 294 const char *name; 295 unsigned long mask; 296 }; 297 298 static struct masks logcfg_class[] = { 299 { "clock", NLOG_OCLOCK }, 300 { "peer", NLOG_OPEER }, 301 { "sync", NLOG_OSYNC }, 302 { "sys", NLOG_OSYS }, 303 { (char *)0, 0 } 304 }; 305 306 static struct masks logcfg_item[] = { 307 { "info", NLOG_INFO }, 308 { "allinfo", NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO }, 309 { "events", NLOG_EVENT }, 310 { "allevents", NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT }, 311 { "status", NLOG_STATUS }, 312 { "allstatus", NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS }, 313 { "statistics", NLOG_STATIST }, 314 { "allstatistics", NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST }, 315 { "allclock", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK }, 316 { "allpeer", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER }, 317 { "allsys", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS }, 318 { "allsync", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC }, 319 { "all", NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK }, 320 { (char *)0, 0 } 321 }; 322 323 /* 324 * Limits on things 325 */ 326 #define MAXTOKENS 20 /* 20 tokens on line */ 327 #define MAXLINE 1024 /* maximum length of line */ 328 #define MAXPHONE 5 /* maximum number of phone strings */ 329 #define MAXPPS 20 /* maximum length of PPS device string */ 330 #define MAXINCLUDELEVEL 5 /* maximum include file levels */ 331 332 /* 333 * Miscellaneous macros 334 */ 335 #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0) 336 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0') 337 #define ISSPACE(c) ((c) == ' ' || (c) == '\t') 338 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 339 340 #define KEY_TYPE_MD5 4 341 342 /* 343 * File descriptor used by the resolver save routines, and temporary file 344 * name. 345 */ 346 static FILE *res_fp; 347 #ifndef SYS_WINNT 348 static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */ 349 #define RES_TEMPFILE "/tmp/ntpXXXXXX" 350 #else 351 static char res_file[MAX_PATH]; 352 #endif /* SYS_WINNT */ 353 354 /* 355 * Definitions of things either imported from or exported to outside 356 */ 357 char const *progname; 358 char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */ 359 char pps_device[MAXPPS + 1]; /* PPS device name */ 360 int pps_assert; 361 int pps_hardpps; 362 #if defined(HAVE_SCHED_SETSCHEDULER) 363 int config_priority_override = 0; 364 int config_priority; 365 #endif 366 367 const char *config_file; 368 #ifdef HAVE_NETINFO 369 struct netinfo_config_state *config_netinfo = NULL; 370 int check_netinfo = 1; 371 #endif /* HAVE_NETINFO */ 372 #ifdef SYS_WINNT 373 char *alt_config_file; 374 LPTSTR temp; 375 char config_file_storage[MAX_PATH]; 376 char alt_config_file_storage[MAX_PATH]; 377 #endif /* SYS_WINNT */ 378 379 #ifdef HAVE_NETINFO 380 /* 381 * NetInfo configuration state 382 */ 383 struct netinfo_config_state { 384 void *domain; /* domain with config */ 385 ni_id config_dir; /* ID config dir */ 386 int prop_index; /* current property */ 387 int val_index; /* current value */ 388 char **val_list; /* value list */ 389 }; 390 #endif 391 392 /* 393 * Function prototypes 394 */ 395 static unsigned long get_pfxmatch P((char **, struct masks *)); 396 static unsigned long get_match P((char *, struct masks *)); 397 static unsigned long get_logmask P((char *)); 398 #ifdef HAVE_NETINFO 399 static struct netinfo_config_state *get_netinfo_config P((void)); 400 static void free_netinfo_config P((struct netinfo_config_state *)); 401 static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *)); 402 #endif 403 static int gettokens P((FILE *, char *, char **, int *)); 404 static int matchkey P((char *, struct keyword *)); 405 static int getnetnum P((const char *, struct sockaddr_in *, int)); 406 static void save_resolve P((char *, int, int, int, int, u_int, int, 407 keyid_t, u_char *)); 408 static void do_resolve_internal P((void)); 409 static void abort_resolve P((void)); 410 #if !defined(VMS) 411 static RETSIGTYPE catchchild P((int)); 412 #endif /* VMS */ 413 414 /* 415 * get_pfxmatch - find value for prefixmatch 416 * and update char * accordingly 417 */ 418 static unsigned long 419 get_pfxmatch( 420 char ** s, 421 struct masks *m 422 ) 423 { 424 while (m->name) { 425 if (strncmp(*s, m->name, strlen(m->name)) == 0) { 426 *s += strlen(m->name); 427 return m->mask; 428 } else { 429 m++; 430 } 431 } 432 return 0; 433 } 434 435 /* 436 * get_match - find logmask value 437 */ 438 static unsigned long 439 get_match( 440 char *s, 441 struct masks *m 442 ) 443 { 444 while (m->name) { 445 if (strcmp(s, m->name) == 0) { 446 return m->mask; 447 } else { 448 m++; 449 } 450 } 451 return 0; 452 } 453 454 /* 455 * get_logmask - build bitmask for ntp_syslogmask 456 */ 457 static unsigned long 458 get_logmask( 459 char *s 460 ) 461 { 462 char *t; 463 unsigned long offset; 464 unsigned long mask; 465 466 t = s; 467 offset = get_pfxmatch(&t, logcfg_class); 468 mask = get_match(t, logcfg_item); 469 470 if (mask) 471 return mask << offset; 472 else 473 msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s); 474 475 return 0; 476 } 477 478 479 /* 480 * getconfig - get command line options and read the configuration file 481 */ 482 void 483 getconfig( 484 int argc, 485 char *argv[] 486 ) 487 { 488 register int i; 489 int c; 490 int errflg; 491 int peerversion; 492 int minpoll; 493 int maxpoll; 494 int ttl; 495 long stratum; 496 unsigned long ul; 497 keyid_t peerkey; 498 u_char *peerkeystr; 499 u_long fudgeflag; 500 u_int peerflags; 501 int hmode; 502 struct sockaddr_in peeraddr; 503 struct sockaddr_in maskaddr; 504 FILE *fp[MAXINCLUDELEVEL+1]; 505 FILE *includefile; 506 int includelevel = 0; 507 char line[MAXLINE]; 508 char *(tokens[MAXTOKENS]); 509 int ntokens; 510 int tok = CONFIG_UNKNOWN; 511 struct interface *localaddr; 512 struct refclockstat clock_stat; 513 FILEGEN *filegen; 514 515 /* 516 * Initialize, initialize 517 */ 518 errflg = 0; 519 /* HMS: don't initialize debug to 0 here! */ 520 #ifndef SYS_WINNT 521 config_file = CONFIG_FILE; 522 #else 523 temp = CONFIG_FILE; 524 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) { 525 msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n"); 526 exit(1); 527 } 528 config_file = config_file_storage; 529 530 temp = ALT_CONFIG_FILE; 531 if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) { 532 msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n"); 533 exit(1); 534 } 535 alt_config_file = alt_config_file_storage; 536 537 #endif /* SYS_WINNT */ 538 progname = argv[0]; 539 res_fp = NULL; 540 memset((char *)sys_phone, 0, sizeof(sys_phone)); 541 ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */ 542 543 /* 544 * install a non default variable with this daemon version 545 */ 546 (void) sprintf(line, "daemon_version=\"%s\"", Version); 547 set_sys_var(line, strlen(line)+1, RO); 548 549 /* 550 * Say how we're setting the time of day 551 */ 552 (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using); 553 set_sys_var(line, strlen(line)+1, RO); 554 555 /* 556 * Initialize the loop. 557 */ 558 loop_config(LOOP_DRIFTINIT, 0.); 559 560 getCmdOpts(argc, argv); 561 562 if ( 563 (fp[0] = fopen(FindConfig(config_file), "r")) == NULL 564 #ifdef HAVE_NETINFO 565 /* If there is no config_file, try NetInfo. */ 566 && check_netinfo && !(config_netinfo = get_netinfo_config()) 567 #endif /* HAVE_NETINFO */ 568 ) { 569 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file)); 570 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file)); 571 #ifdef SYS_WINNT 572 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */ 573 574 if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) { 575 576 /* 577 * Broadcast clients can sometimes run without 578 * a configuration file. 579 */ 580 581 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file)); 582 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file)); 583 return; 584 } 585 #else /* not SYS_WINNT */ 586 return; 587 #endif /* not SYS_WINNT */ 588 } 589 590 for (;;) { 591 if (fp[includelevel]) 592 tok = gettokens(fp[includelevel], line, tokens, &ntokens); 593 #ifdef HAVE_NETINFO 594 else 595 tok = gettokens_netinfo(config_netinfo, tokens, &ntokens); 596 #endif /* HAVE_NETINFO */ 597 598 if (tok == CONFIG_UNKNOWN) { 599 if (includelevel > 0) { 600 fclose(fp[includelevel--]); 601 continue; 602 } else { 603 break; 604 } 605 } 606 607 switch(tok) { 608 case CONFIG_PEER: 609 case CONFIG_SERVER: 610 case CONFIG_MANYCASTCLIENT: 611 case CONFIG_BROADCAST: 612 if (tok == CONFIG_PEER) 613 hmode = MODE_ACTIVE; 614 else if (tok == CONFIG_SERVER) 615 hmode = MODE_CLIENT; 616 else if (tok == CONFIG_MANYCASTCLIENT) 617 hmode = MODE_CLIENT; 618 else 619 hmode = MODE_BROADCAST; 620 621 if (ntokens < 2) { 622 msyslog(LOG_ERR, 623 "No address for %s, line ignored", 624 tokens[0]); 625 break; 626 } 627 628 if (!getnetnum(tokens[1], &peeraddr, 0)) { 629 errflg = -1; 630 } else { 631 errflg = 0; 632 633 if ( 634 #ifdef REFCLOCK 635 !ISREFCLOCKADR(&peeraddr) && 636 #endif 637 ISBADADR(&peeraddr)) { 638 msyslog(LOG_ERR, 639 "attempt to configure invalid address %s", 640 ntoa(&peeraddr)); 641 break; 642 } 643 /* 644 * Shouldn't be able to specify multicast 645 * address for server/peer! 646 * and unicast address for manycastclient! 647 */ 648 if (((tok == CONFIG_SERVER) || 649 (tok == CONFIG_PEER)) && 650 #ifdef REFCLOCK 651 !ISREFCLOCKADR(&peeraddr) && 652 #endif 653 IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))) { 654 msyslog(LOG_ERR, 655 "attempt to configure invalid address %s", 656 ntoa(&peeraddr)); 657 break; 658 } 659 if ((tok == CONFIG_MANYCASTCLIENT) && 660 !IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))) { 661 msyslog(LOG_ERR, 662 "attempt to configure invalid address %s", 663 ntoa(&peeraddr)); 664 break; 665 } 666 } 667 668 peerversion = NTP_VERSION; 669 minpoll = NTP_MINDPOLL; 670 maxpoll = NTP_MAXDPOLL; 671 peerkey = 0; 672 peerkeystr = "*"; 673 peerflags = 0; 674 ttl = 0; 675 for (i = 2; i < ntokens; i++) 676 switch (matchkey(tokens[i], mod_keywords)) { 677 case CONF_MOD_VERSION: 678 if (i >= ntokens-1) { 679 msyslog(LOG_ERR, 680 "peer/server version requires an argument"); 681 errflg = 1; 682 break; 683 } 684 peerversion = atoi(tokens[++i]); 685 if ((u_char)peerversion > NTP_VERSION 686 || (u_char)peerversion < NTP_OLDVERSION) { 687 msyslog(LOG_ERR, 688 "inappropriate version number %s, line ignored", 689 tokens[i]); 690 errflg = 1; 691 } 692 break; 693 694 case CONF_MOD_KEY: 695 if (i >= ntokens-1) { 696 msyslog(LOG_ERR, 697 "key: argument required"); 698 errflg = 1; 699 break; 700 } 701 peerkey = (int)atol(tokens[++i]); 702 peerflags |= FLAG_AUTHENABLE; 703 break; 704 705 case CONF_MOD_MINPOLL: 706 if (i >= ntokens-1) { 707 msyslog(LOG_ERR, 708 "minpoll: argument required"); 709 errflg = 1; 710 break; 711 } 712 minpoll = atoi(tokens[++i]); 713 if (minpoll < NTP_MINPOLL) { 714 msyslog(LOG_INFO, 715 "minpoll: provided value (%d) is below minimum (%d)", 716 minpoll, NTP_MINPOLL); 717 minpoll = NTP_MINPOLL; 718 } 719 break; 720 721 case CONF_MOD_MAXPOLL: 722 if (i >= ntokens-1) { 723 msyslog(LOG_ERR, 724 "maxpoll: argument required" 725 ); 726 errflg = 1; 727 break; 728 } 729 maxpoll = atoi(tokens[++i]); 730 if (maxpoll > NTP_MAXPOLL) { 731 msyslog(LOG_INFO, 732 "maxpoll: provided value (%d) is above maximum (%d)", 733 maxpoll, NTP_MAXPOLL); 734 maxpoll = NTP_MAXPOLL; 735 } 736 break; 737 738 case CONF_MOD_PREFER: 739 peerflags |= FLAG_PREFER; 740 break; 741 742 case CONF_MOD_NOSELECT: 743 peerflags |= FLAG_NOSELECT; 744 break; 745 746 case CONF_MOD_BURST: 747 peerflags |= FLAG_BURST; 748 break; 749 750 case CONF_MOD_IBURST: 751 peerflags |= FLAG_IBURST; 752 break; 753 #ifdef AUTOKEY 754 case CONF_MOD_SKEY: 755 peerflags |= FLAG_SKEY | 756 FLAG_AUTHENABLE; 757 break; 758 759 #ifdef PUBKEY 760 case CONF_MOD_PUBLICKEY: 761 if (i >= ntokens - 1) { 762 msyslog(LOG_ERR, 763 "Public key file name required"); 764 errflg = 1; 765 break; 766 } 767 peerflags |= FLAG_SKEY | 768 FLAG_AUTHENABLE; 769 peerkeystr = tokens[++i]; 770 break; 771 #endif /* PUBKEY */ 772 #endif /* AUTOKEY */ 773 774 case CONF_MOD_TTL: 775 if (i >= ntokens-1) { 776 msyslog(LOG_ERR, 777 "ttl: argument required"); 778 errflg = 1; 779 break; 780 } 781 ttl = atoi(tokens[++i]); 782 break; 783 784 case CONF_MOD_MODE: 785 if (i >= ntokens-1) { 786 msyslog(LOG_ERR, 787 "mode: argument required"); 788 errflg = 1; 789 break; 790 } 791 ttl = atoi(tokens[++i]); 792 break; 793 794 case CONFIG_UNKNOWN: 795 errflg = 1; 796 break; 797 } 798 if (minpoll > maxpoll) { 799 msyslog(LOG_ERR, "config error: minpoll > maxpoll"); 800 errflg = 1; 801 } 802 if (errflg == 0) { 803 if (peer_config(&peeraddr, any_interface, hmode, 804 peerversion, minpoll, maxpoll, peerflags, 805 ttl, peerkey, peerkeystr) == 0) { 806 msyslog(LOG_ERR, 807 "configuration of %s failed", 808 ntoa(&peeraddr)); 809 } 810 811 } else if (errflg == -1) { 812 save_resolve(tokens[1], hmode, peerversion, 813 minpoll, maxpoll, peerflags, ttl, 814 peerkey, peerkeystr); 815 } 816 break; 817 818 case CONFIG_DRIFTFILE: 819 if (ntokens >= 2) 820 stats_config(STATS_FREQ_FILE, tokens[1]); 821 else 822 stats_config(STATS_FREQ_FILE, (char *)0); 823 break; 824 825 case CONFIG_PIDFILE: 826 if (ntokens >= 2) 827 stats_config(STATS_PID_FILE, tokens[1]); 828 else 829 stats_config(STATS_PID_FILE, (char *)0); 830 break; 831 832 case CONFIG_INCLUDEFILE: 833 if (ntokens < 2) { 834 msyslog(LOG_ERR, "includefile needs one argument"); 835 break; 836 } 837 if (includelevel >= MAXINCLUDELEVEL) { 838 fprintf(stderr, "getconfig: Maximum include file level exceeded.\n"); 839 msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded."); 840 break; 841 } 842 includefile = fopen(FindConfig(tokens[1]), "r"); 843 if (includefile == NULL) { 844 fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1])); 845 msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1])); 846 break; 847 } 848 fp[++includelevel] = includefile; 849 break; 850 851 case CONFIG_LOGFILE: 852 if (ntokens >= 2) { 853 FILE *new_file; 854 855 new_file = fopen(tokens[1], "a"); 856 if (new_file != NULL) { 857 NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ 858 msyslog(LOG_NOTICE, "logging to file %s", tokens[1]); 859 if (syslog_file != NULL && 860 fileno(syslog_file) != fileno(new_file)) 861 (void)fclose(syslog_file); 862 863 syslog_file = new_file; 864 syslogit = 0; 865 } 866 else 867 msyslog(LOG_ERR, 868 "Cannot open log file %s", 869 tokens[1]); 870 } 871 else 872 msyslog(LOG_ERR, "logfile needs one argument"); 873 break; 874 875 case CONFIG_LOGCONFIG: 876 for (i = 1; i < ntokens; i++) 877 { 878 int add = 1; 879 int equals = 0; 880 char * s = &tokens[i][0]; 881 882 switch (*s) { 883 case '+': 884 case '-': 885 case '=': 886 add = *s == '+'; 887 equals = *s == '='; 888 s++; 889 break; 890 891 default: 892 break; 893 } 894 if (equals) { 895 ntp_syslogmask = get_logmask(s); 896 } else { 897 if (add) { 898 ntp_syslogmask |= get_logmask(s); 899 } else { 900 ntp_syslogmask &= ~get_logmask(s); 901 } 902 } 903 #ifdef DEBUG 904 if (debug) 905 printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]); 906 #endif 907 } 908 break; 909 910 case CONFIG_BROADCASTCLIENT: 911 proto_config(PROTO_BROADCLIENT, 1, 0.); 912 break; 913 914 case CONFIG_MULTICASTCLIENT: 915 case CONFIG_MANYCASTSERVER: 916 if (ntokens > 1) { 917 for (i = 1; i < ntokens; i++) { 918 if (getnetnum(tokens[i], &peeraddr, 1)) 919 proto_config(PROTO_MULTICAST_ADD, 920 peeraddr.sin_addr.s_addr, 0.); 921 } 922 } else 923 proto_config(PROTO_MULTICAST_ADD, 924 htonl(INADDR_NTP), 0.); 925 if (tok == CONFIG_MULTICASTCLIENT) 926 sys_bclient = 1; 927 else if (tok == CONFIG_MANYCASTSERVER) 928 sys_manycastserver = 1; 929 break; 930 931 case CONFIG_AUTHENTICATE: 932 errflg = 0; 933 if (ntokens >= 2) { 934 if (STREQ(tokens[1], "yes")) 935 proto_config(PROTO_AUTHENTICATE, 1, 0.); 936 else if (STREQ(tokens[1], "no")) 937 proto_config(PROTO_AUTHENTICATE, 0, 0.); 938 else 939 errflg++; 940 } else { 941 errflg++; 942 } 943 944 if (errflg) 945 msyslog(LOG_ERR, 946 "should be `authenticate yes|no'"); 947 break; 948 949 case CONFIG_KEYS: 950 if (ntokens >= 2) { 951 getauthkeys(tokens[1]); 952 } 953 break; 954 955 case CONFIG_TINKER: 956 for (i = 1; i < ntokens; i++) { 957 int temp; 958 double ftemp; 959 960 temp = matchkey(tokens[i++], 961 tinker_keywords); 962 if (i > ntokens - 1) { 963 msyslog(LOG_ERR, 964 "tinker: missing argument"); 965 errflg++; 966 break; 967 } 968 sscanf(tokens[i], "%lf", &ftemp); 969 switch(temp) { 970 case CONF_CLOCK_MAX: 971 loop_config(LOOP_MAX, ftemp); 972 break; 973 974 case CONF_CLOCK_PANIC: 975 loop_config(LOOP_PANIC, ftemp); 976 break; 977 978 case CONF_CLOCK_PHI: 979 loop_config(LOOP_PHI, ftemp); 980 break; 981 982 case CONF_CLOCK_MINSTEP: 983 loop_config(LOOP_MINSTEP, ftemp); 984 break; 985 986 case CONF_CLOCK_MINPOLL: 987 loop_config(LOOP_MINPOLL, ftemp); 988 break; 989 990 case CONF_CLOCK_ALLAN: 991 loop_config(LOOP_ALLAN, ftemp); 992 break; 993 994 case CONF_CLOCK_HUFFPUFF: 995 loop_config(LOOP_HUFFPUFF, ftemp); 996 break; 997 } 998 } 999 break; 1000 1001 #ifdef AUTOKEY 1002 case CONFIG_REVOKE: 1003 if (ntokens >= 2) 1004 sys_revoke = 1 << max(atoi(tokens[1]), 10); 1005 break; 1006 1007 case CONFIG_AUTOMAX: 1008 if (ntokens >= 2) 1009 sys_automax = 1 << max(atoi(tokens[1]), 10); 1010 break; 1011 1012 #ifdef PUBKEY 1013 case CONFIG_KEYSDIR: 1014 if (ntokens < 2) { 1015 msyslog(LOG_ERR, 1016 "Keys directory name required"); 1017 break; 1018 } 1019 crypto_config(CRYPTO_CONF_KEYS, tokens[1]); 1020 break; 1021 1022 case CONFIG_CRYPTO: 1023 if (ntokens == 1) { 1024 crypto_config(CRYPTO_CONF_FLAGS , "0"); 1025 break; 1026 } 1027 for (i = 1; i < ntokens; i++) { 1028 int temp; 1029 1030 temp = matchkey(tokens[i++], crypto_keywords); 1031 if (i > ntokens - 1) { 1032 msyslog(LOG_ERR, 1033 "crypto: missing argument"); 1034 errflg++; 1035 break; 1036 } 1037 switch(temp) { 1038 case CONF_CRYPTO_FLAGS: 1039 crypto_config(CRYPTO_CONF_FLAGS, tokens[i]); 1040 break; 1041 1042 case CONF_CRYPTO_LEAP: 1043 crypto_config(CRYPTO_CONF_LEAP, tokens[i]); 1044 break; 1045 1046 case CONF_CRYPTO_DH: 1047 crypto_config(CRYPTO_CONF_DH, tokens[i]); 1048 break; 1049 1050 case CONF_CRYPTO_PRIVATEKEY: 1051 crypto_config(CRYPTO_CONF_PRIV, tokens[i]); 1052 break; 1053 1054 case CONF_CRYPTO_PUBLICKEY: 1055 crypto_config(CRYPTO_CONF_PUBL, tokens[i]); 1056 break; 1057 1058 case CONF_CRYPTO_CERT: 1059 crypto_config(CRYPTO_CONF_CERT, tokens[i]); 1060 break; 1061 1062 default: 1063 msyslog(LOG_ERR, "crypto: unknown keyword"); 1064 break; 1065 } 1066 } 1067 break; 1068 #endif /* PUBKEY */ 1069 #endif /* AUTOKEY */ 1070 1071 case CONFIG_RESTRICT: 1072 if (ntokens < 2) { 1073 msyslog(LOG_ERR, "restrict requires an address"); 1074 break; 1075 } 1076 if (STREQ(tokens[1], "default")) 1077 peeraddr.sin_addr.s_addr = htonl(INADDR_ANY); 1078 else if (!getnetnum(tokens[1], &peeraddr, 1)) 1079 break; 1080 1081 /* 1082 * Use peerversion as flags, peerkey as mflags. Ick. 1083 */ 1084 peerversion = 0; 1085 peerkey = 0; 1086 errflg = 0; 1087 maskaddr.sin_addr.s_addr = ~(u_int32)0; 1088 for (i = 2; i < ntokens; i++) { 1089 switch (matchkey(tokens[i], res_keywords)) { 1090 case CONF_RES_MASK: 1091 if (i >= ntokens-1) { 1092 msyslog(LOG_ERR, 1093 "mask keyword needs argument"); 1094 errflg++; 1095 break; 1096 } 1097 i++; 1098 if (!getnetnum(tokens[i], &maskaddr, 1)) 1099 errflg++; 1100 break; 1101 1102 case CONF_RES_IGNORE: 1103 peerversion |= RES_IGNORE; 1104 break; 1105 1106 case CONF_RES_NOSERVE: 1107 peerversion |= RES_DONTSERVE; 1108 break; 1109 1110 case CONF_RES_NOTRUST: 1111 peerversion |= RES_DONTTRUST; 1112 break; 1113 1114 case CONF_RES_NOQUERY: 1115 peerversion |= RES_NOQUERY; 1116 break; 1117 1118 case CONF_RES_NOMODIFY: 1119 peerversion |= RES_NOMODIFY; 1120 break; 1121 1122 case CONF_RES_NOPEER: 1123 peerversion |= RES_NOPEER; 1124 break; 1125 1126 case CONF_RES_NOTRAP: 1127 peerversion |= RES_NOTRAP; 1128 break; 1129 1130 case CONF_RES_LPTRAP: 1131 peerversion |= RES_LPTRAP; 1132 break; 1133 1134 case CONF_RES_NTPPORT: 1135 peerkey |= RESM_NTPONLY; 1136 break; 1137 1138 case CONF_RES_VERSION: 1139 peerversion |= RES_VERSION; 1140 break; 1141 1142 case CONF_RES_DEMOBILIZE: 1143 peerversion |= RES_DEMOBILIZE; 1144 break; 1145 1146 case CONF_RES_LIMITED: 1147 peerversion |= RES_LIMITED; 1148 break; 1149 1150 case CONFIG_UNKNOWN: 1151 errflg++; 1152 break; 1153 } 1154 } 1155 if (SRCADR(&peeraddr) == htonl(INADDR_ANY)) 1156 maskaddr.sin_addr.s_addr = 0; 1157 if (!errflg) 1158 hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr, 1159 (int)peerkey, peerversion); 1160 break; 1161 1162 case CONFIG_BDELAY: 1163 if (ntokens >= 2) { 1164 double tmp; 1165 1166 if (sscanf(tokens[1], "%lf", &tmp) != 1) { 1167 msyslog(LOG_ERR, 1168 "broadcastdelay value %s undecodable", 1169 tokens[1]); 1170 } else { 1171 proto_config(PROTO_BROADDELAY, 0, tmp); 1172 } 1173 } 1174 break; 1175 1176 case CONFIG_TRUSTEDKEY: 1177 for (i = 1; i < ntokens; i++) { 1178 keyid_t tkey; 1179 1180 tkey = atol(tokens[i]); 1181 if (tkey == 0) { 1182 msyslog(LOG_ERR, 1183 "trusted key %s unlikely", 1184 tokens[i]); 1185 } else { 1186 authtrust(tkey, 1); 1187 } 1188 } 1189 break; 1190 1191 case CONFIG_REQUESTKEY: 1192 if (ntokens >= 2) { 1193 if (!atouint(tokens[1], &ul)) { 1194 msyslog(LOG_ERR, 1195 "%s is undecodable as request key", 1196 tokens[1]); 1197 } else if (ul == 0) { 1198 msyslog(LOG_ERR, 1199 "%s makes a poor request keyid", 1200 tokens[1]); 1201 } else { 1202 #ifdef DEBUG 1203 if (debug > 3) 1204 printf( 1205 "set info_auth_key to %08lx\n", ul); 1206 #endif 1207 info_auth_keyid = (keyid_t)ul; 1208 } 1209 } 1210 break; 1211 1212 case CONFIG_CONTROLKEY: 1213 if (ntokens >= 2) { 1214 keyid_t ckey; 1215 1216 ckey = atol(tokens[1]); 1217 if (ckey == 0) { 1218 msyslog(LOG_ERR, 1219 "%s makes a poor control keyid", 1220 tokens[1]); 1221 } else { 1222 ctl_auth_keyid = ckey; 1223 } 1224 } 1225 break; 1226 1227 case CONFIG_TRAP: 1228 if (ntokens < 2) { 1229 msyslog(LOG_ERR, 1230 "no address for trap command, line ignored"); 1231 break; 1232 } 1233 if (!getnetnum(tokens[1], &peeraddr, 1)) 1234 break; 1235 1236 /* 1237 * Use peerversion for port number. Barf. 1238 */ 1239 errflg = 0; 1240 peerversion = 0; 1241 localaddr = 0; 1242 for (i = 2; i < ntokens-1; i++) 1243 switch (matchkey(tokens[i], trap_keywords)) { 1244 case CONF_TRAP_PORT: 1245 if (i >= ntokens-1) { 1246 msyslog(LOG_ERR, 1247 "trap port requires an argument"); 1248 errflg = 1; 1249 break; 1250 } 1251 peerversion = atoi(tokens[++i]); 1252 if (peerversion <= 0 1253 || peerversion > 32767) { 1254 msyslog(LOG_ERR, 1255 "invalid port number %s, trap ignored", 1256 tokens[i]); 1257 errflg = 1; 1258 } 1259 break; 1260 1261 case CONF_TRAP_INTERFACE: 1262 if (i >= ntokens-1) { 1263 msyslog(LOG_ERR, 1264 "trap interface requires an argument"); 1265 errflg = 1; 1266 break; 1267 } 1268 1269 if (!getnetnum(tokens[++i], 1270 &maskaddr, 1)) { 1271 errflg = 1; 1272 break; 1273 } 1274 1275 localaddr = findinterface(&maskaddr); 1276 if (localaddr == NULL) { 1277 msyslog(LOG_ERR, 1278 "can't find interface with address %s", 1279 ntoa(&maskaddr)); 1280 errflg = 1; 1281 } 1282 break; 1283 1284 case CONFIG_UNKNOWN: 1285 errflg++; 1286 break; 1287 } 1288 1289 if (!errflg) { 1290 if (peerversion != 0) 1291 peeraddr.sin_port = htons( (u_short) peerversion); 1292 else 1293 peeraddr.sin_port = htons(TRAPPORT); 1294 if (localaddr == NULL) 1295 localaddr = any_interface; 1296 if (!ctlsettrap(&peeraddr, localaddr, 0, 1297 NTP_VERSION)) 1298 msyslog(LOG_ERR, 1299 "can't set trap for %s, no resources", 1300 ntoa(&peeraddr)); 1301 } 1302 break; 1303 1304 case CONFIG_FUDGE: 1305 if (ntokens < 2) { 1306 msyslog(LOG_ERR, 1307 "no address for fudge command, line ignored"); 1308 break; 1309 } 1310 if (!getnetnum(tokens[1], &peeraddr, 1)) 1311 break; 1312 1313 if (!ISREFCLOCKADR(&peeraddr)) { 1314 msyslog(LOG_ERR, 1315 "%s is inappropriate address for the fudge command, line ignored", 1316 ntoa(&peeraddr)); 1317 break; 1318 } 1319 1320 memset((void *)&clock_stat, 0, sizeof clock_stat); 1321 fudgeflag = 0; 1322 errflg = 0; 1323 for (i = 2; i < ntokens-1; i++) { 1324 switch (c = matchkey(tokens[i], 1325 fudge_keywords)) { 1326 case CONF_FDG_TIME1: 1327 if (sscanf(tokens[++i], "%lf", 1328 &clock_stat.fudgetime1) != 1) { 1329 msyslog(LOG_ERR, 1330 "fudge %s time1 value in error", 1331 ntoa(&peeraddr)); 1332 errflg = i; 1333 break; 1334 } 1335 clock_stat.haveflags |= CLK_HAVETIME1; 1336 break; 1337 1338 case CONF_FDG_TIME2: 1339 if (sscanf(tokens[++i], "%lf", 1340 &clock_stat.fudgetime2) != 1) { 1341 msyslog(LOG_ERR, 1342 "fudge %s time2 value in error", 1343 ntoa(&peeraddr)); 1344 errflg = i; 1345 break; 1346 } 1347 clock_stat.haveflags |= CLK_HAVETIME2; 1348 break; 1349 1350 1351 case CONF_FDG_STRATUM: 1352 if (!atoint(tokens[++i], &stratum)) 1353 { 1354 msyslog(LOG_ERR, 1355 "fudge %s stratum value in error", 1356 ntoa(&peeraddr)); 1357 errflg = i; 1358 break; 1359 } 1360 clock_stat.fudgeval1 = stratum; 1361 clock_stat.haveflags |= CLK_HAVEVAL1; 1362 break; 1363 1364 case CONF_FDG_REFID: 1365 /* HMS: Endianness and 0 bytes? */ 1366 /* XXX */ 1367 strncpy((char *)&clock_stat.fudgeval2, 1368 tokens[++i], 4); 1369 clock_stat.haveflags |= CLK_HAVEVAL2; 1370 break; 1371 1372 case CONF_FDG_FLAG1: 1373 case CONF_FDG_FLAG2: 1374 case CONF_FDG_FLAG3: 1375 case CONF_FDG_FLAG4: 1376 if (!atouint(tokens[++i], &fudgeflag) 1377 || fudgeflag > 1) { 1378 msyslog(LOG_ERR, 1379 "fudge %s flag value in error", 1380 ntoa(&peeraddr)); 1381 errflg = i; 1382 break; 1383 } 1384 switch(c) { 1385 case CONF_FDG_FLAG1: 1386 c = CLK_FLAG1; 1387 clock_stat.haveflags|=CLK_HAVEFLAG1; 1388 break; 1389 case CONF_FDG_FLAG2: 1390 c = CLK_FLAG2; 1391 clock_stat.haveflags|=CLK_HAVEFLAG2; 1392 break; 1393 case CONF_FDG_FLAG3: 1394 c = CLK_FLAG3; 1395 clock_stat.haveflags|=CLK_HAVEFLAG3; 1396 break; 1397 case CONF_FDG_FLAG4: 1398 c = CLK_FLAG4; 1399 clock_stat.haveflags|=CLK_HAVEFLAG4; 1400 break; 1401 } 1402 if (fudgeflag == 0) 1403 clock_stat.flags &= ~c; 1404 else 1405 clock_stat.flags |= c; 1406 break; 1407 1408 case CONFIG_UNKNOWN: 1409 errflg = -1; 1410 break; 1411 } 1412 } 1413 1414 #ifdef REFCLOCK 1415 /* 1416 * If reference clock support isn't defined the 1417 * fudge line will still be accepted and syntax 1418 * checked, but will essentially do nothing. 1419 */ 1420 if (!errflg) { 1421 refclock_control(&peeraddr, &clock_stat, 1422 (struct refclockstat *)0); 1423 } 1424 #endif 1425 break; 1426 1427 case CONFIG_STATSDIR: 1428 if (ntokens >= 2) 1429 stats_config(STATS_STATSDIR,tokens[1]); 1430 break; 1431 1432 case CONFIG_STATISTICS: 1433 for (i = 1; i < ntokens; i++) { 1434 filegen = filegen_get(tokens[i]); 1435 1436 if (filegen == NULL) { 1437 msyslog(LOG_ERR, 1438 "no statistics named %s available", 1439 tokens[i]); 1440 continue; 1441 } 1442 #ifdef DEBUG 1443 if (debug > 3) 1444 printf("enabling filegen for %s statistics \"%s%s\"\n", 1445 tokens[i], filegen->prefix, filegen->basename); 1446 #endif 1447 filegen->flag |= FGEN_FLAG_ENABLED; 1448 } 1449 break; 1450 1451 case CONFIG_FILEGEN: 1452 if (ntokens < 2) { 1453 msyslog(LOG_ERR, 1454 "no id for filegen command, line ignored"); 1455 break; 1456 } 1457 1458 filegen = filegen_get(tokens[1]); 1459 if (filegen == NULL) { 1460 msyslog(LOG_ERR, 1461 "unknown filegen \"%s\" ignored", 1462 tokens[1]); 1463 break; 1464 } 1465 /* 1466 * peerversion is (ab)used for filegen file (index) 1467 * peerkey is (ab)used for filegen type 1468 * peerflags is (ab)used for filegen flags 1469 */ 1470 peerversion = 0; 1471 peerkey = filegen->type; 1472 peerflags = filegen->flag; 1473 errflg = 0; 1474 1475 for (i = 2; i < ntokens; i++) { 1476 switch (matchkey(tokens[i], filegen_keywords)) { 1477 case CONF_FGEN_FILE: 1478 if (i >= ntokens - 1) { 1479 msyslog(LOG_ERR, 1480 "filegen %s file requires argument", 1481 tokens[1]); 1482 errflg = i; 1483 break; 1484 } 1485 peerversion = ++i; 1486 break; 1487 case CONF_FGEN_TYPE: 1488 if (i >= ntokens -1) { 1489 msyslog(LOG_ERR, 1490 "filegen %s type requires argument", 1491 tokens[1]); 1492 errflg = i; 1493 break; 1494 } 1495 peerkey = matchkey(tokens[++i], fgen_types); 1496 if (peerkey == CONFIG_UNKNOWN) { 1497 msyslog(LOG_ERR, 1498 "filegen %s unknown type \"%s\"", 1499 tokens[1], tokens[i]); 1500 errflg = i; 1501 break; 1502 } 1503 break; 1504 1505 case CONF_FGEN_FLAG_LINK: 1506 peerflags |= FGEN_FLAG_LINK; 1507 break; 1508 1509 case CONF_FGEN_FLAG_NOLINK: 1510 peerflags &= ~FGEN_FLAG_LINK; 1511 break; 1512 1513 case CONF_FGEN_FLAG_ENABLE: 1514 peerflags |= FGEN_FLAG_ENABLED; 1515 break; 1516 1517 case CONF_FGEN_FLAG_DISABLE: 1518 peerflags &= ~FGEN_FLAG_ENABLED; 1519 break; 1520 } 1521 } 1522 if (!errflg) 1523 filegen_config(filegen, tokens[peerversion], 1524 (u_char)peerkey, (u_char)peerflags); 1525 break; 1526 1527 case CONFIG_SETVAR: 1528 if (ntokens < 2) { 1529 msyslog(LOG_ERR, 1530 "no value for setvar command - line ignored"); 1531 } else { 1532 set_sys_var(tokens[1], strlen(tokens[1])+1, 1533 RW | 1534 ((((ntokens > 2) 1535 && !strcmp(tokens[2], 1536 "default"))) 1537 ? DEF 1538 : 0)); 1539 } 1540 break; 1541 1542 case CONFIG_CLIENTLIMIT: 1543 if (ntokens < 2) { 1544 msyslog(LOG_ERR, 1545 "no value for clientlimit command - line ignored"); 1546 } else { 1547 u_long ui; 1548 1549 if (!atouint(tokens[1], &ui) || !ui) { 1550 msyslog(LOG_ERR, 1551 "illegal value for clientlimit command - line ignored"); 1552 } else { 1553 char bp[80]; 1554 1555 #ifdef DEBUG 1556 if (debug) 1557 sprintf(bp, "client_limit=%lu", ui); 1558 #endif 1559 set_sys_var(bp, strlen(bp)+1, RO); 1560 client_limit = ui; 1561 } 1562 } 1563 break; 1564 1565 case CONFIG_CLIENTPERIOD: 1566 if (ntokens < 2) { 1567 msyslog(LOG_ERR, 1568 "no value for clientperiod command - line ignored"); 1569 } else { 1570 u_long ui; 1571 1572 if (!atouint(tokens[1], &ui) || ui < 64) { 1573 msyslog(LOG_ERR, 1574 "illegal value for clientperiod command - line ignored"); 1575 } else { 1576 char bp[80]; 1577 1578 sprintf(bp, "client_limit_period=%ld", ui); 1579 set_sys_var(bp, strlen(bp)+1, RO); 1580 client_limit_period = ui; 1581 } 1582 } 1583 break; 1584 1585 case CONFIG_ENABLE: 1586 for (i = 1; i < ntokens; i++) { 1587 int flag; 1588 1589 flag = matchkey(tokens[i], flags_keywords); 1590 if (flag == CONFIG_UNKNOWN) { 1591 msyslog(LOG_ERR, 1592 "enable unknown flag %s", 1593 tokens[i]); 1594 errflg = 1; 1595 break; 1596 } 1597 proto_config(flag, 1, 0.); 1598 } 1599 break; 1600 1601 case CONFIG_DISABLE: 1602 for (i = 1; i < ntokens; i++) { 1603 int flag; 1604 1605 flag = matchkey(tokens[i], flags_keywords); 1606 if (flag == CONFIG_UNKNOWN) { 1607 msyslog(LOG_ERR, 1608 "disable unknown flag %s", 1609 tokens[i]); 1610 errflg = 1; 1611 break; 1612 } 1613 proto_config(flag, 0, 0.); 1614 } 1615 break; 1616 1617 case CONFIG_PHONE: 1618 for (i = 1; i < ntokens && i < MAXPHONE; i++) { 1619 (void)strncpy(sys_phone[i - 1], 1620 tokens[i], MAXDIAL); 1621 } 1622 sys_phone[i - 1][0] = '\0'; 1623 break; 1624 1625 case CONFIG_PPS: 1626 if (ntokens < 2) { 1627 msyslog(LOG_ERR, 1628 "pps missing device name"); 1629 break; 1630 } 1631 (void)strncpy(pps_device, tokens[1], MAXPPS); 1632 for (i = 2; i < ntokens; i++) { 1633 int flag; 1634 1635 flag = matchkey(tokens[i], pps_keywords); 1636 switch(flag) { 1637 case CONF_PPS_ASSERT: 1638 pps_assert = 0; 1639 break; 1640 case CONF_PPS_CLEAR: 1641 pps_assert = 1; 1642 break; 1643 case CONF_PPS_HARDPPS: 1644 pps_hardpps = 1; 1645 break; 1646 default: 1647 msyslog(LOG_ERR, 1648 "pps unknown flag %s", 1649 tokens[i]); 1650 errflg = 1; 1651 break; 1652 } 1653 if(errflg) 1654 break; 1655 } 1656 break; 1657 } 1658 } 1659 if (fp[0]) 1660 (void)fclose(fp[0]); 1661 1662 #ifdef HAVE_NETINFO 1663 if (config_netinfo) 1664 free_netinfo_config(config_netinfo); 1665 #endif /* HAVE_NETINFO */ 1666 1667 #if !defined(VMS) && !defined(SYS_VXWORKS) 1668 /* find a keyid */ 1669 if (info_auth_keyid == 0) 1670 req_keyid = 65535; 1671 else 1672 req_keyid = info_auth_keyid; 1673 1674 /* if doesn't exist, make up one at random */ 1675 if (!authhavekey(req_keyid)) { 1676 char rankey[9]; 1677 int j; 1678 1679 for (i = 0; i < 8; i++) 1680 for (j = 1; j < 100; ++j) { 1681 rankey[i] = RANDOM & 0xff; 1682 if (rankey[i] != 0) break; 1683 } 1684 rankey[8] = 0; 1685 authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey); 1686 authtrust(req_keyid, 1); 1687 if (!authhavekey(req_keyid)) { 1688 msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!"); 1689 /* HMS: Should this be fatal? */ 1690 } 1691 } 1692 1693 /* save keyid so we will accept config requests with it */ 1694 info_auth_keyid = req_keyid; 1695 #endif /* !defined(VMS) && !defined(SYS_VXWORKS) */ 1696 1697 if (res_fp != NULL) { 1698 /* 1699 * Need name resolution 1700 */ 1701 do_resolve_internal(); 1702 } 1703 } 1704 1705 1706 #ifdef HAVE_NETINFO 1707 1708 /* 1709 * get_netinfo_config - find the nearest NetInfo domain with an ntp 1710 * configuration and initialize the configuration state. 1711 */ 1712 static struct netinfo_config_state * 1713 get_netinfo_config() 1714 { 1715 ni_status status; 1716 void *domain; 1717 ni_id config_dir; 1718 struct netinfo_config_state *config; 1719 1720 if (ni_open(NULL, ".", &domain) != NI_OK) return NULL; 1721 1722 while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) { 1723 void *next_domain; 1724 if (ni_open(domain, "..", &next_domain) != NI_OK) { 1725 ni_free(next_domain); 1726 break; 1727 } 1728 ni_free(domain); 1729 domain = next_domain; 1730 } 1731 if (status != NI_OK) { 1732 ni_free(domain); 1733 return NULL; 1734 } 1735 1736 config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state)); 1737 config->domain = domain; 1738 config->config_dir = config_dir; 1739 config->prop_index = 0; 1740 config->val_index = 0; 1741 config->val_list = NULL; 1742 1743 return config; 1744 } 1745 1746 1747 1748 /* 1749 * free_netinfo_config - release NetInfo configuration state 1750 */ 1751 static void 1752 free_netinfo_config(struct netinfo_config_state *config) 1753 { 1754 ni_free(config->domain); 1755 free(config); 1756 } 1757 1758 1759 1760 /* 1761 * gettokens_netinfo - return tokens from NetInfo 1762 */ 1763 static int 1764 gettokens_netinfo ( 1765 struct netinfo_config_state *config, 1766 char **tokenlist, 1767 int *ntokens 1768 ) 1769 { 1770 int prop_index = config->prop_index; 1771 int val_index = config->val_index; 1772 char **val_list = config->val_list; 1773 1774 /* 1775 * Iterate through each keyword and look for a property that matches it. 1776 */ 1777 again: 1778 if (!val_list) { 1779 for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++) 1780 { 1781 ni_namelist namelist; 1782 struct keyword current_prop = keywords[prop_index]; 1783 1784 /* 1785 * For each value associated in the property, we're going to return 1786 * a separate line. We squirrel away the values in the config state 1787 * so the next time through, we don't need to do this lookup. 1788 */ 1789 NI_INIT(&namelist); 1790 if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) { 1791 ni_index index; 1792 1793 /* Found the property, but it has no values */ 1794 if (namelist.ni_namelist_len == 0) continue; 1795 1796 if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1)))) 1797 { msyslog(LOG_ERR, "out of memory while configuring"); break; } 1798 1799 for (index = 0; index < namelist.ni_namelist_len; index++) { 1800 char *value = namelist.ni_namelist_val[index]; 1801 1802 if (! (val_list[index] = (char*)malloc(strlen(value+1)))) 1803 { msyslog(LOG_ERR, "out of memory while configuring"); break; } 1804 1805 strcpy(val_list[index], value); 1806 } 1807 val_list[index] = NULL; 1808 1809 break; 1810 } 1811 ni_namelist_free(&namelist); 1812 } 1813 config->prop_index = prop_index; 1814 } 1815 1816 /* No list; we're done here. */ 1817 if (!val_list) return CONFIG_UNKNOWN; 1818 1819 /* 1820 * We have a list of values for the current property. 1821 * Iterate through them and return each in order. 1822 */ 1823 if (val_list[val_index]) 1824 { 1825 int ntok = 1; 1826 int quoted = 0; 1827 char *tokens = val_list[val_index]; 1828 1829 msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]); 1830 1831 (const char*)tokenlist[0] = keywords[prop_index].text; 1832 for (ntok = 1; ntok < MAXTOKENS; ntok++) { 1833 tokenlist[ntok] = tokens; 1834 while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted)) 1835 quoted ^= (*tokens++ == '"'); 1836 1837 if (ISEOL(*tokens)) { 1838 *tokens = '\0'; 1839 break; 1840 } else { /* must be space */ 1841 *tokens++ = '\0'; 1842 while (ISSPACE(*tokens)) tokens++; 1843 if (ISEOL(*tokens)) break; 1844 } 1845 } 1846 *ntokens = ntok + 1; 1847 1848 config->val_index++; 1849 1850 return keywords[prop_index].keytype; 1851 } 1852 1853 /* We're done with the current property. */ 1854 prop_index = ++config->prop_index; 1855 1856 /* Free val_list and reset counters. */ 1857 for (val_index = 0; val_list[val_index]; val_index++) 1858 free(val_list[val_index]); 1859 free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0; 1860 1861 goto again; 1862 } 1863 1864 #endif /* HAVE_NETINFO */ 1865 1866 1867 /* 1868 * gettokens - read a line and return tokens 1869 */ 1870 static int 1871 gettokens ( 1872 FILE *fp, 1873 char *line, 1874 char **tokenlist, 1875 int *ntokens 1876 ) 1877 { 1878 register char *cp; 1879 register int ntok; 1880 register int quoted = 0; 1881 1882 /* 1883 * Find start of first token 1884 */ 1885 again: 1886 while ((cp = fgets(line, MAXLINE, fp)) != NULL) { 1887 cp = line; 1888 while (ISSPACE(*cp)) 1889 cp++; 1890 if (!ISEOL(*cp)) 1891 break; 1892 } 1893 if (cp == NULL) { 1894 *ntokens = 0; 1895 return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */ 1896 } 1897 1898 /* 1899 * Now separate out the tokens 1900 */ 1901 for (ntok = 0; ntok < MAXTOKENS; ntok++) { 1902 tokenlist[ntok] = cp; 1903 while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted)) 1904 quoted ^= (*cp++ == '"'); 1905 1906 if (ISEOL(*cp)) { 1907 *cp = '\0'; 1908 break; 1909 } else { /* must be space */ 1910 *cp++ = '\0'; 1911 while (ISSPACE(*cp)) 1912 cp++; 1913 if (ISEOL(*cp)) 1914 break; 1915 } 1916 } 1917 1918 /* 1919 * Return the match 1920 */ 1921 *ntokens = ntok + 1; 1922 ntok = matchkey(tokenlist[0], keywords); 1923 if (ntok == CONFIG_UNKNOWN) 1924 goto again; 1925 return ntok; 1926 } 1927 1928 1929 1930 /* 1931 * matchkey - match a keyword to a list 1932 */ 1933 static int 1934 matchkey( 1935 register char *word, 1936 register struct keyword *keys 1937 ) 1938 { 1939 for (;;) { 1940 if (keys->keytype == CONFIG_UNKNOWN) { 1941 msyslog(LOG_ERR, 1942 "configure: keyword \"%s\" unknown, line ignored", 1943 word); 1944 return CONFIG_UNKNOWN; 1945 } 1946 if (STRSAME(word, keys->text)) 1947 return keys->keytype; 1948 keys++; 1949 } 1950 } 1951 1952 1953 /* 1954 * getnetnum - return a net number (this is crude, but careful) 1955 */ 1956 static int 1957 getnetnum( 1958 const char *num, 1959 struct sockaddr_in *addr, 1960 int complain 1961 ) 1962 { 1963 register const char *cp; 1964 register char *bp; 1965 register int i; 1966 register int temp; 1967 char buf[80]; /* will core dump on really stupid stuff */ 1968 u_int32 netnum; 1969 1970 /* XXX ELIMINATE replace with decodenetnum */ 1971 cp = num; 1972 netnum = 0; 1973 for (i = 0; i < 4; i++) { 1974 bp = buf; 1975 while (isdigit((int)*cp)) 1976 *bp++ = *cp++; 1977 if (bp == buf) 1978 break; 1979 1980 if (i < 3) { 1981 if (*cp++ != '.') 1982 break; 1983 } else if (*cp != '\0') 1984 break; 1985 1986 *bp = '\0'; 1987 temp = atoi(buf); 1988 if (temp > 255) 1989 break; 1990 netnum <<= 8; 1991 netnum += temp; 1992 #ifdef DEBUG 1993 if (debug > 3) 1994 printf("getnetnum %s step %d buf %s temp %d netnum %lu\n", 1995 num, i, buf, temp, (u_long)netnum); 1996 #endif 1997 } 1998 1999 if (i < 4) { 2000 if (complain) 2001 msyslog(LOG_ERR, 2002 "getnetnum: \"%s\" invalid host number, line ignored", 2003 num); 2004 #ifdef DEBUG 2005 if (debug > 3) 2006 printf( 2007 "getnetnum: \"%s\" invalid host number, line ignored\n", 2008 num); 2009 #endif 2010 return 0; 2011 } 2012 2013 /* 2014 * make up socket address. Clear it out for neatness. 2015 */ 2016 memset((void *)addr, 0, sizeof(struct sockaddr_in)); 2017 addr->sin_family = AF_INET; 2018 addr->sin_port = htons(NTP_PORT); 2019 addr->sin_addr.s_addr = htonl(netnum); 2020 #ifdef DEBUG 2021 if (debug > 1) 2022 printf("getnetnum given %s, got %s (%lx)\n", 2023 num, ntoa(addr), (u_long)netnum); 2024 #endif 2025 return 1; 2026 } 2027 2028 2029 #if !defined(VMS) 2030 /* 2031 * catchchild - receive the resolver's exit status 2032 */ 2033 static RETSIGTYPE 2034 catchchild( 2035 int sig 2036 ) 2037 { 2038 /* 2039 * We only start up one child, and if we're here 2040 * it should have already exited. Hence the following 2041 * shouldn't hang. If it does, please tell me. 2042 */ 2043 #if !defined (SYS_WINNT) && !defined(SYS_VXWORKS) 2044 (void) wait(0); 2045 #endif /* SYS_WINNT && VXWORKS*/ 2046 } 2047 #endif /* VMS */ 2048 2049 2050 /* 2051 * save_resolve - save configuration info into a file for later name resolution 2052 */ 2053 static void 2054 save_resolve( 2055 char *name, 2056 int mode, 2057 int version, 2058 int minpoll, 2059 int maxpoll, 2060 u_int flags, 2061 int ttl, 2062 keyid_t keyid, 2063 u_char *keystr 2064 ) 2065 { 2066 #ifndef SYS_VXWORKS 2067 if (res_fp == NULL) { 2068 #ifndef SYS_WINNT 2069 (void) strcpy(res_file, RES_TEMPFILE); 2070 #else 2071 /* no /tmp directory under NT */ 2072 { 2073 DWORD len; 2074 if(!(len = GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) { 2075 msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m"); 2076 return; 2077 } 2078 (void) strcat(res_file, "ntpdXXXXXX"); 2079 } 2080 #endif /* SYS_WINNT */ 2081 #ifdef HAVE_MKSTEMP 2082 { 2083 int fd; 2084 2085 res_fp = NULL; 2086 if ((fd = mkstemp(res_file)) != -1) 2087 res_fp = fdopen(fd, "r+"); 2088 } 2089 #else 2090 (void) mktemp(res_file); 2091 res_fp = fopen(res_file, "w"); 2092 #endif 2093 if (res_fp == NULL) { 2094 msyslog(LOG_ERR, "open failed for %s: %m", res_file); 2095 return; 2096 } 2097 } 2098 #ifdef DEBUG 2099 if (debug) { 2100 printf("resolving %s\n", name); 2101 } 2102 #endif 2103 2104 (void)fprintf(res_fp, "%s %d %d %d %d %d %d %d %s\n", name, 2105 mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr); 2106 #ifdef DEBUG 2107 if (debug > 1) 2108 printf("config: %s %d %d %d %d %x %d %08x %s\n", name, mode, 2109 version, minpoll, maxpoll, flags, ttl, keyid, keystr); 2110 #endif 2111 2112 #else /* SYS_VXWORKS */ 2113 /* save resolve info to a struct */ 2114 #endif /* SYS_VXWORKS */ 2115 } 2116 2117 2118 /* 2119 * abort_resolve - terminate the resolver stuff and delete the file 2120 */ 2121 static void 2122 abort_resolve(void) 2123 { 2124 /* 2125 * In an ideal world we would might reread the file and 2126 * log the hosts which aren't getting configured. Since 2127 * this is too much work, however, just close and delete 2128 * the temp file. 2129 */ 2130 if (res_fp != NULL) 2131 (void) fclose(res_fp); 2132 res_fp = NULL; 2133 2134 #ifndef SYS_VXWORKS /* we don't open the file to begin with */ 2135 #if !defined(VMS) 2136 (void) unlink(res_file); 2137 #else 2138 (void) delete(res_file); 2139 #endif /* VMS */ 2140 #endif /* SYS_VXWORKS */ 2141 } 2142 2143 2144 /* 2145 * do_resolve_internal - start up the resolver function (not program) 2146 */ 2147 /* 2148 * On VMS, this routine will simply refuse to resolve anything. 2149 * 2150 * Possible implementation: keep `res_file' in memory, do async 2151 * name resolution via QIO, update from within completion AST. 2152 * I'm unlikely to find the time for doing this, though. -wjm 2153 */ 2154 static void 2155 do_resolve_internal(void) 2156 { 2157 int i; 2158 2159 if (res_fp == NULL) { 2160 /* belch */ 2161 msyslog(LOG_ERR, 2162 "do_resolve_internal: Fatal: res_fp == NULL"); 2163 exit(1); 2164 } 2165 2166 /* we are done with this now */ 2167 (void) fclose(res_fp); 2168 res_fp = NULL; 2169 2170 #if !defined(VMS) && !defined (SYS_VXWORKS) 2171 req_file = res_file; /* set up pointer to res file */ 2172 #ifndef SYS_WINNT 2173 (void) signal_no_reset(SIGCHLD, catchchild); 2174 2175 #ifndef SYS_VXWORKS 2176 i = fork(); 2177 if (i == 0) { 2178 /* 2179 * this used to close everything 2180 * I don't think this is necessary 2181 */ 2182 /* 2183 * To the unknown commenter above: 2184 * Well, I think it's better to clean up 2185 * after oneself. I have had problems with 2186 * refclock-io when intres was running - things 2187 * where fine again when ntpintres was gone. 2188 * So some systems react erratic at least. 2189 * 2190 * Frank Kardel 2191 * 2192 * 94-11-16: 2193 * Further debugging has proven that the above is 2194 * absolutely harmful. The internal resolver 2195 * is still in the SIGIO process group and the lingering 2196 * async io information causes it to process requests from 2197 * all file decriptor causing a race between the NTP daemon 2198 * and the resolver. which then eats data when it wins 8-(. 2199 * It is absolutly necessary to kill any IO associations 2200 * shared with the NTP daemon. 2201 * 2202 * We also block SIGIO (currently no ports means to 2203 * disable the signal handle for IO). 2204 * 2205 * Thanks to wgstuken@informatik.uni-erlangen.de to notice 2206 * that it is the ntp-resolver child running into trouble. 2207 * 2208 * THUS: 2209 */ 2210 2211 closelog(); 2212 kill_asyncio(); 2213 2214 (void) signal_no_reset(SIGCHLD, SIG_DFL); 2215 2216 #ifdef DEBUG 2217 if (0) 2218 debug = 2; 2219 #endif 2220 2221 # ifndef LOG_DAEMON 2222 openlog("ntpd_initres", LOG_PID); 2223 # else /* LOG_DAEMON */ 2224 2225 # ifndef LOG_NTP 2226 # define LOG_NTP LOG_DAEMON 2227 # endif 2228 openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP); 2229 #ifndef SYS_CYGWIN32 2230 # ifdef DEBUG 2231 if (debug) 2232 setlogmask(LOG_UPTO(LOG_DEBUG)); 2233 else 2234 # endif /* DEBUG */ 2235 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ 2236 # endif /* LOG_DAEMON */ 2237 #endif 2238 2239 ntp_intres(); 2240 2241 /* 2242 * If we got here, the intres code screwed up. 2243 * Print something so we don't die without complaint 2244 */ 2245 msyslog(LOG_ERR, "call to ntp_intres lost"); 2246 abort_resolve(); 2247 exit(1); 2248 } 2249 #else 2250 /* vxWorks spawns a thread... -casey */ 2251 i = sp (ntp_intres); 2252 /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/ 2253 #endif 2254 if (i == -1) { 2255 msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m"); 2256 (void) signal_no_reset(SIGCHLD, SIG_DFL); 2257 abort_resolve(); 2258 } 2259 #else /* SYS_WINNT */ 2260 { 2261 /* NT's equivalent of fork() is _spawn(), but the start point 2262 * of the new process is an executable filename rather than 2263 * a function name as desired here. 2264 */ 2265 DWORD dwThreadId; 2266 fflush(stdout); 2267 if (!(ResolverThreadHandle = CreateThread( 2268 NULL, /* no security attributes */ 2269 0, /* use default stack size */ 2270 (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */ 2271 NULL, /* argument to thread function */ 2272 0, /* use default creation flags */ 2273 &dwThreadId))) { /* returns the thread identifier */ 2274 msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres"); 2275 abort_resolve(); 2276 } 2277 } 2278 #endif /* SYS_WINNT */ 2279 #else /* VMS VX_WORKS */ 2280 msyslog(LOG_ERR, 2281 "Name resolution not implemented for VMS - use numeric addresses"); 2282 abort_resolve(); 2283 #endif /* VMS VX_WORKS */ 2284 } 2285