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