File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / ntp_config.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:37 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>