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