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