Annotation of embedaddon/ntp/ntpd/ntp_config.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>