Coverage Report

Created: 2026-02-26 06:20

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