Annotation of embedaddon/ntp/ntpd/ntp_config.c, revision 1.1
1.1 ! misho 1: /* ntp_config.c
! 2: *
! 3: * This file contains the ntpd configuration code.
! 4: *
! 5: * Written By: Sachin Kamboj
! 6: * University of Delaware
! 7: * Newark, DE 19711
! 8: * Some parts borrowed from the older ntp_config.c
! 9: * Copyright (c) 2006
! 10: */
! 11:
! 12: #ifdef HAVE_CONFIG_H
! 13: # include <config.h>
! 14: #endif
! 15:
! 16: #ifdef HAVE_NETINFO
! 17: # include <netinfo/ni.h>
! 18: #endif
! 19:
! 20: #include "ntp.h"
! 21: #include "ntpd.h"
! 22: #include "ntp_io.h"
! 23: #include "ntp_unixtime.h"
! 24: #include "ntp_refclock.h"
! 25: #include "ntp_filegen.h"
! 26: #include "ntp_stdlib.h"
! 27: #include "ntp_assert.h"
! 28: #include "ntpd-opts.h"
! 29: /*
! 30: * Sim header. Currently unconditionally included
! 31: * PDMXXX This needs to be a conditional include
! 32: */
! 33: #include "ntpsim.h"
! 34:
! 35: #include <ntp_random.h>
! 36: #include "ntp_intres.h"
! 37: #include <isc/net.h>
! 38: #include <isc/result.h>
! 39:
! 40: #include <stdio.h>
! 41: #include <ctype.h>
! 42: #ifdef HAVE_SYS_PARAM_H
! 43: # include <sys/param.h>
! 44: #endif
! 45: #include <signal.h>
! 46: #ifndef SIGCHLD
! 47: # define SIGCHLD SIGCLD
! 48: #endif
! 49: #if !defined(VMS)
! 50: # ifdef HAVE_SYS_WAIT_H
! 51: # include <sys/wait.h>
! 52: # endif
! 53: #endif /* VMS */
! 54:
! 55: #ifdef SYS_WINNT
! 56: # include <io.h>
! 57: HANDLE ResolverEventHandle;
! 58: #else
! 59: int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
! 60: #endif /* SYS_WINNT */
! 61:
! 62: /*
! 63: * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
! 64: * so #include these later.
! 65: */
! 66:
! 67: #include "ntp_config.h"
! 68: #include "ntp_cmdargs.h"
! 69:
! 70: #include "ntp_scanner.h"
! 71: #include "ntp_parser.h"
! 72: #include "ntp_data_structures.h"
! 73:
! 74:
! 75: /*
! 76: * "logconfig" building blocks
! 77: */
! 78: struct masks {
! 79: const char * const name;
! 80: const u_int32 mask;
! 81: };
! 82:
! 83: static struct masks logcfg_class[] = {
! 84: { "clock", NLOG_OCLOCK },
! 85: { "peer", NLOG_OPEER },
! 86: { "sync", NLOG_OSYNC },
! 87: { "sys", NLOG_OSYS },
! 88: { NULL, 0 }
! 89: };
! 90:
! 91: /* logcfg_noclass_items[] masks are complete and must not be shifted */
! 92: static struct masks logcfg_noclass_items[] = {
! 93: { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
! 94: { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
! 95: { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
! 96: { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
! 97: { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
! 98: /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
! 99: { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
! 100: { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
! 101: { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
! 102: { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
! 103: { NULL, 0 }
! 104: };
! 105:
! 106: /* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
! 107: static struct masks logcfg_class_items[] = {
! 108: { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
! 109: { "info", NLOG_INFO },
! 110: { "events", NLOG_EVENT },
! 111: { "status", NLOG_STATUS },
! 112: { "statistics", NLOG_STATIST },
! 113: { NULL, 0 }
! 114: };
! 115:
! 116: /* Limits */
! 117: #define MAXPHONE 10 /* maximum number of phone strings */
! 118: #define MAXPPS 20 /* maximum length of PPS device string */
! 119:
! 120: /*
! 121: * Miscellaneous macros
! 122: */
! 123: #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
! 124: #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
! 125: #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
! 126: #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
! 127:
! 128: /*
! 129: * File descriptor used by the resolver save routines, and temporary file
! 130: * name.
! 131: */
! 132: int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
! 133: #ifndef SYS_WINNT
! 134: static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
! 135: #define RES_TEMPFILE "/tmp/ntpXXXXXX"
! 136: #else
! 137: static char res_file[MAX_PATH];
! 138: #endif /* SYS_WINNT */
! 139:
! 140: /*
! 141: * Definitions of things either imported from or exported to outside
! 142: */
! 143: extern int yydebug; /* ntp_parser.c (.y) */
! 144: int curr_include_level; /* The current include level */
! 145: struct FILE_INFO *fp[MAXINCLUDELEVEL+1];
! 146: FILE *res_fp;
! 147: struct config_tree cfgt; /* Parser output stored here */
! 148: struct config_tree *cfg_tree_history = NULL; /* History of configs */
! 149: char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
! 150: char default_keysdir[] = NTP_KEYSDIR;
! 151: char *keysdir = default_keysdir; /* crypto keys directory */
! 152: char * saveconfigdir;
! 153: #if defined(HAVE_SCHED_SETSCHEDULER)
! 154: int config_priority_override = 0;
! 155: int config_priority;
! 156: #endif
! 157:
! 158: const char *config_file;
! 159: char default_ntp_signd_socket[] =
! 160: #ifdef NTP_SIGND_PATH
! 161: NTP_SIGND_PATH;
! 162: #else
! 163: "";
! 164: #endif
! 165: char *ntp_signd_socket = default_ntp_signd_socket;
! 166: #ifdef HAVE_NETINFO
! 167: struct netinfo_config_state *config_netinfo = NULL;
! 168: int check_netinfo = 1;
! 169: #endif /* HAVE_NETINFO */
! 170: #ifdef SYS_WINNT
! 171: char *alt_config_file;
! 172: LPTSTR temp;
! 173: char config_file_storage[MAX_PATH];
! 174: char alt_config_file_storage[MAX_PATH];
! 175: #endif /* SYS_WINNT */
! 176:
! 177: #ifdef HAVE_NETINFO
! 178: /*
! 179: * NetInfo configuration state
! 180: */
! 181: struct netinfo_config_state {
! 182: void *domain; /* domain with config */
! 183: ni_id config_dir; /* ID config dir */
! 184: int prop_index; /* current property */
! 185: int val_index; /* current value */
! 186: char **val_list; /* value list */
! 187: };
! 188: #endif
! 189:
! 190: struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
! 191: pointer info */
! 192: int input_from_file = 1; /* A boolean flag, which when set, indicates that
! 193: the input is to be taken from the configuration
! 194: file, instead of the remote-configuration buffer
! 195: */
! 196:
! 197: int old_config_style = 1; /* A boolean flag, which when set,
! 198: * indicates that the old configuration
! 199: * format with a newline at the end of
! 200: * every command is being used
! 201: */
! 202: int cryptosw; /* crypto command called */
! 203:
! 204: extern int sys_maxclock;
! 205: extern char *stats_drift_file; /* name of the driftfile */
! 206: extern char *leapseconds_file_name; /*name of the leapseconds file */
! 207: #ifdef HAVE_IPTOS_SUPPORT
! 208: extern unsigned int qos; /* QoS setting */
! 209: #endif /* HAVE_IPTOS_SUPPORT */
! 210:
! 211: #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
! 212: /*
! 213: * backwards compatibility flags
! 214: */
! 215: bc_entry bc_list[] = {
! 216: { T_Bc_bugXXXX, 1 } /* default enabled */
! 217: };
! 218:
! 219: /*
! 220: * declare an int pointer for each flag for quick testing without
! 221: * walking bc_list. If the pointer is consumed by libntp rather
! 222: * than ntpd, declare it in a libntp source file pointing to storage
! 223: * initialized with the appropriate value for other libntp clients, and
! 224: * redirect it to point into bc_list during ntpd startup.
! 225: */
! 226: int *p_bcXXXX_enabled = &bc_list[0].enabled;
! 227: #endif
! 228:
! 229: /* FUNCTION PROTOTYPES */
! 230:
! 231: static void apply_enable_disable(queue *q, int enable);
! 232: static void init_syntax_tree(struct config_tree *);
! 233:
! 234: #ifdef FREE_CFG_T
! 235: static void free_auth_node(struct config_tree *);
! 236:
! 237: static void free_config_other_modes(struct config_tree *);
! 238: static void free_config_auth(struct config_tree *);
! 239: static void free_config_tos(struct config_tree *);
! 240: static void free_config_monitor(struct config_tree *);
! 241: static void free_config_access(struct config_tree *);
! 242: static void free_config_tinker(struct config_tree *);
! 243: static void free_config_system_opts(struct config_tree *);
! 244: static void free_config_logconfig(struct config_tree *);
! 245: static void free_config_phone(struct config_tree *);
! 246: static void free_config_qos(struct config_tree *);
! 247: static void free_config_setvar(struct config_tree *);
! 248: static void free_config_ttl(struct config_tree *);
! 249: static void free_config_trap(struct config_tree *);
! 250: static void free_config_fudge(struct config_tree *);
! 251: static void free_config_vars(struct config_tree *);
! 252: static void free_config_peers(struct config_tree *);
! 253: static void free_config_unpeers(struct config_tree *);
! 254: static void free_config_nic_rules(struct config_tree *);
! 255: #ifdef SIM
! 256: static void free_config_sim(struct config_tree *);
! 257: #endif
! 258:
! 259: void free_all_config_trees(void); /* atexit() */
! 260: static void free_config_tree(struct config_tree *ptree);
! 261: #endif /* FREE_CFG_T */
! 262:
! 263: double *create_dval(double val);
! 264: void destroy_restrict_node(struct restrict_node *my_node);
! 265: static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
! 266: static int get_correct_host_mode(int hmode);
! 267: static void save_and_apply_config_tree(void);
! 268: void getconfig(int argc,char *argv[]);
! 269: #if !defined(SIM)
! 270: static sockaddr_u *get_next_address(struct address_node *addr);
! 271: #endif
! 272:
! 273: static void config_other_modes(struct config_tree *);
! 274: static void config_auth(struct config_tree *);
! 275: static void config_tos(struct config_tree *);
! 276: static void config_monitor(struct config_tree *);
! 277: static void config_access(struct config_tree *);
! 278: static void config_tinker(struct config_tree *);
! 279: static void config_system_opts(struct config_tree *);
! 280: static void config_logconfig(struct config_tree *);
! 281: static void config_phone(struct config_tree *);
! 282: static void config_qos(struct config_tree *);
! 283: static void config_setvar(struct config_tree *);
! 284: static void config_ttl(struct config_tree *);
! 285: static void config_trap(struct config_tree *);
! 286: static void config_fudge(struct config_tree *);
! 287: static void config_vars(struct config_tree *);
! 288: static void config_peers(struct config_tree *);
! 289: static void config_unpeers(struct config_tree *);
! 290: static void config_nic_rules(struct config_tree *);
! 291:
! 292: #ifdef SIM
! 293: static void config_sim(struct config_tree *);
! 294: static void config_ntpdsim(struct config_tree *);
! 295: #else
! 296: static void config_ntpd(struct config_tree *);
! 297: #endif
! 298:
! 299: enum gnn_type {
! 300: t_UNK, /* Unknown */
! 301: t_REF, /* Refclock */
! 302: t_MSK /* Network Mask */
! 303: };
! 304:
! 305: #define DESTROY_QUEUE(q) \
! 306: do { \
! 307: if (q) { \
! 308: destroy_queue(q); \
! 309: (q) = NULL; \
! 310: } \
! 311: } while (0)
! 312:
! 313: void ntpd_set_tod_using(const char *);
! 314: static u_int32 get_pfxmatch(const char **, struct masks *);
! 315: static u_int32 get_match(const char *, struct masks *);
! 316: static u_int32 get_logmask(const char *);
! 317: static int getnetnum(const char *num,sockaddr_u *addr, int complain,
! 318: enum gnn_type a_type);
! 319: static int get_multiple_netnums(const char *num, sockaddr_u *addr,
! 320: struct addrinfo **res, int complain,
! 321: enum gnn_type a_type);
! 322: static void save_resolve(char *name, int no_needed, int type,
! 323: int mode, int version, int minpoll, int maxpoll,
! 324: u_int flags, int ttl, keyid_t keyid, u_char *keystr);
! 325: static void abort_resolve(void);
! 326: static void do_resolve_internal(void);
! 327:
! 328:
! 329:
! 330: /* FUNCTIONS FOR INITIALIZATION
! 331: * ----------------------------
! 332: */
! 333:
! 334: #ifdef FREE_CFG_T
! 335: static void
! 336: free_auth_node(
! 337: struct config_tree *ptree
! 338: )
! 339: {
! 340: if (ptree->auth.keys) {
! 341: free(ptree->auth.keys);
! 342: ptree->auth.keys = NULL;
! 343: }
! 344:
! 345: if (ptree->auth.keysdir) {
! 346: free(ptree->auth.keysdir);
! 347: ptree->auth.keysdir = NULL;
! 348: }
! 349:
! 350: if (ptree->auth.ntp_signd_socket) {
! 351: free(ptree->auth.ntp_signd_socket);
! 352: ptree->auth.ntp_signd_socket = NULL;
! 353: }
! 354: }
! 355: #endif /* DEBUG */
! 356:
! 357:
! 358: static void
! 359: init_syntax_tree(
! 360: struct config_tree *ptree
! 361: )
! 362: {
! 363: memset(ptree, 0, sizeof(*ptree));
! 364:
! 365: ptree->peers = create_queue();
! 366: ptree->unpeers = create_queue();
! 367: ptree->orphan_cmds = create_queue();
! 368: ptree->manycastserver = create_queue();
! 369: ptree->multicastclient = create_queue();
! 370: ptree->stats_list = create_queue();
! 371: ptree->filegen_opts = create_queue();
! 372: ptree->discard_opts = create_queue();
! 373: ptree->restrict_opts = create_queue();
! 374: ptree->enable_opts = create_queue();
! 375: ptree->disable_opts = create_queue();
! 376: ptree->tinker = create_queue();
! 377: ptree->fudge = create_queue();
! 378: ptree->logconfig = create_queue();
! 379: ptree->phone = create_queue();
! 380: ptree->qos = create_queue();
! 381: ptree->setvar = create_queue();
! 382: ptree->ttl = create_queue();
! 383: ptree->trap = create_queue();
! 384: ptree->vars = create_queue();
! 385: ptree->nic_rules = create_queue();
! 386: ptree->auth.crypto_cmd_list = create_queue();
! 387: ptree->auth.trusted_key_list = create_queue();
! 388: }
! 389:
! 390:
! 391: #ifdef FREE_CFG_T
! 392: void
! 393: free_all_config_trees(void)
! 394: {
! 395: struct config_tree *ptree;
! 396: struct config_tree *pnext;
! 397:
! 398: ptree = cfg_tree_history;
! 399:
! 400: while (ptree != NULL) {
! 401: pnext = ptree->link;
! 402: free_config_tree(ptree);
! 403: ptree = pnext;
! 404: }
! 405: }
! 406:
! 407:
! 408: static void
! 409: free_config_tree(
! 410: struct config_tree *ptree
! 411: )
! 412: {
! 413: #if defined(_MSC_VER) && defined (_DEBUG)
! 414: _CrtCheckMemory();
! 415: #endif
! 416:
! 417: if (ptree->source.value.s != NULL)
! 418: free(ptree->source.value.s);
! 419:
! 420: free_config_other_modes(ptree);
! 421: free_config_auth(ptree);
! 422: free_config_tos(ptree);
! 423: free_config_monitor(ptree);
! 424: free_config_access(ptree);
! 425: free_config_tinker(ptree);
! 426: free_config_system_opts(ptree);
! 427: free_config_logconfig(ptree);
! 428: free_config_phone(ptree);
! 429: free_config_qos(ptree);
! 430: free_config_setvar(ptree);
! 431: free_config_ttl(ptree);
! 432: free_config_trap(ptree);
! 433: free_config_fudge(ptree);
! 434: free_config_vars(ptree);
! 435: free_config_peers(ptree);
! 436: free_config_unpeers(ptree);
! 437: free_config_nic_rules(ptree);
! 438: #ifdef SIM
! 439: free_config_sim(ptree);
! 440: #endif
! 441: /*
! 442: * Most of these DESTROY_QUEUE()s are handled already by the
! 443: * free_config_*() routines above but it's safe to use twice.
! 444: * Please feel free to remove ones you verified are handled
! 445: * in a free_config_*() routine.
! 446: */
! 447: DESTROY_QUEUE(ptree->peers);
! 448: DESTROY_QUEUE(ptree->unpeers);
! 449: DESTROY_QUEUE(ptree->orphan_cmds);
! 450: DESTROY_QUEUE(ptree->manycastserver);
! 451: DESTROY_QUEUE(ptree->multicastclient);
! 452: DESTROY_QUEUE(ptree->stats_list);
! 453: DESTROY_QUEUE(ptree->filegen_opts);
! 454: DESTROY_QUEUE(ptree->discard_opts);
! 455: DESTROY_QUEUE(ptree->restrict_opts);
! 456: DESTROY_QUEUE(ptree->enable_opts);
! 457: DESTROY_QUEUE(ptree->disable_opts);
! 458: DESTROY_QUEUE(ptree->tinker);
! 459: DESTROY_QUEUE(ptree->fudge);
! 460: DESTROY_QUEUE(ptree->logconfig);
! 461: DESTROY_QUEUE(ptree->phone);
! 462: DESTROY_QUEUE(ptree->qos);
! 463: DESTROY_QUEUE(ptree->setvar);
! 464: DESTROY_QUEUE(ptree->ttl);
! 465: DESTROY_QUEUE(ptree->trap);
! 466: DESTROY_QUEUE(ptree->vars);
! 467:
! 468: free_auth_node(ptree);
! 469:
! 470: free(ptree);
! 471:
! 472: #if defined(_MSC_VER) && defined (_DEBUG)
! 473: _CrtCheckMemory();
! 474: #endif
! 475: }
! 476: #endif /* FREE_CFG_T */
! 477:
! 478:
! 479: #ifdef SAVECONFIG
! 480: /* Dump all trees */
! 481: int
! 482: dump_all_config_trees(
! 483: FILE *df,
! 484: int comment
! 485: )
! 486: {
! 487: struct config_tree *cfg_ptr = cfg_tree_history;
! 488: int return_value = 0;
! 489:
! 490: for (cfg_ptr = cfg_tree_history;
! 491: cfg_ptr != NULL;
! 492: cfg_ptr = cfg_ptr->link)
! 493: return_value |= dump_config_tree(cfg_ptr, df, comment);
! 494:
! 495: return return_value;
! 496: }
! 497:
! 498:
! 499: /* The config dumper */
! 500: int
! 501: dump_config_tree(
! 502: struct config_tree *ptree,
! 503: FILE *df,
! 504: int comment
! 505: )
! 506: {
! 507: struct peer_node *peer = NULL;
! 508: struct unpeer_node *unpeers = NULL;
! 509: struct attr_val *atrv = NULL;
! 510: struct address_node *addr = NULL;
! 511: struct address_node *peer_addr;
! 512: struct address_node *fudge_addr;
! 513: struct filegen_node *fgen_node = NULL;
! 514: struct restrict_node *rest_node = NULL;
! 515: struct addr_opts_node *addr_opts = NULL;
! 516: struct setvar_node *setv_node = NULL;
! 517: nic_rule_node *rule_node;
! 518:
! 519: char **pstr = NULL;
! 520: char *s1;
! 521: char *s2;
! 522: int *intp = NULL;
! 523: void *fudge_ptr;
! 524: void *list_ptr = NULL;
! 525: void *options = NULL;
! 526: void *opt_ptr = NULL;
! 527: int *flags = NULL;
! 528: void *opts = NULL;
! 529: char timestamp[80];
! 530: int enable;
! 531:
! 532: DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
! 533:
! 534: if (comment) {
! 535: if (!strftime(timestamp, sizeof(timestamp),
! 536: "%Y-%m-%d %H:%M:%S",
! 537: localtime(&ptree->timestamp)))
! 538: timestamp[0] = '\0';
! 539:
! 540: fprintf(df, "# %s %s %s\n",
! 541: timestamp,
! 542: (CONF_SOURCE_NTPQ == ptree->source.attr)
! 543: ? "ntpq remote config from"
! 544: : "startup configuration file",
! 545: ptree->source.value.s);
! 546: }
! 547:
! 548: /* For options I didn't find documentation I'll just output its name and the cor. value */
! 549: list_ptr = queue_head(ptree->vars);
! 550: for(; list_ptr != NULL;
! 551: list_ptr = next_node(list_ptr)) {
! 552:
! 553: atrv = (struct attr_val *) list_ptr;
! 554:
! 555: switch (atrv->attr) {
! 556:
! 557: default:
! 558: fprintf(df, "\n# dump error:\n"
! 559: "# unknown vars token %s\n",
! 560: token_name(atrv->attr));
! 561: break;
! 562:
! 563: /* doubles */
! 564: case T_Broadcastdelay:
! 565: case T_Tick:
! 566: case T_WanderThreshold:
! 567: fprintf(df, "%s %g\n",
! 568: keyword(atrv->attr),
! 569: atrv->value.d);
! 570: break;
! 571:
! 572: /* ints */
! 573: case T_Calldelay:
! 574: #ifdef OPENSSL
! 575: case T_Automax:
! 576: #endif
! 577: fprintf(df, "%s %d\n",
! 578: keyword(atrv->attr),
! 579: atrv->value.i);
! 580: break;
! 581:
! 582: /* strings */
! 583: case T_Driftfile:
! 584: case T_Leapfile:
! 585: case T_Logfile:
! 586: case T_Pidfile:
! 587: case T_Saveconfigdir:
! 588: fprintf(df, "%s \"%s\"\n",
! 589: keyword(atrv->attr),
! 590: atrv->value.s);
! 591: break;
! 592: }
! 593: }
! 594:
! 595: list_ptr = queue_head(ptree->logconfig);
! 596: if (list_ptr != NULL) {
! 597:
! 598: fprintf(df, "logconfig");
! 599:
! 600: for(; list_ptr != NULL;
! 601: list_ptr = next_node(list_ptr)) {
! 602:
! 603: atrv = list_ptr;
! 604: fprintf(df, " %c%s", atrv->attr, atrv->value.s);
! 605: }
! 606: fprintf(df, "\n");
! 607: }
! 608:
! 609: if (ptree->stats_dir)
! 610: fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
! 611:
! 612: list_ptr = queue_head(ptree->stats_list);
! 613: if (list_ptr != NULL) {
! 614:
! 615: fprintf(df, "statistics");
! 616: for(; list_ptr != NULL;
! 617: list_ptr = next_node(list_ptr)) {
! 618:
! 619: intp = list_ptr;
! 620:
! 621: fprintf(df, " %s", keyword(*intp));
! 622: }
! 623:
! 624: fprintf(df, "\n");
! 625: }
! 626:
! 627: list_ptr = queue_head(ptree->filegen_opts);
! 628: for(; list_ptr != NULL;
! 629: list_ptr = next_node(list_ptr)) {
! 630:
! 631: fgen_node = list_ptr;
! 632: opt_ptr = queue_head(fgen_node->options);
! 633:
! 634: if (opt_ptr != NULL)
! 635: fprintf(df, "filegen %s",
! 636: keyword(fgen_node->filegen_token));
! 637:
! 638: for(; opt_ptr != NULL;
! 639: opt_ptr = next_node(opt_ptr)) {
! 640:
! 641: atrv = opt_ptr;
! 642:
! 643: switch (atrv->attr) {
! 644:
! 645: default:
! 646: fprintf(df, "\n# dump error:\n"
! 647: "# unknown filegen option token %s\n"
! 648: "filegen %s",
! 649: token_name(atrv->attr),
! 650: keyword(fgen_node->filegen_token));
! 651: break;
! 652:
! 653: case T_File:
! 654: fprintf(df, " file %s",
! 655: atrv->value.s);
! 656: break;
! 657:
! 658: case T_Type:
! 659: fprintf(df, " type %s",
! 660: keyword(atrv->value.i));
! 661: break;
! 662:
! 663: case T_Flag:
! 664: fprintf(df, " %s",
! 665: keyword(atrv->value.i));
! 666: break;
! 667: }
! 668:
! 669: }
! 670:
! 671: fprintf(df, "\n");
! 672: }
! 673:
! 674: list_ptr = queue_head(ptree->auth.crypto_cmd_list);
! 675: if (list_ptr != NULL) {
! 676: fprintf(df, "crypto");
! 677:
! 678: for (; list_ptr != NULL;
! 679: list_ptr = next_node(list_ptr)) {
! 680:
! 681: atrv = list_ptr;
! 682: fprintf(df, " %s %s", keyword(atrv->attr),
! 683: atrv->value.s);
! 684: }
! 685: fprintf(df, "\n");
! 686: }
! 687:
! 688: if (ptree->auth.revoke != 0)
! 689: fprintf(df, "revoke %d\n", ptree->auth.revoke);
! 690:
! 691: if (NULL != ptree->auth.keysdir)
! 692: fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
! 693:
! 694: if (NULL != ptree->auth.keys)
! 695: fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
! 696:
! 697: atrv = queue_head(ptree->auth.trusted_key_list);
! 698: if (atrv != NULL) {
! 699: fprintf(df, "trustedkey");
! 700: do {
! 701: if ('i' == atrv->attr)
! 702: fprintf(df, " %d", atrv->value.i);
! 703: else if ('-' == atrv->attr)
! 704: fprintf(df, " (%u ... %u)",
! 705: atrv->value.u >> 16,
! 706: atrv->value.u & 0xffff);
! 707: else
! 708: fprintf(df, "\n# dump error:\n"
! 709: "# unknown trustedkey attr %d\n"
! 710: "trustedkey", atrv->attr);
! 711: } while (NULL != (atrv = next_node(atrv)));
! 712: fprintf(df, "\n");
! 713: }
! 714:
! 715: if (ptree->auth.control_key)
! 716: fprintf(df, "controlkey %d\n", ptree->auth.control_key);
! 717:
! 718: if (ptree->auth.request_key)
! 719: fprintf(df, "requestkey %d\n", ptree->auth.request_key);
! 720:
! 721: /* dump enable list, then disable list */
! 722: for (enable = 1; enable >= 0; enable--) {
! 723:
! 724: list_ptr = (enable)
! 725: ? queue_head(ptree->enable_opts)
! 726: : queue_head(ptree->disable_opts);
! 727:
! 728: if (list_ptr != NULL) {
! 729: fprintf(df, (enable)
! 730: ? "enable"
! 731: : "disable");
! 732:
! 733: for(; list_ptr != NULL;
! 734: list_ptr = next_node(list_ptr)) {
! 735:
! 736: atrv = (struct attr_val *) list_ptr;
! 737:
! 738: fprintf(df, " %s",
! 739: keyword(atrv->value.i));
! 740: }
! 741: fprintf(df, "\n");
! 742: }
! 743: }
! 744:
! 745: list_ptr = queue_head(ptree->orphan_cmds);
! 746: if (list_ptr != NULL)
! 747: fprintf(df, "tos");
! 748:
! 749: for(; list_ptr != NULL;
! 750: list_ptr = next_node(list_ptr)) {
! 751:
! 752: atrv = list_ptr;
! 753:
! 754: switch (atrv->attr) {
! 755:
! 756: default:
! 757: fprintf(df, "\n# dump error:\n"
! 758: "# unknown tos token %s\n"
! 759: "tos", token_name(atrv->attr));
! 760: break;
! 761:
! 762: /* ints */
! 763: case T_Ceiling:
! 764: case T_Floor:
! 765: case T_Cohort:
! 766: case T_Orphan:
! 767: case T_Minclock:
! 768: case T_Maxclock:
! 769: case T_Minsane:
! 770: case T_Beacon:
! 771: fprintf(df, " %s %d", keyword(atrv->attr),
! 772: (int)atrv->value.d);
! 773: break;
! 774:
! 775: /* doubles */
! 776: case T_Mindist:
! 777: case T_Maxdist:
! 778: fprintf(df, " %s %g", keyword(atrv->attr),
! 779: atrv->value.d);
! 780: break;
! 781: }
! 782: }
! 783: if (queue_head(ptree->orphan_cmds) != NULL)
! 784: fprintf(df, "\n");
! 785:
! 786: list_ptr = queue_head(ptree->tinker);
! 787: if (list_ptr != NULL) {
! 788:
! 789: fprintf(df, "tinker");
! 790:
! 791: for(; list_ptr != NULL;
! 792: list_ptr = next_node(list_ptr)) {
! 793:
! 794: atrv = list_ptr;
! 795: fprintf(df, " %s %g", keyword(atrv->attr),
! 796: atrv->value.d);
! 797: }
! 798:
! 799: fprintf(df, "\n");
! 800: }
! 801:
! 802: if (ptree->broadcastclient)
! 803: fprintf(df, "broadcastclient\n");
! 804:
! 805: list_ptr = queue_head(ptree->peers);
! 806: for (; list_ptr != NULL;
! 807: list_ptr = next_node(list_ptr)) {
! 808:
! 809: peer = list_ptr;
! 810: addr = peer->addr;
! 811: fprintf(df, "%s", keyword(peer->host_mode));
! 812:
! 813: switch (addr->type) {
! 814:
! 815: default:
! 816: fprintf(df, "# dump error:\n"
! 817: "# unknown peer family %d for:\n"
! 818: "peer", addr->type);
! 819: break;
! 820:
! 821: case AF_UNSPEC:
! 822: break;
! 823:
! 824: case AF_INET:
! 825: fprintf(df, " -4");
! 826: break;
! 827:
! 828: case AF_INET6:
! 829: fprintf(df, " -6");
! 830: break;
! 831: }
! 832: fprintf(df, " %s", addr->address);
! 833:
! 834: if (peer->minpoll != 0)
! 835: fprintf(df, " minpoll %d", peer->minpoll);
! 836:
! 837: if (peer->maxpoll != 0)
! 838: fprintf(df, " maxpoll %d", peer->maxpoll);
! 839:
! 840: if (peer->ttl != 0) {
! 841: if (strlen(addr->address) > 8
! 842: && !memcmp(addr->address, "127.127.", 8))
! 843: fprintf(df, " mode %d", peer->ttl);
! 844: else
! 845: fprintf(df, " ttl %d", peer->ttl);
! 846: }
! 847:
! 848: if (peer->peerversion != NTP_VERSION)
! 849: fprintf(df, " version %d", peer->peerversion);
! 850:
! 851: if (peer->peerkey != 0)
! 852: fprintf(df, " key %d", peer->peerkey);
! 853:
! 854: if (peer->bias != 0.)
! 855: fprintf(df, " bias %g", peer->bias);
! 856:
! 857: for (atrv = queue_head(peer->peerflags);
! 858: atrv != NULL;
! 859: atrv = next_node(atrv)) {
! 860:
! 861: NTP_INSIST(T_Flag == atrv->attr);
! 862: NTP_INSIST(T_Integer == atrv->type);
! 863:
! 864: fprintf(df, " %s", keyword(atrv->value.i));
! 865: }
! 866:
! 867: fprintf(df, "\n");
! 868:
! 869: fudge_ptr = queue_head(ptree->fudge);
! 870: for(; fudge_ptr != NULL;
! 871: fudge_ptr = next_node(fudge_ptr)) {
! 872:
! 873:
! 874: addr_opts = (struct addr_opts_node *) fudge_ptr;
! 875: peer_addr = peer->addr;
! 876: fudge_addr = addr_opts->addr;
! 877:
! 878: s1 = peer_addr->address;
! 879: s2 = fudge_addr->address;
! 880:
! 881: if (!strcmp(s1, s2)) {
! 882:
! 883: fprintf(df, "fudge %s", addr_opts->addr->address);
! 884:
! 885: opts = queue_head(addr_opts->options);
! 886:
! 887: for(; opts != NULL; opts = next_node(opts)) {
! 888: atrv = (struct attr_val *) opts;
! 889:
! 890: switch (atrv->attr) {
! 891:
! 892: default:
! 893: fprintf(df, "\n# dump error:\n"
! 894: "# unknown fudge option %s\n"
! 895: "fudge %s",
! 896: token_name(atrv->attr),
! 897: addr_opts->addr->address);
! 898: break;
! 899:
! 900: /* doubles */
! 901: case T_Time1:
! 902: case T_Time2:
! 903: fprintf(df, " %s %g",
! 904: keyword(atrv->attr),
! 905: atrv->value.d);
! 906: break;
! 907:
! 908: /* ints */
! 909: case T_Stratum:
! 910: case T_Flag1:
! 911: case T_Flag2:
! 912: case T_Flag3:
! 913: case T_Flag4:
! 914: fprintf(df, " %s %d",
! 915: keyword(atrv->attr),
! 916: atrv->value.i);
! 917: break;
! 918:
! 919: /* strings */
! 920: case T_Refid:
! 921: fprintf(df, " %s %s",
! 922: keyword(atrv->attr),
! 923: atrv->value.s);
! 924: break;
! 925: }
! 926: }
! 927: fprintf(df, "\n");
! 928: }
! 929: }
! 930: }
! 931:
! 932: list_ptr = queue_head(ptree->manycastserver);
! 933: if (list_ptr != NULL) {
! 934: addr = list_ptr;
! 935: fprintf(df, "manycastserver %s", addr->address);
! 936: for (addr = next_node(addr);
! 937: addr != NULL;
! 938: addr = next_node(addr))
! 939: fprintf(df, " %s", addr->address);
! 940: fprintf(df, "\n");
! 941: }
! 942:
! 943: list_ptr = queue_head(ptree->multicastclient);
! 944: if (list_ptr != NULL) {
! 945: addr = list_ptr;
! 946: fprintf(df, "multicastclient %s", addr->address);
! 947: for (addr = next_node(addr);
! 948: addr != NULL;
! 949: addr = next_node(addr))
! 950: fprintf(df, " %s", addr->address);
! 951: fprintf(df, "\n");
! 952: }
! 953:
! 954: list_ptr = queue_head(ptree->unpeers);
! 955: for (; list_ptr != NULL;
! 956: list_ptr = next_node(list_ptr)) {
! 957:
! 958: unpeers = (struct unpeer_node *) list_ptr;
! 959:
! 960: fprintf(df, "unpeer %s\n", (unpeers->addr)->address);
! 961: }
! 962:
! 963: list_ptr = queue_head(ptree->discard_opts);
! 964: if (list_ptr != NULL) {
! 965:
! 966: fprintf(df, "discard");
! 967:
! 968: for(; list_ptr != NULL;
! 969: list_ptr = next_node(list_ptr)) {
! 970:
! 971: atrv = list_ptr;
! 972: fprintf(df, " %s %d", keyword(atrv->attr),
! 973: atrv->value.i);
! 974: }
! 975: fprintf(df, "\n");
! 976: }
! 977:
! 978: list_ptr = queue_head(ptree->restrict_opts);
! 979: for (; list_ptr != NULL;
! 980: list_ptr = next_node(list_ptr)) {
! 981:
! 982: rest_node = list_ptr;
! 983: if (NULL == rest_node->addr)
! 984: s1 = "default";
! 985: else
! 986: s1 = rest_node->addr->address;
! 987:
! 988: fprintf(df, "restrict %s", s1);
! 989:
! 990: if (rest_node->mask != NULL)
! 991: fprintf(df, " mask %s",
! 992: rest_node->mask->address);
! 993:
! 994: flags = queue_head(rest_node->flags);
! 995: for (; flags != NULL; flags = next_node(flags))
! 996: fprintf(df, " %s", keyword(*flags));
! 997:
! 998: fprintf(df, "\n");
! 999: }
! 1000:
! 1001: list_ptr = queue_head(ptree->nic_rules);
! 1002: for (; list_ptr != NULL;
! 1003: list_ptr = next_node(list_ptr)) {
! 1004:
! 1005: rule_node = list_ptr;
! 1006: fprintf(df, "interface %s %s\n",
! 1007: keyword(rule_node->action),
! 1008: (rule_node->match_class)
! 1009: ? keyword(rule_node->match_class)
! 1010: : rule_node->if_name);
! 1011: }
! 1012:
! 1013: list_ptr = queue_head(ptree->phone);
! 1014: if (list_ptr != NULL) {
! 1015:
! 1016: fprintf(df, "phone");
! 1017:
! 1018: for(; list_ptr != NULL;
! 1019: list_ptr = next_node(list_ptr)) {
! 1020:
! 1021: pstr = list_ptr;
! 1022: fprintf(df, " %s", *pstr);
! 1023: }
! 1024:
! 1025: fprintf(df, "\n");
! 1026: }
! 1027:
! 1028: list_ptr = queue_head(ptree->qos);
! 1029: if (list_ptr != NULL) {
! 1030:
! 1031: fprintf(df, "qos");
! 1032:
! 1033: for(; list_ptr != NULL;
! 1034: list_ptr = next_node(list_ptr)) {
! 1035:
! 1036: atrv = list_ptr;
! 1037: fprintf(df, " %s", atrv->value.s);
! 1038: }
! 1039:
! 1040: fprintf(df, "\n");
! 1041: }
! 1042:
! 1043: list_ptr = queue_head(ptree->setvar);
! 1044: for(; list_ptr != NULL;
! 1045: list_ptr = next_node(list_ptr)) {
! 1046:
! 1047: setv_node = list_ptr;
! 1048: s1 = quote_if_needed(setv_node->var);
! 1049: s2 = quote_if_needed(setv_node->val);
! 1050: fprintf(df, "setvar %s = %s", s1, s2);
! 1051: free(s1);
! 1052: free(s2);
! 1053:
! 1054: if (setv_node->isdefault)
! 1055: fprintf(df, " default");
! 1056:
! 1057: fprintf(df, "\n");
! 1058: }
! 1059:
! 1060:
! 1061: list_ptr = queue_head(ptree->ttl);
! 1062: if (list_ptr != NULL) {
! 1063:
! 1064: fprintf(df, "ttl");
! 1065:
! 1066: for(; list_ptr != NULL;
! 1067: list_ptr = next_node(list_ptr)) {
! 1068:
! 1069: intp = list_ptr;
! 1070: fprintf(df, " %d", *intp);
! 1071: }
! 1072:
! 1073: fprintf(df, "\n");
! 1074: }
! 1075:
! 1076: list_ptr = queue_head(ptree->trap);
! 1077: for(; list_ptr != NULL;
! 1078: list_ptr = next_node(list_ptr)) {
! 1079:
! 1080: addr_opts = list_ptr;
! 1081: addr = addr_opts->addr;
! 1082:
! 1083: fprintf(df, "trap %s", addr->address);
! 1084:
! 1085: options = queue_head(addr_opts->options);
! 1086:
! 1087: for(; options != NULL;
! 1088: options = next_node(options)) {
! 1089:
! 1090: atrv = options;
! 1091:
! 1092: switch (atrv->attr) {
! 1093:
! 1094: default:
! 1095: fprintf(df, "\n# dump error:\n"
! 1096: "# unknown trap token %d\n"
! 1097: "trap %s", atrv->attr,
! 1098: addr->address);
! 1099: break;
! 1100:
! 1101: case T_Port:
! 1102: fprintf(df, " port %d", atrv->value.i);
! 1103: break;
! 1104:
! 1105: case T_Interface:
! 1106: addr = (struct address_node *) atrv->value.p;
! 1107: fprintf(df, " interface %s", addr->address);
! 1108: break;
! 1109: }
! 1110: }
! 1111:
! 1112: fprintf(df, "\n");
! 1113: }
! 1114:
! 1115: return 0;
! 1116: }
! 1117: #endif /* SAVECONFIG */
! 1118:
! 1119:
! 1120: /* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
! 1121: * -----------------------------------------------
! 1122: */
! 1123:
! 1124: queue *
! 1125: enqueue_in_new_queue(
! 1126: void *my_node
! 1127: )
! 1128: {
! 1129: queue *my_queue = create_queue();
! 1130:
! 1131: enqueue(my_queue, my_node);
! 1132: return my_queue;
! 1133: }
! 1134:
! 1135: struct attr_val *
! 1136: create_attr_dval(
! 1137: int attr,
! 1138: double value
! 1139: )
! 1140: {
! 1141: struct attr_val *my_val;
! 1142:
! 1143: my_val = get_node(sizeof *my_val);
! 1144: my_val->attr = attr;
! 1145: my_val->value.d = value;
! 1146: my_val->type = T_Double;
! 1147: return my_val;
! 1148: }
! 1149:
! 1150: struct attr_val *
! 1151: create_attr_ival(
! 1152: int attr,
! 1153: int value
! 1154: )
! 1155: {
! 1156: struct attr_val *my_val;
! 1157:
! 1158: my_val = get_node(sizeof *my_val);
! 1159: my_val->attr = attr;
! 1160: my_val->value.i = value;
! 1161: my_val->type = T_Integer;
! 1162: return my_val;
! 1163: }
! 1164:
! 1165: struct attr_val *
! 1166: create_attr_shorts(
! 1167: int attr,
! 1168: ntp_u_int16_t val1,
! 1169: ntp_u_int16_t val2
! 1170: )
! 1171: {
! 1172: struct attr_val *my_val;
! 1173:
! 1174: my_val = get_node(sizeof *my_val);
! 1175: my_val->attr = attr;
! 1176: my_val->value.u = (val1 << 16) | val2;
! 1177: my_val->type = T_Integer;
! 1178: return my_val;
! 1179: }
! 1180:
! 1181: struct attr_val *
! 1182: create_attr_sval(
! 1183: int attr,
! 1184: char *s
! 1185: )
! 1186: {
! 1187: struct attr_val *my_val;
! 1188:
! 1189: my_val = get_node(sizeof *my_val);
! 1190: my_val->attr = attr;
! 1191: if (NULL == s) /* free() hates NULL */
! 1192: s = estrdup("");
! 1193: my_val->value.s = s;
! 1194: my_val->type = T_String;
! 1195: return my_val;
! 1196: }
! 1197:
! 1198: struct attr_val *
! 1199: create_attr_pval(
! 1200: int attr,
! 1201: void *p
! 1202: )
! 1203: {
! 1204: struct attr_val *my_val;
! 1205:
! 1206: my_val = get_node(sizeof *my_val);
! 1207: my_val->attr = attr;
! 1208: my_val->value.p = p;
! 1209: my_val->type = T_Void;
! 1210: return my_val;
! 1211: }
! 1212:
! 1213: int *
! 1214: create_ival(
! 1215: int val
! 1216: )
! 1217: {
! 1218: int *p = get_node(sizeof *p);
! 1219:
! 1220: *p = val;
! 1221: return p;
! 1222: }
! 1223:
! 1224: double *
! 1225: create_dval(
! 1226: double val
! 1227: )
! 1228: {
! 1229: double *p = get_node(sizeof *p);
! 1230:
! 1231: *p = val;
! 1232: return p;
! 1233: }
! 1234:
! 1235: void **
! 1236: create_pval(
! 1237: void *val
! 1238: )
! 1239: {
! 1240: void **p = get_node(sizeof *p);
! 1241:
! 1242: *p = val;
! 1243: return p;
! 1244: }
! 1245:
! 1246: struct address_node *
! 1247: create_address_node(
! 1248: char *addr,
! 1249: int type
! 1250: )
! 1251: {
! 1252: struct address_node *my_node;
! 1253:
! 1254: NTP_REQUIRE(NULL != addr);
! 1255:
! 1256: my_node = get_node(sizeof *my_node);
! 1257:
! 1258: my_node->address = addr;
! 1259: my_node->type = type;
! 1260:
! 1261: return my_node;
! 1262: }
! 1263:
! 1264:
! 1265: void
! 1266: destroy_address_node(
! 1267: struct address_node *my_node
! 1268: )
! 1269: {
! 1270: NTP_REQUIRE(NULL != my_node);
! 1271: NTP_REQUIRE(NULL != my_node->address);
! 1272:
! 1273: free(my_node->address);
! 1274: free_node(my_node);
! 1275: }
! 1276:
! 1277:
! 1278: struct peer_node *
! 1279: create_peer_node(
! 1280: int hmode,
! 1281: struct address_node *addr,
! 1282: queue *options
! 1283: )
! 1284: {
! 1285: struct peer_node *my_node;
! 1286: struct attr_val *option;
! 1287: int freenode;
! 1288: int errflag = 0;
! 1289:
! 1290: my_node = get_node(sizeof(*my_node));
! 1291:
! 1292: /* Initialize node values to default */
! 1293: my_node->minpoll = 0;
! 1294: my_node->maxpoll = 0;
! 1295: my_node->ttl = 0;
! 1296: my_node->peerversion = NTP_VERSION;
! 1297: my_node->peerkey = 0;
! 1298: my_node->bias = 0;
! 1299: my_node->peerflags = create_queue();
! 1300:
! 1301: /* Now set the node to the read values */
! 1302: my_node->host_mode = hmode;
! 1303: my_node->addr = addr;
! 1304:
! 1305: /*
! 1306: * the options list mixes items that will be saved in the
! 1307: * peer_node as explicit members, such as minpoll, and
! 1308: * those that are moved from the options queue intact
! 1309: * to the peer_node's peerflags queue. The options
! 1310: * queue is consumed and destroyed here.
! 1311: */
! 1312:
! 1313: while (options && NULL != (option = dequeue(options))) {
! 1314:
! 1315: freenode = 1;
! 1316: /* Check the kind of option being set */
! 1317: switch (option->attr) {
! 1318:
! 1319: case T_Flag:
! 1320: enqueue(my_node->peerflags, option);
! 1321: freenode = 0;
! 1322: break;
! 1323:
! 1324: case T_Minpoll:
! 1325: if (option->value.i < NTP_MINPOLL) {
! 1326: msyslog(LOG_INFO,
! 1327: "minpoll: provided value (%d) is below minimum (%d)",
! 1328: option->value.i, NTP_MINPOLL);
! 1329: my_node->minpoll = NTP_MINPOLL;
! 1330: }
! 1331: else
! 1332: my_node->minpoll = option->value.i;
! 1333: break;
! 1334:
! 1335: case T_Maxpoll:
! 1336: if (option->value.i > NTP_MAXPOLL) {
! 1337: msyslog(LOG_INFO,
! 1338: "maxpoll: provided value (%d) is above maximum (%d)",
! 1339: option->value.i, NTP_MAXPOLL);
! 1340: my_node->maxpoll = NTP_MAXPOLL;
! 1341: }
! 1342: else
! 1343: my_node->maxpoll = option->value.i;
! 1344: break;
! 1345:
! 1346: case T_Ttl:
! 1347: if (my_node->ttl >= MAX_TTL) {
! 1348: msyslog(LOG_ERR, "ttl: invalid argument");
! 1349: errflag = 1;
! 1350: }
! 1351: else
! 1352: my_node->ttl = option->value.i;
! 1353: break;
! 1354:
! 1355: case T_Mode:
! 1356: my_node->ttl = option->value.i;
! 1357: break;
! 1358:
! 1359: case T_Key:
! 1360: my_node->peerkey = option->value.i;
! 1361: break;
! 1362:
! 1363: case T_Version:
! 1364: my_node->peerversion = option->value.i;
! 1365: break;
! 1366:
! 1367: case T_Bias:
! 1368: my_node->bias = option->value.d;
! 1369: break;
! 1370:
! 1371: default:
! 1372: msyslog(LOG_ERR,
! 1373: "Unknown peer/server option token %s",
! 1374: token_name(option->attr));
! 1375: errflag = 1;
! 1376: }
! 1377: if (freenode)
! 1378: free_node(option);
! 1379: }
! 1380: DESTROY_QUEUE(options);
! 1381:
! 1382: /* Check if errors were reported. If yes, ignore the node */
! 1383: if (errflag) {
! 1384: free_node(my_node);
! 1385: my_node = NULL;
! 1386: }
! 1387: return my_node;
! 1388: }
! 1389:
! 1390:
! 1391: struct unpeer_node *
! 1392: create_unpeer_node(
! 1393: struct address_node *addr
! 1394: )
! 1395: {
! 1396: struct unpeer_node * my_node;
! 1397: char * pch;
! 1398:
! 1399: my_node = get_node(sizeof(*my_node));
! 1400:
! 1401: /*
! 1402: * From the parser's perspective an association ID fits into
! 1403: * its generic T_String definition of a name/address "address".
! 1404: * We treat all valid 16-bit numbers as association IDs.
! 1405: */
! 1406: pch = addr->address;
! 1407: while (*pch && isdigit(*pch))
! 1408: pch++;
! 1409:
! 1410: if (!*pch
! 1411: && 1 == sscanf(addr->address, "%u", &my_node->assocID)
! 1412: && my_node->assocID <= USHRT_MAX) {
! 1413:
! 1414: destroy_address_node(addr);
! 1415: my_node->addr = NULL;
! 1416: } else {
! 1417: my_node->assocID = 0;
! 1418: my_node->addr = addr;
! 1419: }
! 1420:
! 1421: return my_node;
! 1422: }
! 1423:
! 1424: struct filegen_node *
! 1425: create_filegen_node(
! 1426: int filegen_token,
! 1427: queue * options
! 1428: )
! 1429: {
! 1430: struct filegen_node *my_node;
! 1431:
! 1432: my_node = get_node(sizeof *my_node);
! 1433: my_node->filegen_token = filegen_token;
! 1434: my_node->options = options;
! 1435:
! 1436: return my_node;
! 1437: }
! 1438:
! 1439:
! 1440: struct restrict_node *
! 1441: create_restrict_node(
! 1442: struct address_node *addr,
! 1443: struct address_node *mask,
! 1444: queue *flags,
! 1445: int line_no
! 1446: )
! 1447: {
! 1448: struct restrict_node *my_node;
! 1449:
! 1450: my_node = get_node(sizeof *my_node);
! 1451:
! 1452: my_node->addr = addr;
! 1453: my_node->mask = mask;
! 1454: my_node->flags = flags;
! 1455: my_node->line_no = line_no;
! 1456:
! 1457: return my_node;
! 1458: }
! 1459:
! 1460: void
! 1461: destroy_restrict_node(
! 1462: struct restrict_node *my_node
! 1463: )
! 1464: {
! 1465: /* With great care, free all the memory occupied by
! 1466: * the restrict node
! 1467: */
! 1468: if (my_node->addr)
! 1469: destroy_address_node(my_node->addr);
! 1470: if (my_node->mask)
! 1471: destroy_address_node(my_node->mask);
! 1472: DESTROY_QUEUE(my_node->flags);
! 1473: free_node(my_node);
! 1474: }
! 1475:
! 1476:
! 1477: struct setvar_node *
! 1478: create_setvar_node(
! 1479: char * var,
! 1480: char * val,
! 1481: int isdefault
! 1482: )
! 1483: {
! 1484: char * pch;
! 1485: struct setvar_node *my_node;
! 1486:
! 1487: /* do not allow = in the variable name */
! 1488: if (NULL != (pch = strchr(var, '=')))
! 1489: *pch = '\0';
! 1490:
! 1491: /* Now store the string into a setvar_node */
! 1492: my_node = get_node(sizeof *my_node);
! 1493: my_node->var = var;
! 1494: my_node->val = val;
! 1495: my_node->isdefault = isdefault;
! 1496:
! 1497: return my_node;
! 1498: }
! 1499:
! 1500:
! 1501: nic_rule_node *
! 1502: create_nic_rule_node(
! 1503: int match_class,
! 1504: char *if_name, /* interface name or numeric address */
! 1505: int action
! 1506: )
! 1507: {
! 1508: nic_rule_node *my_node;
! 1509:
! 1510: NTP_REQUIRE(match_class != 0 || if_name != NULL);
! 1511:
! 1512: my_node = get_node(sizeof(*my_node));
! 1513: my_node->match_class = match_class;
! 1514: my_node->if_name = if_name;
! 1515: my_node->action = action;
! 1516:
! 1517: return my_node;
! 1518: }
! 1519:
! 1520:
! 1521: struct addr_opts_node *
! 1522: create_addr_opts_node(
! 1523: struct address_node *addr,
! 1524: queue *options
! 1525: )
! 1526: {
! 1527: struct addr_opts_node *my_node;
! 1528:
! 1529: my_node = get_node(sizeof *my_node);
! 1530: my_node->addr = addr;
! 1531: my_node->options = options;
! 1532: return my_node;
! 1533: }
! 1534:
! 1535: script_info *
! 1536: create_sim_script_info(
! 1537: double duration,
! 1538: queue *script_queue
! 1539: )
! 1540: {
! 1541: #ifdef SIM
! 1542: return NULL;
! 1543: #else
! 1544: script_info *my_info;
! 1545: struct attr_val *my_attr_val;
! 1546:
! 1547: my_info = get_node(sizeof *my_info);
! 1548:
! 1549: /* Initialize Script Info with default values*/
! 1550: my_info->duration = duration;
! 1551: my_info->freq_offset = 0;
! 1552: my_info->wander = 0;
! 1553: my_info->jitter = 0;
! 1554: my_info->prop_delay = NET_DLY;
! 1555: my_info->proc_delay = PROC_DLY;
! 1556:
! 1557: /* Traverse the script_queue and fill out non-default values */
! 1558: my_attr_val = queue_head(script_queue);
! 1559: while (my_attr_val != NULL) {
! 1560: /* Set the desired value */
! 1561: switch (my_attr_val->attr) {
! 1562:
! 1563: case T_Freq_Offset:
! 1564: my_info->freq_offset = my_attr_val->value.d;
! 1565: break;
! 1566:
! 1567: case T_Wander:
! 1568: my_info->wander = my_attr_val->value.d;
! 1569: break;
! 1570:
! 1571: case T_Jitter:
! 1572: my_info->jitter = my_attr_val->value.d;
! 1573: break;
! 1574:
! 1575: case T_Prop_Delay:
! 1576: my_info->prop_delay = my_attr_val->value.d;
! 1577: break;
! 1578:
! 1579: case T_Proc_Delay:
! 1580: my_info->proc_delay = my_attr_val->value.d;
! 1581: break;
! 1582:
! 1583: default:
! 1584: msyslog(LOG_ERR,
! 1585: "Unknown script token %d",
! 1586: my_attr_val->attr);
! 1587: }
! 1588: }
! 1589: return (my_info);
! 1590: #endif
! 1591: }
! 1592:
! 1593:
! 1594: #if !defined(SIM)
! 1595:
! 1596: #define ADDR_LENGTH 16 + 1
! 1597:
! 1598: static sockaddr_u *
! 1599: get_next_address(
! 1600: struct address_node *addr
! 1601: )
! 1602: {
! 1603: const char addr_prefix[] = "192.168.0.";
! 1604: static int curr_addr_no = 1;
! 1605: char addr_string[ADDR_LENGTH];
! 1606: sockaddr_u *final_addr;
! 1607: struct addrinfo *ptr;
! 1608: int retval;
! 1609:
! 1610: final_addr = emalloc(sizeof *final_addr);
! 1611:
! 1612: if (addr->type == T_String) {
! 1613: snprintf(addr_string, ADDR_LENGTH, "%s%d", addr_prefix, curr_addr_no++);
! 1614: printf("Selecting ip address %s for hostname %s\n", addr_string, addr->address);
! 1615: retval = getaddrinfo(addr_string, "ntp", NULL, &ptr);
! 1616: } else
! 1617: retval = getaddrinfo(addr->address, "ntp", NULL, &ptr);
! 1618:
! 1619: if (!retval) {
! 1620: memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
! 1621: fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", stoa(final_addr));
! 1622: }
! 1623: else {
! 1624: fprintf(stderr, "ERROR!! Could not get a new address\n");
! 1625: exit(1);
! 1626: }
! 1627: freeaddrinfo(ptr);
! 1628: return final_addr;
! 1629: }
! 1630: #endif /* !SIM */
! 1631:
! 1632:
! 1633: server_info *
! 1634: create_sim_server(
! 1635: struct address_node *addr,
! 1636: double server_offset,
! 1637: queue *script
! 1638: )
! 1639: {
! 1640: #ifdef SIM
! 1641: return NULL;
! 1642: #else
! 1643: server_info *my_info;
! 1644:
! 1645: my_info = get_node(sizeof *my_info);
! 1646:
! 1647: my_info->server_time = server_offset;
! 1648: my_info->addr = get_next_address(addr);
! 1649: my_info->script = script;
! 1650: my_info->curr_script = dequeue(my_info->script);
! 1651: return my_info;
! 1652: #endif /* SIM */
! 1653: }
! 1654:
! 1655: struct sim_node *
! 1656: create_sim_node(
! 1657: queue *init_opts,
! 1658: queue *servers
! 1659: )
! 1660: {
! 1661: struct sim_node *my_node;
! 1662:
! 1663: my_node = get_node(sizeof *my_node);
! 1664:
! 1665: my_node->init_opts = init_opts;
! 1666: my_node->servers = servers;
! 1667: return my_node;
! 1668: }
! 1669:
! 1670:
! 1671:
! 1672:
! 1673: /* FUNCTIONS FOR PERFORMING THE CONFIGURATION
! 1674: * ------------------------------------------
! 1675: */
! 1676:
! 1677: static void
! 1678: config_other_modes(
! 1679: struct config_tree *ptree
! 1680: )
! 1681: {
! 1682: sockaddr_u addr_sock;
! 1683: struct address_node *addr_node;
! 1684:
! 1685: if (ptree->broadcastclient)
! 1686: proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 0., NULL);
! 1687:
! 1688: /* Configure the many-cast servers */
! 1689: addr_node = queue_head(ptree->manycastserver);
! 1690: if (addr_node != NULL) {
! 1691: do {
! 1692: ZERO_SOCK(&addr_sock);
! 1693: AF(&addr_sock) = (u_short)addr_node->type;
! 1694:
! 1695: if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK) == 1)
! 1696: proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
! 1697:
! 1698: addr_node = next_node(addr_node);
! 1699: } while (addr_node != NULL);
! 1700: sys_manycastserver = 1;
! 1701: }
! 1702:
! 1703: /* Configure the multicast clients */
! 1704: addr_node = queue_head(ptree->multicastclient);
! 1705: if (addr_node != NULL) {
! 1706: do {
! 1707: ZERO_SOCK(&addr_sock);
! 1708: AF(&addr_sock) = (u_short)addr_node->type;
! 1709:
! 1710: if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK) == 1)
! 1711: proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
! 1712:
! 1713: addr_node = next_node(addr_node);
! 1714: } while (addr_node != NULL);
! 1715: proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
! 1716: }
! 1717: }
! 1718:
! 1719:
! 1720: #ifdef FREE_CFG_T
! 1721: static void
! 1722: free_config_other_modes(
! 1723: struct config_tree *ptree
! 1724: )
! 1725: {
! 1726: struct address_node *addr_node;
! 1727:
! 1728: while (NULL != (addr_node = dequeue(ptree->manycastserver)))
! 1729: destroy_address_node(addr_node);
! 1730:
! 1731: while (NULL != (addr_node = dequeue(ptree->multicastclient)))
! 1732: destroy_address_node(addr_node);
! 1733: }
! 1734: #endif /* FREE_CFG_T */
! 1735:
! 1736:
! 1737: static void
! 1738: config_auth(
! 1739: struct config_tree *ptree
! 1740: )
! 1741: {
! 1742: ntp_u_int16_t ufirst;
! 1743: ntp_u_int16_t ulast;
! 1744: ntp_u_int16_t u;
! 1745: struct attr_val *my_val;
! 1746: #ifdef OPENSSL
! 1747: #ifndef NO_INTRES
! 1748: u_char digest[EVP_MAX_MD_SIZE];
! 1749: u_int digest_len;
! 1750: EVP_MD_CTX ctx;
! 1751: #endif
! 1752: int item;
! 1753: #endif
! 1754:
! 1755: /* Crypto Command */
! 1756: #ifdef OPENSSL
! 1757: item = -1; /* quiet warning */
! 1758: my_val = queue_head(ptree->auth.crypto_cmd_list);
! 1759: while (my_val != NULL) {
! 1760: switch (my_val->attr) {
! 1761:
! 1762: default:
! 1763: NTP_INSIST(0);
! 1764: break;
! 1765:
! 1766: case T_Host:
! 1767: item = CRYPTO_CONF_PRIV;
! 1768: break;
! 1769:
! 1770: case T_Ident:
! 1771: item = CRYPTO_CONF_IDENT;
! 1772: break;
! 1773:
! 1774: case T_Pw:
! 1775: item = CRYPTO_CONF_PW;
! 1776: break;
! 1777:
! 1778: case T_Randfile:
! 1779: item = CRYPTO_CONF_RAND;
! 1780: break;
! 1781:
! 1782: case T_Sign:
! 1783: item = CRYPTO_CONF_SIGN;
! 1784: break;
! 1785:
! 1786: case T_Digest:
! 1787: item = CRYPTO_CONF_NID;
! 1788: break;
! 1789: }
! 1790: crypto_config(item, my_val->value.s);
! 1791: my_val = next_node(my_val);
! 1792: }
! 1793: #endif /* OPENSSL */
! 1794:
! 1795: /* Keysdir Command */
! 1796: if (ptree->auth.keysdir) {
! 1797: if (keysdir != default_keysdir)
! 1798: free(keysdir);
! 1799: keysdir = estrdup(ptree->auth.keysdir);
! 1800: }
! 1801:
! 1802:
! 1803: /* ntp_signd_socket Command */
! 1804: if (ptree->auth.ntp_signd_socket) {
! 1805: if (ntp_signd_socket != default_ntp_signd_socket)
! 1806: free(ntp_signd_socket);
! 1807: ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
! 1808: }
! 1809:
! 1810: #ifdef OPENSSL
! 1811: if (ptree->auth.cryptosw && !cryptosw) {
! 1812: crypto_setup();
! 1813: cryptosw = 1;
! 1814: }
! 1815: #endif /* OPENSSL */
! 1816:
! 1817: /* Keys Command */
! 1818: if (ptree->auth.keys)
! 1819: getauthkeys(ptree->auth.keys);
! 1820:
! 1821: /* Control Key Command */
! 1822: if (ptree->auth.control_key)
! 1823: ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
! 1824:
! 1825: /* Requested Key Command */
! 1826: if (ptree->auth.request_key) {
! 1827: DPRINTF(4, ("set info_auth_keyid to %08lx\n",
! 1828: (u_long) ptree->auth.request_key));
! 1829: info_auth_keyid = (keyid_t)ptree->auth.request_key;
! 1830: }
! 1831:
! 1832: /* Trusted Key Command */
! 1833: my_val = queue_head(ptree->auth.trusted_key_list);
! 1834: for (; my_val != NULL; my_val = next_node(my_val)) {
! 1835: if ('i' == my_val->attr)
! 1836: authtrust(my_val->value.i, 1);
! 1837: else if ('-' == my_val->attr) {
! 1838: ufirst = my_val->value.u >> 16;
! 1839: ulast = my_val->value.u & 0xffff;
! 1840: for (u = ufirst; u <= ulast; u++)
! 1841: authtrust(u, 1);
! 1842: }
! 1843: }
! 1844:
! 1845: #ifdef OPENSSL
! 1846: /* crypto revoke command */
! 1847: if (ptree->auth.revoke)
! 1848: sys_revoke = ptree->auth.revoke;
! 1849: #endif /* OPENSSL */
! 1850:
! 1851: #ifndef NO_INTRES
! 1852: /* find a keyid */
! 1853: if (info_auth_keyid == 0)
! 1854: req_keyid = 65535;
! 1855: else
! 1856: req_keyid = info_auth_keyid;
! 1857:
! 1858: /* if doesn't exist, make up one at random */
! 1859: if (authhavekey(req_keyid)) {
! 1860: req_keytype = cache_type;
! 1861: #ifndef OPENSSL
! 1862: req_hashlen = 16;
! 1863: #else /* OPENSSL follows */
! 1864: EVP_DigestInit(&ctx, EVP_get_digestbynid(req_keytype));
! 1865: EVP_DigestFinal(&ctx, digest, &digest_len);
! 1866: req_hashlen = digest_len;
! 1867: #endif
! 1868: } else {
! 1869: int rankey;
! 1870:
! 1871: rankey = ntp_random();
! 1872: req_keytype = NID_md5;
! 1873: req_hashlen = 16;
! 1874: MD5auth_setkey(req_keyid, req_keytype,
! 1875: (u_char *)&rankey, sizeof(rankey));
! 1876: authtrust(req_keyid, 1);
! 1877: }
! 1878:
! 1879: /* save keyid so we will accept config requests with it */
! 1880: info_auth_keyid = req_keyid;
! 1881: #endif /* !NO_INTRES */
! 1882:
! 1883: }
! 1884:
! 1885:
! 1886: #ifdef FREE_CFG_T
! 1887: static void
! 1888: free_config_auth(
! 1889: struct config_tree *ptree
! 1890: )
! 1891: {
! 1892: struct attr_val *my_val;
! 1893:
! 1894: while (NULL !=
! 1895: (my_val = dequeue(ptree->auth.crypto_cmd_list))) {
! 1896:
! 1897: free(my_val->value.s);
! 1898: free_node(my_val);
! 1899: }
! 1900: DESTROY_QUEUE(ptree->auth.crypto_cmd_list);
! 1901:
! 1902: DESTROY_QUEUE(ptree->auth.trusted_key_list);
! 1903: }
! 1904: #endif /* FREE_CFG_T */
! 1905:
! 1906:
! 1907: static void
! 1908: config_tos(
! 1909: struct config_tree *ptree
! 1910: )
! 1911: {
! 1912: struct attr_val *tos;
! 1913: int item;
! 1914:
! 1915: item = -1; /* quiet warning */
! 1916: tos = queue_head(ptree->orphan_cmds);
! 1917: while (tos != NULL) {
! 1918: switch(tos->attr) {
! 1919:
! 1920: default:
! 1921: NTP_INSIST(0);
! 1922: break;
! 1923:
! 1924: case T_Ceiling:
! 1925: item = PROTO_CEILING;
! 1926: break;
! 1927:
! 1928: case T_Floor:
! 1929: item = PROTO_FLOOR;
! 1930: break;
! 1931:
! 1932: case T_Cohort:
! 1933: item = PROTO_COHORT;
! 1934: break;
! 1935:
! 1936: case T_Orphan:
! 1937: item = PROTO_ORPHAN;
! 1938: break;
! 1939:
! 1940: case T_Mindist:
! 1941: item = PROTO_MINDISP;
! 1942: break;
! 1943:
! 1944: case T_Maxdist:
! 1945: item = PROTO_MAXDIST;
! 1946: break;
! 1947:
! 1948: case T_Minclock:
! 1949: item = PROTO_MINCLOCK;
! 1950: break;
! 1951:
! 1952: case T_Maxclock:
! 1953: item = PROTO_MAXCLOCK;
! 1954: break;
! 1955:
! 1956: case T_Minsane:
! 1957: item = PROTO_MINSANE;
! 1958: break;
! 1959:
! 1960: case T_Beacon:
! 1961: item = PROTO_BEACON;
! 1962: break;
! 1963: }
! 1964: proto_config(item, 0, tos->value.d, NULL);
! 1965: tos = next_node(tos);
! 1966: }
! 1967: }
! 1968:
! 1969:
! 1970: #ifdef FREE_CFG_T
! 1971: static void
! 1972: free_config_tos(
! 1973: struct config_tree *ptree
! 1974: )
! 1975: {
! 1976: struct attr_val *tos;
! 1977:
! 1978: while (!empty(ptree->orphan_cmds)) {
! 1979: tos = dequeue(ptree->orphan_cmds);
! 1980: free_node(tos);
! 1981: }
! 1982: }
! 1983: #endif /* FREE_CFG_T */
! 1984:
! 1985:
! 1986: static void
! 1987: config_monitor(
! 1988: struct config_tree *ptree
! 1989: )
! 1990: {
! 1991: int *pfilegen_token;
! 1992: const char *filegen_string;
! 1993: const char *filegen_file;
! 1994: FILEGEN *filegen;
! 1995: struct filegen_node *my_node;
! 1996: struct attr_val *my_opts;
! 1997: int filegen_type;
! 1998: int filegen_flag;
! 1999:
! 2000: /* Set the statistics directory */
! 2001: if (ptree->stats_dir)
! 2002: stats_config(STATS_STATSDIR, ptree->stats_dir);
! 2003:
! 2004: /* NOTE:
! 2005: * Calling filegen_get is brain dead. Doing a string
! 2006: * comparison to find the relavant filegen structure is
! 2007: * expensive.
! 2008: *
! 2009: * Through the parser, we already know which filegen is
! 2010: * being specified. Hence, we should either store a
! 2011: * pointer to the specified structure in the syntax tree
! 2012: * or an index into a filegen array.
! 2013: *
! 2014: * Need to change the filegen code to reflect the above.
! 2015: */
! 2016:
! 2017: /* Turn on the specified statistics */
! 2018: pfilegen_token = queue_head(ptree->stats_list);
! 2019: while (pfilegen_token != NULL) {
! 2020: filegen_string = keyword(*pfilegen_token);
! 2021: filegen = filegen_get(filegen_string);
! 2022:
! 2023: DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
! 2024: filegen_string, filegen->prefix,
! 2025: filegen->basename));
! 2026: filegen->flag |= FGEN_FLAG_ENABLED;
! 2027: pfilegen_token = next_node(pfilegen_token);
! 2028: }
! 2029:
! 2030: /* Configure the statistics with the options */
! 2031: my_node = queue_head(ptree->filegen_opts);
! 2032: while (my_node != NULL) {
! 2033: filegen_file = keyword(my_node->filegen_token);
! 2034: filegen = filegen_get(filegen_file);
! 2035:
! 2036: /* Initialize the filegen variables to their pre-configurtion states */
! 2037: filegen_flag = filegen->flag;
! 2038: filegen_type = filegen->type;
! 2039:
! 2040: /* "filegen ... enabled" is the default (when filegen is used) */
! 2041: filegen_flag |= FGEN_FLAG_ENABLED;
! 2042:
! 2043: my_opts = queue_head(my_node->options);
! 2044: while (my_opts != NULL) {
! 2045:
! 2046: switch (my_opts->attr) {
! 2047:
! 2048: case T_File:
! 2049: filegen_file = my_opts->value.p;
! 2050: break;
! 2051:
! 2052: case T_Type:
! 2053: switch (my_opts->value.i) {
! 2054:
! 2055: default:
! 2056: NTP_INSIST(0);
! 2057: break;
! 2058:
! 2059: case T_None:
! 2060: filegen_type = FILEGEN_NONE;
! 2061: break;
! 2062:
! 2063: case T_Pid:
! 2064: filegen_type = FILEGEN_PID;
! 2065: break;
! 2066:
! 2067: case T_Day:
! 2068: filegen_type = FILEGEN_DAY;
! 2069: break;
! 2070:
! 2071: case T_Week:
! 2072: filegen_type = FILEGEN_WEEK;
! 2073: break;
! 2074:
! 2075: case T_Month:
! 2076: filegen_type = FILEGEN_MONTH;
! 2077: break;
! 2078:
! 2079: case T_Year:
! 2080: filegen_type = FILEGEN_YEAR;
! 2081: break;
! 2082:
! 2083: case T_Age:
! 2084: filegen_type = FILEGEN_AGE;
! 2085: break;
! 2086: }
! 2087: break;
! 2088:
! 2089: case T_Flag:
! 2090: switch (my_opts->value.i) {
! 2091:
! 2092: case T_Link:
! 2093: filegen_flag |= FGEN_FLAG_LINK;
! 2094: break;
! 2095:
! 2096: case T_Nolink:
! 2097: filegen_flag &= ~FGEN_FLAG_LINK;
! 2098: break;
! 2099:
! 2100: case T_Enable:
! 2101: filegen_flag |= FGEN_FLAG_ENABLED;
! 2102: break;
! 2103:
! 2104: case T_Disable:
! 2105: filegen_flag &= ~FGEN_FLAG_ENABLED;
! 2106: break;
! 2107:
! 2108: default:
! 2109: msyslog(LOG_ERR,
! 2110: "Unknown filegen flag token %d",
! 2111: my_opts->value.i);
! 2112: exit(1);
! 2113: }
! 2114: break;
! 2115: default:
! 2116: msyslog(LOG_ERR,
! 2117: "Unknown filegen option token %d",
! 2118: my_opts->attr);
! 2119: exit(1);
! 2120: }
! 2121: my_opts = next_node(my_opts);
! 2122: }
! 2123: filegen_config(filegen, filegen_file, filegen_type,
! 2124: filegen_flag);
! 2125: my_node = next_node(my_node);
! 2126: }
! 2127: }
! 2128:
! 2129:
! 2130: #ifdef FREE_CFG_T
! 2131: static void
! 2132: free_config_monitor(
! 2133: struct config_tree *ptree
! 2134: )
! 2135: {
! 2136: char **filegen_string;
! 2137: struct filegen_node *my_node;
! 2138: struct attr_val *my_opts;
! 2139:
! 2140: if (ptree->stats_dir) {
! 2141: free(ptree->stats_dir);
! 2142: ptree->stats_dir = NULL;
! 2143: }
! 2144:
! 2145: while (NULL != (filegen_string = dequeue(ptree->stats_list)))
! 2146: free_node(filegen_string);
! 2147:
! 2148: while (NULL != (my_node = dequeue(ptree->filegen_opts))) {
! 2149:
! 2150: while (NULL != (my_opts = dequeue(my_node->options)))
! 2151: free_node(my_opts);
! 2152:
! 2153: free_node(my_node);
! 2154: }
! 2155: }
! 2156: #endif /* FREE_CFG_T */
! 2157:
! 2158:
! 2159: static void
! 2160: config_access(
! 2161: struct config_tree *ptree
! 2162: )
! 2163: {
! 2164: static int warned_signd;
! 2165: struct attr_val * my_opt;
! 2166: struct restrict_node * my_node;
! 2167: int * curr_flag;
! 2168: sockaddr_u addr_sock;
! 2169: sockaddr_u addr_mask;
! 2170: u_short flags;
! 2171: u_short mflags;
! 2172: int restrict_default;
! 2173: const char * signd_warning =
! 2174: #ifdef HAVE_NTP_SIGND
! 2175: "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
! 2176: #else
! 2177: "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
! 2178: #endif
! 2179:
! 2180: /* Configure the discard options */
! 2181: my_opt = queue_head(ptree->discard_opts);
! 2182: while (my_opt != NULL) {
! 2183:
! 2184: switch(my_opt->attr) {
! 2185:
! 2186: case T_Average:
! 2187: ntp_minpoll = my_opt->value.i;
! 2188: break;
! 2189:
! 2190: case T_Minimum:
! 2191: ntp_minpkt = my_opt->value.i;
! 2192: break;
! 2193:
! 2194: case T_Monitor:
! 2195: mon_age = my_opt->value.i;
! 2196: break;
! 2197:
! 2198: default:
! 2199: msyslog(LOG_ERR,
! 2200: "Unknown discard option token %d",
! 2201: my_opt->attr);
! 2202: exit(1);
! 2203: }
! 2204: my_opt = next_node(my_opt);
! 2205: }
! 2206:
! 2207: /* Configure the restrict options */
! 2208: for (my_node = queue_head(ptree->restrict_opts);
! 2209: my_node != NULL;
! 2210: my_node = next_node(my_node)) {
! 2211:
! 2212: ZERO_SOCK(&addr_sock);
! 2213:
! 2214: if (NULL == my_node->addr) {
! 2215: /*
! 2216: * The user specified a default rule without a
! 2217: * -4 / -6 qualifier, add to both lists
! 2218: */
! 2219: restrict_default = 1;
! 2220: ZERO_SOCK(&addr_mask);
! 2221: } else {
! 2222: restrict_default = 0;
! 2223: /* Resolve the specified address */
! 2224: AF(&addr_sock) = (u_short)my_node->addr->type;
! 2225:
! 2226: if (getnetnum(my_node->addr->address,
! 2227: &addr_sock, 1, t_UNK) != 1) {
! 2228:
! 2229: msyslog(LOG_ERR,
! 2230: "restrict: error in address '%s' on line %d. Ignoring...",
! 2231: my_node->addr->address, my_node->line_no);
! 2232: continue;
! 2233: }
! 2234:
! 2235: SET_HOSTMASK(&addr_mask, AF(&addr_sock));
! 2236:
! 2237: /* Resolve the mask */
! 2238: if (my_node->mask) {
! 2239: ZERO_SOCK(&addr_mask);
! 2240: AF(&addr_mask) = (u_short)my_node->mask->type;
! 2241: if (getnetnum(my_node->mask->address, &addr_mask, 1, t_MSK) != 1) {
! 2242:
! 2243: msyslog(LOG_ERR,
! 2244: "restrict: error in mask '%s' on line %d. Ignoring...",
! 2245: my_node->mask->address, my_node->line_no);
! 2246: continue;
! 2247: }
! 2248: }
! 2249: }
! 2250:
! 2251: /* Parse the flags */
! 2252: flags = 0;
! 2253: mflags = 0;
! 2254:
! 2255: curr_flag = queue_head(my_node->flags);
! 2256: while (curr_flag != NULL) {
! 2257: switch (*curr_flag) {
! 2258:
! 2259: default:
! 2260: NTP_INSIST(0);
! 2261: break;
! 2262:
! 2263: case T_Ntpport:
! 2264: mflags |= RESM_NTPONLY;
! 2265: break;
! 2266:
! 2267: case T_Flake:
! 2268: flags |= RES_TIMEOUT;
! 2269: break;
! 2270:
! 2271: case T_Ignore:
! 2272: flags |= RES_IGNORE;
! 2273: break;
! 2274:
! 2275: case T_Kod:
! 2276: flags |= RES_KOD;
! 2277: break;
! 2278:
! 2279: case T_Mssntp:
! 2280: flags |= RES_MSSNTP;
! 2281: break;
! 2282:
! 2283: case T_Limited:
! 2284: flags |= RES_LIMITED;
! 2285: break;
! 2286:
! 2287: case T_Lowpriotrap:
! 2288: flags |= RES_LPTRAP;
! 2289: break;
! 2290:
! 2291: case T_Nomodify:
! 2292: flags |= RES_NOMODIFY;
! 2293: break;
! 2294:
! 2295: case T_Nopeer:
! 2296: flags |= RES_NOPEER;
! 2297: break;
! 2298:
! 2299: case T_Noquery:
! 2300: flags |= RES_NOQUERY;
! 2301: break;
! 2302:
! 2303: case T_Noserve:
! 2304: flags |= RES_DONTSERVE;
! 2305: break;
! 2306:
! 2307: case T_Notrap:
! 2308: flags |= RES_NOTRAP;
! 2309: break;
! 2310:
! 2311: case T_Notrust:
! 2312: flags |= RES_DONTTRUST;
! 2313: break;
! 2314:
! 2315: case T_Version:
! 2316: flags |= RES_VERSION;
! 2317: break;
! 2318: }
! 2319: curr_flag = next_node(curr_flag);
! 2320: }
! 2321:
! 2322: /* Set the flags */
! 2323: if (restrict_default) {
! 2324: AF(&addr_sock) = AF_INET;
! 2325: hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
! 2326: mflags, flags);
! 2327:
! 2328: AF(&addr_sock) = AF_INET6;
! 2329: }
! 2330:
! 2331: hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
! 2332: mflags, flags);
! 2333:
! 2334: if ((RES_MSSNTP & flags) && !warned_signd) {
! 2335: warned_signd = 1;
! 2336: fprintf(stderr, "%s\n", signd_warning);
! 2337: msyslog(LOG_WARNING, signd_warning);
! 2338: }
! 2339: }
! 2340: }
! 2341:
! 2342:
! 2343: #ifdef FREE_CFG_T
! 2344: static void
! 2345: free_config_access(
! 2346: struct config_tree *ptree
! 2347: )
! 2348: {
! 2349: struct attr_val * my_opt;
! 2350: struct restrict_node * my_node;
! 2351: int * curr_flag;
! 2352:
! 2353: while (NULL != (my_opt = dequeue(ptree->discard_opts)))
! 2354: free_node(my_opt);
! 2355:
! 2356: while (NULL != (my_node = dequeue(ptree->restrict_opts))) {
! 2357: while (NULL != (curr_flag = dequeue(my_node->flags)))
! 2358: free_node(curr_flag);
! 2359:
! 2360: destroy_restrict_node(my_node);
! 2361: }
! 2362: }
! 2363: #endif /* FREE_CFG_T */
! 2364:
! 2365:
! 2366: static void
! 2367: config_tinker(
! 2368: struct config_tree *ptree
! 2369: )
! 2370: {
! 2371: struct attr_val *tinker;
! 2372: int item;
! 2373:
! 2374: item = -1; /* quiet warning */
! 2375: tinker = queue_head(ptree->tinker);
! 2376: while (tinker != NULL) {
! 2377: switch (tinker->attr) {
! 2378:
! 2379: default:
! 2380: NTP_INSIST(0);
! 2381: break;
! 2382:
! 2383: case T_Allan:
! 2384: item = LOOP_ALLAN;
! 2385: break;
! 2386:
! 2387: case T_Dispersion:
! 2388: item = LOOP_PHI;
! 2389: break;
! 2390:
! 2391: case T_Freq:
! 2392: item = LOOP_FREQ;
! 2393: break;
! 2394:
! 2395: case T_Huffpuff:
! 2396: item = LOOP_HUFFPUFF;
! 2397: break;
! 2398:
! 2399: case T_Panic:
! 2400: item = LOOP_PANIC;
! 2401: break;
! 2402:
! 2403: case T_Step:
! 2404: item = LOOP_MAX;
! 2405: break;
! 2406:
! 2407: case T_Stepout:
! 2408: item = LOOP_MINSTEP;
! 2409: break;
! 2410: }
! 2411: loop_config(item, tinker->value.d);
! 2412: tinker = next_node(tinker);
! 2413: }
! 2414: }
! 2415:
! 2416:
! 2417: #ifdef FREE_CFG_T
! 2418: static void
! 2419: free_config_tinker(
! 2420: struct config_tree *ptree
! 2421: )
! 2422: {
! 2423: struct attr_val *tinker;
! 2424:
! 2425: while (NULL != (tinker = dequeue(ptree->tinker)))
! 2426: free_node(tinker);
! 2427: }
! 2428: #endif /* FREE_CFG_T */
! 2429:
! 2430:
! 2431: /*
! 2432: * config_nic_rules - apply interface listen/ignore/drop items
! 2433: */
! 2434: void
! 2435: config_nic_rules(
! 2436: struct config_tree *ptree
! 2437: )
! 2438: {
! 2439: nic_rule_node * curr_node;
! 2440: sockaddr_u addr;
! 2441: nic_rule_match match_type;
! 2442: nic_rule_action action;
! 2443: char * if_name;
! 2444: char * pchSlash;
! 2445: int prefixlen;
! 2446: int addrbits;
! 2447:
! 2448: curr_node = queue_head(ptree->nic_rules);
! 2449:
! 2450: if (curr_node != NULL
! 2451: && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
! 2452: msyslog(LOG_ERR,
! 2453: "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
! 2454: (input_from_file) ? ", exiting" : "");
! 2455: if (input_from_file)
! 2456: exit(1);
! 2457: else
! 2458: return;
! 2459: }
! 2460:
! 2461: for (;
! 2462: curr_node != NULL;
! 2463: curr_node = next_node(curr_node)) {
! 2464:
! 2465: prefixlen = -1;
! 2466: if_name = curr_node->if_name;
! 2467: if (if_name != NULL)
! 2468: if_name = estrdup(if_name);
! 2469:
! 2470: switch (curr_node->match_class) {
! 2471:
! 2472: default:
! 2473: /*
! 2474: * this assignment quiets a gcc "may be used
! 2475: * uninitialized" warning and is here for no
! 2476: * other reason.
! 2477: */
! 2478: match_type = MATCH_ALL;
! 2479: NTP_INSIST(0);
! 2480: break;
! 2481:
! 2482: case 0:
! 2483: /*
! 2484: * 0 is out of range for valid token T_...
! 2485: * and in a nic_rules_node indicates the
! 2486: * interface descriptor is either a name or
! 2487: * address, stored in if_name in either case.
! 2488: */
! 2489: NTP_INSIST(if_name != NULL);
! 2490: pchSlash = strchr(if_name, '/');
! 2491: if (pchSlash != NULL)
! 2492: *pchSlash = '\0';
! 2493: if (is_ip_address(if_name, &addr)) {
! 2494: match_type = MATCH_IFADDR;
! 2495: if (pchSlash != NULL) {
! 2496: sscanf(pchSlash + 1, "%d",
! 2497: &prefixlen);
! 2498: addrbits = 8 *
! 2499: SIZEOF_INADDR(AF(&addr));
! 2500: prefixlen = max(-1, prefixlen);
! 2501: prefixlen = min(prefixlen,
! 2502: addrbits);
! 2503: }
! 2504: } else {
! 2505: match_type = MATCH_IFNAME;
! 2506: if (pchSlash != NULL)
! 2507: *pchSlash = '/';
! 2508: }
! 2509: break;
! 2510:
! 2511: case T_All:
! 2512: match_type = MATCH_ALL;
! 2513: break;
! 2514:
! 2515: case T_Ipv4:
! 2516: match_type = MATCH_IPV4;
! 2517: break;
! 2518:
! 2519: case T_Ipv6:
! 2520: match_type = MATCH_IPV6;
! 2521: break;
! 2522:
! 2523: case T_Wildcard:
! 2524: match_type = MATCH_WILDCARD;
! 2525: break;
! 2526: }
! 2527:
! 2528: switch (curr_node->action) {
! 2529:
! 2530: default:
! 2531: /*
! 2532: * this assignment quiets a gcc "may be used
! 2533: * uninitialized" warning and is here for no
! 2534: * other reason.
! 2535: */
! 2536: action = ACTION_LISTEN;
! 2537: NTP_INSIST(0);
! 2538: break;
! 2539:
! 2540: case T_Listen:
! 2541: action = ACTION_LISTEN;
! 2542: break;
! 2543:
! 2544: case T_Ignore:
! 2545: action = ACTION_IGNORE;
! 2546: break;
! 2547:
! 2548: case T_Drop:
! 2549: action = ACTION_DROP;
! 2550: break;
! 2551: }
! 2552:
! 2553: add_nic_rule(match_type, if_name, prefixlen,
! 2554: action);
! 2555: timer_interfacetimeout(current_time + 2);
! 2556: if (if_name != NULL)
! 2557: free(if_name);
! 2558: }
! 2559: }
! 2560:
! 2561:
! 2562: #ifdef FREE_CFG_T
! 2563: static void
! 2564: free_config_nic_rules(
! 2565: struct config_tree *ptree
! 2566: )
! 2567: {
! 2568: nic_rule_node *curr_node;
! 2569:
! 2570: while (NULL != (curr_node = dequeue(ptree->nic_rules))) {
! 2571: if (curr_node->if_name != NULL)
! 2572: free(curr_node->if_name);
! 2573: free_node(curr_node);
! 2574: }
! 2575: DESTROY_QUEUE(ptree->nic_rules);
! 2576: }
! 2577: #endif /* FREE_CFG_T */
! 2578:
! 2579:
! 2580: static void
! 2581: apply_enable_disable(
! 2582: queue * q,
! 2583: int enable
! 2584: )
! 2585: {
! 2586: struct attr_val *curr_flag;
! 2587: int option;
! 2588: #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
! 2589: bc_entry *pentry;
! 2590: #endif
! 2591:
! 2592: for (curr_flag = queue_head(q);
! 2593: curr_flag != NULL;
! 2594: curr_flag = next_node(curr_flag)) {
! 2595:
! 2596: option = curr_flag->value.i;
! 2597: switch (option) {
! 2598:
! 2599: default:
! 2600: msyslog(LOG_ERR,
! 2601: "can not apply enable/disable token %d, unknown",
! 2602: option);
! 2603: break;
! 2604:
! 2605: case T_Auth:
! 2606: proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
! 2607: break;
! 2608:
! 2609: case T_Bclient:
! 2610: proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
! 2611: break;
! 2612:
! 2613: case T_Calibrate:
! 2614: proto_config(PROTO_CAL, enable, 0., NULL);
! 2615: break;
! 2616:
! 2617: case T_Kernel:
! 2618: proto_config(PROTO_KERNEL, enable, 0., NULL);
! 2619: break;
! 2620:
! 2621: case T_Monitor:
! 2622: proto_config(PROTO_MONITOR, enable, 0., NULL);
! 2623: break;
! 2624:
! 2625: case T_Ntp:
! 2626: proto_config(PROTO_NTP, enable, 0., NULL);
! 2627: break;
! 2628:
! 2629: case T_Stats:
! 2630: proto_config(PROTO_FILEGEN, enable, 0., NULL);
! 2631: break;
! 2632:
! 2633: #ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
! 2634: case T_Bc_bugXXXX:
! 2635: pentry = bc_list;
! 2636: while (pentry->token) {
! 2637: if (pentry->token == option)
! 2638: break;
! 2639: pentry++;
! 2640: }
! 2641: if (!pentry->token) {
! 2642: msyslog(LOG_ERR,
! 2643: "compat token %d not in bc_list[]",
! 2644: option);
! 2645: continue;
! 2646: }
! 2647: pentry->enabled = enable;
! 2648: break;
! 2649: #endif
! 2650: }
! 2651: }
! 2652: }
! 2653:
! 2654:
! 2655: static void
! 2656: config_system_opts(
! 2657: struct config_tree *ptree
! 2658: )
! 2659: {
! 2660: apply_enable_disable(ptree->enable_opts, 1);
! 2661: apply_enable_disable(ptree->disable_opts, 0);
! 2662: }
! 2663:
! 2664:
! 2665: #ifdef FREE_CFG_T
! 2666: static void
! 2667: free_config_system_opts(
! 2668: struct config_tree *ptree
! 2669: )
! 2670: {
! 2671: struct attr_val *flag;
! 2672:
! 2673: while (NULL != (flag = dequeue(ptree->enable_opts)))
! 2674: free_node(flag);
! 2675:
! 2676: while (NULL != (flag = dequeue(ptree->disable_opts)))
! 2677: free_node(flag);
! 2678: }
! 2679: #endif /* FREE_CFG_T */
! 2680:
! 2681:
! 2682: static void
! 2683: config_logconfig(
! 2684: struct config_tree *ptree
! 2685: )
! 2686: {
! 2687: struct attr_val *my_logconfig;
! 2688:
! 2689: my_logconfig = queue_head(ptree->logconfig);
! 2690: while (my_logconfig != NULL) {
! 2691:
! 2692: switch (my_logconfig->attr) {
! 2693: case '+':
! 2694: ntp_syslogmask |= get_logmask(my_logconfig->value.s);
! 2695: break;
! 2696: case '-':
! 2697: ntp_syslogmask &= ~get_logmask(my_logconfig->value.s);
! 2698: break;
! 2699: case '=':
! 2700: ntp_syslogmask = get_logmask(my_logconfig->value.s);
! 2701: break;
! 2702: }
! 2703: my_logconfig = next_node(my_logconfig);
! 2704: }
! 2705: }
! 2706:
! 2707:
! 2708: #ifdef FREE_CFG_T
! 2709: static void
! 2710: free_config_logconfig(
! 2711: struct config_tree *ptree
! 2712: )
! 2713: {
! 2714: struct attr_val *my_logconfig;
! 2715:
! 2716: while (NULL != (my_logconfig = dequeue(ptree->logconfig))) {
! 2717: free(my_logconfig->value.s);
! 2718: free_node(my_logconfig);
! 2719: }
! 2720: }
! 2721: #endif /* FREE_CFG_T */
! 2722:
! 2723:
! 2724: static void
! 2725: config_phone(
! 2726: struct config_tree *ptree
! 2727: )
! 2728: {
! 2729: int i = 0;
! 2730: char **s;
! 2731:
! 2732: s = queue_head(ptree->phone);
! 2733: while (s != NULL) {
! 2734: if (i < COUNTOF(sys_phone) - 1) {
! 2735: sys_phone[i++] = estrdup(*s);
! 2736: sys_phone[i] = NULL;
! 2737: } else {
! 2738: msyslog(LOG_INFO,
! 2739: "phone: Number of phone entries exceeds %lu. Ignoring phone %s...",
! 2740: (u_long)(COUNTOF(sys_phone) - 1), *s);
! 2741: }
! 2742: s = next_node(s);
! 2743: }
! 2744: }
! 2745:
! 2746:
! 2747: #ifdef FREE_CFG_T
! 2748: static void
! 2749: free_config_phone(
! 2750: struct config_tree *ptree
! 2751: )
! 2752: {
! 2753: char **s;
! 2754:
! 2755: while (NULL != (s = dequeue(ptree->phone))) {
! 2756: free(*s);
! 2757: free_node(s);
! 2758: }
! 2759: }
! 2760: #endif /* FREE_CFG_T */
! 2761:
! 2762:
! 2763: static void
! 2764: config_qos(
! 2765: struct config_tree *ptree
! 2766: )
! 2767: {
! 2768: struct attr_val *my_qosconfig;
! 2769: char *s;
! 2770: #ifdef HAVE_IPTOS_SUPPORT
! 2771: unsigned int qtos = 0;
! 2772: #endif
! 2773:
! 2774: my_qosconfig = queue_head(ptree->qos);
! 2775: while (my_qosconfig != NULL) {
! 2776: s = my_qosconfig->value.s;
! 2777: #ifdef HAVE_IPTOS_SUPPORT
! 2778: if (!strcmp(s, "lowdelay"))
! 2779: qtos = CONF_QOS_LOWDELAY;
! 2780: else if (!strcmp(s, "throughput"))
! 2781: qtos = CONF_QOS_THROUGHPUT;
! 2782: else if (!strcmp(s, "reliability"))
! 2783: qtos = CONF_QOS_RELIABILITY;
! 2784: else if (!strcmp(s, "mincost"))
! 2785: qtos = CONF_QOS_MINCOST;
! 2786: #ifdef IPTOS_PREC_INTERNETCONTROL
! 2787: else if (!strcmp(s, "routine") || !strcmp(s, "cs0"))
! 2788: qtos = CONF_QOS_CS0;
! 2789: else if (!strcmp(s, "priority") || !strcmp(s, "cs1"))
! 2790: qtos = CONF_QOS_CS1;
! 2791: else if (!strcmp(s, "immediate") || !strcmp(s, "cs2"))
! 2792: qtos = CONF_QOS_CS2;
! 2793: else if (!strcmp(s, "flash") || !strcmp(s, "cs3"))
! 2794: qtos = CONF_QOS_CS3; /* overlapping prefix on keyword */
! 2795: if (!strcmp(s, "flashoverride") || !strcmp(s, "cs4"))
! 2796: qtos = CONF_QOS_CS4;
! 2797: else if (!strcmp(s, "critical") || !strcmp(s, "cs5"))
! 2798: qtos = CONF_QOS_CS5;
! 2799: else if(!strcmp(s, "internetcontrol") || !strcmp(s, "cs6"))
! 2800: qtos = CONF_QOS_CS6;
! 2801: else if (!strcmp(s, "netcontrol") || !strcmp(s, "cs7"))
! 2802: qtos = CONF_QOS_CS7;
! 2803: #endif /* IPTOS_PREC_INTERNETCONTROL */
! 2804: if (qtos == 0)
! 2805: msyslog(LOG_ERR, "parse error, qos %s not accepted\n", s);
! 2806: else
! 2807: qos = qtos;
! 2808: #endif /* HAVE IPTOS_SUPPORT */
! 2809: /*
! 2810: * value is set, but not being effective. Need code to
! 2811: * change the current connections to notice. Might
! 2812: * also consider logging a message about the action.
! 2813: * XXX msyslog(LOG_INFO, "QoS %s requested by config\n", s);
! 2814: */
! 2815: my_qosconfig = next_node(my_qosconfig);
! 2816: }
! 2817: }
! 2818:
! 2819:
! 2820: #ifdef FREE_CFG_T
! 2821: static void
! 2822: free_config_qos(
! 2823: struct config_tree *ptree
! 2824: )
! 2825: {
! 2826: struct attr_val *my_qosconfig;
! 2827:
! 2828: while (NULL != (my_qosconfig = dequeue(ptree->qos))) {
! 2829: free(my_qosconfig->value.s);
! 2830: free_node(my_qosconfig);
! 2831: }
! 2832: }
! 2833: #endif /* FREE_CFG_T */
! 2834:
! 2835:
! 2836: static void
! 2837: config_setvar(
! 2838: struct config_tree *ptree
! 2839: )
! 2840: {
! 2841: struct setvar_node *my_node;
! 2842: size_t varlen, vallen, octets;
! 2843: char * str;
! 2844:
! 2845: str = NULL;
! 2846: my_node = queue_head(ptree->setvar);
! 2847: while (my_node != NULL) {
! 2848: varlen = strlen(my_node->var);
! 2849: vallen = strlen(my_node->val);
! 2850: octets = varlen + vallen + 1 + 1;
! 2851: str = erealloc(str, octets);
! 2852: snprintf(str, octets, "%s=%s", my_node->var,
! 2853: my_node->val);
! 2854: set_sys_var(str, octets, (my_node->isdefault)
! 2855: ? DEF
! 2856: : 0);
! 2857: my_node = next_node(my_node);
! 2858: }
! 2859: if (str != NULL)
! 2860: free(str);
! 2861: }
! 2862:
! 2863:
! 2864: #ifdef FREE_CFG_T
! 2865: static void
! 2866: free_config_setvar(
! 2867: struct config_tree *ptree
! 2868: )
! 2869: {
! 2870: struct setvar_node *my_node;
! 2871:
! 2872: while (NULL != (my_node = dequeue(ptree->setvar))) {
! 2873: free(my_node->var);
! 2874: free(my_node->val);
! 2875: free_node(my_node);
! 2876: }
! 2877: }
! 2878: #endif /* FREE_CFG_T */
! 2879:
! 2880:
! 2881: static void
! 2882: config_ttl(
! 2883: struct config_tree *ptree
! 2884: )
! 2885: {
! 2886: int i = 0;
! 2887: int *curr_ttl;
! 2888:
! 2889: curr_ttl = queue_head(ptree->ttl);
! 2890: while (curr_ttl != NULL) {
! 2891: if (i < COUNTOF(sys_ttl))
! 2892: sys_ttl[i++] = (u_char)*curr_ttl;
! 2893: else
! 2894: msyslog(LOG_INFO,
! 2895: "ttl: Number of TTL entries exceeds %lu. Ignoring TTL %d...",
! 2896: (u_long)COUNTOF(sys_ttl), *curr_ttl);
! 2897:
! 2898: curr_ttl = next_node(curr_ttl);
! 2899: }
! 2900: sys_ttlmax = i - 1;
! 2901: }
! 2902:
! 2903:
! 2904: #ifdef FREE_CFG_T
! 2905: static void
! 2906: free_config_ttl(
! 2907: struct config_tree *ptree
! 2908: )
! 2909: {
! 2910: /* coming DESTROY_QUEUE(ptree->ttl) is enough */
! 2911: }
! 2912: #endif /* FREE_CFG_T */
! 2913:
! 2914:
! 2915: static void
! 2916: config_trap(
! 2917: struct config_tree *ptree
! 2918: )
! 2919: {
! 2920: struct addr_opts_node *curr_trap;
! 2921: struct attr_val *curr_opt;
! 2922: sockaddr_u addr_sock;
! 2923: sockaddr_u peeraddr;
! 2924: struct address_node *addr_node;
! 2925: struct interface *localaddr;
! 2926: u_short port_no;
! 2927: int err_flag;
! 2928:
! 2929: /* silence warning about addr_sock potentially uninitialized */
! 2930: AF(&addr_sock) = AF_UNSPEC;
! 2931:
! 2932: for (curr_trap = queue_head(ptree->trap);
! 2933: curr_trap != NULL;
! 2934: curr_trap = next_node(curr_trap)) {
! 2935:
! 2936: err_flag = 0;
! 2937: port_no = 0;
! 2938: localaddr = NULL;
! 2939:
! 2940: curr_opt = queue_head(curr_trap->options);
! 2941: while (curr_opt != NULL) {
! 2942: if (T_Port == curr_opt->attr) {
! 2943: if (curr_opt->value.i < 1
! 2944: || curr_opt->value.i > USHRT_MAX) {
! 2945: msyslog(LOG_ERR,
! 2946: "invalid port number "
! 2947: "%d, trap ignored",
! 2948: curr_opt->value.i);
! 2949: err_flag = 1;
! 2950: }
! 2951: port_no = (u_short)curr_opt->value.i;
! 2952: }
! 2953: else if (T_Interface == curr_opt->attr) {
! 2954: addr_node = curr_opt->value.p;
! 2955:
! 2956: /* Resolve the interface address */
! 2957: ZERO_SOCK(&addr_sock);
! 2958: AF(&addr_sock) = (u_short)addr_node->type;
! 2959:
! 2960: if (getnetnum(addr_node->address,
! 2961: &addr_sock, 1, t_UNK) != 1) {
! 2962: err_flag = 1;
! 2963: break;
! 2964: }
! 2965:
! 2966: localaddr = findinterface(&addr_sock);
! 2967:
! 2968: if (NULL == localaddr) {
! 2969: msyslog(LOG_ERR,
! 2970: "can't find interface with address %s",
! 2971: stoa(&addr_sock));
! 2972: err_flag = 1;
! 2973: }
! 2974: }
! 2975: curr_opt = next_node(curr_opt);
! 2976: }
! 2977:
! 2978: /* Now process the trap for the specified interface
! 2979: * and port number
! 2980: */
! 2981: if (!err_flag) {
! 2982: ZERO_SOCK(&peeraddr);
! 2983: if (1 != getnetnum(curr_trap->addr->address,
! 2984: &peeraddr, 1, t_UNK))
! 2985: continue;
! 2986:
! 2987: /* port is at same location for v4 and v6 */
! 2988: SET_PORT(&peeraddr, port_no ? port_no : TRAPPORT);
! 2989:
! 2990: if (NULL == localaddr)
! 2991: localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
! 2992: else
! 2993: AF(&peeraddr) = AF(&addr_sock);
! 2994:
! 2995: if (!ctlsettrap(&peeraddr, localaddr, 0,
! 2996: NTP_VERSION))
! 2997: msyslog(LOG_ERR,
! 2998: "can't set trap for %s",
! 2999: stoa(&peeraddr));
! 3000: }
! 3001: }
! 3002: }
! 3003:
! 3004:
! 3005: #ifdef FREE_CFG_T
! 3006: static void
! 3007: free_config_trap(
! 3008: struct config_tree *ptree
! 3009: )
! 3010: {
! 3011: struct addr_opts_node *curr_trap;
! 3012: struct attr_val *curr_opt;
! 3013: struct address_node *addr_node;
! 3014:
! 3015: while (NULL != (curr_trap = dequeue(ptree->trap))) {
! 3016: while (curr_trap->options != NULL && NULL !=
! 3017: (curr_opt = dequeue(curr_trap->options))) {
! 3018:
! 3019: if (T_Interface == curr_opt->attr) {
! 3020: addr_node = curr_opt->value.p;
! 3021: destroy_address_node(addr_node);
! 3022: }
! 3023: free_node(curr_opt);
! 3024: }
! 3025: DESTROY_QUEUE(curr_trap->options);
! 3026: free_node(curr_trap);
! 3027: }
! 3028: }
! 3029: #endif /* FREE_CFG_T */
! 3030:
! 3031:
! 3032: static void
! 3033: config_fudge(
! 3034: struct config_tree *ptree
! 3035: )
! 3036: {
! 3037: struct addr_opts_node *curr_fudge;
! 3038: struct attr_val *curr_opt;
! 3039: sockaddr_u addr_sock;
! 3040: struct address_node *addr_node;
! 3041: struct refclockstat clock_stat;
! 3042: int err_flag;
! 3043:
! 3044: curr_fudge = queue_head(ptree->fudge);
! 3045: while (curr_fudge != NULL) {
! 3046: err_flag = 0;
! 3047:
! 3048: /* Get the reference clock address and
! 3049: * ensure that it is sane
! 3050: */
! 3051: addr_node = curr_fudge->addr;
! 3052: ZERO_SOCK(&addr_sock);
! 3053: if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
! 3054: != 1)
! 3055: err_flag = 1;
! 3056:
! 3057: if (!ISREFCLOCKADR(&addr_sock)) {
! 3058: msyslog(LOG_ERR,
! 3059: "inappropriate address %s for the fudge command, line ignored",
! 3060: stoa(&addr_sock));
! 3061: err_flag = 1;
! 3062: }
! 3063:
! 3064: /* Parse all the options to the fudge command */
! 3065: memset(&clock_stat, 0, sizeof(clock_stat));
! 3066: curr_opt = queue_head(curr_fudge->options);
! 3067: while (curr_opt != NULL) {
! 3068: switch (curr_opt->attr) {
! 3069: case T_Time1:
! 3070: clock_stat.haveflags |= CLK_HAVETIME1;
! 3071: clock_stat.fudgetime1 = curr_opt->value.d;
! 3072: break;
! 3073: case T_Time2:
! 3074: clock_stat.haveflags |= CLK_HAVETIME2;
! 3075: clock_stat.fudgetime2 = curr_opt->value.d;
! 3076: break;
! 3077: case T_Stratum:
! 3078: clock_stat.haveflags |= CLK_HAVEVAL1;
! 3079: clock_stat.fudgeval1 = curr_opt->value.i;
! 3080: break;
! 3081: case T_Refid:
! 3082: clock_stat.haveflags |= CLK_HAVEVAL2;
! 3083: clock_stat.fudgeval2 = 0;
! 3084: memcpy(&clock_stat.fudgeval2,
! 3085: curr_opt->value.s,
! 3086: min(strlen(curr_opt->value.s), 4));
! 3087: break;
! 3088: case T_Flag1:
! 3089: clock_stat.haveflags |= CLK_HAVEFLAG1;
! 3090: if (curr_opt->value.i)
! 3091: clock_stat.flags |= CLK_FLAG1;
! 3092: else
! 3093: clock_stat.flags &= ~CLK_FLAG1;
! 3094: break;
! 3095: case T_Flag2:
! 3096: clock_stat.haveflags |= CLK_HAVEFLAG2;
! 3097: if (curr_opt->value.i)
! 3098: clock_stat.flags |= CLK_FLAG2;
! 3099: else
! 3100: clock_stat.flags &= ~CLK_FLAG2;
! 3101: break;
! 3102: case T_Flag3:
! 3103: clock_stat.haveflags |= CLK_HAVEFLAG3;
! 3104: if (curr_opt->value.i)
! 3105: clock_stat.flags |= CLK_FLAG3;
! 3106: else
! 3107: clock_stat.flags &= ~CLK_FLAG3;
! 3108: break;
! 3109: case T_Flag4:
! 3110: clock_stat.haveflags |= CLK_HAVEFLAG4;
! 3111: if (curr_opt->value.i)
! 3112: clock_stat.flags |= CLK_FLAG4;
! 3113: else
! 3114: clock_stat.flags &= ~CLK_FLAG4;
! 3115: break;
! 3116: default:
! 3117: msyslog(LOG_ERR,
! 3118: "Unexpected fudge internal flag 0x%x for %s\n",
! 3119: curr_opt->attr, stoa(&addr_sock));
! 3120: exit(curr_opt->attr ? curr_opt->attr : 1);
! 3121: }
! 3122:
! 3123: curr_opt = next_node(curr_opt);
! 3124: }
! 3125:
! 3126: #ifdef REFCLOCK
! 3127: if (!err_flag)
! 3128: refclock_control(&addr_sock, &clock_stat,
! 3129: (struct refclockstat *)0);
! 3130: #endif
! 3131:
! 3132: curr_fudge = next_node(curr_fudge);
! 3133: }
! 3134: }
! 3135:
! 3136:
! 3137: #ifdef FREE_CFG_T
! 3138: static void
! 3139: free_config_fudge(
! 3140: struct config_tree *ptree
! 3141: )
! 3142: {
! 3143: struct addr_opts_node *curr_fudge;
! 3144: struct attr_val *curr_opt;
! 3145:
! 3146: while (NULL != (curr_fudge = dequeue(ptree->fudge))) {
! 3147: while (NULL != (curr_opt = dequeue(curr_fudge->options))) {
! 3148:
! 3149: switch (curr_opt->attr) {
! 3150: case CLK_HAVEVAL2:
! 3151: free(curr_opt->value.s);
! 3152: }
! 3153:
! 3154: free_node(curr_opt);
! 3155: }
! 3156:
! 3157: DESTROY_QUEUE(curr_fudge->options);
! 3158: free_node(curr_fudge);
! 3159: }
! 3160: }
! 3161: #endif /* FREE_CFG_T */
! 3162:
! 3163:
! 3164: static void
! 3165: config_vars(
! 3166: struct config_tree *ptree
! 3167: )
! 3168: {
! 3169: struct attr_val *curr_var;
! 3170: FILE *new_file;
! 3171: int len;
! 3172:
! 3173: curr_var = queue_head(ptree->vars);
! 3174: while (curr_var != NULL) {
! 3175: /* Determine which variable to set and set it */
! 3176: switch (curr_var->attr) {
! 3177: case T_Broadcastdelay:
! 3178: proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
! 3179: break;
! 3180: case T_Calldelay:
! 3181: proto_config(PROTO_CALLDELAY, curr_var->value.i, 0, NULL);
! 3182: break;
! 3183: case T_Tick:
! 3184: proto_config(PROTO_ADJ, 0, curr_var->value.d, NULL);
! 3185: break;
! 3186: case T_Driftfile:
! 3187: if ('\0' == curr_var->value.s[0]) {
! 3188: stats_drift_file = 0;
! 3189: msyslog(LOG_INFO, "config: driftfile disabled\n");
! 3190: } else
! 3191: stats_config(STATS_FREQ_FILE, curr_var->value.s);
! 3192: break;
! 3193: case T_WanderThreshold:
! 3194: wander_threshold = curr_var->value.d;
! 3195: break;
! 3196: case T_Leapfile:
! 3197: stats_config(STATS_LEAP_FILE, curr_var->value.s);
! 3198: break;
! 3199: case T_Pidfile:
! 3200: stats_config(STATS_PID_FILE, curr_var->value.s);
! 3201: break;
! 3202: case T_Logfile:
! 3203: new_file = fopen(curr_var->value.s, "a");
! 3204: if (new_file != NULL) {
! 3205: NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
! 3206: msyslog(LOG_NOTICE, "logging to file %s", curr_var->value.s);
! 3207: if (syslog_file != NULL &&
! 3208: fileno(syslog_file) != fileno(new_file))
! 3209: (void)fclose(syslog_file);
! 3210:
! 3211: syslog_file = new_file;
! 3212: syslogit = 0;
! 3213: }
! 3214: else
! 3215: msyslog(LOG_ERR,
! 3216: "Cannot open log file %s",
! 3217: curr_var->value.s);
! 3218: break;
! 3219:
! 3220: case T_Saveconfigdir:
! 3221: if (saveconfigdir != NULL)
! 3222: free(saveconfigdir);
! 3223: len = strlen(curr_var->value.s);
! 3224: if (0 == len)
! 3225: saveconfigdir = NULL;
! 3226: else if (DIR_SEP != curr_var->value.s[len - 1]
! 3227: #ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
! 3228: && '/' != curr_var->value.s[len - 1]
! 3229: #endif
! 3230: ) {
! 3231: len++;
! 3232: saveconfigdir = emalloc(len + 1);
! 3233: snprintf(saveconfigdir, len + 1,
! 3234: "%s%c",
! 3235: curr_var->value.s,
! 3236: DIR_SEP);
! 3237: } else
! 3238: saveconfigdir = estrdup(
! 3239: curr_var->value.s);
! 3240: break;
! 3241:
! 3242: case T_Automax:
! 3243: #ifdef OPENSSL
! 3244: sys_automax = curr_var->value.i;
! 3245: #endif
! 3246: break;
! 3247:
! 3248: default:
! 3249: msyslog(LOG_ERR,
! 3250: "config_vars(): unexpected token %d",
! 3251: curr_var->attr);
! 3252: }
! 3253: curr_var = next_node(curr_var);
! 3254: }
! 3255: }
! 3256:
! 3257:
! 3258: #ifdef FREE_CFG_T
! 3259: static void
! 3260: free_config_vars(
! 3261: struct config_tree *ptree
! 3262: )
! 3263: {
! 3264: struct attr_val *curr_var;
! 3265:
! 3266: while (NULL != (curr_var = dequeue(ptree->vars))) {
! 3267: /* Determine which variable to set and set it */
! 3268: switch (curr_var->attr) {
! 3269: case T_Driftfile:
! 3270: case T_Leapfile:
! 3271: case T_Pidfile:
! 3272: case T_Logfile:
! 3273: free(curr_var->value.s);
! 3274: }
! 3275: free_node(curr_var);
! 3276: }
! 3277: }
! 3278: #endif /* FREE_CFG_T */
! 3279:
! 3280:
! 3281: /* Define a function to check if a resolved address is sane.
! 3282: * If yes, return 1, else return 0;
! 3283: */
! 3284: static int
! 3285: is_sane_resolved_address(
! 3286: sockaddr_u * peeraddr,
! 3287: int hmode
! 3288: )
! 3289: {
! 3290: if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
! 3291: msyslog(LOG_ERR,
! 3292: "attempt to configure invalid address %s",
! 3293: stoa(peeraddr));
! 3294: return 0;
! 3295: }
! 3296: /*
! 3297: * Shouldn't be able to specify multicast
! 3298: * address for server/peer!
! 3299: * and unicast address for manycastclient!
! 3300: */
! 3301: if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
! 3302: && IS_MCAST(peeraddr)) {
! 3303: msyslog(LOG_ERR,
! 3304: "attempt to configure invalid address %s",
! 3305: stoa(peeraddr));
! 3306: return 0;
! 3307: }
! 3308: if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
! 3309: msyslog(LOG_ERR,
! 3310: "attempt to configure invalid address %s",
! 3311: stoa(peeraddr));
! 3312: return 0;
! 3313: }
! 3314:
! 3315: if (IS_IPV6(peeraddr) && !ipv6_works)
! 3316: return 0;
! 3317:
! 3318: /* Ok, all tests succeeded, now we can return 1 */
! 3319: return 1;
! 3320: }
! 3321:
! 3322: static int
! 3323: get_correct_host_mode(
! 3324: int hmode
! 3325: )
! 3326: {
! 3327: switch (hmode) {
! 3328: case T_Server:
! 3329: case T_Pool:
! 3330: case T_Manycastclient:
! 3331: return MODE_CLIENT;
! 3332: break;
! 3333: case T_Peer:
! 3334: return MODE_ACTIVE;
! 3335: break;
! 3336: case T_Broadcast:
! 3337: return MODE_BROADCAST;
! 3338: break;
! 3339: default:
! 3340: return -1;
! 3341: }
! 3342: }
! 3343:
! 3344: static void
! 3345: config_peers(
! 3346: struct config_tree *ptree
! 3347: )
! 3348: {
! 3349: struct addrinfo *res, *res_bak;
! 3350: sockaddr_u peeraddr;
! 3351: struct peer_node *curr_peer;
! 3352: struct attr_val *option;
! 3353: int hmode;
! 3354: int peerflags;
! 3355: int status;
! 3356: int no_needed;
! 3357: int i;
! 3358:
! 3359: curr_peer = queue_head(ptree->peers);
! 3360: while (curr_peer != NULL) {
! 3361: /* Find the number of associations needed.
! 3362: * If a pool coomand is specified, then sys_maxclock needed
! 3363: * else, only one is needed
! 3364: */
! 3365: no_needed = (T_Pool == curr_peer->host_mode)
! 3366: ? sys_maxclock
! 3367: : 1;
! 3368:
! 3369: /* Find the correct host-mode */
! 3370: hmode = get_correct_host_mode(curr_peer->host_mode);
! 3371: NTP_INSIST(hmode != -1);
! 3372:
! 3373: /* translate peerflags options to bits */
! 3374: peerflags = 0;
! 3375: option = queue_head(curr_peer->peerflags);
! 3376: for (; option != NULL; option = next_node(option))
! 3377: switch (option->value.i) {
! 3378:
! 3379: default:
! 3380: NTP_INSIST(0);
! 3381: break;
! 3382:
! 3383: case T_Autokey:
! 3384: peerflags |= FLAG_SKEY;
! 3385: break;
! 3386:
! 3387: case T_Burst:
! 3388: peerflags |= FLAG_BURST;
! 3389: break;
! 3390:
! 3391: case T_Iburst:
! 3392: peerflags |= FLAG_IBURST;
! 3393: break;
! 3394:
! 3395: case T_Noselect:
! 3396: peerflags |= FLAG_NOSELECT;
! 3397: break;
! 3398:
! 3399: case T_Preempt:
! 3400: peerflags |= FLAG_PREEMPT;
! 3401: break;
! 3402:
! 3403: case T_Prefer:
! 3404: peerflags |= FLAG_PREFER;
! 3405: break;
! 3406:
! 3407: case T_True:
! 3408: peerflags |= FLAG_TRUE;
! 3409: break;
! 3410:
! 3411: case T_Xleave:
! 3412: peerflags |= FLAG_XLEAVE;
! 3413: break;
! 3414: }
! 3415:
! 3416: /* Attempt to resolve the address */
! 3417: ZERO_SOCK(&peeraddr);
! 3418: AF(&peeraddr) = (u_short)curr_peer->addr->type;
! 3419:
! 3420: status = get_multiple_netnums(curr_peer->addr->address,
! 3421: &peeraddr, &res, 0, t_UNK);
! 3422:
! 3423: #ifdef FORCE_DEFER_DNS
! 3424: /* Hack for debugging Deferred DNS
! 3425: * Pretend working names didn't work.
! 3426: */
! 3427: if (status == 1) {
! 3428: /* Deferring everything breaks refclocks. */
! 3429: memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
! 3430: if (!ISREFCLOCKADR(&peeraddr)) {
! 3431: status = 0; /* force deferred DNS path */
! 3432: msyslog(LOG_INFO, "Forcing Deferred DNS for %s, %s",
! 3433: curr_peer->addr->address, stoa(&peeraddr));
! 3434: } else {
! 3435: msyslog(LOG_INFO, "NOT Deferring DNS for %s, %s",
! 3436: curr_peer->addr->address, stoa(&peeraddr));
! 3437: }
! 3438: }
! 3439: #endif
! 3440:
! 3441: /* I don't know why getnetnum would return -1.
! 3442: * The old code had this test, so I guess it must be
! 3443: * useful
! 3444: */
! 3445: if (status == -1) {
! 3446: /* Do nothing, apparently we found an IPv6
! 3447: * address and can't do anything about it */
! 3448: }
! 3449: /* Check if name resolution failed. If yes, store the
! 3450: * peer information in a file for asynchronous
! 3451: * resolution later
! 3452: */
! 3453: else if (status != 1) {
! 3454: msyslog(LOG_INFO, "Deferring DNS for %s %d", curr_peer->addr->address, no_needed);
! 3455: save_resolve(curr_peer->addr->address,
! 3456: no_needed,
! 3457: curr_peer->addr->type,
! 3458: hmode,
! 3459: curr_peer->peerversion,
! 3460: curr_peer->minpoll,
! 3461: curr_peer->maxpoll,
! 3462: peerflags,
! 3463: curr_peer->ttl,
! 3464: curr_peer->peerkey,
! 3465: (u_char *)"*");
! 3466: }
! 3467: /* Yippie!! Name resolution has succeeded!!!
! 3468: * Now we can proceed to some more sanity checks on
! 3469: * the resolved address before we start to configure
! 3470: * the peer
! 3471: */
! 3472: else {
! 3473: res_bak = res;
! 3474:
! 3475: /*
! 3476: * Loop to configure the desired number of
! 3477: * associations
! 3478: */
! 3479: for (i = 0; (i < no_needed) && res; res =
! 3480: res->ai_next) {
! 3481: ++i;
! 3482: memcpy(&peeraddr, res->ai_addr,
! 3483: res->ai_addrlen);
! 3484: if (is_sane_resolved_address(
! 3485: &peeraddr,
! 3486: curr_peer->host_mode))
! 3487:
! 3488: peer_config(&peeraddr,
! 3489: NULL,
! 3490: hmode,
! 3491: curr_peer->peerversion,
! 3492: curr_peer->minpoll,
! 3493: curr_peer->maxpoll,
! 3494: peerflags,
! 3495: curr_peer->ttl,
! 3496: curr_peer->peerkey,
! 3497: (u_char *)"*");
! 3498: }
! 3499: freeaddrinfo(res_bak);
! 3500: }
! 3501: curr_peer = next_node(curr_peer);
! 3502: }
! 3503: }
! 3504:
! 3505:
! 3506: #ifdef FREE_CFG_T
! 3507: static void
! 3508: free_config_peers(
! 3509: struct config_tree *ptree
! 3510: )
! 3511: {
! 3512: struct peer_node *curr_peer;
! 3513:
! 3514: while (NULL != (curr_peer = dequeue(ptree->peers))) {
! 3515: destroy_address_node(curr_peer->addr);
! 3516: DESTROY_QUEUE(curr_peer->peerflags);
! 3517: free_node(curr_peer);
! 3518: }
! 3519: }
! 3520: #endif /* FREE_CFG_T */
! 3521:
! 3522:
! 3523: static void
! 3524: config_unpeers(
! 3525: struct config_tree *ptree
! 3526: )
! 3527: {
! 3528: struct addrinfo *res, *res_bak;
! 3529: sockaddr_u peeraddr;
! 3530: struct unpeer_node *curr_unpeer;
! 3531: struct peer *peer;
! 3532: int status;
! 3533: int found;
! 3534:
! 3535: for (curr_unpeer = queue_head(ptree->unpeers);
! 3536: curr_unpeer != NULL;
! 3537: curr_unpeer = next_node(curr_unpeer)) {
! 3538:
! 3539: /*
! 3540: * Either AssocID will be zero, and we unpeer by name/
! 3541: * address addr, or it is nonzero and addr NULL.
! 3542: */
! 3543: if (curr_unpeer->assocID) {
! 3544: peer = findpeerbyassoc((u_int)curr_unpeer->assocID);
! 3545: if (peer != NULL) {
! 3546: peer_clear(peer, "GONE");
! 3547: unpeer(peer);
! 3548: }
! 3549:
! 3550: continue;
! 3551: }
! 3552:
! 3553: /* Attempt to resolve the name or address */
! 3554: ZERO_SOCK(&peeraddr);
! 3555: AF(&peeraddr) = (u_short)curr_unpeer->addr->type;
! 3556:
! 3557: status = get_multiple_netnums(
! 3558: curr_unpeer->addr->address, &peeraddr, &res, 0,
! 3559: t_UNK);
! 3560:
! 3561: /* I don't know why getnetnum would return -1.
! 3562: * The old code had this test, so I guess it must be
! 3563: * useful
! 3564: */
! 3565: if (status == -1) {
! 3566: /* Do nothing, apparently we found an IPv6
! 3567: * address and can't do anything about it */
! 3568: }
! 3569: /* Check if name resolution failed. If yes, throw
! 3570: * up our hands.
! 3571: */
! 3572: else if (status != 1) {
! 3573: /* Do nothing */
! 3574: }
! 3575: /* Yippie!! Name resolution has succeeded!!!
! 3576: */
! 3577: else {
! 3578: res_bak = res;
! 3579:
! 3580: /*
! 3581: * Loop through the addresses found
! 3582: */
! 3583: while (res) {
! 3584: memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
! 3585:
! 3586: found = 0;
! 3587: peer = NULL;
! 3588:
! 3589: DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
! 3590:
! 3591: while (!found) {
! 3592: peer = findexistingpeer(&peeraddr, peer, -1, 0);
! 3593: if (!peer)
! 3594: break;
! 3595: if (peer->flags & FLAG_CONFIG)
! 3596: found = 1;
! 3597: }
! 3598:
! 3599: if (found) {
! 3600: peer_clear(peer, "GONE");
! 3601: unpeer(peer);
! 3602: }
! 3603:
! 3604: res = res->ai_next;
! 3605: }
! 3606: freeaddrinfo(res_bak);
! 3607: }
! 3608: }
! 3609: }
! 3610:
! 3611:
! 3612: #ifdef FREE_CFG_T
! 3613: static void
! 3614: free_config_unpeers(
! 3615: struct config_tree *ptree
! 3616: )
! 3617: {
! 3618: struct unpeer_node *curr_unpeer;
! 3619:
! 3620: while (NULL != (curr_unpeer = dequeue(ptree->unpeers))) {
! 3621: destroy_address_node(curr_unpeer->addr);
! 3622: free_node(curr_unpeer);
! 3623: }
! 3624: }
! 3625: #endif /* FREE_CFG_T */
! 3626:
! 3627:
! 3628: #ifdef SIM
! 3629: static void
! 3630: config_sim(
! 3631: struct config_tree *ptree
! 3632: )
! 3633: {
! 3634: int i;
! 3635: server_info *serv_info;
! 3636: struct attr_val *init_stmt;
! 3637:
! 3638: /* Check if a simulate block was found in the configuration code.
! 3639: * If not, return an error and exit
! 3640: */
! 3641: if (NULL == ptree->sim_details) {
! 3642: fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
! 3643: fprintf(stderr, "\tCheck your configuration file.\n");
! 3644: exit(1);
! 3645: }
! 3646:
! 3647: /* Process the initialization statements
! 3648: * -------------------------------------
! 3649: */
! 3650: init_stmt = queue_head(ptree->sim_details->init_opts);
! 3651: while (init_stmt != NULL) {
! 3652:
! 3653: switch(init_stmt->attr) {
! 3654:
! 3655: case T_Beep_Delay:
! 3656: simulation.beep_delay = init_stmt->value.d;
! 3657: break;
! 3658:
! 3659: case T_Sim_Duration:
! 3660: simulation.end_time = init_stmt->value.d;
! 3661: break;
! 3662:
! 3663: default:
! 3664: fprintf(stderr,
! 3665: "Unknown simulator init token %d\n",
! 3666: init_stmt->attr);
! 3667: exit(1);
! 3668: }
! 3669: init_stmt = next_node(init_stmt);
! 3670: }
! 3671:
! 3672:
! 3673: /* Process the server list
! 3674: * -----------------------
! 3675: */
! 3676: simulation.num_of_servers =
! 3677: get_no_of_elements(ptree->sim_details->servers);
! 3678: simulation.servers = emalloc(simulation.num_of_servers
! 3679: * sizeof(server_info));
! 3680:
! 3681: serv_info = queue_head(ptree->sim_details->servers);
! 3682: for (i = 0;i < simulation.num_of_servers; i++) {
! 3683: if (NULL == serv_info) {
! 3684: fprintf(stderr, "Simulator server list is corrupt\n");
! 3685: exit(1);
! 3686: } else
! 3687: memcpy(&simulation.servers[i], serv_info, sizeof(server_info));
! 3688: serv_info = next_node(serv_info);
! 3689: }
! 3690:
! 3691: /* Create server associations */
! 3692: printf("Creating server associations\n");
! 3693: create_server_associations();
! 3694: fprintf(stderr,"\tServer associations successfully created!!\n");
! 3695: }
! 3696:
! 3697:
! 3698: #ifdef FREE_CFG_T
! 3699: static void
! 3700: free_config_sim(
! 3701: struct config_tree *ptree
! 3702: )
! 3703: {
! 3704: if (NULL == ptree->sim_details)
! 3705: return;
! 3706:
! 3707: DESTROY_QUEUE(ptree->sim_details->init_opts);
! 3708: DESTROY_QUEUE(ptree->sim_details->servers);
! 3709:
! 3710: /* Free the sim_node memory and set the sim_details as NULL */
! 3711: free_node(ptree->sim_details);
! 3712: ptree->sim_details = NULL;
! 3713: }
! 3714: #endif /* FREE_CFG_T */
! 3715: #endif /* SIM */
! 3716:
! 3717:
! 3718: /* Define two different config functions. One for the daemon and the other for
! 3719: * the simulator. The simulator ignores a lot of the standard ntpd configuration
! 3720: * options
! 3721: */
! 3722: #ifndef SIM
! 3723: static void
! 3724: config_ntpd(
! 3725: struct config_tree *ptree
! 3726: )
! 3727: {
! 3728: config_nic_rules(ptree);
! 3729: io_open_sockets();
! 3730: config_monitor(ptree);
! 3731: config_auth(ptree);
! 3732: config_tos(ptree);
! 3733: config_access(ptree);
! 3734: config_tinker(ptree);
! 3735: config_system_opts(ptree);
! 3736: config_logconfig(ptree);
! 3737: config_phone(ptree);
! 3738: config_setvar(ptree);
! 3739: config_ttl(ptree);
! 3740: config_trap(ptree);
! 3741: config_vars(ptree);
! 3742: config_other_modes(ptree);
! 3743: config_peers(ptree);
! 3744: config_unpeers(ptree);
! 3745: config_fudge(ptree);
! 3746: config_qos(ptree);
! 3747: }
! 3748: #endif /* !SIM */
! 3749:
! 3750:
! 3751: #ifdef SIM
! 3752: static void
! 3753: config_ntpdsim(
! 3754: struct config_tree *ptree
! 3755: )
! 3756: {
! 3757: printf("Configuring Simulator...\n");
! 3758: printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
! 3759:
! 3760: config_tos(ptree);
! 3761: config_monitor(ptree);
! 3762: config_tinker(ptree);
! 3763: config_system_opts(ptree);
! 3764: config_logconfig(ptree);
! 3765: config_vars(ptree);
! 3766: config_sim(ptree);
! 3767: }
! 3768: #endif /* SIM */
! 3769:
! 3770:
! 3771: /*
! 3772: * config_remotely() - implements ntpd side of ntpq :config
! 3773: */
! 3774: void
! 3775: config_remotely(
! 3776: sockaddr_u * remote_addr
! 3777: )
! 3778: {
! 3779: struct FILE_INFO remote_cuckoo;
! 3780: char origin[128];
! 3781:
! 3782: snprintf(origin, sizeof(origin), "remote config from %s",
! 3783: stoa(remote_addr));
! 3784: memset(&remote_cuckoo, 0, sizeof(remote_cuckoo));
! 3785: remote_cuckoo.fname = origin;
! 3786: remote_cuckoo.line_no = 1;
! 3787: remote_cuckoo.col_no = 1;
! 3788: ip_file = &remote_cuckoo;
! 3789: input_from_file = 0;
! 3790:
! 3791: init_syntax_tree(&cfgt);
! 3792: yyparse();
! 3793: cfgt.source.attr = CONF_SOURCE_NTPQ;
! 3794: cfgt.timestamp = time(NULL);
! 3795: cfgt.source.value.s = estrdup(stoa(remote_addr));
! 3796:
! 3797: DPRINTF(1, ("Finished Parsing!!\n"));
! 3798:
! 3799: save_and_apply_config_tree();
! 3800:
! 3801: input_from_file = 1;
! 3802: }
! 3803:
! 3804:
! 3805: /*
! 3806: * getconfig() - process startup configuration file e.g /etc/ntp.conf
! 3807: */
! 3808: void
! 3809: getconfig(
! 3810: int argc,
! 3811: char *argv[]
! 3812: )
! 3813: {
! 3814: char line[MAXLINE];
! 3815:
! 3816: #ifdef DEBUG
! 3817: atexit(free_all_config_trees);
! 3818: #endif
! 3819: #ifndef SYS_WINNT
! 3820: config_file = CONFIG_FILE;
! 3821: #else
! 3822: temp = CONFIG_FILE;
! 3823: if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
! 3824: msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
! 3825: exit(1);
! 3826: }
! 3827: config_file = config_file_storage;
! 3828:
! 3829: temp = ALT_CONFIG_FILE;
! 3830: if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
! 3831: msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
! 3832: exit(1);
! 3833: }
! 3834: alt_config_file = alt_config_file_storage;
! 3835:
! 3836: #endif /* SYS_WINNT */
! 3837: res_fp = NULL;
! 3838: ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
! 3839:
! 3840: /*
! 3841: * install a non default variable with this daemon version
! 3842: */
! 3843: snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
! 3844: set_sys_var(line, strlen(line)+1, RO);
! 3845:
! 3846: /*
! 3847: * Set up for the first time step to install a variable showing
! 3848: * which syscall is being used to step.
! 3849: */
! 3850: set_tod_using = &ntpd_set_tod_using;
! 3851:
! 3852: /*
! 3853: * On Windows, the variable has already been set, on the rest,
! 3854: * initialize it to "UNKNOWN".
! 3855: */
! 3856: #ifndef SYS_WINNT
! 3857: strncpy(line, "settimeofday=\"UNKNOWN\"", sizeof(line));
! 3858: set_sys_var(line, strlen(line) + 1, RO);
! 3859: #endif
! 3860:
! 3861: /*
! 3862: * Initialize the loop.
! 3863: */
! 3864: loop_config(LOOP_DRIFTINIT, 0.);
! 3865:
! 3866: getCmdOpts(argc, argv);
! 3867:
! 3868: init_syntax_tree(&cfgt);
! 3869:
! 3870: curr_include_level = 0;
! 3871: if (
! 3872: (fp[curr_include_level] = F_OPEN(FindConfig(config_file), "r")) == NULL
! 3873: #ifdef HAVE_NETINFO
! 3874: /* If there is no config_file, try NetInfo. */
! 3875: && check_netinfo && !(config_netinfo = get_netinfo_config())
! 3876: #endif /* HAVE_NETINFO */
! 3877: ) {
! 3878: msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
! 3879: #ifndef SYS_WINNT
! 3880: io_open_sockets();
! 3881:
! 3882: return;
! 3883: #else
! 3884: /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
! 3885:
! 3886: if ((fp[curr_include_level] = F_OPEN(FindConfig(alt_config_file), "r")) == NULL) {
! 3887:
! 3888: /*
! 3889: * Broadcast clients can sometimes run without
! 3890: * a configuration file.
! 3891: */
! 3892: msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
! 3893: io_open_sockets();
! 3894:
! 3895: return;
! 3896: }
! 3897: cfgt.source.value.s = estrdup(alt_config_file);
! 3898: #endif /* SYS_WINNT */
! 3899: } else
! 3900: cfgt.source.value.s = estrdup(config_file);
! 3901:
! 3902:
! 3903: /*** BULK OF THE PARSER ***/
! 3904: #ifdef DEBUG
! 3905: yydebug = !!(debug >= 5);
! 3906: #endif
! 3907: ip_file = fp[curr_include_level];
! 3908: yyparse();
! 3909:
! 3910: DPRINTF(1, ("Finished Parsing!!\n"));
! 3911:
! 3912: cfgt.source.attr = CONF_SOURCE_FILE;
! 3913: cfgt.timestamp = time(NULL);
! 3914:
! 3915: save_and_apply_config_tree();
! 3916:
! 3917: while (curr_include_level != -1)
! 3918: FCLOSE(fp[curr_include_level--]);
! 3919:
! 3920: #ifdef HAVE_NETINFO
! 3921: if (config_netinfo)
! 3922: free_netinfo_config(config_netinfo);
! 3923: #endif /* HAVE_NETINFO */
! 3924:
! 3925: /*
! 3926: printf("getconfig: res_fp <%p> call_resolver: %d", res_fp, call_resolver);
! 3927: */
! 3928:
! 3929: if (res_fp != NULL) {
! 3930: if (call_resolver) {
! 3931: /*
! 3932: * Need name resolution
! 3933: */
! 3934: do_resolve_internal();
! 3935: }
! 3936: }
! 3937: }
! 3938:
! 3939:
! 3940: void
! 3941: save_and_apply_config_tree(void)
! 3942: {
! 3943: struct config_tree *ptree;
! 3944: #ifndef SAVECONFIG
! 3945: struct config_tree *punlinked;
! 3946: #endif
! 3947:
! 3948: /*
! 3949: * Keep all the configuration trees applied since startup in
! 3950: * a list that can be used to dump the configuration back to
! 3951: * a text file.
! 3952: */
! 3953: ptree = emalloc(sizeof(*ptree));
! 3954: memcpy(ptree, &cfgt, sizeof(*ptree));
! 3955: memset(&cfgt, 0, sizeof(cfgt));
! 3956:
! 3957: LINK_TAIL_SLIST(cfg_tree_history, ptree, link,
! 3958: struct config_tree);
! 3959:
! 3960: #ifdef SAVECONFIG
! 3961: if (HAVE_OPT( SAVECONFIGQUIT )) {
! 3962: FILE *dumpfile;
! 3963: int err;
! 3964: int dumpfailed;
! 3965:
! 3966: dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
! 3967: if (NULL == dumpfile) {
! 3968: err = errno;
! 3969: fprintf(stderr,
! 3970: "can not create save file %s, error %d %s\n",
! 3971: OPT_ARG( SAVECONFIGQUIT ), err,
! 3972: strerror(err));
! 3973: exit(err);
! 3974: }
! 3975:
! 3976: dumpfailed = dump_all_config_trees(dumpfile, 0);
! 3977: if (dumpfailed)
! 3978: fprintf(stderr,
! 3979: "--saveconfigquit %s error %d\n",
! 3980: OPT_ARG( SAVECONFIGQUIT ),
! 3981: dumpfailed);
! 3982: else
! 3983: fprintf(stderr,
! 3984: "configuration saved to %s\n",
! 3985: OPT_ARG( SAVECONFIGQUIT ));
! 3986:
! 3987: exit(dumpfailed);
! 3988: }
! 3989: #endif /* SAVECONFIG */
! 3990:
! 3991: /* The actual configuration done depends on whether we are configuring the
! 3992: * simulator or the daemon. Perform a check and call the appropriate
! 3993: * function as needed.
! 3994: */
! 3995:
! 3996: #ifndef SIM
! 3997: config_ntpd(ptree);
! 3998: #else
! 3999: config_ntpdsim(ptree);
! 4000: #endif
! 4001:
! 4002: /*
! 4003: * With configure --disable-saveconfig, there's no use keeping
! 4004: * the config tree around after application, so free it.
! 4005: */
! 4006: #ifndef SAVECONFIG
! 4007: UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
! 4008: struct config_tree);
! 4009: NTP_INSIST(punlinked == ptree);
! 4010: free_config_tree(ptree);
! 4011: #endif
! 4012: }
! 4013:
! 4014:
! 4015: void
! 4016: ntpd_set_tod_using(
! 4017: const char *which
! 4018: )
! 4019: {
! 4020: char line[128];
! 4021:
! 4022: snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
! 4023: set_sys_var(line, strlen(line) + 1, RO);
! 4024: }
! 4025:
! 4026:
! 4027: /* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
! 4028: * --------------------------------------------
! 4029: */
! 4030:
! 4031:
! 4032: /*
! 4033: * get_pfxmatch - find value for prefixmatch
! 4034: * and update char * accordingly
! 4035: */
! 4036: static u_int32
! 4037: get_pfxmatch(
! 4038: const char ** pstr,
! 4039: struct masks * m
! 4040: )
! 4041: {
! 4042: while (m->name != NULL) {
! 4043: if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
! 4044: *pstr += strlen(m->name);
! 4045: return m->mask;
! 4046: } else {
! 4047: m++;
! 4048: }
! 4049: }
! 4050: return 0;
! 4051: }
! 4052:
! 4053: /*
! 4054: * get_match - find logmask value
! 4055: */
! 4056: static u_int32
! 4057: get_match(
! 4058: const char * str,
! 4059: struct masks * m
! 4060: )
! 4061: {
! 4062: while (m->name != NULL) {
! 4063: if (strcmp(str, m->name) == 0)
! 4064: return m->mask;
! 4065: else
! 4066: m++;
! 4067: }
! 4068: return 0;
! 4069: }
! 4070:
! 4071: /*
! 4072: * get_logmask - build bitmask for ntp_syslogmask
! 4073: */
! 4074: static u_int32
! 4075: get_logmask(
! 4076: const char * str
! 4077: )
! 4078: {
! 4079: const char * t;
! 4080: u_int32 offset;
! 4081: u_int32 mask;
! 4082:
! 4083: mask = get_match(str, logcfg_noclass_items);
! 4084: if (mask != 0)
! 4085: return mask;
! 4086:
! 4087: t = str;
! 4088: offset = get_pfxmatch(&t, logcfg_class);
! 4089: mask = get_match(t, logcfg_class_items);
! 4090:
! 4091: if (mask)
! 4092: return mask << offset;
! 4093: else
! 4094: msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
! 4095: str);
! 4096:
! 4097: return 0;
! 4098: }
! 4099:
! 4100:
! 4101: #ifdef HAVE_NETINFO
! 4102:
! 4103: /*
! 4104: * get_netinfo_config - find the nearest NetInfo domain with an ntp
! 4105: * configuration and initialize the configuration state.
! 4106: */
! 4107: static struct netinfo_config_state *
! 4108: get_netinfo_config(void)
! 4109: {
! 4110: ni_status status;
! 4111: void *domain;
! 4112: ni_id config_dir;
! 4113: struct netinfo_config_state *config;
! 4114:
! 4115: if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
! 4116:
! 4117: while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
! 4118: void *next_domain;
! 4119: if (ni_open(domain, "..", &next_domain) != NI_OK) {
! 4120: ni_free(next_domain);
! 4121: break;
! 4122: }
! 4123: ni_free(domain);
! 4124: domain = next_domain;
! 4125: }
! 4126: if (status != NI_OK) {
! 4127: ni_free(domain);
! 4128: return NULL;
! 4129: }
! 4130:
! 4131: config = emalloc(sizeof(*config));
! 4132: config->domain = domain;
! 4133: config->config_dir = config_dir;
! 4134: config->prop_index = 0;
! 4135: config->val_index = 0;
! 4136: config->val_list = NULL;
! 4137:
! 4138: return config;
! 4139: }
! 4140:
! 4141:
! 4142:
! 4143: /*
! 4144: * free_netinfo_config - release NetInfo configuration state
! 4145: */
! 4146: static void
! 4147: free_netinfo_config(
! 4148: struct netinfo_config_state *config
! 4149: )
! 4150: {
! 4151: ni_free(config->domain);
! 4152: free(config);
! 4153: }
! 4154:
! 4155:
! 4156:
! 4157: /*
! 4158: * gettokens_netinfo - return tokens from NetInfo
! 4159: */
! 4160: static int
! 4161: gettokens_netinfo (
! 4162: struct netinfo_config_state *config,
! 4163: char **tokenlist,
! 4164: int *ntokens
! 4165: )
! 4166: {
! 4167: int prop_index = config->prop_index;
! 4168: int val_index = config->val_index;
! 4169: char **val_list = config->val_list;
! 4170:
! 4171: /*
! 4172: * Iterate through each keyword and look for a property that matches it.
! 4173: */
! 4174: again:
! 4175: if (!val_list) {
! 4176: for (; prop_index < COUNTOF(keywords); prop_index++)
! 4177: {
! 4178: ni_namelist namelist;
! 4179: struct keyword current_prop = keywords[prop_index];
! 4180: ni_index index;
! 4181:
! 4182: /*
! 4183: * For each value associated in the property, we're going to return
! 4184: * a separate line. We squirrel away the values in the config state
! 4185: * so the next time through, we don't need to do this lookup.
! 4186: */
! 4187: NI_INIT(&namelist);
! 4188: if (NI_OK == ni_lookupprop(config->domain,
! 4189: &config->config_dir, current_prop.text,
! 4190: &namelist)) {
! 4191:
! 4192: /* Found the property, but it has no values */
! 4193: if (namelist.ni_namelist_len == 0) continue;
! 4194:
! 4195: config->val_list =
! 4196: emalloc(sizeof(char*) *
! 4197: (namelist.ni_namelist_len + 1));
! 4198: val_list = config->val_list;
! 4199:
! 4200: for (index = 0;
! 4201: index < namelist.ni_namelist_len;
! 4202: index++) {
! 4203: char *value;
! 4204:
! 4205: value = namelist.ni_namelist_val[index];
! 4206: val_list[index] = estrdup(value);
! 4207: }
! 4208: val_list[index] = NULL;
! 4209:
! 4210: break;
! 4211: }
! 4212: ni_namelist_free(&namelist);
! 4213: }
! 4214: config->prop_index = prop_index;
! 4215: }
! 4216:
! 4217: /* No list; we're done here. */
! 4218: if (!val_list)
! 4219: return CONFIG_UNKNOWN;
! 4220:
! 4221: /*
! 4222: * We have a list of values for the current property.
! 4223: * Iterate through them and return each in order.
! 4224: */
! 4225: if (val_list[val_index]) {
! 4226: int ntok = 1;
! 4227: int quoted = 0;
! 4228: char *tokens = val_list[val_index];
! 4229:
! 4230: msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
! 4231:
! 4232: (const char*)tokenlist[0] = keywords[prop_index].text;
! 4233: for (ntok = 1; ntok < MAXTOKENS; ntok++) {
! 4234: tokenlist[ntok] = tokens;
! 4235: while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
! 4236: quoted ^= (*tokens++ == '"');
! 4237:
! 4238: if (ISEOL(*tokens)) {
! 4239: *tokens = '\0';
! 4240: break;
! 4241: } else { /* must be space */
! 4242: *tokens++ = '\0';
! 4243: while (ISSPACE(*tokens))
! 4244: tokens++;
! 4245: if (ISEOL(*tokens))
! 4246: break;
! 4247: }
! 4248: }
! 4249:
! 4250: if (ntok == MAXTOKENS) {
! 4251: /* HMS: chomp it to lose the EOL? */
! 4252: msyslog(LOG_ERR,
! 4253: "gettokens_netinfo: too many tokens. Ignoring: %s",
! 4254: tokens);
! 4255: } else {
! 4256: *ntokens = ntok + 1;
! 4257: }
! 4258:
! 4259: config->val_index++; /* HMS: Should this be in the 'else'? */
! 4260:
! 4261: return keywords[prop_index].keytype;
! 4262: }
! 4263:
! 4264: /* We're done with the current property. */
! 4265: prop_index = ++config->prop_index;
! 4266:
! 4267: /* Free val_list and reset counters. */
! 4268: for (val_index = 0; val_list[val_index]; val_index++)
! 4269: free(val_list[val_index]);
! 4270: free(val_list);
! 4271: val_list = config->val_list = NULL;
! 4272: val_index = config->val_index = 0;
! 4273:
! 4274: goto again;
! 4275: }
! 4276:
! 4277: #endif /* HAVE_NETINFO */
! 4278:
! 4279: /*
! 4280: * getnetnum - return a net number (this is crude, but careful)
! 4281: *
! 4282: * returns 1 for success, and mysteriously, 0 or -1 for failure
! 4283: */
! 4284: static int
! 4285: getnetnum(
! 4286: const char *num,
! 4287: sockaddr_u *addr,
! 4288: int complain,
! 4289: enum gnn_type a_type
! 4290: )
! 4291: {
! 4292: int retval;
! 4293: struct addrinfo *res;
! 4294:
! 4295: /* Get all the addresses that resolve to this name */
! 4296: retval = get_multiple_netnums(num, addr, &res, complain, a_type);
! 4297:
! 4298: if (retval != 1) {
! 4299: /* Name resolution failed */
! 4300: return retval;
! 4301: }
! 4302:
! 4303: memcpy(addr, res->ai_addr, res->ai_addrlen);
! 4304:
! 4305: DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
! 4306:
! 4307: freeaddrinfo(res);
! 4308: return 1;
! 4309: }
! 4310:
! 4311:
! 4312: /*
! 4313: * get_multiple_netnums
! 4314: *
! 4315: * returns 1 for success, and mysteriously, 0 or -1 for failure
! 4316: */
! 4317: static int
! 4318: get_multiple_netnums(
! 4319: const char *nameornum,
! 4320: sockaddr_u *addr,
! 4321: struct addrinfo **res,
! 4322: int complain,
! 4323: enum gnn_type a_type
! 4324: )
! 4325: {
! 4326: char lookbuf[1024];
! 4327: const char *lookup;
! 4328: char *pch;
! 4329: struct addrinfo hints;
! 4330: struct addrinfo *ptr;
! 4331: int retval;
! 4332: sockaddr_u ipaddr;
! 4333:
! 4334: memset(&hints, 0, sizeof(hints));
! 4335:
! 4336: if (strlen(nameornum) >= sizeof(lookbuf)) {
! 4337: NTP_INSIST(strlen(nameornum) < sizeof(lookbuf));
! 4338: return 0;
! 4339: }
! 4340:
! 4341: lookup = nameornum;
! 4342: if (is_ip_address(nameornum, &ipaddr)) {
! 4343: hints.ai_flags = AI_NUMERICHOST;
! 4344: hints.ai_family = AF(&ipaddr);
! 4345: if ('[' == nameornum[0]) {
! 4346: lookup = lookbuf;
! 4347: strncpy(lookbuf, &nameornum[1],
! 4348: sizeof(lookbuf));
! 4349: pch = strchr(lookbuf, ']');
! 4350: if (pch != NULL)
! 4351: *pch = '\0';
! 4352: }
! 4353: pch = strchr(lookup, '%');
! 4354: if (pch != NULL) {
! 4355: if (lookup != lookbuf) {
! 4356: lookup = lookbuf;
! 4357: strncpy(lookbuf, nameornum,
! 4358: sizeof(lookbuf));
! 4359: pch = strchr(lookup, '%');
! 4360: }
! 4361: *pch = '\0';
! 4362: }
! 4363: }
! 4364:
! 4365: if (AF_INET6 == hints.ai_family && !ipv6_works)
! 4366: return 0;
! 4367:
! 4368: if (AF_UNSPEC == hints.ai_family) {
! 4369: if (!ipv6_works)
! 4370: hints.ai_family = AF_INET;
! 4371: else if (!ipv4_works)
! 4372: hints.ai_family = AF_INET6;
! 4373: else if (IS_IPV4(addr) || IS_IPV6(addr))
! 4374: hints.ai_family = AF(addr);
! 4375: }
! 4376:
! 4377: /* Get host address. Looking for UDP datagram connection */
! 4378: hints.ai_socktype = SOCK_DGRAM;
! 4379:
! 4380: DPRINTF(4, ("getaddrinfo %s%s\n",
! 4381: (AF_UNSPEC == hints.ai_family)
! 4382: ? ""
! 4383: : (AF_INET == hints.ai_family)
! 4384: ? "v4 "
! 4385: : "v6 ",
! 4386: lookup));
! 4387:
! 4388: retval = getaddrinfo(lookup, "ntp", &hints, &ptr);
! 4389:
! 4390: if (retval || (AF_INET6 == ptr->ai_family && !ipv6_works)) {
! 4391: if (complain)
! 4392: msyslog(LOG_ERR,
! 4393: "getaddrinfo: \"%s\" invalid host address, ignored",
! 4394: lookup);
! 4395: else
! 4396: DPRINTF(1, ("getaddrinfo: \"%s\" invalid host address.\n",
! 4397: lookup));
! 4398:
! 4399: if (!retval) {
! 4400: freeaddrinfo(ptr);
! 4401: return -1;
! 4402: } else {
! 4403: return 0;
! 4404: }
! 4405: }
! 4406: *res = ptr;
! 4407:
! 4408: return 1;
! 4409: }
! 4410:
! 4411:
! 4412: #if !defined(VMS) && !defined(SYS_WINNT)
! 4413: /*
! 4414: * catchchild - receive the resolver's exit status
! 4415: */
! 4416: static RETSIGTYPE
! 4417: catchchild(
! 4418: int sig
! 4419: )
! 4420: {
! 4421: /*
! 4422: * We only start up one child, and if we're here
! 4423: * it should have already exited. Hence the following
! 4424: * shouldn't hang. If it does, please tell me.
! 4425: */
! 4426: #if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
! 4427: (void) wait(0);
! 4428: #endif /* SYS_WINNT && VXWORKS*/
! 4429: }
! 4430: #endif /* VMS */
! 4431:
! 4432:
! 4433: /*
! 4434: * save_resolve - save configuration info into a file for later name resolution
! 4435: */
! 4436: static void
! 4437: save_resolve(
! 4438: char *name,
! 4439: int no_needed,
! 4440: int type,
! 4441: int mode,
! 4442: int version,
! 4443: int minpoll,
! 4444: int maxpoll,
! 4445: u_int flags,
! 4446: int ttl,
! 4447: keyid_t keyid,
! 4448: u_char *keystr
! 4449: )
! 4450: {
! 4451: #ifndef SYS_VXWORKS
! 4452: if (res_fp == NULL) {
! 4453: #ifndef SYS_WINNT
! 4454: strcpy(res_file, RES_TEMPFILE);
! 4455: #else
! 4456: int len;
! 4457:
! 4458: /* no /tmp directory under NT */
! 4459: if (!GetTempPath(sizeof res_file, res_file)) {
! 4460: msyslog(LOG_ERR, "can not get temp dir: %m");
! 4461: exit(1);
! 4462: }
! 4463:
! 4464: len = strlen(res_file);
! 4465: if (sizeof res_file < len + sizeof "ntpdXXXXXX") {
! 4466: msyslog(LOG_ERR,
! 4467: "temporary directory path %s too long",
! 4468: res_file);
! 4469: exit(1);
! 4470: }
! 4471:
! 4472: memmove(res_file + len, "ntpdXXXXXX",
! 4473: sizeof "ntpdXXXXXX");
! 4474: #endif /* SYS_WINNT */
! 4475: #ifdef HAVE_MKSTEMP
! 4476: {
! 4477: int fd;
! 4478:
! 4479: res_fp = NULL;
! 4480: if ((fd = mkstemp(res_file)) != -1)
! 4481: res_fp = fdopen(fd, "r+");
! 4482: }
! 4483: #else
! 4484: mktemp(res_file);
! 4485: res_fp = fopen(res_file, "w");
! 4486: #endif
! 4487: if (res_fp == NULL) {
! 4488: msyslog(LOG_ERR, "open failed for %s: %m", res_file);
! 4489: return;
! 4490: }
! 4491: }
! 4492: #ifdef DEBUG
! 4493: if (debug) {
! 4494: printf("resolving %s\n", name);
! 4495: }
! 4496: #endif
! 4497:
! 4498: (void)fprintf(res_fp, "%s %d %d %d %d %d %d %d %d %u %s\n",
! 4499: name, no_needed, type,
! 4500: mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
! 4501: #ifdef DEBUG
! 4502: if (debug > 1)
! 4503: printf("config: %s %d %d %d %d %d %d %x %d %u %s\n",
! 4504: name, no_needed, type,
! 4505: mode, version, minpoll, maxpoll, flags,
! 4506: ttl, keyid, keystr);
! 4507: #endif
! 4508:
! 4509: #else /* SYS_VXWORKS */
! 4510: /* save resolve info to a struct */
! 4511: #endif /* SYS_VXWORKS */
! 4512: }
! 4513:
! 4514:
! 4515: /*
! 4516: * abort_resolve - terminate the resolver stuff and delete the file
! 4517: */
! 4518: static void
! 4519: abort_resolve(void)
! 4520: {
! 4521: /*
! 4522: * In an ideal world we would might reread the file and
! 4523: * log the hosts which aren't getting configured. Since
! 4524: * this is too much work, however, just close and delete
! 4525: * the temp file.
! 4526: */
! 4527: if (res_fp != NULL)
! 4528: (void) fclose(res_fp);
! 4529: res_fp = NULL;
! 4530:
! 4531: #ifndef SYS_VXWORKS /* we don't open the file to begin with */
! 4532: #if !defined(VMS)
! 4533: if (unlink(res_file))
! 4534: msyslog(LOG_WARNING,
! 4535: "Unable to remove temporary resolver file %s, %m",
! 4536: res_file);
! 4537: #else
! 4538: (void) delete(res_file);
! 4539: #endif /* VMS */
! 4540: #endif /* SYS_VXWORKS */
! 4541: }
! 4542:
! 4543:
! 4544: /*
! 4545: * do_resolve_internal - start up the resolver function (not program)
! 4546: *
! 4547: * On VMS, VxWorks, and Unix-like systems lacking fork(), this routine
! 4548: * will simply refuse to resolve anything.
! 4549: *
! 4550: * Possible implementation: keep `res_file' in memory, do async
! 4551: * name resolution via QIO, update from within completion AST.
! 4552: * I'm unlikely to find the time for doing this, though. -wjm
! 4553: */
! 4554: static void
! 4555: do_resolve_internal(void)
! 4556: {
! 4557: #ifndef SYS_WINNT
! 4558: int i;
! 4559: #endif
! 4560:
! 4561: if (res_fp == NULL) {
! 4562: /* belch */
! 4563: msyslog(LOG_ERR,
! 4564: "do_resolve_internal: Fatal: res_fp == NULL");
! 4565: exit(1);
! 4566: }
! 4567:
! 4568: /* we are done with this now */
! 4569: (void) fclose(res_fp);
! 4570: res_fp = NULL;
! 4571:
! 4572: #ifndef NO_INTRES
! 4573: req_file = res_file; /* set up pointer to res file */
! 4574: #ifndef SYS_WINNT
! 4575: (void) signal_no_reset(SIGCHLD, catchchild);
! 4576:
! 4577: /* the parent process will write to the pipe
! 4578: * in order to wake up to child process
! 4579: * which may be waiting in a select() call
! 4580: * on the read fd */
! 4581: if (pipe(resolver_pipe_fd) < 0) {
! 4582: msyslog(LOG_ERR,
! 4583: "unable to open resolver pipe");
! 4584: exit(1);
! 4585: }
! 4586:
! 4587: i = fork();
! 4588: /* Shouldn't the code below be re-ordered?
! 4589: * I.e. first check if the fork() returned an error, then
! 4590: * check whether we're parent or child.
! 4591: * Martin Burnicki
! 4592: */
! 4593: if (i == 0) {
! 4594: /*
! 4595: * this used to close everything
! 4596: * I don't think this is necessary
! 4597: */
! 4598: /*
! 4599: * To the unknown commenter above:
! 4600: * Well, I think it's better to clean up
! 4601: * after oneself. I have had problems with
! 4602: * refclock-io when intres was running - things
! 4603: * where fine again when ntpintres was gone.
! 4604: * So some systems react erratic at least.
! 4605: *
! 4606: * Frank Kardel
! 4607: *
! 4608: * 94-11-16:
! 4609: * Further debugging has proven that the above is
! 4610: * absolutely harmful. The internal resolver
! 4611: * is still in the SIGIO process group and the lingering
! 4612: * async io information causes it to process requests from
! 4613: * all file decriptor causing a race between the NTP daemon
! 4614: * and the resolver. which then eats data when it wins 8-(.
! 4615: * It is absolutly necessary to kill any IO associations
! 4616: * shared with the NTP daemon.
! 4617: *
! 4618: * We also block SIGIO (currently no ports means to
! 4619: * disable the signal handle for IO).
! 4620: *
! 4621: * Thanks to wgstuken@informatik.uni-erlangen.de to notice
! 4622: * that it is the ntp-resolver child running into trouble.
! 4623: *
! 4624: * THUS:
! 4625: */
! 4626:
! 4627: /*
! 4628: msyslog(LOG_INFO, "do_resolve_internal: pre-closelog");
! 4629: */
! 4630: closelog();
! 4631: kill_asyncio(0);
! 4632:
! 4633: (void) signal_no_reset(SIGCHLD, SIG_DFL);
! 4634:
! 4635: init_logging("ntpd_intres", 0);
! 4636: setup_logfile();
! 4637: /*
! 4638: msyslog(LOG_INFO, "do_resolve_internal: post-closelog");
! 4639: */
! 4640:
! 4641: ntp_intres();
! 4642:
! 4643: /*
! 4644: * If we got here, the intres code screwed up.
! 4645: * Print something so we don't die without complaint
! 4646: */
! 4647: msyslog(LOG_ERR, "call to ntp_intres lost");
! 4648: abort_resolve();
! 4649: exit(1);
! 4650: }
! 4651: if (i == -1) {
! 4652: msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
! 4653: (void) signal_no_reset(SIGCHLD, SIG_DFL);
! 4654: abort_resolve();
! 4655: } else
! 4656: /* This is the parent process who will write to the pipe,
! 4657: * so we close the read fd */
! 4658: close(resolver_pipe_fd[0]);
! 4659: #else /* SYS_WINNT */
! 4660: {
! 4661: /* NT's equivalent of fork() is _spawn(), but the start point
! 4662: * of the new process is an executable filename rather than
! 4663: * a function name as desired here.
! 4664: */
! 4665: unsigned thread_id;
! 4666: uintptr_t res_thd_handle;
! 4667:
! 4668: fflush(stdout);
! 4669: ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
! 4670: if (ResolverEventHandle == NULL) {
! 4671: msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
! 4672: abort_resolve();
! 4673: }
! 4674: res_thd_handle = _beginthreadex(
! 4675: NULL, /* no security attributes */
! 4676: 0, /* use default stack size */
! 4677: ntp_intres_thread, /* thread function */
! 4678: NULL, /* argument to thread function */
! 4679: 0, /* use default creation flags */
! 4680: &thread_id); /* receives thread identifier */
! 4681: if (!res_thd_handle) {
! 4682: msyslog(LOG_ERR, "_beginthreadex ntp_intres_thread failed %m");
! 4683: CloseHandle(ResolverEventHandle);
! 4684: ResolverEventHandle = NULL;
! 4685: abort_resolve();
! 4686: }
! 4687: }
! 4688: #endif /* SYS_WINNT */
! 4689: #else /* NO_INTRES follows */
! 4690: msyslog(LOG_ERR,
! 4691: "Deferred DNS not implemented - use numeric addresses");
! 4692: abort_resolve();
! 4693: #endif
! 4694: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>