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