Annotation of embedaddon/ntp/ntpd/ntp_config.c, revision 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>