Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/ntpd/ntp_config.c
Line
Count
Source (jump to first uncovered line)
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 <stdio.h>
21
#include <ctype.h>
22
#ifdef HAVE_SYS_PARAM_H
23
# include <sys/param.h>
24
#endif
25
#include <signal.h>
26
#ifndef SIGCHLD
27
# define SIGCHLD SIGCLD
28
#endif
29
#ifdef HAVE_SYS_WAIT_H
30
# include <sys/wait.h>
31
#endif
32
33
#include <isc/net.h>
34
#include <isc/result.h>
35
36
#include "ntp.h"
37
#include "ntpd.h"
38
#include "ntp_io.h"
39
#include "ntp_unixtime.h"
40
#include "ntp_refclock.h"
41
#include "ntp_filegen.h"
42
#include "ntp_stdlib.h"
43
#include "lib_strbuf.h"
44
#include "ntp_assert.h"
45
#include "ntp_random.h"
46
/*
47
 * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
48
 * so #include these later.
49
 */
50
#include "ntp_config.h"
51
#include "ntp_cmdargs.h"
52
#include "ntp_scanner.h"
53
#include "ntp_parser.h"
54
#include "ntpd-opts.h"
55
56
#ifndef IGNORE_DNS_ERRORS
57
0
# define DNSFLAGS 0
58
#else
59
# define DNSFLAGS GAIR_F_IGNDNSERR
60
#endif
61
62
extern int yyparse(void);
63
64
/* Bug 2817 */
65
#if defined(HAVE_SYS_MMAN_H)
66
# include <sys/mman.h>
67
#endif
68
69
/* list of servers from command line for config_peers() */
70
int cmdline_server_count;
71
char ** cmdline_servers;
72
73
/* Current state of memory locking:
74
 * -1: default
75
 *  0: memory locking disabled
76
 *  1: Memory locking enabled
77
 */
78
int cur_memlock = -1;
79
80
/*
81
 * "logconfig" building blocks
82
 */
83
struct masks {
84
  const char * const  name;
85
  const u_int32   mask;
86
};
87
88
static struct masks logcfg_class[] = {
89
  { "clock",  NLOG_OCLOCK },
90
  { "peer", NLOG_OPEER },
91
  { "sync", NLOG_OSYNC },
92
  { "sys",  NLOG_OSYS },
93
  { NULL,   0 }
94
};
95
96
/* logcfg_noclass_items[] masks are complete and must not be shifted */
97
static struct masks logcfg_noclass_items[] = {
98
  { "allall",   NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
99
  { "allinfo",    NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
100
  { "allevents",    NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
101
  { "allstatus",    NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
102
  { "allstatistics",  NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
103
  /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
104
  { "allclock",   (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
105
  { "allpeer",    (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
106
  { "allsys",   (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
107
  { "allsync",    (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
108
  { NULL,     0 }
109
};
110
111
/* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
112
static struct masks logcfg_class_items[] = {
113
  { "all",    NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
114
  { "info",   NLOG_INFO },
115
  { "events",   NLOG_EVENT },
116
  { "status",   NLOG_STATUS },
117
  { "statistics",   NLOG_STATIST },
118
  { NULL,     0 }
119
};
120
121
typedef struct peer_resolved_ctx_tag {
122
  int   flags;
123
  int   host_mode;  /* T_* token identifier */
124
  u_short   family;
125
  keyid_t   keyid;
126
  u_char    hmode;    /* MODE_* */
127
  u_char    version;
128
  u_char    minpoll;
129
  u_char    maxpoll;
130
  u_int32   ttl;
131
  const char *  group;
132
} peer_resolved_ctx;
133
134
/* Limits */
135
#define MAXPHONE  10  /* maximum number of phone strings */
136
#define MAXPPS    20  /* maximum length of PPS device string */
137
138
/*
139
 * Miscellaneous macros
140
 */
141
#define ISEOL(c)  ((c) == '#' || (c) == '\n' || (c) == '\0')
142
#define ISSPACE(c)  ((c) == ' ' || (c) == '\t')
143
144
0
#define _UC(str)  ((char *)(intptr_t)(str))
145
146
/*
147
 * Definitions of things either imported from or exported to outside
148
 */
149
extern int yydebug;     /* ntp_parser.c (.y) */
150
config_tree cfgt;     /* Parser output stored here */
151
struct config_tree_tag *cfg_tree_history; /* History of configs */
152
char *  sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
153
char  default_keysdir[] = NTP_KEYSDIR;
154
char *  keysdir = default_keysdir;  /* crypto keys directory */
155
char *  saveconfigdir;
156
#if defined(HAVE_SCHED_SETSCHEDULER)
157
int config_priority_override = 0;
158
int config_priority;
159
#endif
160
161
const char *config_file;
162
static char default_ntp_signd_socket[] =
163
#ifdef NTP_SIGND_PATH
164
          NTP_SIGND_PATH;
165
#else
166
          "";
167
#endif
168
char *ntp_signd_socket = default_ntp_signd_socket;
169
#ifdef HAVE_NETINFO
170
struct netinfo_config_state *config_netinfo = NULL;
171
int check_netinfo = 1;
172
#endif /* HAVE_NETINFO */
173
#ifdef SYS_WINNT
174
char *alt_config_file;
175
LPTSTR temp;
176
char config_file_storage[MAX_PATH];
177
char alt_config_file_storage[MAX_PATH];
178
#endif /* SYS_WINNT */
179
180
#ifdef HAVE_NETINFO
181
/*
182
 * NetInfo configuration state
183
 */
184
struct netinfo_config_state {
185
  void *domain;   /* domain with config */
186
  ni_id config_dir; /* ID config dir      */
187
  int prop_index;   /* current property   */
188
  int val_index;    /* current value      */
189
  char **val_list;  /* value list         */
190
};
191
#endif
192
193
struct REMOTE_CONFIG_INFO remote_config;  /* Remote configuration buffer and
194
               pointer info */
195
int old_config_style = 1;    /* A boolean flag, which when set,
196
            * indicates that the old configuration
197
            * format with a newline at the end of
198
            * every command is being used
199
            */
200
int cryptosw;   /* crypto command called */
201
202
extern char *stats_drift_file;  /* name of the driftfile */
203
204
#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
205
/*
206
 * backwards compatibility flags
207
 */
208
bc_entry bc_list[] = {
209
  { T_Bc_bugXXXX,   1 } /* default enabled */
210
};
211
212
/*
213
 * declare an int pointer for each flag for quick testing without
214
 * walking bc_list.  If the pointer is consumed by libntp rather
215
 * than ntpd, declare it in a libntp source file pointing to storage
216
 * initialized with the appropriate value for other libntp clients, and
217
 * redirect it to point into bc_list during ntpd startup.
218
 */
219
int *p_bcXXXX_enabled = &bc_list[0].enabled;
220
#endif
221
222
/* FUNCTION PROTOTYPES */
223
224
static void init_syntax_tree(config_tree *);
225
static void apply_enable_disable(attr_val_fifo *q, int enable);
226
227
#ifdef FREE_CFG_T
228
static void free_auth_node(config_tree *);
229
static void free_all_config_trees(void);
230
231
static void free_config_access(config_tree *);
232
static void free_config_auth(config_tree *);
233
static void free_config_fudge(config_tree *);
234
static void free_config_logconfig(config_tree *);
235
static void free_config_monitor(config_tree *);
236
static void free_config_nic_rules(config_tree *);
237
static void free_config_other_modes(config_tree *);
238
static void free_config_peers(config_tree *);
239
static void free_config_phone(config_tree *);
240
static void free_config_reset_counters(config_tree *);
241
static void free_config_rlimit(config_tree *);
242
static void free_config_setvar(config_tree *);
243
static void free_config_system_opts(config_tree *);
244
static void free_config_tinker(config_tree *);
245
static void free_config_tos(config_tree *);
246
static void free_config_trap(config_tree *);
247
static void free_config_ttl(config_tree *);
248
static void free_config_unpeers(config_tree *);
249
static void free_config_vars(config_tree *);
250
251
#ifdef SIM
252
static void free_config_sim(config_tree *);
253
#endif
254
static void destroy_address_fifo(address_fifo *);
255
#define FREE_ADDRESS_FIFO(pf)     \
256
0
  do {         \
257
0
    destroy_address_fifo(pf); \
258
0
    (pf) = NULL;      \
259
0
  } while (0)
260
       void free_all_config_trees(void);  /* atexit() */
261
static void free_config_tree(config_tree *ptree);
262
#endif  /* FREE_CFG_T */
263
264
static void destroy_restrict_node(restrict_node *my_node);
265
static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
266
static void save_and_apply_config_tree(int/*BOOL*/ from_file);
267
static void destroy_int_fifo(int_fifo *);
268
#define FREE_INT_FIFO(pf)     \
269
0
  do {         \
270
0
    destroy_int_fifo(pf);   \
271
0
    (pf) = NULL;      \
272
0
  } while (0)
273
static void destroy_string_fifo(string_fifo *);
274
#define FREE_STRING_FIFO(pf)      \
275
0
  do {         \
276
0
    destroy_string_fifo(pf);    \
277
0
    (pf) = NULL;      \
278
0
  } while (0)
279
static void destroy_attr_val_fifo(attr_val_fifo *);
280
#define FREE_ATTR_VAL_FIFO(pf)      \
281
0
  do {         \
282
0
    destroy_attr_val_fifo(pf);  \
283
0
    (pf) = NULL;      \
284
0
  } while (0)
285
static void destroy_filegen_fifo(filegen_fifo *);
286
#define FREE_FILEGEN_FIFO(pf)     \
287
0
  do {         \
288
0
    destroy_filegen_fifo(pf); \
289
0
    (pf) = NULL;      \
290
0
  } while (0)
291
static void destroy_restrict_fifo(restrict_fifo *);
292
#define FREE_RESTRICT_FIFO(pf)      \
293
0
  do {         \
294
0
    destroy_restrict_fifo(pf);  \
295
0
    (pf) = NULL;      \
296
0
  } while (0)
297
static void destroy_setvar_fifo(setvar_fifo *);
298
#define FREE_SETVAR_FIFO(pf)      \
299
0
  do {         \
300
0
    destroy_setvar_fifo(pf);  \
301
0
    (pf) = NULL;      \
302
0
  } while (0)
303
static void destroy_addr_opts_fifo(addr_opts_fifo *);
304
#define FREE_ADDR_OPTS_FIFO(pf)     \
305
0
  do {         \
306
0
    destroy_addr_opts_fifo(pf); \
307
0
    (pf) = NULL;      \
308
0
  } while (0)
309
310
static void config_logconfig(config_tree *);
311
static void config_monitor(config_tree *);
312
static void config_rlimit(config_tree *);
313
static void config_system_opts(config_tree *);
314
static void config_tinker(config_tree *);
315
static int  config_tos_clock(config_tree *);
316
static void config_tos(config_tree *);
317
static void config_vars(config_tree *);
318
319
#ifdef SIM
320
static sockaddr_u *get_next_address(address_node *addr);
321
static void config_sim(config_tree *);
322
static void config_ntpdsim(config_tree *);
323
#else /* !SIM follows */
324
static void config_ntpd(config_tree *, int/*BOOL*/ input_from_file);
325
static void config_other_modes(config_tree *);
326
static void config_auth(config_tree *);
327
static void config_access(config_tree *);
328
static void config_mdnstries(config_tree *);
329
static void config_phone(config_tree *);
330
static void config_setvar(config_tree *);
331
static void config_ttl(config_tree *);
332
static void config_trap(config_tree *);
333
static void config_fudge(config_tree *);
334
static void config_peers(config_tree *);
335
static void config_unpeers(config_tree *);
336
static void config_nic_rules(config_tree *, int/*BOOL*/ input_from_file);
337
static void config_reset_counters(config_tree *);
338
static u_char get_correct_host_mode(int token);
339
static int peerflag_bits(peer_node *);
340
#endif  /* !SIM */
341
342
#ifdef WORKER
343
static void peer_name_resolved(int, int, void *, const char *, const char *,
344
      const struct addrinfo *,
345
      const struct addrinfo *);
346
static void unpeer_name_resolved(int, int, void *, const char *, const char *,
347
        const struct addrinfo *,
348
        const struct addrinfo *);
349
static void trap_name_resolved(int, int, void *, const char *, const char *,
350
      const struct addrinfo *,
351
      const struct addrinfo *);
352
#endif
353
354
enum gnn_type {
355
  t_UNK,    /* Unknown */
356
  t_REF,    /* Refclock */
357
  t_MSK   /* Network Mask */
358
};
359
360
static void ntpd_set_tod_using(const char *);
361
static char * normal_dtoa(double);
362
static u_int32 get_pfxmatch(const char **, struct masks *);
363
static u_int32 get_match(const char *, struct masks *);
364
static u_int32 get_logmask(const char *);
365
static int/*BOOL*/ is_refclk_addr(const address_node * addr);
366
367
static void appendstr(char *, size_t, const char *);
368
369
370
#ifndef SIM
371
static int getnetnum(const char *num, sockaddr_u *addr, int complain,
372
         enum gnn_type a_type);
373
374
#endif
375
376
#if defined(__GNUC__) /* this covers CLANG, too */
377
static void  __attribute__((noreturn,format(printf,1,2))) fatal_error(const char *fmt, ...)
378
#elif defined(_MSC_VER)
379
static void __declspec(noreturn) fatal_error(const char *fmt, ...)
380
#else
381
static void fatal_error(const char *fmt, ...)
382
#endif
383
0
{
384
0
  va_list va;
385
386
0
  va_start(va, fmt);
387
0
  mvsyslog(LOG_EMERG, fmt, va);
388
0
  va_end(va);
389
0
  _exit(1);
390
0
}
391
392
393
/* FUNCTIONS FOR INITIALIZATION
394
 * ----------------------------
395
 */
396
397
#ifdef FREE_CFG_T
398
static void
399
free_auth_node(
400
  config_tree *ptree
401
  )
402
0
{
403
0
  if (ptree->auth.keys) {
404
0
    free(ptree->auth.keys);
405
0
    ptree->auth.keys = NULL;
406
0
  }
407
408
0
  if (ptree->auth.keysdir) {
409
0
    free(ptree->auth.keysdir);
410
0
    ptree->auth.keysdir = NULL;
411
0
  }
412
413
0
  if (ptree->auth.ntp_signd_socket) {
414
0
    free(ptree->auth.ntp_signd_socket);
415
0
    ptree->auth.ntp_signd_socket = NULL;
416
0
  }
417
0
}
418
#endif /* DEBUG */
419
420
421
static void
422
init_syntax_tree(
423
  config_tree *ptree
424
  )
425
0
{
426
0
  ZERO(*ptree);
427
0
  ptree->mdnstries = 5;
428
0
}
429
430
431
#ifdef FREE_CFG_T
432
static void
433
free_all_config_trees(void)
434
0
{
435
0
  config_tree *ptree;
436
0
  config_tree *pnext;
437
438
0
  ptree = cfg_tree_history;
439
440
0
  while (ptree != NULL) {
441
0
    pnext = ptree->link;
442
0
    free_config_tree(ptree);
443
0
    ptree = pnext;
444
0
  }
445
0
}
446
447
448
static void
449
free_config_tree(
450
  config_tree *ptree
451
  )
452
0
{
453
#if defined(_MSC_VER) && defined (_DEBUG)
454
  _CrtCheckMemory();
455
#endif
456
457
0
  if (ptree->source.value.s != NULL)
458
0
    free(ptree->source.value.s);
459
460
0
  free_config_other_modes(ptree);
461
0
  free_config_auth(ptree);
462
0
  free_config_tos(ptree);
463
0
  free_config_monitor(ptree);
464
0
  free_config_access(ptree);
465
0
  free_config_tinker(ptree);
466
0
  free_config_rlimit(ptree);
467
0
  free_config_system_opts(ptree);
468
0
  free_config_logconfig(ptree);
469
0
  free_config_phone(ptree);
470
0
  free_config_setvar(ptree);
471
0
  free_config_ttl(ptree);
472
0
  free_config_trap(ptree);
473
0
  free_config_fudge(ptree);
474
0
  free_config_vars(ptree);
475
0
  free_config_peers(ptree);
476
0
  free_config_unpeers(ptree);
477
0
  free_config_nic_rules(ptree);
478
0
  free_config_reset_counters(ptree);
479
#ifdef SIM
480
  free_config_sim(ptree);
481
#endif
482
0
  free_auth_node(ptree);
483
484
0
  free(ptree);
485
486
#if defined(_MSC_VER) && defined (_DEBUG)
487
  _CrtCheckMemory();
488
#endif
489
0
}
490
#endif /* FREE_CFG_T */
491
492
493
#ifdef SAVECONFIG
494
/* Dump all trees */
495
int
496
dump_all_config_trees(
497
  FILE *df,
498
  int comment
499
  )
500
0
{
501
0
  config_tree * cfg_ptr;
502
0
  int   return_value;
503
504
0
  return_value = 0;
505
0
  for (cfg_ptr = cfg_tree_history;
506
0
       cfg_ptr != NULL;
507
0
       cfg_ptr = cfg_ptr->link)
508
0
    return_value |= dump_config_tree(cfg_ptr, df, comment);
509
510
0
  return return_value;
511
0
}
512
513
514
/* The config dumper */
515
int
516
dump_config_tree(
517
  config_tree *ptree,
518
  FILE *df,
519
  int comment
520
  )
521
0
{
522
0
  peer_node *peern;
523
0
  unpeer_node *unpeern;
524
0
  attr_val *atrv;
525
0
  address_node *addr;
526
0
  address_node *peer_addr;
527
0
  address_node *fudge_addr;
528
0
  filegen_node *fgen_node;
529
0
  restrict_node *rest_node;
530
0
  addr_opts_node *addr_opts;
531
0
  setvar_node *setv_node;
532
0
  nic_rule_node *rule_node;
533
0
  int_node *i_n;
534
0
  int_node *flag_tok_fifo;
535
0
  int_node *counter_set;
536
0
  string_node *str_node;
537
538
0
  const char *s = NULL;
539
0
  char *s1;
540
0
  char *s2;
541
0
  char timestamp[80];
542
0
  int enable;
543
544
0
  DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
545
546
0
  if (comment) {
547
0
    if (!strftime(timestamp, sizeof(timestamp),
548
0
            "%Y-%m-%d %H:%M:%S",
549
0
            localtime(&ptree->timestamp)))
550
0
      timestamp[0] = '\0';
551
552
0
    fprintf(df, "# %s %s %s\n",
553
0
      timestamp,
554
0
      (CONF_SOURCE_NTPQ == ptree->source.attr)
555
0
          ? "ntpq remote config from"
556
0
          : "startup configuration file",
557
0
      ptree->source.value.s);
558
0
  }
559
560
  /*
561
   * For options without documentation we just output the name
562
   * and its data value
563
   */
564
0
  atrv = HEAD_PFIFO(ptree->vars);
565
0
  for ( ; atrv != NULL; atrv = atrv->link) {
566
0
    switch (atrv->type) {
567
0
#ifdef DEBUG
568
0
    default:
569
0
      fprintf(df, "\n# dump error:\n"
570
0
        "# unknown vars type %d (%s) for %s\n",
571
0
        atrv->type, token_name(atrv->type),
572
0
        token_name(atrv->attr));
573
0
      break;
574
0
#endif
575
0
    case T_Double:
576
0
      fprintf(df, "%s %s\n", keyword(atrv->attr),
577
0
        normal_dtoa(atrv->value.d));
578
0
      break;
579
580
0
    case T_Integer:
581
0
      fprintf(df, "%s %d\n", keyword(atrv->attr),
582
0
        atrv->value.i);
583
0
      break;
584
585
0
    case T_String:
586
0
      fprintf(df, "%s \"%s\"", keyword(atrv->attr),
587
0
        atrv->value.s);
588
0
      if (T_Driftfile == atrv->attr &&
589
0
          atrv->link != NULL &&
590
0
          T_WanderThreshold == atrv->link->attr) {
591
0
        atrv = atrv->link;
592
0
        fprintf(df, " %s\n",
593
0
          normal_dtoa(atrv->value.d));
594
0
      } else {
595
0
        fprintf(df, "\n");
596
0
      }
597
0
      break;
598
0
    }
599
0
  }
600
601
0
  atrv = HEAD_PFIFO(ptree->logconfig);
602
0
  if (atrv != NULL) {
603
0
    fprintf(df, "logconfig");
604
0
    for ( ; atrv != NULL; atrv = atrv->link)
605
0
      fprintf(df, " %c%s", atrv->attr, atrv->value.s);
606
0
    fprintf(df, "\n");
607
0
  }
608
609
0
  if (ptree->stats_dir)
610
0
    fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
611
612
0
  i_n = HEAD_PFIFO(ptree->stats_list);
613
0
  if (i_n != NULL) {
614
0
    fprintf(df, "statistics");
615
0
    for ( ; i_n != NULL; i_n = i_n->link)
616
0
      fprintf(df, " %s", keyword(i_n->i));
617
0
    fprintf(df, "\n");
618
0
  }
619
620
0
  fgen_node = HEAD_PFIFO(ptree->filegen_opts);
621
0
  for ( ; fgen_node != NULL; fgen_node = fgen_node->link) {
622
0
    atrv = HEAD_PFIFO(fgen_node->options);
623
0
    if (atrv != NULL) {
624
0
      fprintf(df, "filegen %s",
625
0
        keyword(fgen_node->filegen_token));
626
0
      for ( ; atrv != NULL; atrv = atrv->link) {
627
0
        switch (atrv->attr) {
628
0
#ifdef DEBUG
629
0
        default:
630
0
          fprintf(df, "\n# dump error:\n"
631
0
            "# unknown filegen option token %s\n"
632
0
            "filegen %s",
633
0
            token_name(atrv->attr),
634
0
            keyword(fgen_node->filegen_token));
635
0
          break;
636
0
#endif
637
0
        case T_File:
638
0
          fprintf(df, " file %s",
639
0
            atrv->value.s);
640
0
          break;
641
642
0
        case T_Type:
643
0
          fprintf(df, " type %s",
644
0
            keyword(atrv->value.i));
645
0
          break;
646
647
0
        case T_Flag:
648
0
          fprintf(df, " %s",
649
0
            keyword(atrv->value.i));
650
0
          break;
651
0
        }
652
0
      }
653
0
      fprintf(df, "\n");
654
0
    }
655
0
  }
656
657
0
  atrv = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
658
0
  if (atrv != NULL) {
659
0
    fprintf(df, "crypto");
660
0
    for ( ; atrv != NULL; atrv = atrv->link) {
661
0
      fprintf(df, " %s %s", keyword(atrv->attr),
662
0
        atrv->value.s);
663
0
    }
664
0
    fprintf(df, "\n");
665
0
  }
666
667
0
  if (ptree->auth.revoke != 0)
668
0
    fprintf(df, "revoke %d\n", ptree->auth.revoke);
669
670
0
  if (ptree->auth.keysdir != NULL)
671
0
    fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
672
673
0
  if (ptree->auth.keys != NULL)
674
0
    fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
675
676
0
  atrv = HEAD_PFIFO(ptree->auth.trusted_key_list);
677
0
  if (atrv != NULL) {
678
0
    fprintf(df, "trustedkey");
679
0
    for ( ; atrv != NULL; atrv = atrv->link) {
680
0
      if (T_Integer == atrv->type)
681
0
        fprintf(df, " %d", atrv->value.i);
682
0
      else if (T_Intrange == atrv->type)
683
0
        fprintf(df, " (%d ... %d)",
684
0
          atrv->value.r.first,
685
0
          atrv->value.r.last);
686
0
#ifdef DEBUG
687
0
      else
688
0
        fprintf(df, "\n# dump error:\n"
689
0
          "# unknown trustedkey attr type %d\n"
690
0
          "trustedkey", atrv->type);
691
0
#endif
692
0
    }
693
0
    fprintf(df, "\n");
694
0
  }
695
696
0
  if (ptree->auth.control_key)
697
0
    fprintf(df, "controlkey %d\n", ptree->auth.control_key);
698
699
0
  if (ptree->auth.request_key)
700
0
    fprintf(df, "requestkey %d\n", ptree->auth.request_key);
701
702
  /* dump enable list, then disable list */
703
0
  for (enable = 1; enable >= 0; enable--) {
704
0
    atrv = (enable)
705
0
         ? HEAD_PFIFO(ptree->enable_opts)
706
0
         : HEAD_PFIFO(ptree->disable_opts);
707
0
    if (atrv != NULL) {
708
0
      fprintf(df, "%s", (enable)
709
0
          ? "enable"
710
0
          : "disable");
711
0
      for ( ; atrv != NULL; atrv = atrv->link)
712
0
        fprintf(df, " %s",
713
0
          keyword(atrv->value.i));
714
0
      fprintf(df, "\n");
715
0
    }
716
0
  }
717
718
0
  atrv = HEAD_PFIFO(ptree->orphan_cmds);
719
0
  if (atrv != NULL) {
720
0
    fprintf(df, "tos");
721
0
    for ( ; atrv != NULL; atrv = atrv->link) {
722
0
      switch (atrv->type) {
723
0
#ifdef DEBUG
724
0
      default:
725
0
        fprintf(df, "\n# dump error:\n"
726
0
          "# unknown tos attr type %d %s\n"
727
0
          "tos", atrv->type,
728
0
          token_name(atrv->type));
729
0
        break;
730
0
#endif
731
0
      case T_Integer:
732
0
        if (atrv->attr == T_Basedate) {
733
0
          struct calendar jd;
734
0
          ntpcal_rd_to_date(&jd, atrv->value.i + DAY_NTP_STARTS);
735
0
          fprintf(df, " %s \"%04hu-%02hu-%02hu\"",
736
0
            keyword(atrv->attr), jd.year,
737
0
            (u_short)jd.month,
738
0
            (u_short)jd.monthday);
739
0
        } else {
740
0
          fprintf(df, " %s %d",
741
0
          keyword(atrv->attr),
742
0
          atrv->value.i);
743
0
        }
744
0
        break;
745
746
0
      case T_Double:
747
0
        fprintf(df, " %s %s",
748
0
          keyword(atrv->attr),
749
0
          normal_dtoa(atrv->value.d));
750
0
        break;
751
0
      }
752
0
    }
753
0
    fprintf(df, "\n");
754
0
  }
755
756
0
  atrv = HEAD_PFIFO(ptree->rlimit);
757
0
  if (atrv != NULL) {
758
0
    fprintf(df, "rlimit");
759
0
    for ( ; atrv != NULL; atrv = atrv->link) {
760
0
      INSIST(T_Integer == atrv->type);
761
0
      fprintf(df, " %s %d", keyword(atrv->attr),
762
0
        atrv->value.i);
763
0
    }
764
0
    fprintf(df, "\n");
765
0
  }
766
767
0
  atrv = HEAD_PFIFO(ptree->tinker);
768
0
  if (atrv != NULL) {
769
0
    fprintf(df, "tinker");
770
0
    for ( ; atrv != NULL; atrv = atrv->link) {
771
0
      INSIST(T_Double == atrv->type);
772
0
      fprintf(df, " %s %s", keyword(atrv->attr),
773
0
        normal_dtoa(atrv->value.d));
774
0
    }
775
0
    fprintf(df, "\n");
776
0
  }
777
778
0
  if (ptree->broadcastclient)
779
0
    fprintf(df, "broadcastclient\n");
780
781
0
  peern = HEAD_PFIFO(ptree->peers);
782
0
  for ( ; peern != NULL; peern = peern->link) {
783
0
    addr = peern->addr;
784
0
    fprintf(df, "%s", keyword(peern->host_mode));
785
0
    switch (addr->type) {
786
0
#ifdef DEBUG
787
0
    default:
788
0
      fprintf(df, "# dump error:\n"
789
0
        "# unknown peer family %d for:\n"
790
0
        "%s", addr->type,
791
0
        keyword(peern->host_mode));
792
0
      break;
793
0
#endif
794
0
    case AF_UNSPEC:
795
0
      break;
796
797
0
    case AF_INET:
798
0
      fprintf(df, " -4");
799
0
      break;
800
801
0
    case AF_INET6:
802
0
      fprintf(df, " -6");
803
0
      break;
804
0
    }
805
0
    fprintf(df, " %s", addr->address);
806
807
0
    if (peern->minpoll != 0)
808
0
      fprintf(df, " minpoll %u", peern->minpoll);
809
810
0
    if (peern->maxpoll != 0)
811
0
      fprintf(df, " maxpoll %u", peern->maxpoll);
812
813
0
    if (peern->ttl != 0) {
814
0
      if (strlen(addr->address) > 8
815
0
          && !memcmp(addr->address, "127.127.", 8))
816
0
        fprintf(df, " mode %u", peern->ttl);
817
0
      else
818
0
        fprintf(df, " ttl %u", peern->ttl);
819
0
    }
820
821
0
    if (peern->peerversion != NTP_VERSION)
822
0
      fprintf(df, " version %u", peern->peerversion);
823
824
0
    if (peern->peerkey != 0)
825
0
      fprintf(df, " key %u", peern->peerkey);
826
827
0
    if (peern->group != NULL)
828
0
      fprintf(df, " ident \"%s\"", peern->group);
829
830
0
    atrv = HEAD_PFIFO(peern->peerflags);
831
0
    for ( ; atrv != NULL; atrv = atrv->link) {
832
0
      INSIST(T_Flag == atrv->attr);
833
0
      INSIST(T_Integer == atrv->type);
834
0
      fprintf(df, " %s", keyword(atrv->value.i));
835
0
    }
836
837
0
    fprintf(df, "\n");
838
839
0
    addr_opts = HEAD_PFIFO(ptree->fudge);
840
0
    for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
841
0
      peer_addr = peern->addr;
842
0
      fudge_addr = addr_opts->addr;
843
844
0
      s1 = peer_addr->address;
845
0
      s2 = fudge_addr->address;
846
847
0
      if (strcmp(s1, s2))
848
0
        continue;
849
850
0
      fprintf(df, "fudge %s", s1);
851
852
0
      for (atrv = HEAD_PFIFO(addr_opts->options);
853
0
           atrv != NULL;
854
0
           atrv = atrv->link) {
855
856
0
        switch (atrv->type) {
857
0
#ifdef DEBUG
858
0
        default:
859
0
          fprintf(df, "\n# dump error:\n"
860
0
            "# unknown fudge atrv->type %d\n"
861
0
            "fudge %s", atrv->type,
862
0
            s1);
863
0
          break;
864
0
#endif
865
0
        case T_Double:
866
0
          fprintf(df, " %s %s",
867
0
            keyword(atrv->attr),
868
0
            normal_dtoa(atrv->value.d));
869
0
          break;
870
871
0
        case T_Integer:
872
0
          fprintf(df, " %s %d",
873
0
            keyword(atrv->attr),
874
0
            atrv->value.i);
875
0
          break;
876
877
0
        case T_String:
878
0
          fprintf(df, " %s %s",
879
0
            keyword(atrv->attr),
880
0
            atrv->value.s);
881
0
          break;
882
0
        }
883
0
      }
884
0
      fprintf(df, "\n");
885
0
    }
886
0
  }
887
888
0
  addr = HEAD_PFIFO(ptree->manycastserver);
889
0
  if (addr != NULL) {
890
0
    fprintf(df, "manycastserver");
891
0
    for ( ; addr != NULL; addr = addr->link)
892
0
      fprintf(df, " %s", addr->address);
893
0
    fprintf(df, "\n");
894
0
  }
895
896
0
  addr = HEAD_PFIFO(ptree->multicastclient);
897
0
  if (addr != NULL) {
898
0
    fprintf(df, "multicastclient");
899
0
    for ( ; addr != NULL; addr = addr->link)
900
0
      fprintf(df, " %s", addr->address);
901
0
    fprintf(df, "\n");
902
0
  }
903
904
905
0
  for (unpeern = HEAD_PFIFO(ptree->unpeers);
906
0
       unpeern != NULL;
907
0
       unpeern = unpeern->link)
908
0
    fprintf(df, "unpeer %s\n", unpeern->addr->address);
909
910
0
  atrv = HEAD_PFIFO(ptree->mru_opts);
911
0
  if (atrv != NULL) {
912
0
    fprintf(df, "mru");
913
0
    for ( ; atrv != NULL; atrv = atrv->link)
914
0
      fprintf(df, " %s %d", keyword(atrv->attr),
915
0
        atrv->value.i);
916
0
    fprintf(df, "\n");
917
0
  }
918
919
0
  atrv = HEAD_PFIFO(ptree->discard_opts);
920
0
  if (atrv != NULL) {
921
0
    fprintf(df, "discard");
922
0
    for ( ; atrv != NULL; atrv = atrv->link)
923
0
      fprintf(df, " %s %d", keyword(atrv->attr),
924
0
        atrv->value.i);
925
0
    fprintf(df, "\n");
926
0
  }
927
928
0
  for (rest_node = HEAD_PFIFO(ptree->restrict_opts);
929
0
       rest_node != NULL;
930
0
       rest_node = rest_node->link) {
931
0
    int is_default = 0;
932
933
0
    if (NULL == rest_node->addr) {
934
0
      s = "default";
935
      /* Don't need to set is_default=1 here */
936
0
      flag_tok_fifo = HEAD_PFIFO(rest_node->flag_tok_fifo);
937
0
      for ( ; flag_tok_fifo != NULL; flag_tok_fifo = flag_tok_fifo->link) {
938
0
        if (T_Source == flag_tok_fifo->i) {
939
0
          s = "source";
940
0
          break;
941
0
        }
942
0
      }
943
0
    } else {
944
0
      const char *ap = rest_node->addr->address;
945
0
      const char *mp = "";
946
947
0
      if (rest_node->mask)
948
0
        mp = rest_node->mask->address;
949
950
0
      if (   rest_node->addr->type == AF_INET
951
0
          && !strcmp(ap, "0.0.0.0")
952
0
          && !strcmp(mp, "0.0.0.0")) {
953
0
        is_default = 1;
954
0
        s = "-4 default";
955
0
      } else if (   rest_node->mask
956
0
           && rest_node->mask->type == AF_INET6
957
0
           && !strcmp(ap, "::")
958
0
           && !strcmp(mp, "::")) {
959
0
        is_default = 1;
960
0
        s = "-6 default";
961
0
      } else {
962
0
        s = ap;
963
0
      }
964
0
    }
965
0
    fprintf(df, "restrict %s", s);
966
0
    if (rest_node->mask != NULL && !is_default)
967
0
      fprintf(df, " mask %s",
968
0
        rest_node->mask->address);
969
0
    fprintf(df, " ippeerlimit %d", rest_node->ippeerlimit);
970
0
    flag_tok_fifo = HEAD_PFIFO(rest_node->flag_tok_fifo);
971
0
    for ( ; flag_tok_fifo != NULL; flag_tok_fifo = flag_tok_fifo->link)
972
0
      if (T_Source != flag_tok_fifo->i)
973
0
        fprintf(df, " %s", keyword(flag_tok_fifo->i));
974
0
    fprintf(df, "\n");
975
0
  }
976
977
0
  rule_node = HEAD_PFIFO(ptree->nic_rules);
978
0
  for ( ; rule_node != NULL; rule_node = rule_node->link) {
979
0
    fprintf(df, "interface %s %s\n",
980
0
      keyword(rule_node->action),
981
0
      (rule_node->match_class)
982
0
          ? keyword(rule_node->match_class)
983
0
          : rule_node->if_name);
984
0
  }
985
986
0
  str_node = HEAD_PFIFO(ptree->phone);
987
0
  if (str_node != NULL) {
988
0
    fprintf(df, "phone");
989
0
    for ( ; str_node != NULL; str_node = str_node->link)
990
0
      fprintf(df, " \"%s\"", str_node->s);
991
0
    fprintf(df, "\n");
992
0
  }
993
994
0
  setv_node = HEAD_PFIFO(ptree->setvar);
995
0
  for ( ; setv_node != NULL; setv_node = setv_node->link) {
996
0
    s1 = quote_if_needed(setv_node->var);
997
0
    s2 = quote_if_needed(setv_node->val);
998
0
    fprintf(df, "setvar %s = %s", s1, s2);
999
0
    free(s1);
1000
0
    free(s2);
1001
0
    if (setv_node->isdefault)
1002
0
      fprintf(df, " default");
1003
0
    fprintf(df, "\n");
1004
0
  }
1005
1006
0
  i_n = HEAD_PFIFO(ptree->ttl);
1007
0
  if (i_n != NULL) {
1008
0
    fprintf(df, "ttl");
1009
0
    for( ; i_n != NULL; i_n = i_n->link)
1010
0
      fprintf(df, " %d", i_n->i);
1011
0
    fprintf(df, "\n");
1012
0
  }
1013
1014
0
  addr_opts = HEAD_PFIFO(ptree->trap);
1015
0
  for ( ; addr_opts != NULL; addr_opts = addr_opts->link) {
1016
0
    addr = addr_opts->addr;
1017
0
    fprintf(df, "trap %s", addr->address);
1018
0
    atrv = HEAD_PFIFO(addr_opts->options);
1019
0
    for ( ; atrv != NULL; atrv = atrv->link) {
1020
0
      switch (atrv->attr) {
1021
0
#ifdef DEBUG
1022
0
      default:
1023
0
        fprintf(df, "\n# dump error:\n"
1024
0
          "# unknown trap token %d\n"
1025
0
          "trap %s", atrv->attr,
1026
0
          addr->address);
1027
0
        break;
1028
0
#endif
1029
0
      case T_Port:
1030
0
        fprintf(df, " port %d", atrv->value.i);
1031
0
        break;
1032
1033
0
      case T_Interface:
1034
0
        fprintf(df, " interface %s",
1035
0
          atrv->value.s);
1036
0
        break;
1037
0
      }
1038
0
    }
1039
0
    fprintf(df, "\n");
1040
0
  }
1041
1042
0
  counter_set = HEAD_PFIFO(ptree->reset_counters);
1043
0
  if (counter_set != NULL) {
1044
0
    fprintf(df, "reset");
1045
0
    for ( ; counter_set != NULL;
1046
0
         counter_set = counter_set->link)
1047
0
      fprintf(df, " %s", keyword(counter_set->i));
1048
0
    fprintf(df, "\n");
1049
0
  }
1050
1051
0
  return 0;
1052
0
}
1053
#endif  /* SAVECONFIG */
1054
1055
1056
1057
/* generic fifo routines for structs linked by 1st member */
1058
void *
1059
append_gen_fifo(
1060
  void *fifo,
1061
  void *entry
1062
  )
1063
0
{
1064
0
  gen_fifo *pf;
1065
0
  gen_node *pe;
1066
1067
0
  pf = fifo;
1068
0
  pe = entry;
1069
0
  if (NULL == pf)
1070
0
    pf = emalloc_zero(sizeof(*pf));
1071
0
  else
1072
0
    CHECK_FIFO_CONSISTENCY(*pf);
1073
0
  if (pe != NULL)
1074
0
    LINK_FIFO(*pf, pe, link);
1075
0
  CHECK_FIFO_CONSISTENCY(*pf);
1076
1077
0
  return pf;
1078
0
}
1079
1080
1081
void *
1082
concat_gen_fifos(
1083
  void *first,
1084
  void *second
1085
  )
1086
0
{
1087
0
  gen_fifo *pf1;
1088
0
  gen_fifo *pf2;
1089
1090
0
  pf1 = first;
1091
0
  pf2 = second;
1092
0
  if (NULL == pf1)
1093
0
    return pf2;
1094
0
  if (NULL == pf2)
1095
0
    return pf1;
1096
1097
0
  CONCAT_FIFO(*pf1, *pf2, link);
1098
0
  free(pf2);
1099
1100
0
  return pf1;
1101
0
}
1102
1103
void*
1104
destroy_gen_fifo(
1105
  void        *fifo,
1106
  fifo_deleter func
1107
  )
1108
0
{
1109
0
  any_node *  np  = NULL;
1110
0
  any_node_fifo * pf1 = fifo;
1111
1112
0
  if (pf1 != NULL) {
1113
0
    if (!func)
1114
0
      func = free;
1115
0
    for (;;) {
1116
0
      UNLINK_FIFO(np, *pf1, link);
1117
0
      if (np == NULL)
1118
0
        break;
1119
0
      (*func)(np);
1120
0
    }
1121
0
    free(pf1);
1122
0
  }
1123
0
  return NULL;
1124
0
}
1125
1126
/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
1127
 * -----------------------------------------------
1128
 */
1129
1130
void
1131
destroy_attr_val(
1132
  attr_val *  av
1133
  )
1134
0
{
1135
0
  if (av) {
1136
0
    if (T_String == av->type)
1137
0
      free(av->value.s);
1138
0
    free(av);
1139
0
  }
1140
0
}
1141
1142
attr_val *
1143
create_attr_dval(
1144
  int attr,
1145
  double value
1146
  )
1147
0
{
1148
0
  attr_val *my_val;
1149
1150
0
  my_val = emalloc_zero(sizeof(*my_val));
1151
0
  my_val->attr = attr;
1152
0
  my_val->value.d = value;
1153
0
  my_val->type = T_Double;
1154
1155
0
  return my_val;
1156
0
}
1157
1158
1159
attr_val *
1160
create_attr_ival(
1161
  int attr,
1162
  int value
1163
  )
1164
0
{
1165
0
  attr_val *my_val;
1166
1167
0
  my_val = emalloc_zero(sizeof(*my_val));
1168
0
  my_val->attr = attr;
1169
0
  my_val->value.i = value;
1170
0
  my_val->type = T_Integer;
1171
1172
0
  return my_val;
1173
0
}
1174
1175
1176
attr_val *
1177
create_attr_uval(
1178
  int attr,
1179
  u_int value
1180
  )
1181
0
{
1182
0
  attr_val *my_val;
1183
1184
0
  my_val = emalloc_zero(sizeof(*my_val));
1185
0
  my_val->attr = attr;
1186
0
  my_val->value.u = value;
1187
0
  my_val->type = T_U_int;
1188
1189
0
  return my_val;
1190
0
}
1191
1192
1193
attr_val *
1194
create_attr_rangeval(
1195
  int attr,
1196
  int first,
1197
  int last
1198
  )
1199
0
{
1200
0
  attr_val *my_val;
1201
1202
0
  my_val = emalloc_zero(sizeof(*my_val));
1203
0
  my_val->attr = attr;
1204
0
  my_val->value.r.first = first;
1205
0
  my_val->value.r.last = last;
1206
0
  my_val->type = T_Intrange;
1207
1208
0
  return my_val;
1209
0
}
1210
1211
1212
attr_val *
1213
create_attr_sval(
1214
  int attr,
1215
  const char *s
1216
  )
1217
0
{
1218
0
  attr_val *my_val;
1219
1220
0
  my_val = emalloc_zero(sizeof(*my_val));
1221
0
  my_val->attr = attr;
1222
0
  if (NULL == s)     /* free() hates NULL */
1223
0
    s = estrdup("");
1224
0
  my_val->value.s = _UC(s);
1225
0
  my_val->type = T_String;
1226
1227
0
  return my_val;
1228
0
}
1229
1230
1231
int_node *
1232
create_int_node(
1233
  int val
1234
  )
1235
0
{
1236
0
  int_node *i_n;
1237
1238
0
  i_n = emalloc_zero(sizeof(*i_n));
1239
0
  i_n->i = val;
1240
1241
0
  return i_n;
1242
0
}
1243
1244
1245
string_node *
1246
create_string_node(
1247
  char *str
1248
  )
1249
0
{
1250
0
  string_node *sn;
1251
1252
0
  sn = emalloc_zero(sizeof(*sn));
1253
0
  sn->s = str;
1254
1255
0
  return sn;
1256
0
}
1257
1258
1259
address_node *
1260
create_address_node(
1261
  char *  addr,
1262
  int type
1263
  )
1264
0
{
1265
0
  address_node *my_node;
1266
1267
0
  REQUIRE(NULL != addr);
1268
0
  REQUIRE(AF_INET == type || AF_INET6 == type || AF_UNSPEC == type);
1269
0
  my_node = emalloc_zero(sizeof(*my_node));
1270
0
  my_node->address = addr;
1271
0
  my_node->type = (u_short)type;
1272
1273
0
  return my_node;
1274
0
}
1275
1276
1277
void
1278
destroy_address_node(
1279
  address_node *my_node
1280
  )
1281
0
{
1282
0
  if (NULL == my_node)
1283
0
    return;
1284
0
  REQUIRE(NULL != my_node->address);
1285
1286
0
  free(my_node->address);
1287
0
  free(my_node);
1288
0
}
1289
1290
1291
peer_node *
1292
create_peer_node(
1293
  int   hmode,
1294
  address_node *  addr,
1295
  attr_val_fifo * options
1296
  )
1297
0
{
1298
0
  peer_node *my_node;
1299
0
  attr_val *option;
1300
0
  int freenode;
1301
0
  int errflag = 0;
1302
1303
0
  my_node = emalloc_zero(sizeof(*my_node));
1304
1305
  /* Initialize node values to default */
1306
0
  my_node->peerversion = NTP_VERSION;
1307
1308
  /* Now set the node to the read values */
1309
0
  my_node->host_mode = hmode;
1310
0
  my_node->addr = addr;
1311
1312
  /*
1313
   * the options FIFO mixes items that will be saved in the
1314
   * peer_node as explicit members, such as minpoll, and
1315
   * those that are moved intact to the peer_node's peerflags
1316
   * FIFO.  The options FIFO is consumed and reclaimed here.
1317
   */
1318
1319
0
  if (options != NULL)
1320
0
    CHECK_FIFO_CONSISTENCY(*options);
1321
0
  while (options != NULL) {
1322
0
    UNLINK_FIFO(option, *options, link);
1323
0
    if (NULL == option) {
1324
0
      free(options);
1325
0
      break;
1326
0
    }
1327
1328
0
    freenode = 1;
1329
    /* Check the kind of option being set */
1330
0
    switch (option->attr) {
1331
1332
0
    case T_Flag:
1333
0
      APPEND_G_FIFO(my_node->peerflags, option);
1334
0
      freenode = 0;
1335
0
      break;
1336
1337
0
    case T_Minpoll:
1338
0
      if (option->value.i < NTP_MINPOLL ||
1339
0
          option->value.i > UCHAR_MAX) {
1340
0
        msyslog(LOG_INFO,
1341
0
          "minpoll: provided value (%d) is out of range [%d-%d])",
1342
0
          option->value.i, NTP_MINPOLL,
1343
0
          UCHAR_MAX);
1344
0
        my_node->minpoll = NTP_MINPOLL;
1345
0
      } else {
1346
0
        my_node->minpoll =
1347
0
          (u_char)option->value.u;
1348
0
      }
1349
0
      break;
1350
1351
0
    case T_Maxpoll:
1352
0
      if (option->value.i < 0 ||
1353
0
          option->value.i > NTP_MAXPOLL) {
1354
0
        msyslog(LOG_INFO,
1355
0
          "maxpoll: provided value (%d) is out of range [0-%d])",
1356
0
          option->value.i, NTP_MAXPOLL);
1357
0
        my_node->maxpoll = NTP_MAXPOLL;
1358
0
      } else {
1359
0
        my_node->maxpoll =
1360
0
          (u_char)option->value.u;
1361
0
      }
1362
0
      break;
1363
1364
0
    case T_Ttl:
1365
0
      if (is_refclk_addr(addr)) {
1366
0
        msyslog(LOG_ERR, "'ttl' does not apply for refclocks");
1367
0
        errflag = 1;
1368
0
      } else if (option->value.u >= MAX_TTL) {
1369
0
        msyslog(LOG_ERR, "ttl: invalid argument");
1370
0
        errflag = 1;
1371
0
      } else {
1372
0
        my_node->ttl = (u_char)option->value.u;
1373
0
      }
1374
0
      break;
1375
1376
0
    case T_Mode:
1377
0
      if (is_refclk_addr(addr)) {
1378
0
        my_node->ttl = option->value.u;
1379
0
      } else {
1380
0
        msyslog(LOG_ERR, "'mode' does not apply for network peers");
1381
0
        errflag = 1;
1382
0
      }
1383
0
      break;
1384
1385
0
    case T_Key:
1386
0
      if (option->value.u >= KEYID_T_MAX) {
1387
0
        msyslog(LOG_ERR, "key: invalid argument");
1388
0
        errflag = 1;
1389
0
      } else {
1390
0
        my_node->peerkey =
1391
0
          (keyid_t)option->value.u;
1392
0
      }
1393
0
      break;
1394
1395
0
    case T_Version:
1396
0
      if (option->value.u >= UCHAR_MAX) {
1397
0
        msyslog(LOG_ERR, "version: invalid argument");
1398
0
        errflag = 1;
1399
0
      } else {
1400
0
        my_node->peerversion =
1401
0
          (u_char)option->value.u;
1402
0
      }
1403
0
      break;
1404
1405
0
    case T_Ident:
1406
0
      my_node->group = option->value.s;
1407
0
      break;
1408
1409
0
    default:
1410
0
      msyslog(LOG_ERR,
1411
0
        "Unknown peer/server option token %s",
1412
0
        token_name(option->attr));
1413
0
      errflag = 1;
1414
0
    }
1415
0
    if (freenode)
1416
0
      free(option);
1417
0
  }
1418
1419
  /* Check if errors were reported. If yes, ignore the node */
1420
0
  if (errflag) {
1421
0
    free(my_node);
1422
0
    my_node = NULL;
1423
0
  }
1424
1425
0
  return my_node;
1426
0
}
1427
1428
1429
unpeer_node *
1430
create_unpeer_node(
1431
  address_node *addr
1432
  )
1433
0
{
1434
0
  unpeer_node * my_node;
1435
0
  u_long    u;
1436
0
  const u_char *  pch;
1437
1438
0
  my_node = emalloc_zero(sizeof(*my_node));
1439
1440
  /*
1441
   * From the parser's perspective an association ID fits into
1442
   * its generic T_String definition of a name/address "address".
1443
   * We treat all valid 16-bit numbers as association IDs.
1444
   */
1445
0
  for (u = 0, pch = (u_char*)addr->address; isdigit(*pch); ++pch) {
1446
    /* accumulate with overflow retention */
1447
0
    u = (10 * u + *pch - '0') | (u & 0xFF000000u);
1448
0
  }
1449
1450
0
  if (!*pch && u <= ASSOCID_MAX) {
1451
0
    my_node->assocID = (associd_t)u;
1452
0
    my_node->addr = NULL;
1453
0
    destroy_address_node(addr);
1454
0
  } else {
1455
0
    my_node->assocID = 0;
1456
0
    my_node->addr = addr;
1457
0
  }
1458
1459
0
  return my_node;
1460
0
}
1461
1462
filegen_node *
1463
create_filegen_node(
1464
  int   filegen_token,
1465
  attr_val_fifo * options
1466
  )
1467
0
{
1468
0
  filegen_node *my_node;
1469
1470
0
  my_node = emalloc_zero(sizeof(*my_node));
1471
0
  my_node->filegen_token = filegen_token;
1472
0
  my_node->options = options;
1473
1474
0
  return my_node;
1475
0
}
1476
1477
1478
restrict_node *
1479
create_restrict_node(
1480
  address_node *  addr,
1481
  address_node *  mask,
1482
  short   ippeerlimit,
1483
  int_fifo *  flag_tok_fifo,
1484
  int   line_no
1485
  )
1486
0
{
1487
0
  restrict_node *my_node;
1488
1489
0
  my_node = emalloc_zero(sizeof(*my_node));
1490
0
  my_node->addr = addr;
1491
0
  my_node->mask = mask;
1492
0
  my_node->ippeerlimit = ippeerlimit;
1493
0
  my_node->flag_tok_fifo = flag_tok_fifo;
1494
0
  my_node->line_no = line_no;
1495
1496
0
  return my_node;
1497
0
}
1498
1499
1500
static void
1501
destroy_restrict_node(
1502
  restrict_node *my_node
1503
  )
1504
0
{
1505
  /* With great care, free all the memory occupied by
1506
   * the restrict node
1507
   */
1508
0
  destroy_address_node(my_node->addr);
1509
0
  destroy_address_node(my_node->mask);
1510
0
  destroy_int_fifo(my_node->flag_tok_fifo);
1511
0
  free(my_node);
1512
0
}
1513
1514
1515
static void
1516
destroy_int_fifo(
1517
  int_fifo *  fifo
1518
  )
1519
0
{
1520
0
  int_node *  i_n;
1521
1522
0
  if (fifo != NULL) {
1523
0
    for (;;) {
1524
0
      UNLINK_FIFO(i_n, *fifo, link);
1525
0
      if (i_n == NULL)
1526
0
        break;
1527
0
      free(i_n);
1528
0
    }
1529
0
    free(fifo);
1530
0
  }
1531
0
}
1532
1533
1534
static void
1535
destroy_string_fifo(
1536
  string_fifo * fifo
1537
  )
1538
0
{
1539
0
  string_node * sn;
1540
1541
0
  if (fifo != NULL) {
1542
0
    for (;;) {
1543
0
      UNLINK_FIFO(sn, *fifo, link);
1544
0
      if (sn == NULL)
1545
0
        break;
1546
0
      free(sn->s);
1547
0
      free(sn);
1548
0
    }
1549
0
    free(fifo);
1550
0
  }
1551
0
}
1552
1553
1554
static void
1555
destroy_attr_val_fifo(
1556
  attr_val_fifo * av_fifo
1557
  )
1558
0
{
1559
0
  attr_val *  av;
1560
1561
0
  if (av_fifo != NULL) {
1562
0
    for (;;) {
1563
0
      UNLINK_FIFO(av, *av_fifo, link);
1564
0
      if (av == NULL)
1565
0
        break;
1566
0
      destroy_attr_val(av);
1567
0
    }
1568
0
    free(av_fifo);
1569
0
  }
1570
0
}
1571
1572
1573
static void
1574
destroy_filegen_fifo(
1575
  filegen_fifo *  fifo
1576
  )
1577
0
{
1578
0
  filegen_node *  fg;
1579
1580
0
  if (fifo != NULL) {
1581
0
    for (;;) {
1582
0
      UNLINK_FIFO(fg, *fifo, link);
1583
0
      if (fg == NULL)
1584
0
        break;
1585
0
      destroy_attr_val_fifo(fg->options);
1586
0
      free(fg);
1587
0
    }
1588
0
    free(fifo);
1589
0
  }
1590
0
}
1591
1592
1593
static void
1594
destroy_restrict_fifo(
1595
  restrict_fifo * fifo
1596
  )
1597
0
{
1598
0
  restrict_node * rn;
1599
1600
0
  if (fifo != NULL) {
1601
0
    for (;;) {
1602
0
      UNLINK_FIFO(rn, *fifo, link);
1603
0
      if (rn == NULL)
1604
0
        break;
1605
0
      destroy_restrict_node(rn);
1606
0
    }
1607
0
    free(fifo);
1608
0
  }
1609
0
}
1610
1611
1612
static void
1613
destroy_setvar_fifo(
1614
  setvar_fifo * fifo
1615
  )
1616
0
{
1617
0
  setvar_node * sv;
1618
1619
0
  if (fifo != NULL) {
1620
0
    for (;;) {
1621
0
      UNLINK_FIFO(sv, *fifo, link);
1622
0
      if (sv == NULL)
1623
0
        break;
1624
0
      free(sv->var);
1625
0
      free(sv->val);
1626
0
      free(sv);
1627
0
    }
1628
0
    free(fifo);
1629
0
  }
1630
0
}
1631
1632
1633
static void
1634
destroy_addr_opts_fifo(
1635
  addr_opts_fifo *  fifo
1636
  )
1637
0
{
1638
0
  addr_opts_node *  aon;
1639
1640
0
  if (fifo != NULL) {
1641
0
    for (;;) {
1642
0
      UNLINK_FIFO(aon, *fifo, link);
1643
0
      if (aon == NULL)
1644
0
        break;
1645
0
      destroy_address_node(aon->addr);
1646
0
      destroy_attr_val_fifo(aon->options);
1647
0
      free(aon);
1648
0
    }
1649
0
    free(fifo);
1650
0
  }
1651
0
}
1652
1653
1654
setvar_node *
1655
create_setvar_node(
1656
  char *  var,
1657
  char *  val,
1658
  int isdefault
1659
  )
1660
0
{
1661
0
  setvar_node * my_node;
1662
0
  char *    pch;
1663
1664
  /* do not allow = in the variable name */
1665
0
  pch = strchr(var, '=');
1666
0
  if (NULL != pch)
1667
0
    *pch = '\0';
1668
1669
  /* Now store the string into a setvar_node */
1670
0
  my_node = emalloc_zero(sizeof(*my_node));
1671
0
  my_node->var = var;
1672
0
  my_node->val = val;
1673
0
  my_node->isdefault = isdefault;
1674
1675
0
  return my_node;
1676
0
}
1677
1678
1679
nic_rule_node *
1680
create_nic_rule_node(
1681
  int match_class,
1682
  char *if_name,  /* interface name or numeric address */
1683
  int action
1684
  )
1685
0
{
1686
0
  nic_rule_node *my_node;
1687
1688
0
  REQUIRE(match_class != 0 || if_name != NULL);
1689
1690
0
  my_node = emalloc_zero(sizeof(*my_node));
1691
0
  my_node->match_class = match_class;
1692
0
  my_node->if_name = if_name;
1693
0
  my_node->action = action;
1694
1695
0
  return my_node;
1696
0
}
1697
1698
1699
addr_opts_node *
1700
create_addr_opts_node(
1701
  address_node *  addr,
1702
  attr_val_fifo * options
1703
  )
1704
0
{
1705
0
  addr_opts_node *my_node;
1706
1707
0
  my_node = emalloc_zero(sizeof(*my_node));
1708
0
  my_node->addr = addr;
1709
0
  my_node->options = options;
1710
1711
0
  return my_node;
1712
0
}
1713
1714
1715
#ifdef SIM
1716
script_info *
1717
create_sim_script_info(
1718
  double    duration,
1719
  attr_val_fifo * script_queue
1720
  )
1721
{
1722
  script_info *my_info;
1723
  attr_val *my_attr_val;
1724
1725
  my_info = emalloc_zero(sizeof(*my_info));
1726
1727
  /* Initialize Script Info with default values*/
1728
  my_info->duration = duration;
1729
  my_info->prop_delay = NET_DLY;
1730
  my_info->proc_delay = PROC_DLY;
1731
1732
  /* Traverse the script_queue and fill out non-default values */
1733
1734
  for (my_attr_val = HEAD_PFIFO(script_queue);
1735
       my_attr_val != NULL;
1736
       my_attr_val = my_attr_val->link) {
1737
1738
    /* Set the desired value */
1739
    switch (my_attr_val->attr) {
1740
1741
    case T_Freq_Offset:
1742
      my_info->freq_offset = my_attr_val->value.d;
1743
      break;
1744
1745
    case T_Wander:
1746
      my_info->wander = my_attr_val->value.d;
1747
      break;
1748
1749
    case T_Jitter:
1750
      my_info->jitter = my_attr_val->value.d;
1751
      break;
1752
1753
    case T_Prop_Delay:
1754
      my_info->prop_delay = my_attr_val->value.d;
1755
      break;
1756
1757
    case T_Proc_Delay:
1758
      my_info->proc_delay = my_attr_val->value.d;
1759
      break;
1760
1761
    default:
1762
      msyslog(LOG_ERR, "Unknown script token %d",
1763
        my_attr_val->attr);
1764
    }
1765
  }
1766
1767
  return my_info;
1768
}
1769
#endif  /* SIM */
1770
1771
1772
#ifdef SIM
1773
static sockaddr_u *
1774
get_next_address(
1775
  address_node *addr
1776
  )
1777
{
1778
  const char addr_prefix[] = "192.168.0.";
1779
  static int curr_addr_num = 1;
1780
#define ADDR_LENGTH 16 + 1  /* room for 192.168.1.255 */
1781
  char addr_string[ADDR_LENGTH];
1782
  sockaddr_u *final_addr;
1783
  struct addrinfo *ptr;
1784
  int gai_err;
1785
1786
  final_addr = emalloc(sizeof(*final_addr));
1787
1788
  if (addr->type == T_String) {
1789
    snprintf(addr_string, sizeof(addr_string), "%s%d",
1790
       addr_prefix, curr_addr_num++);
1791
    printf("Selecting ip address %s for hostname %s\n",
1792
           addr_string, addr->address);
1793
    gai_err = getaddrinfo(addr_string, "ntp", NULL, &ptr);
1794
  } else {
1795
    gai_err = getaddrinfo(addr->address, "ntp", NULL, &ptr);
1796
  }
1797
1798
  if (gai_err) {
1799
    fprintf(stderr, "ERROR!! Could not get a new address\n");
1800
    exit(1);
1801
  }
1802
  memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
1803
  fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n",
1804
    stoa(final_addr));
1805
  freeaddrinfo(ptr);
1806
1807
  return final_addr;
1808
}
1809
#endif /* SIM */
1810
1811
1812
#ifdef SIM
1813
server_info *
1814
create_sim_server(
1815
  address_node *    addr,
1816
  double      server_offset,
1817
  script_info_fifo *  script
1818
  )
1819
{
1820
  server_info *my_info;
1821
1822
  my_info = emalloc_zero(sizeof(*my_info));
1823
  my_info->server_time = server_offset;
1824
  my_info->addr = get_next_address(addr);
1825
  my_info->script = script;
1826
  UNLINK_FIFO(my_info->curr_script, *my_info->script, link);
1827
1828
  return my_info;
1829
}
1830
#endif  /* SIM */
1831
1832
sim_node *
1833
create_sim_node(
1834
  attr_val_fifo *   init_opts,
1835
  server_info_fifo *  servers
1836
  )
1837
0
{
1838
0
  sim_node *my_node;
1839
1840
0
  my_node = emalloc(sizeof(*my_node));
1841
0
  my_node->init_opts = init_opts;
1842
0
  my_node->servers = servers;
1843
1844
0
  return my_node;
1845
0
}
1846
1847
1848
1849
1850
/* FUNCTIONS FOR PERFORMING THE CONFIGURATION
1851
 * ------------------------------------------
1852
 */
1853
1854
#ifndef SIM
1855
static void
1856
config_other_modes(
1857
  config_tree * ptree
1858
  )
1859
0
{
1860
0
  sockaddr_u  addr_sock;
1861
0
  address_node *  addr_node;
1862
1863
0
  if (ptree->broadcastclient)
1864
0
    proto_config(PROTO_BROADCLIENT, ptree->broadcastclient,
1865
0
           0., NULL);
1866
1867
0
  addr_node = HEAD_PFIFO(ptree->manycastserver);
1868
0
  while (addr_node != NULL) {
1869
0
    ZERO_SOCK(&addr_sock);
1870
0
    AF(&addr_sock) = addr_node->type;
1871
0
    if (1 == getnetnum(addr_node->address, &addr_sock, 1,
1872
0
           t_UNK)) {
1873
0
      proto_config(PROTO_MULTICAST_ADD,
1874
0
             0, 0., &addr_sock);
1875
0
      sys_manycastserver = 1;
1876
0
    }
1877
0
    addr_node = addr_node->link;
1878
0
  }
1879
1880
  /* Configure the multicast clients */
1881
0
  addr_node = HEAD_PFIFO(ptree->multicastclient);
1882
0
  if (addr_node != NULL) {
1883
0
    do {
1884
0
      ZERO_SOCK(&addr_sock);
1885
0
      AF(&addr_sock) = addr_node->type;
1886
0
      if (1 == getnetnum(addr_node->address,
1887
0
             &addr_sock, 1, t_UNK)) {
1888
0
        proto_config(PROTO_MULTICAST_ADD, 0, 0.,
1889
0
               &addr_sock);
1890
0
      }
1891
0
      addr_node = addr_node->link;
1892
0
    } while (addr_node != NULL);
1893
0
    proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
1894
0
  }
1895
0
}
1896
#endif  /* !SIM */
1897
1898
1899
#ifdef FREE_CFG_T
1900
static void
1901
destroy_address_fifo(
1902
  address_fifo *  pfifo
1903
  )
1904
0
{
1905
0
  address_node *  addr_node;
1906
1907
0
  if (pfifo != NULL) {
1908
0
    for (;;) {
1909
0
      UNLINK_FIFO(addr_node, *pfifo, link);
1910
0
      if (addr_node == NULL)
1911
0
        break;
1912
0
      destroy_address_node(addr_node);
1913
0
    }
1914
0
    free(pfifo);
1915
0
  }
1916
0
}
1917
1918
1919
static void
1920
free_config_other_modes(
1921
  config_tree *ptree
1922
  )
1923
0
{
1924
0
  FREE_ADDRESS_FIFO(ptree->manycastserver);
1925
0
  FREE_ADDRESS_FIFO(ptree->multicastclient);
1926
0
}
1927
#endif  /* FREE_CFG_T */
1928
1929
1930
#ifndef SIM
1931
static void
1932
config_auth(
1933
  config_tree *ptree
1934
  )
1935
0
{
1936
0
  attr_val *  my_val;
1937
0
  int   first;
1938
0
  int   last;
1939
0
  int   i;
1940
0
  int   count;
1941
#ifdef AUTOKEY
1942
  int   item;
1943
#endif
1944
1945
  /* Crypto Command */
1946
#ifdef AUTOKEY
1947
  my_val = HEAD_PFIFO(ptree->auth.crypto_cmd_list);
1948
  for (; my_val != NULL; my_val = my_val->link) {
1949
    switch (my_val->attr) {
1950
1951
    default:
1952
      fatal_error("config_auth: attr-token=%d", my_val->attr);
1953
1954
    case T_Host:
1955
      item = CRYPTO_CONF_PRIV;
1956
      break;
1957
1958
    case T_Ident:
1959
      item = CRYPTO_CONF_IDENT;
1960
      break;
1961
1962
    case T_Pw:
1963
      item = CRYPTO_CONF_PW;
1964
      break;
1965
1966
    case T_Randfile:
1967
      item = CRYPTO_CONF_RAND;
1968
      break;
1969
1970
    case T_Digest:
1971
      item = CRYPTO_CONF_NID;
1972
      break;
1973
    }
1974
    crypto_config(item, my_val->value.s);
1975
  }
1976
#endif  /* AUTOKEY */
1977
1978
  /* Keysdir Command */
1979
0
  if (ptree->auth.keysdir) {
1980
0
    if (keysdir != default_keysdir)
1981
0
      free(keysdir);
1982
0
    keysdir = estrdup(ptree->auth.keysdir);
1983
0
  }
1984
1985
1986
  /* ntp_signd_socket Command */
1987
0
  if (ptree->auth.ntp_signd_socket) {
1988
0
    if (ntp_signd_socket != default_ntp_signd_socket)
1989
0
      free(ntp_signd_socket);
1990
0
    ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
1991
0
  }
1992
1993
#ifdef AUTOKEY
1994
  if (ptree->auth.cryptosw && !cryptosw) {
1995
    crypto_setup();
1996
    cryptosw = 1;
1997
  }
1998
#endif  /* AUTOKEY */
1999
2000
  /*
2001
   * Count the number of trusted keys to preallocate storage and
2002
   * size the hash table.
2003
   */
2004
0
  count = 0;
2005
0
  my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
2006
0
  for (; my_val != NULL; my_val = my_val->link) {
2007
0
    if (T_Integer == my_val->type) {
2008
0
      first = my_val->value.i;
2009
0
      if (first > 1 && first <= NTP_MAXKEY)
2010
0
        count++;
2011
0
    } else {
2012
0
      REQUIRE(T_Intrange == my_val->type);
2013
0
      first = my_val->value.r.first;
2014
0
      last = my_val->value.r.last;
2015
0
      if (!(first > last || first < 1 ||
2016
0
          last > NTP_MAXKEY)) {
2017
0
        count += 1 + last - first;
2018
0
      }
2019
0
    }
2020
0
  }
2021
0
  auth_prealloc_symkeys(count);
2022
2023
  /* Keys Command */
2024
0
  if (ptree->auth.keys)
2025
0
    getauthkeys(ptree->auth.keys);
2026
2027
  /* Control Key Command */
2028
0
  if (ptree->auth.control_key)
2029
0
    ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
2030
2031
  /* Requested Key Command */
2032
0
  if (ptree->auth.request_key) {
2033
0
    DPRINTF(4, ("set info_auth_keyid to %08lx\n",
2034
0
          (u_long) ptree->auth.request_key));
2035
0
    info_auth_keyid = (keyid_t)ptree->auth.request_key;
2036
0
  }
2037
2038
  /* Trusted Key Command */
2039
0
  my_val = HEAD_PFIFO(ptree->auth.trusted_key_list);
2040
0
  for (; my_val != NULL; my_val = my_val->link) {
2041
0
    if (T_Integer == my_val->type) {
2042
0
      first = my_val->value.i;
2043
0
      if (first >= 1 && first <= NTP_MAXKEY) {
2044
0
        authtrust(first, TRUE);
2045
0
      } else {
2046
0
        msyslog(LOG_NOTICE,
2047
0
          "Ignoring invalid trustedkey %d, min 1 max %d.",
2048
0
          first, NTP_MAXKEY);
2049
0
      }
2050
0
    } else {
2051
0
      first = my_val->value.r.first;
2052
0
      last = my_val->value.r.last;
2053
0
      if (first > last || first < 1 ||
2054
0
          last > NTP_MAXKEY) {
2055
0
        msyslog(LOG_NOTICE,
2056
0
          "Ignoring invalid trustedkey range %d ... %d, min 1 max %d.",
2057
0
          first, last, NTP_MAXKEY);
2058
0
      } else {
2059
0
        for (i = first; i <= last; i++) {
2060
0
          authtrust(i, TRUE);
2061
0
        }
2062
0
      }
2063
0
    }
2064
0
  }
2065
2066
#ifdef AUTOKEY
2067
  /* crypto revoke command */
2068
  if (ptree->auth.revoke > 2 && ptree->auth.revoke < 32)
2069
    sys_revoke = (u_char)ptree->auth.revoke;
2070
  else if (ptree->auth.revoke)
2071
    msyslog(LOG_ERR,
2072
      "'revoke' value %d ignored",
2073
      ptree->auth.revoke);
2074
#endif  /* AUTOKEY */
2075
0
}
2076
#endif  /* !SIM */
2077
2078
2079
#ifdef FREE_CFG_T
2080
static void
2081
free_config_auth(
2082
  config_tree *ptree
2083
  )
2084
0
{
2085
0
  destroy_attr_val_fifo(ptree->auth.crypto_cmd_list);
2086
0
  ptree->auth.crypto_cmd_list = NULL;
2087
0
  destroy_attr_val_fifo(ptree->auth.trusted_key_list);
2088
0
  ptree->auth.trusted_key_list = NULL;
2089
0
}
2090
#endif  /* FREE_CFG_T */
2091
2092
2093
/* Configure low-level clock-related parameters. Return TRUE if the
2094
 * clock might need adjustment like era-checking after the call, FALSE
2095
 * otherwise.
2096
 */
2097
static int/*BOOL*/
2098
config_tos_clock(
2099
  config_tree *ptree
2100
  )
2101
0
{
2102
0
  int   ret;
2103
0
  attr_val *  tos;
2104
2105
0
  ret = FALSE;
2106
0
  tos = HEAD_PFIFO(ptree->orphan_cmds);
2107
0
  for (; tos != NULL; tos = tos->link) {
2108
0
    switch(tos->attr) {
2109
2110
0
    default:
2111
0
      break;
2112
2113
0
    case T_Basedate:
2114
0
      basedate_set_day(tos->value.i);
2115
0
      ret = TRUE;
2116
0
      break;
2117
0
    }
2118
0
  }
2119
2120
0
  if (basedate_get_day() <= NTP_TO_UNIX_DAYS)
2121
0
    basedate_set_day(basedate_eval_buildstamp() - 11);
2122
      
2123
0
  return ret;
2124
0
}
2125
2126
static void
2127
config_tos(
2128
  config_tree *ptree
2129
  )
2130
0
{
2131
0
  attr_val *  tos;
2132
0
  int   item;
2133
0
  double    val;
2134
2135
  /* [Bug 2896] For the daemon to work properly it is essential
2136
   * that minsane < minclock <= maxclock.
2137
   *
2138
   * If either constraint is violated, the daemon will be or might
2139
   * become dysfunctional. Fixing the values is too fragile here,
2140
   * since three variables with interdependecies are involved. We
2141
   * just log an error but do not stop: This might be caused by
2142
   * remote config, and it might be fixed by remote config, too.
2143
   */
2144
0
  int l_maxclock = sys_maxclock;
2145
0
  int l_minclock = sys_minclock;
2146
0
  int l_minsane  = sys_minsane;
2147
2148
  /* -*- phase one: inspect / sanitize the values */
2149
0
  tos = HEAD_PFIFO(ptree->orphan_cmds);
2150
0
  for (; tos != NULL; tos = tos->link) {
2151
    /* not all attributes are doubles (any more), so loading
2152
     * 'val' in all cases is not a good idea: It should be
2153
     * done as needed in every case processed here.
2154
     */
2155
0
    switch(tos->attr) {
2156
0
    default:
2157
0
      break;
2158
2159
0
    case T_Bcpollbstep:
2160
0
      val = tos->value.d;
2161
0
      if (val > 4) {
2162
0
        msyslog(LOG_WARNING,
2163
0
          "Using maximum bcpollbstep ceiling %d, %d requested",
2164
0
          4, (int)val);
2165
0
        tos->value.d = 4;
2166
0
      } else if (val < 0) {
2167
0
        msyslog(LOG_WARNING,
2168
0
          "Using minimum bcpollbstep floor %d, %d requested",
2169
0
          0, (int)val);
2170
0
        tos->value.d = 0;
2171
0
      }
2172
0
      break;
2173
2174
0
    case T_Ceiling:
2175
0
      val = tos->value.d;
2176
0
      if (val > STRATUM_UNSPEC - 1) {
2177
0
        msyslog(LOG_WARNING,
2178
0
          "Using maximum tos ceiling %d, %d requested",
2179
0
          STRATUM_UNSPEC - 1, (int)val);
2180
0
        tos->value.d = STRATUM_UNSPEC - 1;
2181
0
      } else if (val < 1) {
2182
0
        msyslog(LOG_WARNING,
2183
0
          "Using minimum tos floor %d, %d requested",
2184
0
          1, (int)val);
2185
0
        tos->value.d = 1;
2186
0
      }
2187
0
      break;
2188
2189
0
    case T_Minclock:
2190
0
      val = tos->value.d;
2191
0
      if ((int)tos->value.d < 1)
2192
0
        tos->value.d = 1;
2193
0
      l_minclock = (int)tos->value.d;
2194
0
      break;
2195
2196
0
    case T_Maxclock:
2197
0
      val = tos->value.d;
2198
0
      if ((int)tos->value.d < 1)
2199
0
        tos->value.d = 1;
2200
0
      l_maxclock = (int)tos->value.d;
2201
0
      break;
2202
2203
0
    case T_Minsane:
2204
0
      val = tos->value.d;
2205
0
      if ((int)tos->value.d < 0)
2206
0
        tos->value.d = 0;
2207
0
      l_minsane = (int)tos->value.d;
2208
0
      break;
2209
0
    }
2210
0
  }
2211
2212
0
  if ( ! (l_minsane < l_minclock && l_minclock <= l_maxclock)) {
2213
0
    msyslog(LOG_ERR,
2214
0
      "tos error: must have minsane (%d) < minclock (%d) <= maxclock (%d)"
2215
0
      " - daemon will not operate properly!",
2216
0
      l_minsane, l_minclock, l_maxclock);
2217
0
  }
2218
2219
  /* -*- phase two: forward the values to the protocol machinery */
2220
0
  tos = HEAD_PFIFO(ptree->orphan_cmds);
2221
0
  for (; tos != NULL; tos = tos->link) {
2222
0
    switch(tos->attr) {
2223
2224
0
    default:
2225
0
      fatal_error("config-tos: attr-token=%d", tos->attr);
2226
2227
0
    case T_Bcpollbstep:
2228
0
      item = PROTO_BCPOLLBSTEP;
2229
0
      break;
2230
2231
0
    case T_Ceiling:
2232
0
      item = PROTO_CEILING;
2233
0
      break;
2234
2235
0
    case T_Floor:
2236
0
      item = PROTO_FLOOR;
2237
0
      break;
2238
2239
0
    case T_Cohort:
2240
0
      item = PROTO_COHORT;
2241
0
      break;
2242
2243
0
    case T_Orphan:
2244
0
      item = PROTO_ORPHAN;
2245
0
      break;
2246
2247
0
    case T_Orphanwait:
2248
0
      item = PROTO_ORPHWAIT;
2249
0
      break;
2250
2251
0
    case T_Mindist:
2252
0
      item = PROTO_MINDISP;
2253
0
      break;
2254
2255
0
    case T_Maxdist:
2256
0
      item = PROTO_MAXDIST;
2257
0
      break;
2258
2259
0
    case T_Minclock:
2260
0
      item = PROTO_MINCLOCK;
2261
0
      break;
2262
2263
0
    case T_Maxclock:
2264
0
      item = PROTO_MAXCLOCK;
2265
0
      break;
2266
2267
0
    case T_Minsane:
2268
0
      item = PROTO_MINSANE;
2269
0
      break;
2270
2271
0
    case T_Beacon:
2272
0
      item = PROTO_BEACON;
2273
0
      break;
2274
2275
0
    case T_Basedate:
2276
0
      continue; /* SKIP proto-config for this! */
2277
0
    }
2278
0
    proto_config(item, 0, tos->value.d, NULL);
2279
0
  }
2280
0
}
2281
2282
2283
#ifdef FREE_CFG_T
2284
static void
2285
free_config_tos(
2286
  config_tree *ptree
2287
  )
2288
0
{
2289
0
  FREE_ATTR_VAL_FIFO(ptree->orphan_cmds);
2290
0
}
2291
#endif  /* FREE_CFG_T */
2292
2293
2294
static void
2295
config_monitor(
2296
  config_tree *ptree
2297
  )
2298
0
{
2299
0
  int_node *pfilegen_token;
2300
0
  const char *filegen_string;
2301
0
  const char *filegen_file;
2302
0
  FILEGEN *filegen;
2303
0
  filegen_node *my_node;
2304
0
  attr_val *my_opts;
2305
0
  int filegen_type;
2306
0
  int filegen_flag;
2307
2308
  /* Set the statistics directory */
2309
0
  if (ptree->stats_dir)
2310
0
    stats_config(STATS_STATSDIR, ptree->stats_dir);
2311
2312
  /* NOTE:
2313
   * Calling filegen_get is brain dead. Doing a string
2314
   * comparison to find the relavant filegen structure is
2315
   * expensive.
2316
   *
2317
   * Through the parser, we already know which filegen is
2318
   * being specified. Hence, we should either store a
2319
   * pointer to the specified structure in the syntax tree
2320
   * or an index into a filegen array.
2321
   *
2322
   * Need to change the filegen code to reflect the above.
2323
   */
2324
2325
  /* Turn on the specified statistics */
2326
0
  pfilegen_token = HEAD_PFIFO(ptree->stats_list);
2327
0
  for (; pfilegen_token != NULL; pfilegen_token = pfilegen_token->link) {
2328
0
    filegen_string = keyword(pfilegen_token->i);
2329
0
    filegen = filegen_get(filegen_string);
2330
0
    if (NULL == filegen) {
2331
0
      msyslog(LOG_ERR,
2332
0
        "stats %s unrecognized",
2333
0
        filegen_string);
2334
0
      continue;
2335
0
    }
2336
0
    DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
2337
0
          filegen_string, filegen->dir,
2338
0
          filegen->fname));
2339
0
    filegen_flag = filegen->flag;
2340
0
    filegen_flag |= FGEN_FLAG_ENABLED;
2341
0
    filegen_config(filegen, statsdir, filegen_string,
2342
0
             filegen->type, filegen_flag);
2343
0
  }
2344
2345
  /* Configure the statistics with the options */
2346
0
  my_node = HEAD_PFIFO(ptree->filegen_opts);
2347
0
  for (; my_node != NULL; my_node = my_node->link) {
2348
0
    filegen_string = keyword(my_node->filegen_token);
2349
0
    filegen = filegen_get(filegen_string);
2350
0
    if (NULL == filegen) {
2351
0
      msyslog(LOG_ERR,
2352
0
        "filegen category '%s' unrecognized",
2353
0
        filegen_string);
2354
0
      continue;
2355
0
    }
2356
0
    filegen_file = filegen_string;
2357
2358
    /* Initialize the filegen variables to their pre-configuration states */
2359
0
    filegen_flag = filegen->flag;
2360
0
    filegen_type = filegen->type;
2361
2362
    /* "filegen ... enabled" is the default (when filegen is used) */
2363
0
    filegen_flag |= FGEN_FLAG_ENABLED;
2364
2365
0
    my_opts = HEAD_PFIFO(my_node->options);
2366
0
    for (; my_opts != NULL; my_opts = my_opts->link) {
2367
0
      switch (my_opts->attr) {
2368
2369
0
      case T_File:
2370
0
        filegen_file = my_opts->value.s;
2371
0
        break;
2372
2373
0
      case T_Type:
2374
0
        switch (my_opts->value.i) {
2375
2376
0
        default:
2377
0
          fatal_error("config-monitor: type-token=%d", my_opts->value.i);
2378
2379
0
        case T_None:
2380
0
          filegen_type = FILEGEN_NONE;
2381
0
          break;
2382
2383
0
        case T_Pid:
2384
0
          filegen_type = FILEGEN_PID;
2385
0
          break;
2386
2387
0
        case T_Day:
2388
0
          filegen_type = FILEGEN_DAY;
2389
0
          break;
2390
2391
0
        case T_Week:
2392
0
          filegen_type = FILEGEN_WEEK;
2393
0
          break;
2394
2395
0
        case T_Month:
2396
0
          filegen_type = FILEGEN_MONTH;
2397
0
          break;
2398
2399
0
        case T_Year:
2400
0
          filegen_type = FILEGEN_YEAR;
2401
0
          break;
2402
2403
0
        case T_Age:
2404
0
          filegen_type = FILEGEN_AGE;
2405
0
          break;
2406
0
        }
2407
0
        break;
2408
2409
0
      case T_Flag:
2410
0
        switch (my_opts->value.i) {
2411
2412
0
        case T_Link:
2413
0
          filegen_flag |= FGEN_FLAG_LINK;
2414
0
          break;
2415
2416
0
        case T_Nolink:
2417
0
          filegen_flag &= ~FGEN_FLAG_LINK;
2418
0
          break;
2419
2420
0
        case T_Enable:
2421
0
          filegen_flag |= FGEN_FLAG_ENABLED;
2422
0
          break;
2423
2424
0
        case T_Disable:
2425
0
          filegen_flag &= ~FGEN_FLAG_ENABLED;
2426
0
          break;
2427
2428
0
        default:
2429
0
          msyslog(LOG_ERR,
2430
0
            "Unknown filegen flag token %d",
2431
0
            my_opts->value.i);
2432
0
          exit(1);
2433
0
        }
2434
0
        break;
2435
2436
0
      default:
2437
0
        msyslog(LOG_ERR,
2438
0
          "Unknown filegen option token %d",
2439
0
          my_opts->attr);
2440
0
        exit(1);
2441
0
      }
2442
0
    }
2443
0
    filegen_config(filegen, statsdir, filegen_file,
2444
0
             filegen_type, filegen_flag);
2445
0
  }
2446
0
}
2447
2448
2449
#ifdef FREE_CFG_T
2450
static void
2451
free_config_monitor(
2452
  config_tree *ptree
2453
  )
2454
0
{
2455
0
  if (ptree->stats_dir) {
2456
0
    free(ptree->stats_dir);
2457
0
    ptree->stats_dir = NULL;
2458
0
  }
2459
2460
0
  FREE_INT_FIFO(ptree->stats_list);
2461
0
  FREE_FILEGEN_FIFO(ptree->filegen_opts);
2462
0
}
2463
#endif  /* FREE_CFG_T */
2464
2465
2466
#ifndef SIM
2467
static void
2468
config_access(
2469
  config_tree *ptree
2470
  )
2471
0
{
2472
0
  static int    warned_signd;
2473
0
  attr_val *    my_opt;
2474
0
  restrict_node *   my_node;
2475
0
  int_node *    curr_tok_fifo;
2476
0
  sockaddr_u    addr;
2477
0
  sockaddr_u    mask;
2478
0
  struct addrinfo   hints;
2479
0
  struct addrinfo * ai_list;
2480
0
  struct addrinfo * pai;
2481
0
  int     rc;
2482
0
  int     restrict_default;
2483
0
  u_short     rflags;
2484
0
  u_short     mflags;
2485
0
  short     ippeerlimit;
2486
0
  int     range_err;
2487
0
  const char *    signd_warning =
2488
#ifdef HAVE_NTP_SIGND
2489
      "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
2490
#else
2491
0
      "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
2492
0
#endif
2493
2494
  /* Configure the mru options */
2495
0
  my_opt = HEAD_PFIFO(ptree->mru_opts);
2496
0
  for (; my_opt != NULL; my_opt = my_opt->link) {
2497
2498
0
    range_err = FALSE;
2499
2500
0
    switch (my_opt->attr) {
2501
2502
0
    case T_Incalloc:
2503
0
      if (0 <= my_opt->value.i)
2504
0
        mru_incalloc = my_opt->value.u;
2505
0
      else
2506
0
        range_err = TRUE;
2507
0
      break;
2508
2509
0
    case T_Incmem:
2510
0
      if (0 <= my_opt->value.i)
2511
0
        mru_incalloc = (my_opt->value.u * 1024U)
2512
0
            / sizeof(mon_entry);
2513
0
      else
2514
0
        range_err = TRUE;
2515
0
      break;
2516
2517
0
    case T_Initalloc:
2518
0
      if (0 <= my_opt->value.i)
2519
0
        mru_initalloc = my_opt->value.u;
2520
0
      else
2521
0
        range_err = TRUE;
2522
0
      break;
2523
2524
0
    case T_Initmem:
2525
0
      if (0 <= my_opt->value.i)
2526
0
        mru_initalloc = (my_opt->value.u * 1024U)
2527
0
             / sizeof(mon_entry);
2528
0
      else
2529
0
        range_err = TRUE;
2530
0
      break;
2531
2532
0
    case T_Mindepth:
2533
0
      if (0 <= my_opt->value.i)
2534
0
        mru_mindepth = my_opt->value.u;
2535
0
      else
2536
0
        range_err = TRUE;
2537
0
      break;
2538
2539
0
    case T_Maxage:
2540
0
      mru_maxage = my_opt->value.i;
2541
0
      break;
2542
2543
0
    case T_Maxdepth:
2544
0
      if (0 <= my_opt->value.i)
2545
0
        mru_maxdepth = my_opt->value.u;
2546
0
      else
2547
0
        mru_maxdepth = UINT_MAX;
2548
0
      break;
2549
2550
0
    case T_Maxmem:
2551
0
      if (0 <= my_opt->value.i)
2552
0
        mru_maxdepth = (my_opt->value.u * 1024U) /
2553
0
                 sizeof(mon_entry);
2554
0
      else
2555
0
        mru_maxdepth = UINT_MAX;
2556
0
      break;
2557
2558
0
    default:
2559
0
      msyslog(LOG_ERR,
2560
0
        "Unknown mru option %s (%d)",
2561
0
        keyword(my_opt->attr), my_opt->attr);
2562
0
      exit(1);
2563
0
    }
2564
0
    if (range_err)
2565
0
      msyslog(LOG_ERR,
2566
0
        "mru %s %d out of range, ignored.",
2567
0
        keyword(my_opt->attr), my_opt->value.i);
2568
0
  }
2569
2570
  /* Configure the discard options */
2571
0
  my_opt = HEAD_PFIFO(ptree->discard_opts);
2572
0
  for (; my_opt != NULL; my_opt = my_opt->link) {
2573
2574
0
    switch (my_opt->attr) {
2575
2576
0
    case T_Average:
2577
0
      if (0 <= my_opt->value.i &&
2578
0
          my_opt->value.i <= UCHAR_MAX)
2579
0
        ntp_minpoll = (u_char)my_opt->value.u;
2580
0
      else
2581
0
        msyslog(LOG_ERR,
2582
0
          "discard average %d out of range, ignored.",
2583
0
          my_opt->value.i);
2584
0
      break;
2585
2586
0
    case T_Minimum:
2587
0
      ntp_minpkt = my_opt->value.i;
2588
0
      break;
2589
2590
0
    case T_Monitor:
2591
0
      mon_age = my_opt->value.i;
2592
0
      break;
2593
2594
0
    default:
2595
0
      msyslog(LOG_ERR,
2596
0
        "Unknown discard option %s (%d)",
2597
0
        keyword(my_opt->attr), my_opt->attr);
2598
0
      exit(1);
2599
0
    }
2600
0
  }
2601
2602
  /* Configure the restrict options */
2603
0
  my_node = HEAD_PFIFO(ptree->restrict_opts);
2604
2605
0
  for (; my_node != NULL; my_node = my_node->link) {
2606
    /* Grab the ippeerlmit */
2607
0
    ippeerlimit = my_node->ippeerlimit;
2608
2609
0
DPRINTF(1, ("config_access: top-level node %p: ippeerlimit %d\n", my_node, ippeerlimit));
2610
2611
    /* Parse the flags */
2612
0
    rflags = 0;
2613
0
    mflags = 0;
2614
2615
0
    curr_tok_fifo = HEAD_PFIFO(my_node->flag_tok_fifo);
2616
0
    for (; curr_tok_fifo != NULL; curr_tok_fifo = curr_tok_fifo->link) {
2617
0
      switch (curr_tok_fifo->i) {
2618
2619
0
      default:
2620
0
        fatal_error("config_access: flag-type-token=%d", curr_tok_fifo->i);
2621
2622
0
      case T_Ntpport:
2623
0
        mflags |= RESM_NTPONLY;
2624
0
        break;
2625
2626
0
      case T_Source:
2627
0
        mflags |= RESM_SOURCE;
2628
0
        break;
2629
2630
0
      case T_Flake:
2631
0
        rflags |= RES_FLAKE;
2632
0
        break;
2633
2634
0
      case T_Ignore:
2635
0
        rflags |= RES_IGNORE;
2636
0
        break;
2637
2638
0
      case T_Kod:
2639
0
        rflags |= RES_KOD;
2640
0
        break;
2641
2642
0
      case T_Mssntp:
2643
0
        rflags |= RES_MSSNTP;
2644
0
        break;
2645
2646
0
      case T_Limited:
2647
0
        rflags |= RES_LIMITED;
2648
0
        break;
2649
2650
0
      case T_Lowpriotrap:
2651
0
        rflags |= RES_LPTRAP;
2652
0
        break;
2653
2654
0
      case T_Nomodify:
2655
0
        rflags |= RES_NOMODIFY;
2656
0
        break;
2657
2658
0
      case T_Nomrulist:
2659
0
        rflags |= RES_NOMRULIST;
2660
0
        break;
2661
2662
0
      case T_Noepeer:
2663
0
        rflags |= RES_NOEPEER;
2664
0
        break;
2665
2666
0
      case T_Nopeer:
2667
0
        rflags |= RES_NOPEER;
2668
0
        break;
2669
2670
0
      case T_Noquery:
2671
0
        rflags |= RES_NOQUERY;
2672
0
        break;
2673
2674
0
      case T_Noserve:
2675
0
        rflags |= RES_DONTSERVE;
2676
0
        break;
2677
2678
0
      case T_Notrap:
2679
0
        rflags |= RES_NOTRAP;
2680
0
        break;
2681
2682
0
      case T_Notrust:
2683
0
        rflags |= RES_DONTTRUST;
2684
0
        break;
2685
2686
0
      case T_Version:
2687
0
        rflags |= RES_VERSION;
2688
0
        break;
2689
0
      }
2690
0
    }
2691
2692
0
    if ((RES_MSSNTP & rflags) && !warned_signd) {
2693
0
      warned_signd = 1;
2694
0
      fprintf(stderr, "%s\n", signd_warning);
2695
0
      msyslog(LOG_WARNING, "%s", signd_warning);
2696
0
    }
2697
2698
    /* It would be swell if we could identify the line number */
2699
0
    if ((RES_KOD & rflags) && !(RES_LIMITED & rflags)) {
2700
0
      const char *kod_where = (my_node->addr)
2701
0
            ? my_node->addr->address
2702
0
            : (mflags & RESM_SOURCE)
2703
0
              ? "source"
2704
0
              : "default";
2705
0
      const char *kod_warn = "KOD does nothing without LIMITED.";
2706
2707
0
      fprintf(stderr, "restrict %s: %s\n", kod_where, kod_warn);
2708
0
      msyslog(LOG_WARNING, "restrict %s: %s", kod_where, kod_warn);
2709
0
    }
2710
2711
0
    ZERO_SOCK(&addr);
2712
0
    ai_list = NULL;
2713
0
    pai = NULL;
2714
0
    restrict_default = 0;
2715
2716
0
    if (NULL == my_node->addr) {
2717
0
      ZERO_SOCK(&mask);
2718
0
      if (!(RESM_SOURCE & mflags)) {
2719
        /*
2720
         * The user specified a default rule
2721
         * without a -4 / -6 qualifier, add to
2722
         * both lists
2723
         */
2724
0
        restrict_default = 1;
2725
0
      } else {
2726
        /* apply "restrict source ..." */
2727
0
        DPRINTF(1, ("restrict source template ippeerlimit %d mflags %x rflags %x\n",
2728
0
          ippeerlimit, mflags, rflags));
2729
0
        hack_restrict(RESTRICT_FLAGS, NULL, NULL,
2730
0
                ippeerlimit, mflags, rflags, 0);
2731
0
        continue;
2732
0
      }
2733
0
    } else {
2734
      /* Resolve the specified address */
2735
0
      AF(&addr) = (u_short)my_node->addr->type;
2736
2737
0
      if (getnetnum(my_node->addr->address,
2738
0
              &addr, 1, t_UNK) != 1) {
2739
        /*
2740
         * Attempt a blocking lookup.  This
2741
         * is in violation of the nonblocking
2742
         * design of ntpd's mainline code.  The
2743
         * alternative of running without the
2744
         * restriction until the name resolved
2745
         * seems worse.
2746
         * Ideally some scheme could be used for
2747
         * restrict directives in the startup
2748
         * ntp.conf to delay starting up the
2749
         * protocol machinery until after all
2750
         * restrict hosts have been resolved.
2751
         */
2752
0
        ai_list = NULL;
2753
0
        ZERO(hints);
2754
0
        hints.ai_protocol = IPPROTO_UDP;
2755
0
        hints.ai_socktype = SOCK_DGRAM;
2756
0
        hints.ai_family = my_node->addr->type;
2757
0
        rc = getaddrinfo(my_node->addr->address,
2758
0
             "ntp", &hints,
2759
0
             &ai_list);
2760
0
        if (rc) {
2761
0
          msyslog(LOG_ERR,
2762
0
            "restrict: ignoring line %d, address/host '%s' unusable.",
2763
0
            my_node->line_no,
2764
0
            my_node->addr->address);
2765
0
          continue;
2766
0
        }
2767
0
        INSIST(ai_list != NULL);
2768
0
        pai = ai_list;
2769
0
        INSIST(pai->ai_addr != NULL);
2770
0
        INSIST(sizeof(addr) >=
2771
0
             pai->ai_addrlen);
2772
0
        memcpy(&addr, pai->ai_addr,
2773
0
               pai->ai_addrlen);
2774
0
        INSIST(AF_INET == AF(&addr) ||
2775
0
             AF_INET6 == AF(&addr));
2776
0
      }
2777
2778
0
      SET_HOSTMASK(&mask, AF(&addr));
2779
2780
      /* Resolve the mask */
2781
0
      if (my_node->mask) {
2782
0
        ZERO_SOCK(&mask);
2783
0
        AF(&mask) = my_node->mask->type;
2784
0
        if (getnetnum(my_node->mask->address,
2785
0
                &mask, 1, t_MSK) != 1) {
2786
0
          msyslog(LOG_ERR,
2787
0
            "restrict: ignoring line %d, mask '%s' unusable.",
2788
0
            my_node->line_no,
2789
0
            my_node->mask->address);
2790
0
          continue;
2791
0
        }
2792
0
      }
2793
0
    }
2794
2795
    /* Set the flags */
2796
0
    if (restrict_default) {
2797
0
      AF(&addr) = AF_INET;
2798
0
      AF(&mask) = AF_INET;
2799
0
      hack_restrict(RESTRICT_FLAGS, &addr, &mask,
2800
0
              ippeerlimit, mflags, rflags, 0);
2801
0
      AF(&addr) = AF_INET6;
2802
0
      AF(&mask) = AF_INET6;
2803
0
    }
2804
2805
0
    do {
2806
0
      hack_restrict(RESTRICT_FLAGS, &addr, &mask,
2807
0
              ippeerlimit, mflags, rflags, 0);
2808
0
      if (pai != NULL &&
2809
0
          NULL != (pai = pai->ai_next)) {
2810
0
        INSIST(pai->ai_addr != NULL);
2811
0
        INSIST(sizeof(addr) >=
2812
0
             pai->ai_addrlen);
2813
0
        ZERO_SOCK(&addr);
2814
0
        memcpy(&addr, pai->ai_addr,
2815
0
               pai->ai_addrlen);
2816
0
        INSIST(AF_INET == AF(&addr) ||
2817
0
             AF_INET6 == AF(&addr));
2818
0
        SET_HOSTMASK(&mask, AF(&addr));
2819
0
      }
2820
0
    } while (pai != NULL);
2821
2822
0
    if (ai_list != NULL)
2823
0
      freeaddrinfo(ai_list);
2824
0
  }
2825
0
}
2826
#endif  /* !SIM */
2827
2828
2829
#ifdef FREE_CFG_T
2830
static void
2831
free_config_access(
2832
  config_tree *ptree
2833
  )
2834
0
{
2835
0
  FREE_ATTR_VAL_FIFO(ptree->mru_opts);
2836
0
  FREE_ATTR_VAL_FIFO(ptree->discard_opts);
2837
0
  FREE_RESTRICT_FIFO(ptree->restrict_opts);
2838
0
}
2839
#endif  /* FREE_CFG_T */
2840
2841
2842
static void
2843
config_rlimit(
2844
  config_tree *ptree
2845
  )
2846
0
{
2847
0
  attr_val *  rlimit_av;
2848
2849
0
  rlimit_av = HEAD_PFIFO(ptree->rlimit);
2850
0
  for (; rlimit_av != NULL; rlimit_av = rlimit_av->link) {
2851
0
    switch (rlimit_av->attr) {
2852
2853
0
    default:
2854
0
      fatal_error("config-rlimit: value-token=%d", rlimit_av->attr);
2855
2856
0
    case T_Memlock:
2857
      /* What if we HAVE_OPT(SAVECONFIGQUIT) ? */
2858
0
      if (HAVE_OPT( SAVECONFIGQUIT )) {
2859
0
        break;
2860
0
      }
2861
0
      if (rlimit_av->value.i == -1) {
2862
0
# if defined(HAVE_MLOCKALL)
2863
0
        if (cur_memlock != 0) {
2864
0
          if (-1 == munlockall()) {
2865
0
            msyslog(LOG_ERR, "munlockall() failed: %m");
2866
0
          }
2867
0
        }
2868
0
        cur_memlock = 0;
2869
0
# endif /* HAVE_MLOCKALL */
2870
0
      } else if (rlimit_av->value.i >= 0) {
2871
0
#if defined(RLIMIT_MEMLOCK)
2872
0
# if defined(HAVE_MLOCKALL)
2873
0
        if (cur_memlock != 1) {
2874
0
          if (-1 == mlockall(MCL_CURRENT|MCL_FUTURE)) {
2875
0
            msyslog(LOG_ERR, "mlockall() failed: %m");
2876
0
          }
2877
0
        }
2878
0
# endif /* HAVE_MLOCKALL */
2879
0
        ntp_rlimit(RLIMIT_MEMLOCK,
2880
0
             (rlim_t)(rlimit_av->value.i * 1024 * 1024),
2881
0
             1024 * 1024,
2882
0
             "MB");
2883
0
        cur_memlock = 1;
2884
#else
2885
        /* STDERR as well would be fine... */
2886
        msyslog(LOG_WARNING, "'rlimit memlock' specified but is not available on this system.");
2887
#endif /* RLIMIT_MEMLOCK */
2888
0
      } else {
2889
0
        msyslog(LOG_WARNING, "'rlimit memlock' value of %d is unexpected!", rlimit_av->value.i);
2890
0
      }
2891
0
      break;
2892
2893
0
    case T_Stacksize:
2894
0
#if defined(RLIMIT_STACK)
2895
0
      ntp_rlimit(RLIMIT_STACK,
2896
0
           (rlim_t)(rlimit_av->value.i * 4096),
2897
0
           4096,
2898
0
           "4k");
2899
#else
2900
      /* STDERR as well would be fine... */
2901
      msyslog(LOG_WARNING, "'rlimit stacksize' specified but is not available on this system.");
2902
#endif /* RLIMIT_STACK */
2903
0
      break;
2904
2905
0
    case T_Filenum:
2906
0
#if defined(RLIMIT_NOFILE)
2907
0
      ntp_rlimit(RLIMIT_NOFILE,
2908
0
          (rlim_t)(rlimit_av->value.i),
2909
0
          1,
2910
0
          "");
2911
#else
2912
      /* STDERR as well would be fine... */
2913
      msyslog(LOG_WARNING, "'rlimit filenum' specified but is not available on this system.");
2914
#endif /* RLIMIT_NOFILE */
2915
0
      break;
2916
2917
0
    }
2918
0
  }
2919
0
}
2920
2921
2922
static void
2923
config_tinker(
2924
  config_tree *ptree
2925
  )
2926
0
{
2927
0
  attr_val *  tinker;
2928
0
  int   item;
2929
2930
0
  tinker = HEAD_PFIFO(ptree->tinker);
2931
0
  for (; tinker != NULL; tinker = tinker->link) {
2932
0
    switch (tinker->attr) {
2933
2934
0
    default:
2935
0
      fatal_error("config_tinker: attr-token=%d", tinker->attr);
2936
2937
0
    case T_Allan:
2938
0
      item = LOOP_ALLAN;
2939
0
      break;
2940
2941
0
    case T_Dispersion:
2942
0
      item = LOOP_PHI;
2943
0
      break;
2944
2945
0
    case T_Freq:
2946
0
      item = LOOP_FREQ;
2947
0
      break;
2948
2949
0
    case T_Huffpuff:
2950
0
      item = LOOP_HUFFPUFF;
2951
0
      break;
2952
2953
0
    case T_Panic:
2954
0
      item = LOOP_PANIC;
2955
0
      break;
2956
2957
0
    case T_Step:
2958
0
      item = LOOP_MAX;
2959
0
      break;
2960
2961
0
    case T_Stepback:
2962
0
      item = LOOP_MAX_BACK;
2963
0
      break;
2964
2965
0
    case T_Stepfwd:
2966
0
      item = LOOP_MAX_FWD;
2967
0
      break;
2968
2969
0
    case T_Stepout:
2970
0
      item = LOOP_MINSTEP;
2971
0
      break;
2972
2973
0
    case T_Tick:
2974
0
      item = LOOP_TICK;
2975
0
      break;
2976
0
    }
2977
0
    loop_config(item, tinker->value.d);
2978
0
  }
2979
0
}
2980
2981
2982
#ifdef FREE_CFG_T
2983
static void
2984
free_config_rlimit(
2985
  config_tree *ptree
2986
  )
2987
0
{
2988
0
  FREE_ATTR_VAL_FIFO(ptree->rlimit);
2989
0
}
2990
2991
static void
2992
free_config_tinker(
2993
  config_tree *ptree
2994
  )
2995
0
{
2996
0
  FREE_ATTR_VAL_FIFO(ptree->tinker);
2997
0
}
2998
#endif  /* FREE_CFG_T */
2999
3000
3001
/*
3002
 * config_nic_rules - apply interface listen/ignore/drop items
3003
 */
3004
#ifndef SIM
3005
static void
3006
config_nic_rules(
3007
  config_tree *ptree,
3008
  int/*BOOL*/ input_from_file
3009
  )
3010
0
{
3011
0
  nic_rule_node * curr_node;
3012
0
  sockaddr_u  addr;
3013
0
  nic_rule_match  match_type;
3014
0
  nic_rule_action action;
3015
0
  char *    if_name;
3016
0
  char *    pchSlash;
3017
0
  int   prefixlen;
3018
0
  int   addrbits;
3019
3020
0
  curr_node = HEAD_PFIFO(ptree->nic_rules);
3021
3022
0
  if (curr_node != NULL
3023
0
      && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
3024
0
    msyslog(LOG_ERR,
3025
0
      "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
3026
0
      (input_from_file) ? ", exiting" : "");
3027
0
    if (input_from_file)
3028
0
      exit(1);
3029
0
    else
3030
0
      return;
3031
0
  }
3032
3033
0
  for (; curr_node != NULL; curr_node = curr_node->link) {
3034
0
    prefixlen = -1;
3035
0
    if_name = curr_node->if_name;
3036
0
    if (if_name != NULL)
3037
0
      if_name = estrdup(if_name);
3038
3039
0
    switch (curr_node->match_class) {
3040
3041
0
    default:
3042
0
      fatal_error("config_nic_rules: match-class-token=%d", curr_node->match_class);
3043
3044
0
    case 0:
3045
      /*
3046
       * 0 is out of range for valid token T_...
3047
       * and in a nic_rules_node indicates the
3048
       * interface descriptor is either a name or
3049
       * address, stored in if_name in either case.
3050
       */
3051
0
      INSIST(if_name != NULL);
3052
0
      pchSlash = strchr(if_name, '/');
3053
0
      if (pchSlash != NULL)
3054
0
        *pchSlash = '\0';
3055
0
      if (is_ip_address(if_name, AF_UNSPEC, &addr)) {
3056
0
        match_type = MATCH_IFADDR;
3057
0
        if (pchSlash != NULL
3058
0
            && 1 == sscanf(pchSlash + 1, "%d",
3059
0
              &prefixlen)) {
3060
0
          addrbits = 8 *
3061
0
              SIZEOF_INADDR(AF(&addr));
3062
0
          prefixlen = max(-1, prefixlen);
3063
0
          prefixlen = min(prefixlen,
3064
0
              addrbits);
3065
0
        }
3066
0
      } else {
3067
0
        match_type = MATCH_IFNAME;
3068
0
        if (pchSlash != NULL)
3069
0
          *pchSlash = '/';
3070
0
      }
3071
0
      break;
3072
3073
0
    case T_All:
3074
0
      match_type = MATCH_ALL;
3075
0
      break;
3076
3077
0
    case T_Ipv4:
3078
0
      match_type = MATCH_IPV4;
3079
0
      break;
3080
3081
0
    case T_Ipv6:
3082
0
      match_type = MATCH_IPV6;
3083
0
      break;
3084
3085
0
    case T_Wildcard:
3086
0
      match_type = MATCH_WILDCARD;
3087
0
      break;
3088
0
    }
3089
3090
0
    switch (curr_node->action) {
3091
3092
0
    default:
3093
0
      fatal_error("config_nic_rules: action-token=%d", curr_node->action);
3094
3095
0
    case T_Listen:
3096
0
      action = ACTION_LISTEN;
3097
0
      break;
3098
3099
0
    case T_Ignore:
3100
0
      action = ACTION_IGNORE;
3101
0
      break;
3102
3103
0
    case T_Drop:
3104
0
      action = ACTION_DROP;
3105
0
      break;
3106
0
    }
3107
3108
0
    add_nic_rule(match_type, if_name, prefixlen,
3109
0
           action);
3110
0
    timer_interfacetimeout(current_time + 2);
3111
0
    if (if_name != NULL)
3112
0
      free(if_name);
3113
0
  }
3114
0
}
3115
#endif  /* !SIM */
3116
3117
3118
#ifdef FREE_CFG_T
3119
static void
3120
free_config_nic_rules(
3121
  config_tree *ptree
3122
  )
3123
0
{
3124
0
  nic_rule_node *curr_node;
3125
3126
0
  if (ptree->nic_rules != NULL) {
3127
0
    for (;;) {
3128
0
      UNLINK_FIFO(curr_node, *ptree->nic_rules, link);
3129
0
      if (NULL == curr_node)
3130
0
        break;
3131
0
      free(curr_node->if_name);
3132
0
      free(curr_node);
3133
0
    }
3134
0
    free(ptree->nic_rules);
3135
0
    ptree->nic_rules = NULL;
3136
0
  }
3137
0
}
3138
#endif  /* FREE_CFG_T */
3139
3140
3141
static void
3142
apply_enable_disable(
3143
  attr_val_fifo * fifo,
3144
  int   enable
3145
  )
3146
0
{
3147
0
  attr_val *curr_tok_fifo;
3148
0
  int option;
3149
#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3150
  bc_entry *pentry;
3151
#endif
3152
3153
0
  for (curr_tok_fifo = HEAD_PFIFO(fifo);
3154
0
       curr_tok_fifo != NULL;
3155
0
       curr_tok_fifo = curr_tok_fifo->link) {
3156
3157
0
    option = curr_tok_fifo->value.i;
3158
0
    switch (option) {
3159
3160
0
    default:
3161
0
      msyslog(LOG_ERR,
3162
0
        "can not apply enable/disable token %d, unknown",
3163
0
        option);
3164
0
      break;
3165
3166
0
    case T_Auth:
3167
0
      proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
3168
0
      break;
3169
3170
0
    case T_Bclient:
3171
0
      proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
3172
0
      break;
3173
3174
0
    case T_Calibrate:
3175
0
      proto_config(PROTO_CAL, enable, 0., NULL);
3176
0
      break;
3177
3178
0
    case T_Kernel:
3179
0
      proto_config(PROTO_KERNEL, enable, 0., NULL);
3180
0
      break;
3181
3182
0
    case T_Monitor:
3183
0
      proto_config(PROTO_MONITOR, enable, 0., NULL);
3184
0
      break;
3185
3186
0
    case T_Mode7:
3187
0
      proto_config(PROTO_MODE7, enable, 0., NULL);
3188
0
      break;
3189
3190
0
    case T_Ntp:
3191
0
      proto_config(PROTO_NTP, enable, 0., NULL);
3192
0
      break;
3193
3194
0
    case T_PCEdigest:
3195
0
      proto_config(PROTO_PCEDIGEST, enable, 0., NULL);
3196
0
      break;
3197
3198
0
    case T_Stats:
3199
0
      proto_config(PROTO_FILEGEN, enable, 0., NULL);
3200
0
      break;
3201
3202
0
    case T_UEcrypto:
3203
0
      proto_config(PROTO_UECRYPTO, enable, 0., NULL);
3204
0
      break;
3205
3206
0
    case T_UEcryptonak:
3207
0
      proto_config(PROTO_UECRYPTONAK, enable, 0., NULL);
3208
0
      break;
3209
3210
0
    case T_UEdigest:
3211
0
      proto_config(PROTO_UEDIGEST, enable, 0., NULL);
3212
0
      break;
3213
3214
#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
3215
    case T_Bc_bugXXXX:
3216
      pentry = bc_list;
3217
      while (pentry->token) {
3218
        if (pentry->token == option)
3219
          break;
3220
        pentry++;
3221
      }
3222
      if (!pentry->token) {
3223
        msyslog(LOG_ERR,
3224
          "compat token %d not in bc_list[]",
3225
          option);
3226
        continue;
3227
      }
3228
      pentry->enabled = enable;
3229
      break;
3230
#endif
3231
0
    }
3232
0
  }
3233
0
}
3234
3235
3236
static void
3237
config_system_opts(
3238
  config_tree *ptree
3239
  )
3240
0
{
3241
0
  apply_enable_disable(ptree->enable_opts, 1);
3242
0
  apply_enable_disable(ptree->disable_opts, 0);
3243
0
}
3244
3245
3246
#ifdef FREE_CFG_T
3247
static void
3248
free_config_system_opts(
3249
  config_tree *ptree
3250
  )
3251
0
{
3252
0
  FREE_ATTR_VAL_FIFO(ptree->enable_opts);
3253
0
  FREE_ATTR_VAL_FIFO(ptree->disable_opts);
3254
0
}
3255
#endif  /* FREE_CFG_T */
3256
3257
3258
static void
3259
config_logconfig(
3260
  config_tree *ptree
3261
  )
3262
0
{
3263
0
  attr_val *  my_lc;
3264
3265
0
  my_lc = HEAD_PFIFO(ptree->logconfig);
3266
0
  for (; my_lc != NULL; my_lc = my_lc->link) {
3267
0
    switch (my_lc->attr) {
3268
3269
0
    case '+':
3270
0
      ntp_syslogmask |= get_logmask(my_lc->value.s);
3271
0
      break;
3272
3273
0
    case '-':
3274
0
      ntp_syslogmask &= ~get_logmask(my_lc->value.s);
3275
0
      break;
3276
3277
0
    case '=':
3278
0
      ntp_syslogmask = get_logmask(my_lc->value.s);
3279
0
      break;
3280
0
    default:
3281
0
      fatal_error("config-logconfig: modifier='%c'", my_lc->attr);
3282
0
    }
3283
0
  }
3284
0
}
3285
3286
3287
#ifdef FREE_CFG_T
3288
static void
3289
free_config_logconfig(
3290
  config_tree *ptree
3291
  )
3292
0
{
3293
0
  FREE_ATTR_VAL_FIFO(ptree->logconfig);
3294
0
}
3295
#endif  /* FREE_CFG_T */
3296
3297
3298
#ifndef SIM
3299
static void
3300
config_phone(
3301
  config_tree *ptree
3302
  )
3303
0
{
3304
0
  size_t    i;
3305
0
  string_node * sn;
3306
3307
0
  i = 0;
3308
0
  sn = HEAD_PFIFO(ptree->phone);
3309
0
  for (; sn != NULL; sn = sn->link) {
3310
    /* need to leave array entry for NULL terminator */
3311
0
    if (i < COUNTOF(sys_phone) - 1) {
3312
0
      sys_phone[i++] = estrdup(sn->s);
3313
0
      sys_phone[i] = NULL;
3314
0
    } else {
3315
0
      msyslog(LOG_INFO,
3316
0
        "phone: Number of phone entries exceeds %zu. Ignoring phone %s...",
3317
0
        (COUNTOF(sys_phone) - 1), sn->s);
3318
0
    }
3319
0
  }
3320
0
}
3321
#endif  /* !SIM */
3322
3323
static void
3324
config_mdnstries(
3325
  config_tree *ptree
3326
  )
3327
0
{
3328
#ifdef HAVE_DNSREGISTRATION
3329
  extern int mdnstries;
3330
  mdnstries = ptree->mdnstries;
3331
#endif  /* HAVE_DNSREGISTRATION */
3332
0
}
3333
3334
#ifdef FREE_CFG_T
3335
static void
3336
free_config_phone(
3337
  config_tree *ptree
3338
  )
3339
0
{
3340
0
  FREE_STRING_FIFO(ptree->phone);
3341
0
}
3342
#endif  /* FREE_CFG_T */
3343
3344
3345
#ifndef SIM
3346
static void
3347
config_setvar(
3348
  config_tree *ptree
3349
  )
3350
0
{
3351
0
  setvar_node *my_node;
3352
0
  size_t  varlen, vallen, octets;
3353
0
  char *  str;
3354
3355
0
  str = NULL;
3356
0
  my_node = HEAD_PFIFO(ptree->setvar);
3357
0
  for (; my_node != NULL; my_node = my_node->link) {
3358
0
    varlen = strlen(my_node->var);
3359
0
    vallen = strlen(my_node->val);
3360
0
    octets = varlen + vallen + 1 + 1;
3361
0
    str = erealloc(str, octets);
3362
0
    snprintf(str, octets, "%s=%s", my_node->var,
3363
0
       my_node->val);
3364
0
    set_sys_var(str, octets, (my_node->isdefault)
3365
0
            ? DEF
3366
0
            : 0);
3367
0
  }
3368
0
  if (str != NULL)
3369
0
    free(str);
3370
0
}
3371
#endif  /* !SIM */
3372
3373
3374
#ifdef FREE_CFG_T
3375
static void
3376
free_config_setvar(
3377
  config_tree *ptree
3378
  )
3379
0
{
3380
0
  FREE_SETVAR_FIFO(ptree->setvar);
3381
0
}
3382
#endif  /* FREE_CFG_T */
3383
3384
3385
#ifndef SIM
3386
static void
3387
config_ttl(
3388
  config_tree *ptree
3389
  )
3390
0
{
3391
0
  size_t i = 0;
3392
0
  int_node *curr_ttl;
3393
3394
  /* [Bug 3465] There is a built-in default for the TTLs. We must
3395
   * overwrite 'sys_ttlmax' if we change that preset, and leave it
3396
   * alone otherwise!
3397
   */
3398
0
  curr_ttl = HEAD_PFIFO(ptree->ttl);
3399
0
  for (; curr_ttl != NULL; curr_ttl = curr_ttl->link) {
3400
0
    if (i < COUNTOF(sys_ttl))
3401
0
      sys_ttl[i++] = (u_char)curr_ttl->i;
3402
0
    else
3403
0
      msyslog(LOG_INFO,
3404
0
        "ttl: Number of TTL entries exceeds %zu. Ignoring TTL %d...",
3405
0
        COUNTOF(sys_ttl), curr_ttl->i);
3406
0
  }
3407
0
  if (0 != i) /* anything written back at all? */
3408
0
    sys_ttlmax = i - 1;
3409
0
}
3410
#endif  /* !SIM */
3411
3412
3413
#ifdef FREE_CFG_T
3414
static void
3415
free_config_ttl(
3416
  config_tree *ptree
3417
  )
3418
0
{
3419
0
  FREE_INT_FIFO(ptree->ttl);
3420
0
}
3421
#endif  /* FREE_CFG_T */
3422
3423
3424
#ifndef SIM
3425
static void
3426
config_trap(
3427
  config_tree *ptree
3428
  )
3429
0
{
3430
0
  addr_opts_node *curr_trap;
3431
0
  attr_val *curr_opt;
3432
0
  sockaddr_u addr_sock;
3433
0
  sockaddr_u peeraddr;
3434
0
  struct interface *localaddr;
3435
0
  struct addrinfo hints;
3436
0
  char port_text[8];
3437
0
  settrap_parms *pstp;
3438
0
  u_short port;
3439
0
  int err_flag;
3440
0
  int rc;
3441
3442
  /* silence warning about addr_sock potentially uninitialized */
3443
0
  AF(&addr_sock) = AF_UNSPEC;
3444
3445
0
  curr_trap = HEAD_PFIFO(ptree->trap);
3446
0
  for (; curr_trap != NULL; curr_trap = curr_trap->link) {
3447
0
    err_flag = 0;
3448
0
    port = 0;
3449
0
    localaddr = NULL;
3450
3451
0
    curr_opt = HEAD_PFIFO(curr_trap->options);
3452
0
    for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3453
0
      if (T_Port == curr_opt->attr) {
3454
0
        if (curr_opt->value.i < 1
3455
0
            || curr_opt->value.i > USHRT_MAX) {
3456
0
          msyslog(LOG_ERR,
3457
0
            "invalid port number "
3458
0
            "%d, trap ignored",
3459
0
            curr_opt->value.i);
3460
0
          err_flag = 1;
3461
0
        }
3462
0
        port = (u_short)curr_opt->value.i;
3463
0
      }
3464
0
      else if (T_Interface == curr_opt->attr) {
3465
        /* Resolve the interface address */
3466
0
        ZERO_SOCK(&addr_sock);
3467
0
        if (getnetnum(curr_opt->value.s,
3468
0
                &addr_sock, 1, t_UNK) != 1) {
3469
0
          err_flag = 1;
3470
0
          break;
3471
0
        }
3472
3473
0
        localaddr = findinterface(&addr_sock);
3474
3475
0
        if (NULL == localaddr) {
3476
0
          msyslog(LOG_ERR,
3477
0
            "can't find interface with address %s",
3478
0
            stoa(&addr_sock));
3479
0
          err_flag = 1;
3480
0
        }
3481
0
      }
3482
0
    }
3483
3484
    /* Now process the trap for the specified interface
3485
     * and port number
3486
     */
3487
0
    if (!err_flag) {
3488
0
      if (!port)
3489
0
        port = TRAPPORT;
3490
0
      ZERO_SOCK(&peeraddr);
3491
0
      rc = getnetnum(curr_trap->addr->address,
3492
0
               &peeraddr, 1, t_UNK);
3493
0
      if (1 != rc) {
3494
#ifndef WORKER
3495
        msyslog(LOG_ERR,
3496
          "trap: unable to use IP address %s.",
3497
          curr_trap->addr->address);
3498
#else /* WORKER follows */
3499
        /*
3500
         * save context and hand it off
3501
         * for name resolution.
3502
         */
3503
0
        ZERO(hints);
3504
0
        hints.ai_protocol = IPPROTO_UDP;
3505
0
        hints.ai_socktype = SOCK_DGRAM;
3506
0
        snprintf(port_text, sizeof(port_text),
3507
0
           "%u", port);
3508
0
        hints.ai_flags = Z_AI_NUMERICSERV;
3509
0
        pstp = emalloc_zero(sizeof(*pstp));
3510
0
        if (localaddr != NULL) {
3511
0
          hints.ai_family = localaddr->family;
3512
0
          pstp->ifaddr_nonnull = 1;
3513
0
          memcpy(&pstp->ifaddr,
3514
0
                 &localaddr->sin,
3515
0
                 sizeof(pstp->ifaddr));
3516
0
        }
3517
0
        rc = getaddrinfo_sometime(
3518
0
          curr_trap->addr->address,
3519
0
          port_text, &hints,
3520
0
          INITIAL_DNS_RETRY,
3521
0
          &trap_name_resolved,
3522
0
          pstp);
3523
0
        if (!rc)
3524
0
          msyslog(LOG_ERR,
3525
0
            "config_trap: getaddrinfo_sometime(%s,%s): %m",
3526
0
            curr_trap->addr->address,
3527
0
            port_text);
3528
0
#endif  /* WORKER */
3529
0
        continue;
3530
0
      }
3531
      /* port is at same location for v4 and v6 */
3532
0
      SET_PORT(&peeraddr, port);
3533
3534
0
      if (NULL == localaddr)
3535
0
        localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3536
0
      else
3537
0
        AF(&peeraddr) = AF(&addr_sock);
3538
3539
0
      if (!ctlsettrap(&peeraddr, localaddr, 0,
3540
0
          NTP_VERSION))
3541
0
        msyslog(LOG_ERR,
3542
0
          "set trap %s -> %s failed.",
3543
0
          latoa(localaddr),
3544
0
          stoa(&peeraddr));
3545
0
    }
3546
0
  }
3547
0
}
3548
3549
3550
/*
3551
 * trap_name_resolved()
3552
 *
3553
 * Callback invoked when config_trap()'s DNS lookup completes.
3554
 */
3555
# ifdef WORKER
3556
static void
3557
trap_name_resolved(
3558
  int     rescode,
3559
  int     gai_errno,
3560
  void *      context,
3561
  const char *    name,
3562
  const char *    service,
3563
  const struct addrinfo * hints,
3564
  const struct addrinfo * res
3565
  )
3566
0
{
3567
0
  settrap_parms *pstp;
3568
0
  struct interface *localaddr;
3569
0
  sockaddr_u peeraddr;
3570
3571
0
  (void)gai_errno;
3572
0
  (void)service;
3573
0
  (void)hints;
3574
0
  pstp = context;
3575
0
  if (rescode) {
3576
0
    msyslog(LOG_ERR,
3577
0
      "giving up resolving trap host %s: %s (%d)",
3578
0
      name, gai_strerror(rescode), rescode);
3579
0
    free(pstp);
3580
0
    return;
3581
0
  }
3582
0
  INSIST(sizeof(peeraddr) >= res->ai_addrlen);
3583
0
  ZERO(peeraddr);
3584
0
  memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
3585
0
  localaddr = NULL;
3586
0
  if (pstp->ifaddr_nonnull)
3587
0
    localaddr = findinterface(&pstp->ifaddr);
3588
0
  if (NULL == localaddr)
3589
0
    localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
3590
0
  if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION))
3591
0
    msyslog(LOG_ERR, "set trap %s -> %s failed.",
3592
0
      latoa(localaddr), stoa(&peeraddr));
3593
0
  free(pstp);
3594
0
}
3595
# endif /* WORKER */
3596
#endif  /* !SIM */
3597
3598
3599
#ifdef FREE_CFG_T
3600
static void
3601
free_config_trap(
3602
  config_tree *ptree
3603
  )
3604
0
{
3605
0
  FREE_ADDR_OPTS_FIFO(ptree->trap);
3606
0
}
3607
#endif  /* FREE_CFG_T */
3608
3609
3610
#ifndef SIM
3611
static void
3612
config_fudge(
3613
  config_tree *ptree
3614
  )
3615
0
{
3616
0
  addr_opts_node *curr_fudge;
3617
0
  attr_val *curr_opt;
3618
0
  sockaddr_u addr_sock;
3619
0
  address_node *addr_node;
3620
0
  struct refclockstat clock_stat;
3621
0
  int err_flag;
3622
3623
0
  curr_fudge = HEAD_PFIFO(ptree->fudge);
3624
0
  for (; curr_fudge != NULL; curr_fudge = curr_fudge->link) {
3625
0
    err_flag = 0;
3626
3627
    /* Get the reference clock address and
3628
     * ensure that it is sane
3629
     */
3630
0
    addr_node = curr_fudge->addr;
3631
0
    ZERO_SOCK(&addr_sock);
3632
0
    if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
3633
0
        != 1) {
3634
0
      err_flag = 1;
3635
0
      msyslog(LOG_ERR,
3636
0
        "unrecognized fudge reference clock address %s, line ignored",
3637
0
        addr_node->address);
3638
0
    } else if (!ISREFCLOCKADR(&addr_sock)) {
3639
0
      err_flag = 1;
3640
0
      msyslog(LOG_ERR,
3641
0
        "inappropriate address %s for the fudge command, line ignored",
3642
0
        stoa(&addr_sock));
3643
0
    }
3644
3645
    /* Parse all the options to the fudge command */
3646
0
    ZERO(clock_stat);
3647
0
    curr_opt = HEAD_PFIFO(curr_fudge->options);
3648
0
    for (; curr_opt != NULL; curr_opt = curr_opt->link) {
3649
0
      switch (curr_opt->attr) {
3650
3651
0
      case T_Time1:
3652
0
        clock_stat.haveflags |= CLK_HAVETIME1;
3653
0
        clock_stat.fudgetime1 = curr_opt->value.d;
3654
0
        break;
3655
3656
0
      case T_Time2:
3657
0
        clock_stat.haveflags |= CLK_HAVETIME2;
3658
0
        clock_stat.fudgetime2 = curr_opt->value.d;
3659
0
        break;
3660
3661
0
      case T_Stratum:
3662
0
        clock_stat.haveflags |= CLK_HAVEVAL1;
3663
0
        clock_stat.fudgeval1 = curr_opt->value.i;
3664
0
        break;
3665
3666
0
      case T_Refid:
3667
0
        clock_stat.haveflags |= CLK_HAVEVAL2;
3668
0
        clock_stat.fudgeval2 = 0;
3669
0
        memcpy(&clock_stat.fudgeval2,
3670
0
               curr_opt->value.s,
3671
0
               min(strlen(curr_opt->value.s), 4));
3672
0
        break;
3673
3674
0
      case T_Flag1:
3675
0
        clock_stat.haveflags |= CLK_HAVEFLAG1;
3676
0
        if (curr_opt->value.i)
3677
0
          clock_stat.flags |= CLK_FLAG1;
3678
0
        else
3679
0
          clock_stat.flags &= ~CLK_FLAG1;
3680
0
        break;
3681
3682
0
      case T_Flag2:
3683
0
        clock_stat.haveflags |= CLK_HAVEFLAG2;
3684
0
        if (curr_opt->value.i)
3685
0
          clock_stat.flags |= CLK_FLAG2;
3686
0
        else
3687
0
          clock_stat.flags &= ~CLK_FLAG2;
3688
0
        break;
3689
3690
0
      case T_Flag3:
3691
0
        clock_stat.haveflags |= CLK_HAVEFLAG3;
3692
0
        if (curr_opt->value.i)
3693
0
          clock_stat.flags |= CLK_FLAG3;
3694
0
        else
3695
0
          clock_stat.flags &= ~CLK_FLAG3;
3696
0
        break;
3697
3698
0
      case T_Flag4:
3699
0
        clock_stat.haveflags |= CLK_HAVEFLAG4;
3700
0
        if (curr_opt->value.i)
3701
0
          clock_stat.flags |= CLK_FLAG4;
3702
0
        else
3703
0
          clock_stat.flags &= ~CLK_FLAG4;
3704
0
        break;
3705
3706
0
      default:
3707
0
        msyslog(LOG_ERR,
3708
0
          "Unexpected fudge flag %s (%d) for %s",
3709
0
          token_name(curr_opt->attr),
3710
0
          curr_opt->attr, addr_node->address);
3711
0
        exit(curr_opt->attr ? curr_opt->attr : 1);
3712
0
      }
3713
0
    }
3714
0
# ifdef REFCLOCK
3715
0
    if (!err_flag)
3716
0
      refclock_control(&addr_sock, &clock_stat, NULL);
3717
0
# endif
3718
0
  }
3719
0
}
3720
#endif  /* !SIM */
3721
3722
3723
#ifdef FREE_CFG_T
3724
static void
3725
free_config_fudge(
3726
  config_tree *ptree
3727
  )
3728
0
{
3729
0
  FREE_ADDR_OPTS_FIFO(ptree->fudge);
3730
0
}
3731
#endif  /* FREE_CFG_T */
3732
3733
3734
static void
3735
config_vars(
3736
  config_tree *ptree
3737
  )
3738
0
{
3739
0
  attr_val *curr_var;
3740
0
  int len;
3741
3742
0
  curr_var = HEAD_PFIFO(ptree->vars);
3743
0
  for (; curr_var != NULL; curr_var = curr_var->link) {
3744
    /* Determine which variable to set and set it */
3745
0
    switch (curr_var->attr) {
3746
3747
0
    case T_Broadcastdelay:
3748
0
      proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
3749
0
      break;
3750
3751
0
    case T_Tick:
3752
0
      loop_config(LOOP_TICK, curr_var->value.d);
3753
0
      break;
3754
3755
0
    case T_Driftfile:
3756
0
      if ('\0' == curr_var->value.s[0]) {
3757
0
        stats_drift_file = 0;
3758
0
        msyslog(LOG_INFO, "config: driftfile disabled");
3759
0
      } else
3760
0
        stats_config(STATS_FREQ_FILE, curr_var->value.s);
3761
0
      break;
3762
3763
0
    case T_Dscp:
3764
      /* DSCP is in the upper 6 bits of the IP TOS/DS field */
3765
0
      qos = curr_var->value.i << 2;
3766
0
      break;
3767
3768
0
    case T_Ident:
3769
0
      sys_ident = curr_var->value.s;
3770
0
      break;
3771
3772
0
    case T_WanderThreshold:   /* FALLTHROUGH */
3773
0
    case T_Nonvolatile:
3774
0
      wander_threshold = curr_var->value.d;
3775
0
      break;
3776
3777
0
    case T_Leapfile:
3778
0
      stats_config(STATS_LEAP_FILE, curr_var->value.s);
3779
0
      break;
3780
3781
#ifdef LEAP_SMEAR
3782
    case T_Leapsmearinterval:
3783
      leap_smear_intv = curr_var->value.i;
3784
      msyslog(LOG_INFO, "config: leap smear interval %i s", leap_smear_intv);
3785
      break;
3786
#endif
3787
3788
0
    case T_Pidfile:
3789
0
      stats_config(STATS_PID_FILE, curr_var->value.s);
3790
0
      break;
3791
3792
0
    case T_Logfile:
3793
0
      if (-1 == change_logfile(curr_var->value.s, TRUE))
3794
0
        msyslog(LOG_ERR,
3795
0
          "Cannot open logfile %s: %m",
3796
0
          curr_var->value.s);
3797
0
      break;
3798
3799
0
    case T_Saveconfigdir:
3800
0
      if (saveconfigdir != NULL)
3801
0
        free(saveconfigdir);
3802
0
      len = strlen(curr_var->value.s);
3803
0
      if (0 == len) {
3804
0
        saveconfigdir = NULL;
3805
0
      } else if (DIR_SEP != curr_var->value.s[len - 1]
3806
#ifdef SYS_WINNT  /* slash is also a dir. sep. on Windows */
3807
           && '/' != curr_var->value.s[len - 1]
3808
#endif
3809
0
         ) {
3810
0
          len++;
3811
0
          saveconfigdir = emalloc(len + 1);
3812
0
          snprintf(saveconfigdir, len + 1,
3813
0
             "%s%c",
3814
0
             curr_var->value.s,
3815
0
             DIR_SEP);
3816
0
      } else {
3817
0
          saveconfigdir = estrdup(
3818
0
              curr_var->value.s);
3819
0
      }
3820
0
      break;
3821
3822
0
    case T_Automax:
3823
#ifdef AUTOKEY
3824
      if (curr_var->value.i > 2 && curr_var->value.i < 32)
3825
        sys_automax = (u_char)curr_var->value.i;
3826
      else
3827
        msyslog(LOG_ERR,
3828
          "'automax' value %d ignored",
3829
          curr_var->value.i);
3830
#endif
3831
0
      break;
3832
3833
0
    default:
3834
0
      msyslog(LOG_ERR,
3835
0
        "config_vars(): unexpected token %d",
3836
0
        curr_var->attr);
3837
0
    }
3838
0
  }
3839
0
}
3840
3841
3842
#ifdef FREE_CFG_T
3843
static void
3844
free_config_vars(
3845
  config_tree *ptree
3846
  )
3847
0
{
3848
0
  FREE_ATTR_VAL_FIFO(ptree->vars);
3849
0
}
3850
#endif  /* FREE_CFG_T */
3851
3852
3853
/* Define a function to check if a resolved address is sane.
3854
 * If yes, return 1, else return 0;
3855
 */
3856
static int
3857
is_sane_resolved_address(
3858
  sockaddr_u *  peeraddr,
3859
  int   hmode
3860
  )
3861
0
{
3862
0
  if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
3863
0
    msyslog(LOG_ERR,
3864
0
      "attempt to configure invalid address %s",
3865
0
      stoa(peeraddr));
3866
0
    return 0;
3867
0
  }
3868
  /*
3869
   * Shouldn't be able to specify multicast
3870
   * address for server/peer!
3871
   * and unicast address for manycastclient!
3872
   */
3873
0
  if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
3874
0
      && IS_MCAST(peeraddr)) {
3875
0
    msyslog(LOG_ERR,
3876
0
      "attempt to configure invalid address %s",
3877
0
      stoa(peeraddr));
3878
0
    return 0;
3879
0
  }
3880
0
  if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
3881
0
    msyslog(LOG_ERR,
3882
0
      "attempt to configure invalid address %s",
3883
0
      stoa(peeraddr));
3884
0
    return 0;
3885
0
  }
3886
3887
0
  if (IS_IPV6(peeraddr) && !ipv6_works)
3888
0
    return 0;
3889
3890
  /* Ok, all tests succeeded, now we can return 1 */
3891
0
  return 1;
3892
0
}
3893
3894
3895
#ifndef SIM
3896
static u_char
3897
get_correct_host_mode(
3898
  int token
3899
  )
3900
0
{
3901
0
  switch (token) {
3902
3903
0
  case T_Server:
3904
0
  case T_Pool:
3905
0
  case T_Manycastclient:
3906
0
    return MODE_CLIENT;
3907
3908
0
  case T_Peer:
3909
0
    return MODE_ACTIVE;
3910
3911
0
  case T_Broadcast:
3912
0
    return MODE_BROADCAST;
3913
3914
0
  default:
3915
0
    return 0;
3916
0
  }
3917
0
}
3918
3919
3920
/*
3921
 * peerflag_bits()  get config_peers() peerflags value from a
3922
 *      peer_node's queue of flag attr_val entries.
3923
 */
3924
static int
3925
peerflag_bits(
3926
  peer_node *pn
3927
  )
3928
0
{
3929
0
  int peerflags;
3930
0
  attr_val *option;
3931
3932
  /* translate peerflags options to bits */
3933
0
  peerflags = 0;
3934
0
  option = HEAD_PFIFO(pn->peerflags);
3935
0
  for (; option != NULL; option = option->link) {
3936
0
    switch (option->value.i) {
3937
3938
0
    default:
3939
0
      fatal_error("peerflag_bits: option-token=%d", option->value.i);
3940
3941
0
    case T_Autokey:
3942
0
      peerflags |= FLAG_SKEY;
3943
0
      break;
3944
3945
0
    case T_Burst:
3946
0
      peerflags |= FLAG_BURST;
3947
0
      break;
3948
3949
0
    case T_Iburst:
3950
0
      peerflags |= FLAG_IBURST;
3951
0
      break;
3952
3953
0
    case T_Noselect:
3954
0
      peerflags |= FLAG_NOSELECT;
3955
0
      break;
3956
3957
0
    case T_Preempt:
3958
0
      peerflags |= FLAG_PREEMPT;
3959
0
      break;
3960
3961
0
    case T_Prefer:
3962
0
      peerflags |= FLAG_PREFER;
3963
0
      break;
3964
3965
0
    case T_True:
3966
0
      peerflags |= FLAG_TRUE;
3967
0
      break;
3968
3969
0
    case T_Xleave:
3970
0
      peerflags |= FLAG_XLEAVE;
3971
0
      break;
3972
0
    }
3973
0
  }
3974
3975
0
  return peerflags;
3976
0
}
3977
3978
3979
static void
3980
config_peers(
3981
  config_tree *ptree
3982
  )
3983
0
{
3984
0
  sockaddr_u    peeraddr;
3985
0
  struct addrinfo   hints;
3986
0
  peer_node *   curr_peer;
3987
0
  peer_resolved_ctx * ctx;
3988
0
  u_char      hmode;
3989
3990
  /* add servers named on the command line with iburst implied */
3991
0
  for (;
3992
0
       cmdline_server_count > 0;
3993
0
       cmdline_server_count--, cmdline_servers++) {
3994
3995
0
    ZERO_SOCK(&peeraddr);
3996
    /*
3997
     * If we have a numeric address, we can safely
3998
     * proceed in the mainline with it.  Otherwise, hand
3999
     * the hostname off to the blocking child.
4000
     *
4001
     * Note that if we're told to add the peer here, we
4002
     * do that regardless of ippeerlimit.
4003
     */
4004
0
    if (is_ip_address(*cmdline_servers, AF_UNSPEC,
4005
0
          &peeraddr)) {
4006
4007
0
      SET_PORT(&peeraddr, NTP_PORT);
4008
0
      if (is_sane_resolved_address(&peeraddr,
4009
0
                 T_Server))
4010
0
        peer_config(
4011
0
          &peeraddr,
4012
0
          NULL,
4013
0
          NULL,
4014
0
          -1,
4015
0
          MODE_CLIENT,
4016
0
          NTP_VERSION,
4017
0
          0,
4018
0
          0,
4019
0
          FLAG_IBURST,
4020
0
          0,
4021
0
          0,
4022
0
          NULL);
4023
0
    } else {
4024
      /* we have a hostname to resolve */
4025
0
# ifdef WORKER
4026
0
      ctx = emalloc_zero(sizeof(*ctx));
4027
0
      ctx->family = AF_UNSPEC;
4028
0
      ctx->host_mode = T_Server;
4029
0
      ctx->hmode = MODE_CLIENT;
4030
0
      ctx->version = NTP_VERSION;
4031
0
      ctx->flags = FLAG_IBURST;
4032
4033
0
      ZERO(hints);
4034
0
      hints.ai_family = (u_short)ctx->family;
4035
0
      hints.ai_socktype = SOCK_DGRAM;
4036
0
      hints.ai_protocol = IPPROTO_UDP;
4037
4038
0
      getaddrinfo_sometime_ex(*cmdline_servers,
4039
0
               "ntp", &hints,
4040
0
               INITIAL_DNS_RETRY,
4041
0
               &peer_name_resolved,
4042
0
               (void *)ctx, DNSFLAGS);
4043
# else  /* !WORKER follows */
4044
      msyslog(LOG_ERR,
4045
        "hostname %s can not be used, please use IP address instead.",
4046
        curr_peer->addr->address);
4047
# endif
4048
0
    }
4049
0
  }
4050
4051
  /* add associations from the configuration file */
4052
0
  curr_peer = HEAD_PFIFO(ptree->peers);
4053
0
  for (; curr_peer != NULL; curr_peer = curr_peer->link) {
4054
0
    ZERO_SOCK(&peeraddr);
4055
    /* Find the correct host-mode */
4056
0
    hmode = get_correct_host_mode(curr_peer->host_mode);
4057
0
    INSIST(hmode != 0);
4058
4059
0
    if (T_Pool == curr_peer->host_mode) {
4060
0
      AF(&peeraddr) = curr_peer->addr->type;
4061
0
      peer_config(
4062
0
        &peeraddr,
4063
0
        curr_peer->addr->address,
4064
0
        NULL,
4065
0
        -1,
4066
0
        hmode,
4067
0
        curr_peer->peerversion,
4068
0
        curr_peer->minpoll,
4069
0
        curr_peer->maxpoll,
4070
0
        peerflag_bits(curr_peer),
4071
0
        curr_peer->ttl,
4072
0
        curr_peer->peerkey,
4073
0
        curr_peer->group);
4074
    /*
4075
     * If we have a numeric address, we can safely
4076
     * proceed in the mainline with it.  Otherwise, hand
4077
     * the hostname off to the blocking child.
4078
     */
4079
0
    } else if (is_ip_address(curr_peer->addr->address,
4080
0
          curr_peer->addr->type, &peeraddr)) {
4081
4082
0
      SET_PORT(&peeraddr, NTP_PORT);
4083
0
      if (is_sane_resolved_address(&peeraddr,
4084
0
          curr_peer->host_mode))
4085
0
        peer_config(
4086
0
          &peeraddr,
4087
0
          NULL,
4088
0
          NULL,
4089
0
          -1,
4090
0
          hmode,
4091
0
          curr_peer->peerversion,
4092
0
          curr_peer->minpoll,
4093
0
          curr_peer->maxpoll,
4094
0
          peerflag_bits(curr_peer),
4095
0
          curr_peer->ttl,
4096
0
          curr_peer->peerkey,
4097
0
          curr_peer->group);
4098
0
    } else {
4099
      /* we have a hostname to resolve */
4100
0
# ifdef WORKER
4101
0
      ctx = emalloc_zero(sizeof(*ctx));
4102
0
      ctx->family = curr_peer->addr->type;
4103
0
      ctx->host_mode = curr_peer->host_mode;
4104
0
      ctx->hmode = hmode;
4105
0
      ctx->version = curr_peer->peerversion;
4106
0
      ctx->minpoll = curr_peer->minpoll;
4107
0
      ctx->maxpoll = curr_peer->maxpoll;
4108
0
      ctx->flags = peerflag_bits(curr_peer);
4109
0
      ctx->ttl = curr_peer->ttl;
4110
0
      ctx->keyid = curr_peer->peerkey;
4111
0
      ctx->group = curr_peer->group;
4112
4113
0
      ZERO(hints);
4114
0
      hints.ai_family = ctx->family;
4115
0
      hints.ai_socktype = SOCK_DGRAM;
4116
0
      hints.ai_protocol = IPPROTO_UDP;
4117
4118
0
      getaddrinfo_sometime_ex(curr_peer->addr->address,
4119
0
               "ntp", &hints,
4120
0
               INITIAL_DNS_RETRY,
4121
0
               &peer_name_resolved, ctx,
4122
0
               DNSFLAGS);
4123
# else  /* !WORKER follows */
4124
      msyslog(LOG_ERR,
4125
        "hostname %s can not be used, please use IP address instead.",
4126
        curr_peer->addr->address);
4127
# endif
4128
0
    }
4129
0
  }
4130
0
}
4131
#endif  /* !SIM */
4132
4133
/*
4134
 * peer_name_resolved()
4135
 *
4136
 * Callback invoked when config_peers()'s DNS lookup completes.
4137
 */
4138
#ifdef WORKER
4139
static void
4140
peer_name_resolved(
4141
  int     rescode,
4142
  int     gai_errno,
4143
  void *      context,
4144
  const char *    name,
4145
  const char *    service,
4146
  const struct addrinfo * hints,
4147
  const struct addrinfo * res
4148
  )
4149
0
{
4150
0
  sockaddr_u    peeraddr;
4151
0
  peer_resolved_ctx * ctx;
4152
0
  u_short     af;
4153
0
  const char *    fam_spec;
4154
4155
0
  (void)gai_errno;
4156
0
  (void)service;
4157
0
  (void)hints;
4158
0
  ctx = context;
4159
4160
0
  DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
4161
4162
0
  if (rescode) {
4163
0
    free(ctx);
4164
0
    msyslog(LOG_ERR,
4165
0
      "giving up resolving host %s: %s (%d)",
4166
0
      name, gai_strerror(rescode), rescode);
4167
0
    return;
4168
0
  }
4169
4170
  /* Loop to configure a single association */
4171
0
  for (; res != NULL; res = res->ai_next) {
4172
0
    memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4173
0
    if (is_sane_resolved_address(&peeraddr,
4174
0
               ctx->host_mode)) {
4175
0
      NLOG(NLOG_SYSINFO) {
4176
0
        af = ctx->family;
4177
0
        fam_spec = (AF_INET6 == af)
4178
0
                 ? "(AAAA) "
4179
0
                 : (AF_INET == af)
4180
0
                 ? "(A) "
4181
0
                 : "";
4182
0
        msyslog(LOG_INFO, "DNS %s %s-> %s",
4183
0
          name, fam_spec,
4184
0
          stoa(&peeraddr));
4185
0
      }
4186
0
      peer_config(
4187
0
        &peeraddr,
4188
0
        NULL,
4189
0
        NULL,
4190
0
        -1,
4191
0
        ctx->hmode,
4192
0
        ctx->version,
4193
0
        ctx->minpoll,
4194
0
        ctx->maxpoll,
4195
0
        ctx->flags,
4196
0
        ctx->ttl,
4197
0
        ctx->keyid,
4198
0
        ctx->group);
4199
0
      break;
4200
0
    }
4201
0
  }
4202
0
  free(ctx);
4203
0
}
4204
#endif  /* WORKER */
4205
4206
4207
#ifdef FREE_CFG_T
4208
static void
4209
free_config_peers(
4210
  config_tree *ptree
4211
  )
4212
0
{
4213
0
  peer_node *curr_peer;
4214
4215
0
  if (ptree->peers != NULL) {
4216
0
    for (;;) {
4217
0
      UNLINK_FIFO(curr_peer, *ptree->peers, link);
4218
0
      if (NULL == curr_peer)
4219
0
        break;
4220
0
      destroy_address_node(curr_peer->addr);
4221
0
      destroy_attr_val_fifo(curr_peer->peerflags);
4222
0
      free(curr_peer);
4223
0
    }
4224
0
    free(ptree->peers);
4225
0
    ptree->peers = NULL;
4226
0
  }
4227
0
}
4228
#endif  /* FREE_CFG_T */
4229
4230
4231
#ifndef SIM
4232
static void
4233
config_unpeers(
4234
  config_tree *ptree
4235
  )
4236
0
{
4237
0
  sockaddr_u    peeraddr;
4238
0
  struct addrinfo   hints;
4239
0
  unpeer_node *   curr_unpeer;
4240
0
  struct peer *   p;
4241
0
  const char *    name;
4242
0
  int     rc;
4243
4244
0
  curr_unpeer = HEAD_PFIFO(ptree->unpeers);
4245
0
  for (; curr_unpeer != NULL; curr_unpeer = curr_unpeer->link) {
4246
    /*
4247
     * If we have no address attached, assume we have to
4248
     * unpeer by AssocID.
4249
     */
4250
0
    if (!curr_unpeer->addr) {
4251
0
      p = findpeerbyassoc(curr_unpeer->assocID);
4252
0
      if (p != NULL) {
4253
0
        msyslog(LOG_NOTICE, "unpeered %s",
4254
0
          stoa(&p->srcadr));
4255
0
        peer_clear(p, "GONE");
4256
0
        unpeer(p);
4257
0
      }
4258
0
      continue;
4259
0
    }
4260
4261
0
    ZERO(peeraddr);
4262
0
    AF(&peeraddr) = curr_unpeer->addr->type;
4263
0
    name = curr_unpeer->addr->address;
4264
0
    rc = getnetnum(name, &peeraddr, 0, t_UNK);
4265
    /* Do we have a numeric address? */
4266
0
    if (rc > 0) {
4267
0
      DPRINTF(1, ("unpeer: searching for %s\n",
4268
0
            stoa(&peeraddr)));
4269
0
      p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4270
0
      if (p != NULL) {
4271
0
        msyslog(LOG_NOTICE, "unpeered %s",
4272
0
          stoa(&peeraddr));
4273
0
        peer_clear(p, "GONE");
4274
0
        unpeer(p);
4275
0
      }
4276
0
      continue;
4277
0
    }
4278
    /*
4279
     * It's not a numeric IP address, it's a hostname.
4280
     * Check for associations with a matching hostname.
4281
     */
4282
0
    for (p = peer_list; p != NULL; p = p->p_link)
4283
0
      if (p->hostname != NULL)
4284
0
        if (!strcasecmp(p->hostname, name))
4285
0
          break;
4286
0
    if (p != NULL) {
4287
0
      msyslog(LOG_NOTICE, "unpeered %s", name);
4288
0
      peer_clear(p, "GONE");
4289
0
      unpeer(p);
4290
0
    }
4291
    /* Resolve the hostname to address(es). */
4292
0
# ifdef WORKER
4293
0
    ZERO(hints);
4294
0
    hints.ai_family = curr_unpeer->addr->type;
4295
0
    hints.ai_socktype = SOCK_DGRAM;
4296
0
    hints.ai_protocol = IPPROTO_UDP;
4297
0
    getaddrinfo_sometime(name, "ntp", &hints,
4298
0
             INITIAL_DNS_RETRY,
4299
0
             &unpeer_name_resolved, NULL);
4300
# else  /* !WORKER follows */
4301
    msyslog(LOG_ERR,
4302
      "hostname %s can not be used, please use IP address instead.",
4303
      name);
4304
# endif
4305
0
  }
4306
0
}
4307
#endif  /* !SIM */
4308
4309
4310
/*
4311
 * unpeer_name_resolved()
4312
 *
4313
 * Callback invoked when config_unpeers()'s DNS lookup completes.
4314
 */
4315
#ifdef WORKER
4316
static void
4317
unpeer_name_resolved(
4318
  int     rescode,
4319
  int     gai_errno,
4320
  void *      context,
4321
  const char *    name,
4322
  const char *    service,
4323
  const struct addrinfo * hints,
4324
  const struct addrinfo * res
4325
  )
4326
0
{
4327
0
  sockaddr_u  peeraddr;
4328
0
  struct peer * peer;
4329
0
  u_short   af;
4330
0
  const char *  fam_spec;
4331
4332
0
  (void)context;
4333
0
  (void)hints;
4334
0
  DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
4335
4336
0
  if (rescode) {
4337
0
    msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)",
4338
0
      name, gai_strerror(rescode), rescode);
4339
0
    return;
4340
0
  }
4341
  /*
4342
   * Loop through the addresses found
4343
   */
4344
0
  for (; res != NULL; res = res->ai_next) {
4345
0
    INSIST(res->ai_addrlen <= sizeof(peeraddr));
4346
0
    memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
4347
0
    DPRINTF(1, ("unpeer: searching for peer %s\n",
4348
0
          stoa(&peeraddr)));
4349
0
    peer = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL);
4350
0
    if (peer != NULL) {
4351
0
      af = AF(&peeraddr);
4352
0
      fam_spec = (AF_INET6 == af)
4353
0
               ? "(AAAA) "
4354
0
               : (AF_INET == af)
4355
0
               ? "(A) "
4356
0
               : "";
4357
0
      msyslog(LOG_NOTICE, "unpeered %s %s-> %s", name,
4358
0
        fam_spec, stoa(&peeraddr));
4359
0
      peer_clear(peer, "GONE");
4360
0
      unpeer(peer);
4361
0
    }
4362
0
  }
4363
0
}
4364
#endif  /* WORKER */
4365
4366
4367
#ifdef FREE_CFG_T
4368
static void
4369
free_config_unpeers(
4370
  config_tree *ptree
4371
  )
4372
0
{
4373
0
  unpeer_node *curr_unpeer;
4374
4375
0
  if (ptree->unpeers != NULL) {
4376
0
    for (;;) {
4377
0
      UNLINK_FIFO(curr_unpeer, *ptree->unpeers, link);
4378
0
      if (NULL == curr_unpeer)
4379
0
        break;
4380
0
      destroy_address_node(curr_unpeer->addr);
4381
0
      free(curr_unpeer);
4382
0
    }
4383
0
    free(ptree->unpeers);
4384
0
  }
4385
0
}
4386
#endif  /* FREE_CFG_T */
4387
4388
4389
#ifndef SIM
4390
static void
4391
config_reset_counters(
4392
  config_tree *ptree
4393
  )
4394
0
{
4395
0
  int_node *counter_set;
4396
4397
0
  for (counter_set = HEAD_PFIFO(ptree->reset_counters);
4398
0
       counter_set != NULL;
4399
0
       counter_set = counter_set->link) {
4400
0
    switch (counter_set->i) {
4401
0
    default:
4402
0
      DPRINTF(1, ("config_reset_counters %s (%d) invalid\n",
4403
0
            keyword(counter_set->i), counter_set->i));
4404
0
      break;
4405
4406
0
    case T_Allpeers:
4407
0
      peer_all_reset();
4408
0
      break;
4409
4410
0
    case T_Auth:
4411
0
      reset_auth_stats();
4412
0
      break;
4413
4414
0
    case T_Ctl:
4415
0
      ctl_clr_stats();
4416
0
      break;
4417
4418
0
    case T_Io:
4419
0
      io_clr_stats();
4420
0
      break;
4421
4422
0
    case T_Mem:
4423
0
      peer_clr_stats();
4424
0
      break;
4425
4426
0
    case T_Sys:
4427
0
      proto_clr_stats();
4428
0
      break;
4429
4430
0
    case T_Timer:
4431
0
      timer_clr_stats();
4432
0
      break;
4433
0
    }
4434
0
  }
4435
0
}
4436
#endif  /* !SIM */
4437
4438
4439
#ifdef FREE_CFG_T
4440
static void
4441
free_config_reset_counters(
4442
  config_tree *ptree
4443
  )
4444
0
{
4445
0
  FREE_INT_FIFO(ptree->reset_counters);
4446
0
}
4447
#endif  /* FREE_CFG_T */
4448
4449
4450
#ifdef SIM
4451
static void
4452
config_sim(
4453
  config_tree *ptree
4454
  )
4455
{
4456
  int i;
4457
  server_info *serv_info;
4458
  attr_val *init_stmt;
4459
  sim_node *sim_n;
4460
4461
  /* Check if a simulate block was found in the configuration code.
4462
   * If not, return an error and exit
4463
   */
4464
  sim_n = HEAD_PFIFO(ptree->sim_details);
4465
  if (NULL == sim_n) {
4466
    fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
4467
    fprintf(stderr, "\tCheck your configuration file.\n");
4468
    exit(1);
4469
  }
4470
4471
  /* Process the initialization statements
4472
   * -------------------------------------
4473
   */
4474
  init_stmt = HEAD_PFIFO(sim_n->init_opts);
4475
  for (; init_stmt != NULL; init_stmt = init_stmt->link) {
4476
    switch(init_stmt->attr) {
4477
4478
    case T_Beep_Delay:
4479
      simulation.beep_delay = init_stmt->value.d;
4480
      break;
4481
4482
    case T_Sim_Duration:
4483
      simulation.end_time = init_stmt->value.d;
4484
      break;
4485
4486
    default:
4487
      fprintf(stderr,
4488
        "Unknown simulator init token %d\n",
4489
        init_stmt->attr);
4490
      exit(1);
4491
    }
4492
  }
4493
4494
  /* Process the server list
4495
   * -----------------------
4496
   */
4497
  simulation.num_of_servers = 0;
4498
  serv_info = HEAD_PFIFO(sim_n->servers);
4499
  for (; serv_info != NULL; serv_info = serv_info->link)
4500
    simulation.num_of_servers++;
4501
  simulation.servers = eallocarray(simulation.num_of_servers,
4502
             sizeof(simulation.servers[0]));
4503
4504
  i = 0;
4505
  serv_info = HEAD_PFIFO(sim_n->servers);
4506
  for (; serv_info != NULL; serv_info = serv_info->link) {
4507
    if (NULL == serv_info) {
4508
      fprintf(stderr, "Simulator server list is corrupt\n");
4509
      exit(1);
4510
    } else {
4511
      simulation.servers[i] = *serv_info;
4512
      simulation.servers[i].link = NULL;
4513
      i++;
4514
    }
4515
  }
4516
4517
  printf("Creating server associations\n");
4518
  create_server_associations();
4519
  fprintf(stderr,"\tServer associations successfully created!!\n");
4520
}
4521
4522
4523
#ifdef FREE_CFG_T
4524
static void
4525
free_config_sim(
4526
  config_tree *ptree
4527
  )
4528
{
4529
  sim_node *sim_n;
4530
  server_info *serv_n;
4531
  script_info *script_n;
4532
4533
  if (NULL == ptree->sim_details)
4534
    return;
4535
  sim_n = HEAD_PFIFO(ptree->sim_details);
4536
  free(ptree->sim_details);
4537
  ptree->sim_details = NULL;
4538
  if (NULL == sim_n)
4539
    return;
4540
4541
  FREE_ATTR_VAL_FIFO(sim_n->init_opts);
4542
  for (;;) {
4543
    UNLINK_FIFO(serv_n, *sim_n->servers, link);
4544
    if (NULL == serv_n)
4545
      break;
4546
    free(serv_n->curr_script);
4547
    if (serv_n->script != NULL) {
4548
      for (;;) {
4549
        UNLINK_FIFO(script_n, *serv_n->script,
4550
              link);
4551
        if (script_n == NULL)
4552
          break;
4553
        free(script_n);
4554
      }
4555
      free(serv_n->script);
4556
    }
4557
    free(serv_n);
4558
  }
4559
  free(sim_n);
4560
}
4561
#endif  /* FREE_CFG_T */
4562
#endif  /* SIM */
4563
4564
4565
/* Define two different config functions. One for the daemon and the other for
4566
 * the simulator. The simulator ignores a lot of the standard ntpd configuration
4567
 * options
4568
 */
4569
#ifndef SIM
4570
static void
4571
config_ntpd(
4572
  config_tree *ptree,
4573
  int/*BOOL*/ input_from_files
4574
  )
4575
0
{
4576
  /* [Bug 3435] check and esure clock sanity if configured from
4577
   * file and clock sanity parameters (-> basedate) are given. Do
4578
   * this ASAP, so we don't disturb the closed loop controller.
4579
   */
4580
0
  if (input_from_files) {
4581
0
    if (config_tos_clock(ptree))
4582
0
      clamp_systime();
4583
0
  }
4584
4585
0
  config_nic_rules(ptree, input_from_files);
4586
0
  config_monitor(ptree);
4587
0
  config_auth(ptree);
4588
0
  config_tos(ptree);
4589
0
  config_access(ptree);
4590
0
  config_tinker(ptree);
4591
0
  config_rlimit(ptree);
4592
0
  config_system_opts(ptree);
4593
0
  config_logconfig(ptree);
4594
0
  config_phone(ptree);
4595
0
  config_mdnstries(ptree);
4596
0
  config_setvar(ptree);
4597
0
  config_ttl(ptree);
4598
0
  config_vars(ptree);
4599
4600
0
  io_open_sockets();  /* [bug 2837] dep. on config_vars() */
4601
4602
0
  config_trap(ptree); /* [bug 2923] dep. on io_open_sockets() */
4603
0
  config_other_modes(ptree);
4604
0
  config_peers(ptree);
4605
0
  config_unpeers(ptree);
4606
0
  config_fudge(ptree);
4607
0
  config_reset_counters(ptree);
4608
4609
0
#ifdef DEBUG
4610
0
  if (debug > 1) {
4611
0
    dump_restricts();
4612
0
  }
4613
0
#endif
4614
4615
#ifdef TEST_BLOCKING_WORKER
4616
  {
4617
    struct addrinfo hints;
4618
4619
    ZERO(hints);
4620
    hints.ai_socktype = SOCK_STREAM;
4621
    hints.ai_protocol = IPPROTO_TCP;
4622
    getaddrinfo_sometime("www.cnn.com", "ntp", &hints,
4623
             INITIAL_DNS_RETRY,
4624
             gai_test_callback, (void *)1);
4625
    hints.ai_family = AF_INET6;
4626
    getaddrinfo_sometime("ipv6.google.com", "ntp", &hints,
4627
             INITIAL_DNS_RETRY,
4628
             gai_test_callback, (void *)0x600);
4629
  }
4630
#endif
4631
0
}
4632
#endif  /* !SIM */
4633
4634
4635
#ifdef SIM
4636
static void
4637
config_ntpdsim(
4638
  config_tree *ptree
4639
  )
4640
{
4641
  printf("Configuring Simulator...\n");
4642
  printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
4643
4644
  config_tos(ptree);
4645
  config_monitor(ptree);
4646
  config_tinker(ptree);
4647
  if (0)
4648
    config_rlimit(ptree); /* not needed for the simulator */
4649
  config_system_opts(ptree);
4650
  config_logconfig(ptree);
4651
  config_vars(ptree);
4652
  config_sim(ptree);
4653
}
4654
#endif /* SIM */
4655
4656
4657
/*
4658
 * config_remotely() - implements ntpd side of ntpq :config
4659
 */
4660
void
4661
config_remotely(
4662
  sockaddr_u *  remote_addr
4663
  )
4664
0
{
4665
0
  char origin[128];
4666
4667
0
  snprintf(origin, sizeof(origin), "remote config from %s",
4668
0
     stoa(remote_addr));
4669
0
  lex_init_stack(origin, NULL); /* no checking needed... */
4670
0
  init_syntax_tree(&cfgt);
4671
0
  yyparse();
4672
0
  lex_drop_stack();
4673
4674
0
  cfgt.source.attr = CONF_SOURCE_NTPQ;
4675
0
  cfgt.timestamp = time(NULL);
4676
0
  cfgt.source.value.s = estrdup(stoa(remote_addr));
4677
4678
0
  DPRINTF(1, ("Finished Parsing!!\n"));
4679
4680
0
  save_and_apply_config_tree(FALSE);
4681
0
}
4682
4683
4684
/*
4685
 * getconfig() - process startup configuration file e.g /etc/ntp.conf
4686
 */
4687
void
4688
getconfig(
4689
  int argc,
4690
  char ** argv
4691
  )
4692
0
{
4693
0
  char  line[256];
4694
4695
0
#ifdef DEBUG
4696
0
  atexit(free_all_config_trees);
4697
0
#endif
4698
0
#ifndef SYS_WINNT
4699
0
  config_file = CONFIG_FILE;
4700
#else
4701
  temp = CONFIG_FILE;
4702
  if (!ExpandEnvironmentStringsA(temp, config_file_storage,
4703
               sizeof(config_file_storage))) {
4704
    msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m");
4705
    exit(1);
4706
  }
4707
  config_file = config_file_storage;
4708
4709
  temp = ALT_CONFIG_FILE;
4710
  if (!ExpandEnvironmentStringsA(temp, alt_config_file_storage,
4711
               sizeof(alt_config_file_storage))) {
4712
    msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m");
4713
    exit(1);
4714
  }
4715
  alt_config_file = alt_config_file_storage;
4716
#endif /* SYS_WINNT */
4717
4718
  /*
4719
   * install a non default variable with this daemon version
4720
   */
4721
0
  snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
4722
0
  set_sys_var(line, strlen(line) + 1, RO);
4723
4724
  /*
4725
   * Set up for the first time step to install a variable showing
4726
   * which syscall is being used to step.
4727
   */
4728
0
  set_tod_using = &ntpd_set_tod_using;
4729
4730
0
  getCmdOpts(argc, argv);
4731
0
  init_syntax_tree(&cfgt);
4732
0
  if (
4733
0
    !lex_init_stack(FindConfig(config_file), "r")
4734
#ifdef HAVE_NETINFO
4735
    /* If there is no config_file, try NetInfo. */
4736
    && check_netinfo && !(config_netinfo = get_netinfo_config())
4737
#endif /* HAVE_NETINFO */
4738
0
    ) {
4739
0
    msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(config_file));
4740
0
#ifndef SYS_WINNT
4741
0
    io_open_sockets();
4742
4743
0
    return;
4744
#else
4745
    /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
4746
4747
    if (!lex_init_stack(FindConfig(alt_config_file), "r"))  {
4748
      /*
4749
       * Broadcast clients can sometimes run without
4750
       * a configuration file.
4751
       */
4752
      msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", FindConfig(alt_config_file));
4753
      io_open_sockets();
4754
4755
      return;
4756
    }
4757
    cfgt.source.value.s = estrdup(alt_config_file);
4758
#endif  /* SYS_WINNT */
4759
0
  } else
4760
0
    cfgt.source.value.s = estrdup(config_file);
4761
4762
4763
  /*** BULK OF THE PARSER ***/
4764
0
#ifdef DEBUG
4765
0
  yydebug = !!(debug >= 5);
4766
0
#endif
4767
0
  yyparse();
4768
0
  lex_drop_stack();
4769
4770
0
  DPRINTF(1, ("Finished Parsing!!\n"));
4771
4772
0
  cfgt.source.attr = CONF_SOURCE_FILE;
4773
0
  cfgt.timestamp = time(NULL);
4774
4775
0
  save_and_apply_config_tree(TRUE);
4776
4777
#ifdef HAVE_NETINFO
4778
  if (config_netinfo)
4779
    free_netinfo_config(config_netinfo);
4780
#endif /* HAVE_NETINFO */
4781
0
}
4782
4783
4784
void
4785
save_and_apply_config_tree(int/*BOOL*/ input_from_file)
4786
0
{
4787
0
  config_tree *ptree;
4788
#ifndef SAVECONFIG
4789
  config_tree *punlinked;
4790
#endif
4791
4792
  /*
4793
   * Keep all the configuration trees applied since startup in
4794
   * a list that can be used to dump the configuration back to
4795
   * a text file.
4796
   */
4797
0
  ptree = emalloc(sizeof(*ptree));
4798
0
  memcpy(ptree, &cfgt, sizeof(*ptree));
4799
0
  ZERO(cfgt);
4800
4801
0
  LINK_TAIL_SLIST(cfg_tree_history, ptree, link, config_tree);
4802
4803
0
#ifdef SAVECONFIG
4804
0
  if (HAVE_OPT( SAVECONFIGQUIT )) {
4805
0
    FILE *dumpfile;
4806
0
    int err;
4807
0
    int dumpfailed;
4808
4809
0
    dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
4810
0
    if (NULL == dumpfile) {
4811
0
      err = errno;
4812
0
      mfprintf(stderr,
4813
0
         "can not create save file %s, error %d %m\n",
4814
0
         OPT_ARG(SAVECONFIGQUIT), err);
4815
0
      exit(err);
4816
0
    }
4817
4818
0
    dumpfailed = dump_all_config_trees(dumpfile, 0);
4819
0
    if (dumpfailed)
4820
0
      fprintf(stderr,
4821
0
        "--saveconfigquit %s error %d\n",
4822
0
        OPT_ARG( SAVECONFIGQUIT ),
4823
0
        dumpfailed);
4824
0
    else
4825
0
      fprintf(stderr,
4826
0
        "configuration saved to %s\n",
4827
0
        OPT_ARG( SAVECONFIGQUIT ));
4828
4829
0
    exit(dumpfailed);
4830
0
  }
4831
0
#endif  /* SAVECONFIG */
4832
4833
  /* The actual configuration done depends on whether we are configuring the
4834
   * simulator or the daemon. Perform a check and call the appropriate
4835
   * function as needed.
4836
   */
4837
4838
0
#ifndef SIM
4839
0
  config_ntpd(ptree, input_from_file);
4840
#else
4841
  config_ntpdsim(ptree);
4842
#endif
4843
4844
  /*
4845
   * With configure --disable-saveconfig, there's no use keeping
4846
   * the config tree around after application, so free it.
4847
   */
4848
#ifndef SAVECONFIG
4849
  UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
4850
         config_tree);
4851
  INSIST(punlinked == ptree);
4852
  free_config_tree(ptree);
4853
#endif
4854
0
}
4855
4856
/* Hack to disambiguate 'server' statements for refclocks and network peers.
4857
 * Please note the qualification 'hack'. It's just that.
4858
 */
4859
static int/*BOOL*/
4860
is_refclk_addr(
4861
  const address_node * addr
4862
  )
4863
0
{
4864
0
  return addr && addr->address && !strncmp(addr->address, "127.127.", 8);
4865
0
}
4866
4867
static void
4868
ntpd_set_tod_using(
4869
  const char *which
4870
  )
4871
0
{
4872
0
  char line[128];
4873
4874
0
  snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
4875
0
  set_sys_var(line, strlen(line) + 1, RO);
4876
0
}
4877
4878
4879
static char *
4880
normal_dtoa(
4881
  double d
4882
  )
4883
0
{
4884
0
  char *  buf;
4885
0
  char *  pch_e;
4886
0
  char *  pch_nz;
4887
4888
0
  LIB_GETBUF(buf);
4889
0
  snprintf(buf, LIB_BUFLENGTH, "%g", d);
4890
4891
  /* use lowercase 'e', strip any leading zeroes in exponent */
4892
0
  pch_e = strchr(buf, 'e');
4893
0
  if (NULL == pch_e) {
4894
0
    pch_e = strchr(buf, 'E');
4895
0
    if (NULL == pch_e)
4896
0
      return buf;
4897
0
    *pch_e = 'e';
4898
0
  }
4899
0
  pch_e++;
4900
0
  if ('-' == *pch_e)
4901
0
    pch_e++;
4902
0
  pch_nz = pch_e;
4903
0
  while ('0' == *pch_nz)
4904
0
    pch_nz++;
4905
0
  if (pch_nz == pch_e)
4906
0
    return buf;
4907
0
  strlcpy(pch_e, pch_nz, LIB_BUFLENGTH - (pch_e - buf));
4908
4909
0
  return buf;
4910
0
}
4911
4912
4913
/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
4914
 * --------------------------------------------
4915
 */
4916
4917
4918
/*
4919
 * get_pfxmatch - find value for prefixmatch
4920
 * and update char * accordingly
4921
 */
4922
static u_int32
4923
get_pfxmatch(
4924
  const char ** pstr,
4925
  struct masks *  m
4926
  )
4927
0
{
4928
0
  while (m->name != NULL) {
4929
0
    if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
4930
0
      *pstr += strlen(m->name);
4931
0
      return m->mask;
4932
0
    } else {
4933
0
      m++;
4934
0
    }
4935
0
  }
4936
0
  return 0;
4937
0
}
4938
4939
/*
4940
 * get_match - find logmask value
4941
 */
4942
static u_int32
4943
get_match(
4944
  const char *  str,
4945
  struct masks *  m
4946
  )
4947
0
{
4948
0
  while (m->name != NULL) {
4949
0
    if (strcmp(str, m->name) == 0)
4950
0
      return m->mask;
4951
0
    else
4952
0
      m++;
4953
0
  }
4954
0
  return 0;
4955
0
}
4956
4957
/*
4958
 * get_logmask - build bitmask for ntp_syslogmask
4959
 */
4960
static u_int32
4961
get_logmask(
4962
  const char *  str
4963
  )
4964
0
{
4965
0
  const char *  t;
4966
0
  u_int32   offset;
4967
0
  u_int32   mask;
4968
4969
0
  mask = get_match(str, logcfg_noclass_items);
4970
0
  if (mask != 0)
4971
0
    return mask;
4972
4973
0
  t = str;
4974
0
  offset = get_pfxmatch(&t, logcfg_class);
4975
0
  mask   = get_match(t, logcfg_class_items);
4976
4977
0
  if (mask)
4978
0
    return mask << offset;
4979
0
  else
4980
0
    msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
4981
0
      str);
4982
4983
0
  return 0;
4984
0
}
4985
4986
4987
#ifdef HAVE_NETINFO
4988
4989
/*
4990
 * get_netinfo_config - find the nearest NetInfo domain with an ntp
4991
 * configuration and initialize the configuration state.
4992
 */
4993
static struct netinfo_config_state *
4994
get_netinfo_config(void)
4995
{
4996
  ni_status status;
4997
  void *domain;
4998
  ni_id config_dir;
4999
  struct netinfo_config_state *config;
5000
5001
  if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
5002
5003
  while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
5004
    void *next_domain;
5005
    if (ni_open(domain, "..", &next_domain) != NI_OK) {
5006
      ni_free(next_domain);
5007
      break;
5008
    }
5009
    ni_free(domain);
5010
    domain = next_domain;
5011
  }
5012
  if (status != NI_OK) {
5013
    ni_free(domain);
5014
    return NULL;
5015
  }
5016
5017
  config = emalloc(sizeof(*config));
5018
  config->domain = domain;
5019
  config->config_dir = config_dir;
5020
  config->prop_index = 0;
5021
  config->val_index = 0;
5022
  config->val_list = NULL;
5023
5024
  return config;
5025
}
5026
5027
5028
/*
5029
 * free_netinfo_config - release NetInfo configuration state
5030
 */
5031
static void
5032
free_netinfo_config(
5033
  struct netinfo_config_state *config
5034
  )
5035
{
5036
  ni_free(config->domain);
5037
  free(config);
5038
}
5039
5040
5041
/*
5042
 * gettokens_netinfo - return tokens from NetInfo
5043
 */
5044
static int
5045
gettokens_netinfo (
5046
  struct netinfo_config_state *config,
5047
  char **tokenlist,
5048
  int *ntokens
5049
  )
5050
{
5051
  int prop_index = config->prop_index;
5052
  int val_index = config->val_index;
5053
  char **val_list = config->val_list;
5054
5055
  /*
5056
   * Iterate through each keyword and look for a property that matches it.
5057
   */
5058
  again:
5059
  if (!val_list) {
5060
    for (; prop_index < COUNTOF(keywords); prop_index++)
5061
    {
5062
      ni_namelist namelist;
5063
      struct keyword current_prop = keywords[prop_index];
5064
      ni_index index;
5065
5066
      /*
5067
       * For each value associated in the property, we're going to return
5068
       * a separate line. We squirrel away the values in the config state
5069
       * so the next time through, we don't need to do this lookup.
5070
       */
5071
      NI_INIT(&namelist);
5072
      if (NI_OK == ni_lookupprop(config->domain,
5073
          &config->config_dir, current_prop.text,
5074
          &namelist)) {
5075
5076
        /* Found the property, but it has no values */
5077
        if (namelist.ni_namelist_len == 0) continue;
5078
5079
        config->val_list =
5080
            eallocarray(
5081
          (namelist.ni_namelist_len + 1),
5082
          sizeof(char*));
5083
        val_list = config->val_list;
5084
5085
        for (index = 0;
5086
             index < namelist.ni_namelist_len;
5087
             index++) {
5088
          char *value;
5089
5090
          value = namelist.ni_namelist_val[index];
5091
          val_list[index] = estrdup(value);
5092
        }
5093
        val_list[index] = NULL;
5094
5095
        break;
5096
      }
5097
      ni_namelist_free(&namelist);
5098
    }
5099
    config->prop_index = prop_index;
5100
  }
5101
5102
  /* No list; we're done here. */
5103
  if (!val_list)
5104
    return CONFIG_UNKNOWN;
5105
5106
  /*
5107
   * We have a list of values for the current property.
5108
   * Iterate through them and return each in order.
5109
   */
5110
  if (val_list[val_index]) {
5111
    int ntok = 1;
5112
    int quoted = 0;
5113
    char *tokens = val_list[val_index];
5114
5115
    msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
5116
5117
    (const char*)tokenlist[0] = keywords[prop_index].text;
5118
    for (ntok = 1; ntok < MAXTOKENS; ntok++) {
5119
      tokenlist[ntok] = tokens;
5120
      while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
5121
        quoted ^= (*tokens++ == '"');
5122
5123
      if (ISEOL(*tokens)) {
5124
        *tokens = '\0';
5125
        break;
5126
      } else {    /* must be space */
5127
        *tokens++ = '\0';
5128
        while (ISSPACE(*tokens))
5129
          tokens++;
5130
        if (ISEOL(*tokens))
5131
          break;
5132
      }
5133
    }
5134
5135
    if (ntok == MAXTOKENS) {
5136
      /* HMS: chomp it to lose the EOL? */
5137
      msyslog(LOG_ERR,
5138
        "gettokens_netinfo: too many tokens.  Ignoring: %s",
5139
        tokens);
5140
    } else {
5141
      *ntokens = ntok + 1;
5142
    }
5143
5144
    config->val_index++;  /* HMS: Should this be in the 'else'? */
5145
5146
    return keywords[prop_index].keytype;
5147
  }
5148
5149
  /* We're done with the current property. */
5150
  prop_index = ++config->prop_index;
5151
5152
  /* Free val_list and reset counters. */
5153
  for (val_index = 0; val_list[val_index]; val_index++)
5154
    free(val_list[val_index]);
5155
  free(val_list);
5156
  val_list = config->val_list = NULL;
5157
  val_index = config->val_index = 0;
5158
5159
  goto again;
5160
}
5161
#endif /* HAVE_NETINFO */
5162
5163
5164
/*
5165
 * getnetnum - return a net number (this is crude, but careful)
5166
 *
5167
 * returns 1 for success, and mysteriously, 0 for most failures, and
5168
 * -1 if the address found is IPv6 and we believe IPv6 isn't working.
5169
 */
5170
#ifndef SIM
5171
static int
5172
getnetnum(
5173
  const char *num,
5174
  sockaddr_u *addr,
5175
  int complain,
5176
  enum gnn_type a_type  /* ignored */
5177
  )
5178
0
{
5179
0
  REQUIRE(AF_UNSPEC == AF(addr) ||
5180
0
    AF_INET == AF(addr) ||
5181
0
    AF_INET6 == AF(addr));
5182
5183
0
  if (!is_ip_address(num, AF(addr), addr))
5184
0
    return 0;
5185
5186
0
  if (IS_IPV6(addr) && !ipv6_works)
5187
0
    return -1;
5188
5189
# ifdef ISC_PLATFORM_HAVESALEN
5190
  addr->sa.sa_len = SIZEOF_SOCKADDR(AF(addr));
5191
# endif
5192
0
  SET_PORT(addr, NTP_PORT);
5193
5194
0
  DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
5195
5196
0
  return 1;
5197
0
}
5198
#endif  /* !SIM */
5199
5200
#if defined(HAVE_SETRLIMIT)
5201
void
5202
ntp_rlimit(
5203
  int rl_what,
5204
  rlim_t  rl_value,
5205
  int rl_scale,
5206
  const char *  rl_sstr
5207
  )
5208
0
{
5209
0
  struct rlimit rl;
5210
5211
0
  switch (rl_what) {
5212
0
# ifdef RLIMIT_MEMLOCK
5213
0
      case RLIMIT_MEMLOCK:
5214
0
    if (HAVE_OPT( SAVECONFIGQUIT )) {
5215
0
      break;
5216
0
    }
5217
    /*
5218
     * The default RLIMIT_MEMLOCK is very low on Linux systems.
5219
     * Unless we increase this limit malloc calls are likely to
5220
     * fail if we drop root privilege.  To be useful the value
5221
     * has to be larger than the largest ntpd resident set size.
5222
     */
5223
0
    DPRINTF(2, ("ntp_rlimit: MEMLOCK: %d %s\n",
5224
0
      (int)(rl_value / rl_scale), rl_sstr));
5225
0
    rl.rlim_cur = rl.rlim_max = rl_value;
5226
0
    if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
5227
0
      msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
5228
0
    break;
5229
0
# endif /* RLIMIT_MEMLOCK */
5230
5231
0
# ifdef RLIMIT_NOFILE
5232
0
      case RLIMIT_NOFILE:
5233
    /*
5234
     * For large systems the default file descriptor limit may
5235
     * not be enough.
5236
     */
5237
0
    DPRINTF(2, ("ntp_rlimit: NOFILE: %d %s\n",
5238
0
      (int)(rl_value / rl_scale), rl_sstr));
5239
0
    rl.rlim_cur = rl.rlim_max = rl_value;
5240
0
    if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
5241
0
      msyslog(LOG_ERR, "Cannot set RLIMIT_NOFILE: %m");
5242
0
    break;
5243
0
# endif /* RLIMIT_NOFILE */
5244
5245
0
# ifdef RLIMIT_STACK
5246
0
      case RLIMIT_STACK:
5247
    /*
5248
     * Provide a way to set the stack limit to something
5249
     * smaller, so that we don't lock a lot of unused
5250
     * stack memory.
5251
     */
5252
0
    DPRINTF(2, ("ntp_rlimit: STACK: %d %s pages\n",
5253
0
          (int)(rl_value / rl_scale), rl_sstr));
5254
0
    if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
5255
0
      msyslog(LOG_ERR, "getrlimit(RLIMIT_STACK) failed: %m");
5256
0
    } else {
5257
0
      if (rl_value > rl.rlim_max) {
5258
0
        msyslog(LOG_WARNING,
5259
0
          "ntp_rlimit: using maximum allowed stack limit %lu instead of %lu.",
5260
0
          (u_long)rl.rlim_max,
5261
0
          (u_long)rl_value);
5262
0
        rl_value = rl.rlim_max;
5263
0
      }
5264
0
      rl.rlim_cur = rl_value;
5265
0
      if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
5266
0
        msyslog(LOG_ERR,
5267
0
          "ntp_rlimit: Cannot set RLIMIT_STACK: %m");
5268
0
      }
5269
0
    }
5270
0
    break;
5271
0
# endif /* RLIMIT_STACK */
5272
5273
0
      default:
5274
0
        fatal_error("ntp_rlimit: unexpected RLIMIT case: %d", rl_what);
5275
0
  }
5276
0
}
5277
#endif  /* HAVE_SETRLIMIT */
5278
5279
5280
char *
5281
build_iflags(u_int32 iflags)
5282
0
{
5283
0
  static char ifs[1024];
5284
5285
0
  ifs[0] = '\0';
5286
5287
0
  if (iflags & INT_UP) {
5288
0
    iflags &= ~INT_UP;
5289
0
    appendstr(ifs, sizeof ifs, "up");
5290
0
  }
5291
5292
0
  if (iflags & INT_PPP) {
5293
0
    iflags &= ~INT_PPP;
5294
0
    appendstr(ifs, sizeof ifs, "ppp");
5295
0
  }
5296
5297
0
  if (iflags & INT_LOOPBACK) {
5298
0
    iflags &= ~INT_LOOPBACK;
5299
0
    appendstr(ifs, sizeof ifs, "loopback");
5300
0
  }
5301
5302
0
  if (iflags & INT_BROADCAST) {
5303
0
    iflags &= ~INT_BROADCAST;
5304
0
    appendstr(ifs, sizeof ifs, "broadcast");
5305
0
  }
5306
5307
0
  if (iflags & INT_MULTICAST) {
5308
0
    iflags &= ~INT_MULTICAST;
5309
0
    appendstr(ifs, sizeof ifs, "multicast");
5310
0
  }
5311
5312
0
  if (iflags & INT_BCASTOPEN) {
5313
0
    iflags &= ~INT_BCASTOPEN;
5314
0
    appendstr(ifs, sizeof ifs, "bcastopen");
5315
0
  }
5316
5317
0
  if (iflags & INT_MCASTOPEN) {
5318
0
    iflags &= ~INT_MCASTOPEN;
5319
0
    appendstr(ifs, sizeof ifs, "mcastopen");
5320
0
  }
5321
5322
0
  if (iflags & INT_WILDCARD) {
5323
0
    iflags &= ~INT_WILDCARD;
5324
0
    appendstr(ifs, sizeof ifs, "wildcard");
5325
0
  }
5326
5327
0
  if (iflags & INT_MCASTIF) {
5328
0
    iflags &= ~INT_MCASTIF;
5329
0
    appendstr(ifs, sizeof ifs, "MCASTif");
5330
0
  }
5331
5332
0
  if (iflags & INT_PRIVACY) {
5333
0
    iflags &= ~INT_PRIVACY;
5334
0
    appendstr(ifs, sizeof ifs, "IPv6privacy");
5335
0
  }
5336
5337
0
  if (iflags & INT_BCASTXMIT) {
5338
0
    iflags &= ~INT_BCASTXMIT;
5339
0
    appendstr(ifs, sizeof ifs, "bcastxmit");
5340
0
  }
5341
5342
0
  if (iflags) {
5343
0
    char string[10];
5344
5345
0
    snprintf(string, sizeof string, "%0x", iflags);
5346
0
    appendstr(ifs, sizeof ifs, string);
5347
0
  }
5348
5349
0
  return ifs;
5350
0
}
5351
5352
5353
char *
5354
build_mflags(u_short mflags)
5355
0
{
5356
0
  static char mfs[1024];
5357
5358
0
  mfs[0] = '\0';
5359
5360
0
  if (mflags & RESM_NTPONLY) {
5361
0
    mflags &= ~RESM_NTPONLY;
5362
0
    appendstr(mfs, sizeof mfs, "ntponly");
5363
0
  }
5364
5365
0
  if (mflags & RESM_SOURCE) {
5366
0
    mflags &= ~RESM_SOURCE;
5367
0
    appendstr(mfs, sizeof mfs, "source");
5368
0
  }
5369
5370
0
  if (mflags) {
5371
0
    char string[10];
5372
5373
0
    snprintf(string, sizeof string, "%0x", mflags);
5374
0
    appendstr(mfs, sizeof mfs, string);
5375
0
  }
5376
5377
0
  return mfs;
5378
0
}
5379
5380
5381
char *
5382
build_rflags(u_short rflags)
5383
0
{
5384
0
  static char rfs[1024];
5385
5386
0
  rfs[0] = '\0';
5387
5388
0
  if (rflags & RES_FLAKE) {
5389
0
    rflags &= ~RES_FLAKE;
5390
0
    appendstr(rfs, sizeof rfs, "flake");
5391
0
  }
5392
5393
0
  if (rflags & RES_IGNORE) {
5394
0
    rflags &= ~RES_IGNORE;
5395
0
    appendstr(rfs, sizeof rfs, "ignore");
5396
0
  }
5397
5398
0
  if (rflags & RES_KOD) {
5399
0
    rflags &= ~RES_KOD;
5400
0
    appendstr(rfs, sizeof rfs, "kod");
5401
0
  }
5402
5403
0
  if (rflags & RES_MSSNTP) {
5404
0
    rflags &= ~RES_MSSNTP;
5405
0
    appendstr(rfs, sizeof rfs, "mssntp");
5406
0
  }
5407
5408
0
  if (rflags & RES_LIMITED) {
5409
0
    rflags &= ~RES_LIMITED;
5410
0
    appendstr(rfs, sizeof rfs, "limited");
5411
0
  }
5412
5413
0
  if (rflags & RES_LPTRAP) {
5414
0
    rflags &= ~RES_LPTRAP;
5415
0
    appendstr(rfs, sizeof rfs, "lptrap");
5416
0
  }
5417
5418
0
  if (rflags & RES_NOMODIFY) {
5419
0
    rflags &= ~RES_NOMODIFY;
5420
0
    appendstr(rfs, sizeof rfs, "nomodify");
5421
0
  }
5422
5423
0
  if (rflags & RES_NOMRULIST) {
5424
0
    rflags &= ~RES_NOMRULIST;
5425
0
    appendstr(rfs, sizeof rfs, "nomrulist");
5426
0
  }
5427
5428
0
  if (rflags & RES_NOEPEER) {
5429
0
    rflags &= ~RES_NOEPEER;
5430
0
    appendstr(rfs, sizeof rfs, "noepeer");
5431
0
  }
5432
5433
0
  if (rflags & RES_NOPEER) {
5434
0
    rflags &= ~RES_NOPEER;
5435
0
    appendstr(rfs, sizeof rfs, "nopeer");
5436
0
  }
5437
5438
0
  if (rflags & RES_NOQUERY) {
5439
0
    rflags &= ~RES_NOQUERY;
5440
0
    appendstr(rfs, sizeof rfs, "noquery");
5441
0
  }
5442
5443
0
  if (rflags & RES_DONTSERVE) {
5444
0
    rflags &= ~RES_DONTSERVE;
5445
0
    appendstr(rfs, sizeof rfs, "dontserve");
5446
0
  }
5447
5448
0
  if (rflags & RES_NOTRAP) {
5449
0
    rflags &= ~RES_NOTRAP;
5450
0
    appendstr(rfs, sizeof rfs, "notrap");
5451
0
  }
5452
5453
0
  if (rflags & RES_DONTTRUST) {
5454
0
    rflags &= ~RES_DONTTRUST;
5455
0
    appendstr(rfs, sizeof rfs, "notrust");
5456
0
  }
5457
5458
0
  if (rflags & RES_VERSION) {
5459
0
    rflags &= ~RES_VERSION;
5460
0
    appendstr(rfs, sizeof rfs, "version");
5461
0
  }
5462
5463
0
  if (rflags) {
5464
0
    char string[10];
5465
5466
0
    snprintf(string, sizeof string, "%0x", rflags);
5467
0
    appendstr(rfs, sizeof rfs, string);
5468
0
  }
5469
5470
0
  if ('\0' == rfs[0]) {
5471
0
    appendstr(rfs, sizeof rfs, "(none)");
5472
0
  }
5473
5474
0
  return rfs;
5475
0
}
5476
5477
5478
static void
5479
appendstr(
5480
  char *string,
5481
  size_t s,
5482
  const char *new
5483
  )
5484
0
{
5485
0
  if (*string != '\0') {
5486
0
    (void)strlcat(string, ",", s);
5487
0
  }
5488
0
  (void)strlcat(string, new, s);
5489
5490
0
  return;
5491
0
}