home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / xntpd / ntp_config.c < prev    next >
C/C++ Source or Header  |  1992-08-29  |  34KB  |  1,616 lines

  1. /*
  2.  * ntp_config.c - read and apply configuration information
  3.  */
  4. #include <stdio.h>
  5. #include <strings.h>
  6. #include <ctype.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <signal.h>
  11. #include <sys/wait.h>
  12.  
  13. #include "ntp_syslog.h"
  14. #include "ntp_fp.h"
  15. #include "ntp.h"
  16. #include "ntp_refclock.h"
  17.  
  18. #define RESOLVE_INTERNAL    /* gdt */
  19.  
  20. #ifdef RESOLVE_INTERNAL
  21. #include  <sys/time.h>
  22. #endif
  23.  
  24. /*
  25.  * These routines are used to read the configuration file at
  26.  * startup time.  An entry in the file must fit on a single line.
  27.  * Entries are processed as multiple tokens separated by white space
  28.  * Lines are considered terminated when a '#' is encountered.  Blank
  29.  * lines are ignored.
  30.  */
  31.  
  32. /*
  33.  * Configuration file name
  34.  */
  35. #ifndef    CONFIG_FILE
  36. #define    CONFIG_FILE    "/etc/ntp.conf"
  37. #endif    /* CONFIG_FILE */
  38.  
  39. /*
  40.  * We understand the following configuration entries.
  41.  *
  42.  * peer 128.100.1.1 [ version 2 ] [ key 5 ] [ minpoll ]
  43.  * server 128.100.2.2 [ version 1 ] [ key 6 ] [ minpoll ]
  44.  * precision -7
  45.  * broadcast 128.100.224.255 [ version 2 ] [ key 2 ] [ minpoll ]
  46.  * broadcastclient yes|no
  47.  * broadcastdelay 0.0102
  48.  * authenticate yes|no
  49.  * monitor yes|no
  50.  * authdelay 0.00842
  51.  * ppsdelay 0.000247
  52.  * restrict 128.100.100.0 [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
  53.  * driftfile file_name
  54.  * keys file_name
  55.  * statfile  file_name
  56.  * loopstats file_name
  57.  * resolver /path/progname
  58.  *
  59.  * And then some.  See the manual page.
  60.  */
  61.  
  62. /*
  63.  * Types of entries we understand.
  64.  */
  65. #define CONFIG_UNKNOWN        0
  66.  
  67. #define    CONFIG_PEER        1
  68. #define    CONFIG_SERVER        2
  69. #define    CONFIG_PRECISION    3
  70. #define    CONFIG_DRIFTFILE    4
  71. #define    CONFIG_BROADCAST    5
  72. #define    CONFIG_BROADCASTCLIENT    6
  73. #define    CONFIG_AUTHENTICATE    7
  74. #define    CONFIG_KEYS        8
  75. #define    CONFIG_MONITOR        9
  76. #define    CONFIG_AUTHDELAY    10
  77. #define    CONFIG_RESTRICT        11
  78. #define    CONFIG_BDELAY        12
  79. #define    CONFIG_TRUSTEDKEY    13
  80. #define    CONFIG_REQUESTKEY    14
  81. #define    CONFIG_CONTROLKEY    15
  82. #define    CONFIG_TRAP        16
  83. #define    CONFIG_FUDGE        17
  84. #define    CONFIG_MAXSKEW        18
  85. #define    CONFIG_RESOLVER        19
  86. #define    CONFIG_SELECT        20
  87. #define CONFIG_STATFILE        21
  88. #define CONFIG_LOOPFILE        22
  89. #define CONFIG_PPSDELAY        23
  90. #define    CONFIG_PIDFILE        24
  91.  
  92. #define    CONF_MOD_VERSION    1
  93. #define    CONF_MOD_KEY        2
  94. #define    CONF_MOD_MINPOLL    3
  95. #define CONF_MOD_PREFER        4
  96.  
  97. #define    CONF_RES_MASK        1
  98. #define    CONF_RES_IGNORE        2
  99. #define    CONF_RES_NOSERVE    3
  100. #define    CONF_RES_NOTRUST    4
  101. #define    CONF_RES_NOQUERY    5
  102. #define    CONF_RES_NOMODIFY    6
  103. #define    CONF_RES_NOPEER        7
  104. #define    CONF_RES_NOTRAP        8
  105. #define    CONF_RES_LPTRAP        9
  106. #define    CONF_RES_NTPPORT    10
  107.  
  108. #define    CONF_TRAP_PORT        1
  109. #define    CONF_TRAP_INTERFACE    2
  110.  
  111. #define    CONF_FDG_TIME1        1
  112. #define    CONF_FDG_TIME2        2
  113. #define    CONF_FDG_VALUE1        3
  114. #define    CONF_FDG_VALUE2        4
  115. #define    CONF_FDG_FLAG1        5
  116. #define    CONF_FDG_FLAG2        6
  117. #define    CONF_FDG_FLAG3        7
  118. #define    CONF_FDG_FLAG4        8
  119.  
  120. /*
  121.  * Translation table - keywords to function index
  122.  */
  123. struct keyword {
  124.     char *text;
  125.     int keytype;
  126. };
  127.  
  128. struct keyword keywords[] = {
  129.     { "peer",        CONFIG_PEER },
  130.     { "server",        CONFIG_SERVER },
  131.     { "precision",        CONFIG_PRECISION },
  132.     { "driftfile",        CONFIG_DRIFTFILE },
  133.     { "broadcast",        CONFIG_BROADCAST },
  134.     { "broadcastclient",    CONFIG_BROADCASTCLIENT },
  135.     { "authenticate",    CONFIG_AUTHENTICATE },
  136.     { "keys",        CONFIG_KEYS },
  137.     { "monitor",        CONFIG_MONITOR },
  138.     { "authdelay",        CONFIG_AUTHDELAY },
  139.     { "ppsdelay",        CONFIG_PPSDELAY },
  140.     { "restrict",        CONFIG_RESTRICT },
  141.     { "broadcastdelay",    CONFIG_BDELAY },
  142.     { "trustedkey",        CONFIG_TRUSTEDKEY },
  143.     { "requestkey",        CONFIG_REQUESTKEY },
  144.     { "controlkey",        CONFIG_CONTROLKEY },
  145.     { "trap",        CONFIG_TRAP },
  146.     { "fudge",        CONFIG_FUDGE },
  147.     { "maxskew",        CONFIG_MAXSKEW },
  148.     { "resolver",        CONFIG_RESOLVER },
  149.     { "select",        CONFIG_SELECT },
  150.     { "statfile",        CONFIG_STATFILE },
  151.     { "loopstats",        CONFIG_LOOPFILE },  
  152.     { "pidfile",        CONFIG_PIDFILE },
  153.     { "",            CONFIG_UNKNOWN }
  154. };
  155.  
  156. /*
  157.  * Modifier keywords
  158.  */
  159. struct keyword mod_keywords[] = {
  160.     { "version",    CONF_MOD_VERSION },
  161.     { "key",    CONF_MOD_KEY },
  162.     { "minpoll",    CONF_MOD_MINPOLL },
  163.     { "prefer",    CONF_MOD_PREFER },
  164.     { "",        CONFIG_UNKNOWN }
  165. };
  166.  
  167.  
  168. /*
  169.  * Special restrict keywords
  170.  */
  171. struct keyword res_keywords[] = {
  172.     { "mask",    CONF_RES_MASK },
  173.     { "ignore",    CONF_RES_IGNORE },
  174.     { "noserve",    CONF_RES_NOSERVE },
  175.     { "notrust",    CONF_RES_NOTRUST },
  176.     { "noquery",    CONF_RES_NOQUERY },
  177.     { "nomodify",    CONF_RES_NOMODIFY },
  178.     { "nopeer",    CONF_RES_NOPEER },
  179.     { "notrap",    CONF_RES_NOTRAP },
  180.     { "lowpriotrap",    CONF_RES_LPTRAP },
  181.     { "ntpport",    CONF_RES_NTPPORT },
  182.     { "",        CONFIG_UNKNOWN }
  183. };
  184.  
  185.  
  186. /*
  187.  * Keywords for the trap command
  188.  */
  189. struct keyword trap_keywords[] = {
  190.     { "port",    CONF_TRAP_PORT },
  191.     { "interface",    CONF_TRAP_INTERFACE },
  192.     { "",        CONFIG_UNKNOWN }
  193. };
  194.  
  195.  
  196. /*
  197.  * Keywords for the fudge command
  198.  */
  199. struct keyword fudge_keywords[] = {
  200.     { "time1",    CONF_FDG_TIME1 },
  201.     { "time2",    CONF_FDG_TIME2 },
  202.     { "value1",    CONF_FDG_VALUE1 },
  203.     { "value2",    CONF_FDG_VALUE2 },
  204.     { "flag1",    CONF_FDG_FLAG1 },
  205.     { "flag2",    CONF_FDG_FLAG2 },
  206.     { "flag3",    CONF_FDG_FLAG3 },
  207.     { "flag4",    CONF_FDG_FLAG4 },
  208.     { "",        CONFIG_UNKNOWN }
  209. };
  210.  
  211.  
  212. /*
  213.  * Limits on things
  214.  */
  215. #define    MAXTOKENS    20    /* 20 tokens on line */
  216. #define    MAXLINE        1024    /* maximum length of line */
  217. #define    MAXFILENAME    128    /* maximum length of a file name (alloca()?) */
  218.  
  219.  
  220. /*
  221.  * Miscellaneous macros
  222.  */
  223. #define    STRSAME(s1, s2)        (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
  224. #define    ISEOL(c)        ((c) == '#' || (c) == '\n' || (c) == '\0')
  225. #define    ISSPACE(c)        ((c) == ' ' || (c) == '\t')
  226. #define    STREQ(a, b)        (*(a) == *(b) && strcmp((a), (b)) == 0)
  227.  
  228. /*
  229.  * File descriptor used by the resolver save routines, and temporary file
  230.  * name.
  231.  */
  232. static FILE *res_fp;
  233. static char res_file[20];    /* enough for /tmp/xntpXXXXXX\0 */
  234. #define    RES_TEMPFILE    "/tmp/xntpXXXXXX"
  235.  
  236. /*
  237.  * Definitions of things either imported from or exported to outside
  238.  */
  239. #ifdef DEBUG
  240. extern int debug;
  241. #endif
  242. #if defined(HPUX)
  243. extern char *FindConfig();
  244. #endif
  245. char *progname;
  246. char *xntp_options = "abc:de:f:k:l:p:r:s:t:";
  247.  
  248. /*
  249.  * getstartup - search through the options looking for a debugging flag
  250.  */
  251. void
  252. getstartup(argc, argv)
  253.     int argc;
  254.     char *argv[];
  255. {
  256. #ifdef DEBUG
  257.     int errflg;
  258.     int c;
  259.     extern int optind;
  260.     extern char *optarg;
  261.     extern int getopt();
  262.  
  263.     debug = 0;        /* no debugging by default */
  264.  
  265.     /*
  266.      * This is a big hack.  We don't really want to read command line
  267.      * configuration until everything else is initialized, since
  268.      * the ability to configure the system may depend on storage
  269.      * and the like having been initialized.  Except that we also
  270.      * don't want to initialize anything until after detaching from
  271.      * the terminal, but we won't know to do that until we've
  272.      * parsed the command line.  Do that now, crudely, and do it
  273.      * again later.  Our getopt() is explicitly reusable, by the
  274.      * way.  Your own mileage may vary.
  275.      */
  276.     errflg = 0;
  277.     progname = argv[0];
  278.  
  279.     /*
  280.      * Decode argument list
  281.      */
  282.     while ((c = getopt(argc, argv, xntp_options)) != EOF)
  283.         switch (c) {
  284.         case 'd':
  285.             ++debug;
  286.             break;
  287.         case '?':
  288.             ++errflg;
  289.             break;
  290.         default:
  291.             break;
  292.         }
  293.     
  294.     if (errflg || optind != argc) {
  295.         (void) fprintf(stderr,
  296.             "usage: %s [ -bd ] [ -c config_file ]\n", progname);
  297.         exit(2);
  298.     }
  299.     optind = 0;        /* reset optind to restart getopt */
  300.  
  301.     if (debug)
  302.         setlinebuf(stdout);
  303. #endif    /* DEBUG */
  304. }
  305.  
  306. /*
  307.  * getconfig - get command line options and read the configuration file
  308.  */
  309. void
  310. getconfig(argc, argv)
  311.     int argc;
  312.     char *argv[];
  313. {
  314.     register int i;
  315.     int c;
  316.     int errflg;
  317.     int peerversion;
  318.     u_long peerkey;
  319.     int peerflags;
  320.     int hmode;
  321.     struct sockaddr_in peeraddr;
  322.     struct sockaddr_in maskaddr;
  323.     FILE *fp;
  324.     char line[MAXLINE];
  325.     char *tokens[MAXTOKENS];
  326.     int ntokens;
  327.     int tok;
  328.     struct interface *localaddr;
  329.     char *config_file;
  330.     struct refclockstat clock;
  331.     int have_resolver;
  332. #ifdef RESOLVE_INTERNAL
  333.     int resolve_internal;
  334. #endif
  335.     char resolver_name[MAXFILENAME];
  336.     int have_keyfile;
  337.     char keyfile[MAXFILENAME];
  338.     extern int optind;
  339.     extern char *optarg;
  340. #ifndef    __convex__
  341.     static int gettokens();
  342.     static int matchkey();
  343.     static int getnetnum();
  344. #else    /* __convex__ */
  345.     extern int gettokens();
  346.     extern int matchkey();
  347.     extern int getnetnum();
  348. #endif    /* __convex__ */
  349.     extern void proto_config();
  350.     extern void loop_config();
  351.     extern void authtrust();
  352.     extern struct peer *peer_config();
  353.     extern void stats_config();
  354.     extern void mon_start(), mon_stop();
  355.     extern int atolfp();
  356.     extern int authreadkeys();
  357.     extern struct interface *findinterface();
  358.     extern char *ntoa();
  359. #ifndef    __convex__
  360.     static void save_resolve();
  361.     static void do_resolve();
  362. #ifdef RESOLVE_INTERNAL
  363.     static void do_resolve_internal();
  364. #endif
  365.     static void abort_resolve();
  366. #else    /* __convex__ */
  367.     extern void save_resolve();
  368.     extern void do_resolve();
  369. #ifdef RESOLVE_INTERNAL
  370.     extern void do_resolve_internal();
  371. #endif
  372.     extern void abort_resolve();
  373. #endif    /* __convex__ */
  374.     extern u_long info_auth_keyid;
  375.     extern l_fp pps_fudge;
  376.  
  377.     /*
  378.      * Initialize, initialize
  379.      */
  380.     errflg = 0;
  381. #ifdef DEBUG
  382.     debug = 0;
  383. #endif    /* DEBUG */
  384.     config_file = CONFIG_FILE;
  385.     progname = argv[0];
  386.     res_fp = NULL;
  387.     have_resolver = have_keyfile = 0;
  388.  
  389. #ifdef RESOLVE_INTERNAL
  390.     resolve_internal = 1;
  391. #endif
  392.  
  393.     /*
  394.      * Decode argument list
  395.      */
  396.     while ((c = getopt(argc, argv, xntp_options)) != EOF) {
  397.         switch (c) {
  398.         case 'a':
  399.             proto_config(PROTO_AUTHENTICATE, 1);
  400.             break;
  401.         case 'b':
  402.             proto_config(PROTO_BROADCLIENT, 1);
  403.             break;
  404.         case 'c':
  405.             config_file = optarg;
  406.             break;
  407.         case 'd':
  408. #ifdef DEBUG
  409.             debug++;
  410. #else
  411.             errflg++;
  412. #endif    /* DEBUG */
  413.             break;
  414.  
  415.         case 'e':
  416.             do {
  417.                 l_fp tmp;
  418.  
  419.                 if (!atolfp(optarg, &tmp)) {
  420.                     syslog(LOG_ERR,
  421.             "command line encryption delay value %s undecodable",
  422.                         optarg);
  423.                     errflg++;
  424.                 } else if (tmp.l_ui != 0) {
  425.                     syslog(LOG_ERR,
  426.             "command line encryption delay value %s is unlikely",
  427.                         optarg);
  428.                     errflg++;
  429.                 } else {
  430.                     proto_config(PROTO_AUTHDELAY, tmp.l_f);
  431.                 }
  432.             } while (0);
  433.             break;
  434.  
  435.         case 'f':
  436.             stats_config(STATS_FREQ_FILE, optarg);
  437.             break;
  438.         case 'k':
  439.             getauthkeys(optarg);
  440.             if (strlen(optarg) >= MAXFILENAME) {
  441.                 syslog(LOG_ERR,
  442.                     "key file name too long (>%d, sigh), no name resolution possible",
  443.                     MAXFILENAME);
  444.             } else {
  445.                 have_keyfile = 1;
  446.                 (void)strcpy(keyfile, optarg);
  447.             }
  448.             break;
  449.  
  450.         case 'p':
  451.             stats_config(STATS_PID_FILE, optarg);
  452.             break;
  453.  
  454.         case 'r':
  455.             do {
  456.                 l_fp tmp;
  457.  
  458.                 if (!atolfp(optarg, &tmp)) {
  459.                     syslog(LOG_ERR,
  460.             "command line broadcast delay value %s undecodable",
  461.                         optarg);
  462.                 } else if (tmp.l_ui != 0) {
  463.                     syslog(LOG_ERR,
  464.              "command line broadcast delay value %s is unlikely",
  465.                         optarg);
  466.                 } else {
  467.                     proto_config(PROTO_BROADDELAY, tmp.l_f);
  468.                 }
  469.             } while (0);
  470.             break;
  471.  
  472.         case 's':
  473.             stats_config(STATS_STAT_FILE, optarg);
  474.             break;
  475.  
  476.         case 't':
  477.             do {
  478.                 int tkey;
  479.  
  480.                 tkey = atoi(optarg);
  481.                 if (tkey <= 0 || tkey > NTP_MAXKEY) {
  482.                     syslog(LOG_ERR,
  483.                 "command line trusted key %s is unlikely",
  484.                         optarg);
  485.                 } else {
  486.                     authtrust(tkey, 1);
  487.                 }
  488.             } while (0);
  489.             break;
  490.  
  491.  
  492.         default:
  493.             errflg++;
  494.             break;
  495.         }
  496.     }
  497.     
  498.     if (errflg || optind != argc) {
  499.         (void) fprintf(stderr,
  500.             "usage: %s [ -bd ] [ -c config_file ]\n", progname);
  501.         exit(2);
  502.     }
  503.  
  504. #if defined(HPUX)
  505.     if ((fp = fopen(FindConfig(config_file), "r")) == NULL) {
  506. #else
  507.     if ((fp = fopen(config_file, "r")) == NULL) {
  508. #endif
  509.         /*
  510.          * Broadcast clients can sometimes run without
  511.          * a configuration file.
  512.          */
  513.         return;
  514.     }
  515.  
  516.     while ((tok = gettokens(fp, line, tokens, &ntokens))
  517.         != CONFIG_UNKNOWN) {
  518.         switch(tok) {
  519.         case CONFIG_PEER:
  520.         case CONFIG_SERVER:
  521.         case CONFIG_BROADCAST:
  522.             if (tok == CONFIG_PEER)
  523.                 hmode = MODE_ACTIVE;
  524.             else if (tok == CONFIG_SERVER)
  525.                 hmode = MODE_CLIENT;
  526.             else
  527.                 hmode = MODE_BROADCAST;
  528.  
  529.             if (ntokens < 2) {
  530.                 syslog(LOG_ERR,
  531.                     "No address for %s, line ignored",
  532.                     tokens[0]);
  533.                 break;
  534.             }
  535.  
  536.             if (!getnetnum(tokens[1], &peeraddr, 0)) {
  537.                 errflg = -1;
  538.             } else {
  539.                 errflg = 0;
  540.  
  541. #ifdef REFCLOCK
  542.                 if (!ISREFCLOCKADR(&peeraddr)
  543.                     && ISBADADR(&peeraddr)) {
  544. #else
  545.                 if (ISBADADR(&peeraddr)) {
  546. #endif
  547.                     syslog(LOG_ERR,
  548.                     "attempt to configure invalid address %s",
  549.                         ntoa(&peeraddr));
  550.                     break;
  551.                 }
  552.             }
  553.             
  554.             peerversion = NTP_VERSION;
  555.             peerkey = 0;
  556.             peerflags = 0;
  557.             for (i = 2; i < ntokens; i++)
  558.                 switch (matchkey(tokens[i], mod_keywords)) {
  559.                 case CONF_MOD_VERSION:
  560.                     if (i >= ntokens-1) {
  561.                         syslog(LOG_ERR,
  562.                 "peer/server version requires an argument");
  563.                         errflg = 1;
  564.                         break;
  565.                     }
  566.                     peerversion = atoi(tokens[++i]);
  567.                     if (peerversion > NTP_VERSION
  568.                         || peerversion < NTP_OLDVERSION) {
  569.                         syslog(LOG_ERR,
  570.                 "inappropriate version number %s, line ignored",
  571.                             tokens[i]);
  572.                         errflg = 1;
  573.                     }
  574.                     break;
  575.  
  576.                 case CONF_MOD_KEY:
  577.                     /*
  578.                      * XXX
  579.                      * This is bad because atoi
  580.                      * returns 0 on errors.  Do
  581.                      * something later.
  582.                      */
  583.                     if (i >= ntokens-1) {
  584.                         syslog(LOG_ERR,
  585.                     "peer/server key requires an argument");
  586.                         errflg = 1;
  587.                         break;
  588.                     }
  589.                     peerkey = (u_long)atoi(tokens[++i]);
  590.                     peerflags |= FLAG_AUTHENABLE;
  591.                     break;
  592.  
  593.                 case CONF_MOD_MINPOLL:
  594.                     peerflags |= FLAG_MINPOLL;
  595.                     break;
  596.  
  597.                 case CONF_MOD_PREFER:
  598.                     peerflags |= FLAG_PREFER;
  599.                     break;
  600.  
  601.                 case CONFIG_UNKNOWN:
  602.                     errflg = 1;
  603.                     break;
  604.                 }
  605.             if (errflg == 0) {
  606.                 if (peer_config(&peeraddr,
  607.                     (struct interface *)0,
  608.                     hmode, peerversion, peerkey,
  609.                     peerflags) == 0) {
  610.                     syslog(LOG_ERR,
  611.                         "configuration of %s failed",
  612.                         ntoa(&peeraddr));
  613.                 }
  614.             } else if (errflg == -1) {
  615.                 save_resolve(tokens[1], hmode, peerversion,
  616.                     peerflags, peerkey);
  617.             }
  618.             break;
  619.  
  620.         case CONFIG_PRECISION:
  621.             if (ntokens >= 2) {
  622.                 i = atoi(tokens[1]);
  623.                 if (i >= 0 || i < -25)
  624.                     syslog(LOG_ERR,
  625.                 "unlikely precision %s, line ignored",
  626.                         tokens[1]);
  627.                 else
  628.                     proto_config(PROTO_PRECISION, i);
  629.             }
  630.             break;
  631.  
  632.         case CONFIG_DRIFTFILE:
  633.             if (ntokens >= 2)
  634.                 stats_config(STATS_FREQ_FILE, tokens[1]);
  635.             else
  636.                 stats_config(STATS_FREQ_FILE, (char *)0);
  637.             break;
  638.     
  639.                 case CONFIG_STATFILE:
  640.             if (ntokens >= 2)
  641.                 stats_config(STATS_STAT_FILE, tokens[1]);
  642.             else
  643.                 stats_config(STATS_STAT_FILE, (char *)0);
  644.             break;
  645.                 
  646.                 case CONFIG_LOOPFILE:
  647.             if (ntokens >= 2)
  648.                 stats_config(STATS_LOOP_FILE, tokens[1]);
  649.             else
  650.                 stats_config(STATS_LOOP_FILE, (char *)0);
  651.             break;
  652.  
  653.         case CONFIG_PIDFILE:
  654.             if (ntokens >= 2)
  655.                 stats_config(STATS_PID_FILE, tokens[1]);
  656.             else
  657.                 stats_config(STATS_PID_FILE, (char *)0);
  658.             break;
  659.                 
  660.         case CONFIG_BROADCASTCLIENT:
  661.             errflg = 0;
  662.             if (ntokens >= 2) {
  663.                 if (STREQ(tokens[1], "yes"))
  664.                     proto_config(PROTO_BROADCLIENT, 1);
  665.                 else if (STREQ(tokens[1], "no"))
  666.                     proto_config(PROTO_BROADCLIENT, 0);
  667.                 else
  668.                     errflg++;
  669.             } else {
  670.                 errflg++;
  671.             }
  672.  
  673.             if (errflg)
  674.                 syslog(LOG_ERR,
  675.                     "should be `broadcastclient yes|no'");
  676.             break;
  677.         
  678.         case CONFIG_AUTHENTICATE:
  679.             errflg = 0;
  680.             if (ntokens >= 2) {
  681.                 if (STREQ(tokens[1], "yes"))
  682.                     proto_config(PROTO_AUTHENTICATE, 1);
  683.                 else if (STREQ(tokens[1], "no"))
  684.                     proto_config(PROTO_AUTHENTICATE, 0);
  685.                 else
  686.                     errflg++;
  687.             } else {
  688.                 errflg++;
  689.             }
  690.  
  691.             if (errflg)
  692.                 syslog(LOG_ERR,
  693.                     "should be `authenticate yes|no'");
  694.             break;
  695.  
  696.         case CONFIG_KEYS:
  697.             if (ntokens >= 2) {
  698.                 getauthkeys(tokens[1]);
  699.                 if (strlen(tokens[1]) >= MAXFILENAME) {
  700.                     syslog(LOG_ERR,
  701.     "key file name too long (>%d, sigh), no name resolution possible",
  702.                         MAXFILENAME);
  703.                 } else {
  704.                     have_keyfile = 1;
  705.                     (void)strcpy(keyfile, tokens[1]);
  706.                 }
  707.             }
  708.             break;
  709.  
  710.         case CONFIG_MONITOR:
  711.             errflg = 0;
  712.             if (ntokens >= 2) {
  713.                 if (STREQ(tokens[1], "yes"))
  714.                     mon_start();
  715.                 else if (STREQ(tokens[1], "no"))
  716.                     mon_stop();
  717.                 else
  718.                     errflg++;
  719.             } else {
  720.                 errflg++;
  721.             }
  722.  
  723.             if (errflg)
  724.                 syslog(LOG_ERR,
  725.                     "should be `monitor yes|no'");
  726.             break;
  727.         
  728.         case CONFIG_AUTHDELAY:
  729.             if (ntokens >= 2) {
  730.                 l_fp tmp;
  731.  
  732.                 if (!atolfp(tokens[1], &tmp)) {
  733.                     syslog(LOG_ERR,
  734.                         "authdelay value %s undecodable",
  735.                         tokens[1]);
  736.                 } else if (tmp.l_ui != 0) {
  737.                     syslog(LOG_ERR,
  738.                         "authdelay value %s is unlikely",
  739.                         tokens[1]);
  740.                 } else {
  741.                     proto_config(PROTO_AUTHDELAY, tmp.l_f);
  742.                 }
  743.             }
  744.             break;
  745.  
  746.         case CONFIG_PPSDELAY:
  747.             if (ntokens >= 2) {
  748.                 l_fp tmp;
  749.  
  750.                 if (!atolfp(tokens[1], &tmp)) {
  751.                     syslog(LOG_ERR,
  752.                         "ppsdelay value %s undecodable",
  753.                         tokens[1]);
  754.                 } else {
  755.                     loop_config(LOOP_PPSDELAY, &tmp);
  756.                 }
  757.             }
  758.             break;
  759.  
  760.         case CONFIG_RESTRICT:
  761.             if (ntokens < 2) {
  762.                 syslog(LOG_ERR, "restrict requires an address");
  763.                 break;
  764.             }
  765.             if (STREQ(tokens[1], "default"))
  766.                 peeraddr.sin_addr.s_addr = INADDR_ANY;
  767.             else if (!getnetnum(tokens[1], &peeraddr, 1))
  768.                 break;
  769.             
  770.             /*
  771.              * Use peerversion as flags, peerkey as mflags.  Ick.
  772.              */
  773.             peerversion = 0;
  774.             peerkey = 0;
  775.             errflg = 0;
  776.             maskaddr.sin_addr.s_addr = ~0;
  777.             for (i = 2; i < ntokens; i++) {
  778.                 switch (matchkey(tokens[i], res_keywords)) {
  779.                 case CONF_RES_MASK:
  780.                     if (i >= ntokens-1) {
  781.                         syslog(LOG_ERR,
  782.                         "mask keyword needs argument");
  783.                         errflg++;
  784.                         break;
  785.                     }
  786.                     i++;
  787.                     if (!getnetnum(tokens[i], &maskaddr, 1))
  788.                         errflg++;
  789.                     break;
  790.  
  791.                 case CONF_RES_IGNORE:
  792.                     peerversion |= RES_IGNORE;
  793.                     break;
  794.                 
  795.                 case CONF_RES_NOSERVE:
  796.                     peerversion |= RES_DONTSERVE;
  797.                     break;
  798.                 
  799.                 case CONF_RES_NOTRUST:
  800.                     peerversion |= RES_DONTTRUST;
  801.                     break;
  802.                 
  803.                 case CONF_RES_NOQUERY:
  804.                     peerversion |= RES_NOQUERY;
  805.                     break;
  806.  
  807.                 case CONF_RES_NOMODIFY:
  808.                     peerversion |= RES_NOMODIFY;
  809.                     break;
  810.  
  811.                 case CONF_RES_NOPEER:
  812.                     peerversion |= RES_NOPEER;
  813.                     break;
  814.  
  815.                 case CONF_RES_NOTRAP:
  816.                     peerversion |= RES_NOTRAP;
  817.                     break;
  818.  
  819.                 case CONF_RES_LPTRAP:
  820.                     peerversion |= RES_LPTRAP;
  821.                     break;
  822.  
  823.                 case CONF_RES_NTPPORT:
  824.                     peerkey |= RESM_NTPONLY;
  825.                     break;
  826.  
  827.                 case CONFIG_UNKNOWN:
  828.                     errflg++;
  829.                     break;
  830.                 }
  831.             }
  832.             if (SRCADR(&peeraddr) == INADDR_ANY)
  833.                 maskaddr.sin_addr.s_addr = 0;
  834.             if (!errflg)
  835.                 restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
  836.                     (int)peerkey, peerversion);
  837.             break;
  838.  
  839.         case CONFIG_BDELAY:
  840.             if (ntokens >= 2) {
  841.                 l_fp tmp;
  842.  
  843.                 if (!atolfp(tokens[1], &tmp)) {
  844.                     syslog(LOG_ERR,
  845.                      "broadcastdelay value %s undecodable",
  846.                         tokens[1]);
  847.                 } else if (tmp.l_ui != 0) {
  848.                     syslog(LOG_ERR,
  849.                       "broadcastdelay value %s is unlikely",
  850.                         tokens[1]);
  851.                 } else {
  852.                     proto_config(PROTO_BROADDELAY, tmp.l_f);
  853.                 }
  854.             }
  855.             break;
  856.         
  857.         case CONFIG_TRUSTEDKEY:
  858.             for (i = 1; i < ntokens; i++) {
  859.                 u_long tkey;
  860.  
  861.                 tkey = (u_long) atoi(tokens[i]);
  862.                 if (tkey == 0) {
  863.                     syslog(LOG_ERR,
  864.                         "trusted key %s unlikely",
  865.                         tokens[i]);
  866.                 } else {
  867.                     authtrust(tkey, 1);
  868.                 }
  869.             }
  870.             break;
  871.  
  872.         case CONFIG_REQUESTKEY:
  873.             if (ntokens >= 2) {
  874.                 u_long rkey;
  875.  
  876.                 if (!atouint(tokens[1], &rkey)) {
  877.                     syslog(LOG_ERR,
  878.                         "%s is undecodeable as request key",
  879.                         tokens[1]);
  880.                 } else if (rkey == 0) {
  881.                     syslog(LOG_ERR,
  882.                         "%s makes a poor request keyid",
  883.                         tokens[1]);
  884.                 } else {
  885. #ifdef DEBUG
  886.                     if (debug > 3)
  887.                         printf(
  888.                     "set info_auth_key to %lu\n", rkey);
  889. #endif
  890.                     info_auth_keyid = rkey;
  891.                 }
  892.             }
  893.             break;
  894.         
  895.         case CONFIG_CONTROLKEY:
  896.             if (ntokens >= 2) {
  897.                 u_long ckey;
  898.                 extern u_long ctl_auth_keyid;
  899.  
  900.                 ckey = (u_long)atoi(tokens[1]);
  901.                 if (ckey == 0) {
  902.                     syslog(LOG_ERR,
  903.                         "%s makes a poor control keyid",
  904.                         tokens[1]);
  905.                 } else {
  906.                     ctl_auth_keyid = ckey;
  907.                 }
  908.             }
  909.             break;
  910.         
  911.         case CONFIG_TRAP:
  912.             if (ntokens < 2) {
  913.                 syslog(LOG_ERR,
  914.                   "no address for trap command, line ignored");
  915.                   break;
  916.             }
  917.             if (!getnetnum(tokens[1], &peeraddr, 1))
  918.                 break;
  919.             
  920.             /*
  921.              * Use peerversion for port number.  Barf.
  922.              */
  923.             errflg = 0;
  924.             peerversion = 0;
  925.             localaddr = 0;
  926.             for (i = 2; i < ntokens-1; i++)
  927.                 switch (matchkey(tokens[i], trap_keywords)) {
  928.                 case CONF_TRAP_PORT:
  929.                     if (i >= ntokens-1) {
  930.                         syslog(LOG_ERR,
  931.                         "trap port requires an argument");
  932.                         errflg = 1;
  933.                         break;
  934.                     }
  935.                     peerversion = atoi(tokens[++i]);
  936.                     if (peerversion <= 0
  937.                         || peerversion > 32767) {
  938.                         syslog(LOG_ERR,
  939.                     "invalid port number %s, trap ignored",
  940.                             tokens[i]);
  941.                         errflg = 1;
  942.                     }
  943.                     break;
  944.  
  945.                 case CONF_TRAP_INTERFACE:
  946.                     if (i >= ntokens-1) {
  947.                         syslog(LOG_ERR,
  948.                      "trap interface requires an argument");
  949.                         errflg = 1;
  950.                         break;
  951.                     }
  952.  
  953.                     if (!getnetnum(tokens[++i],
  954.                         &maskaddr, 1)) {
  955.                         errflg = 1;
  956.                         break;
  957.                     }
  958.  
  959.                     localaddr = findinterface(&maskaddr);
  960.                     if (localaddr == NULL) {
  961.                         syslog(LOG_ERR,
  962.                     "can't find interface with address %s",
  963.                             ntoa(&maskaddr));
  964.                         errflg = 1;
  965.                     }
  966.                     break;
  967.  
  968.                 case CONFIG_UNKNOWN:
  969.                     errflg++;
  970.                     break;
  971.                 }
  972.  
  973.             if (!errflg) {
  974.                 extern struct interface *any_interface;
  975.  
  976.                 if (peerversion != 0)
  977.                     peeraddr.sin_port = htons(peerversion);
  978.                 else
  979.                     peeraddr.sin_port = htons(TRAPPORT);
  980.                 if (localaddr == NULL)
  981.                     localaddr = any_interface;
  982.                 if (!ctlsettrap(&peeraddr, localaddr, 0,
  983.                     NTP_VERSION))
  984.                     syslog(LOG_ERR,
  985.                     "can't set trap for %s, no resources",
  986.                         ntoa(&peeraddr));
  987.             }
  988.             break;
  989.         
  990.         case CONFIG_FUDGE:
  991.             if (ntokens < 2) {
  992.                 syslog(LOG_ERR,
  993.                   "no address for fudge command, line ignored");
  994.                   break;
  995.             }
  996.             if (!getnetnum(tokens[1], &peeraddr, 1))
  997.                 break;
  998.  
  999.             if (!ISREFCLOCKADR(&peeraddr)) {
  1000.                 syslog(LOG_ERR,
  1001.     "%s is inappropriate address for the fudge command, line ignored",
  1002.                     ntoa(&peeraddr));
  1003.                 break;
  1004.             }
  1005.  
  1006.             bzero((char *)&clock, sizeof clock);
  1007.             errflg = 0;
  1008.             for (i = 2; i < ntokens-1; i++) {
  1009.                 switch (c = matchkey(tokens[i],
  1010.                     fudge_keywords)) {
  1011.                 case CONF_FDG_TIME1:
  1012.                     if (!atolfp(tokens[++i],
  1013.                         &clock.fudgetime1)) {
  1014.                         syslog(LOG_ERR,
  1015.                     "fudge %s time1 value in error",
  1016.                             ntoa(&peeraddr));
  1017.                         errflg = i;
  1018.                         break;
  1019.                     }
  1020.                     clock.haveflags |= CLK_HAVETIME1;
  1021.                     break;
  1022.  
  1023.                 case CONF_FDG_TIME2:
  1024.                     if (!atolfp(tokens[++i],
  1025.                         &clock.fudgetime2)) {
  1026.                         syslog(LOG_ERR,
  1027.                     "fudge %s time2 value in error",
  1028.                             ntoa(&peeraddr));
  1029.                         errflg = i;
  1030.                         break;
  1031.                     }
  1032.                     clock.haveflags |= CLK_HAVETIME2;
  1033.                     break;
  1034.  
  1035.                 case CONF_FDG_VALUE1:
  1036.                     if (!atoint(tokens[++i],
  1037.                         &clock.fudgeval1)) {
  1038.                         syslog(LOG_ERR,
  1039.                     "fudge %s value1 value in error",
  1040.                             ntoa(&peeraddr));
  1041.                         errflg = i;
  1042.                         break;
  1043.                     }
  1044.                     clock.haveflags |= CLK_HAVEVAL1;
  1045.                     break;
  1046.  
  1047.                 case CONF_FDG_VALUE2:
  1048.                     if (!atoint(tokens[++i],
  1049.                         &clock.fudgeval2)) {
  1050.                         syslog(LOG_ERR,
  1051.                     "fudge %s value2 value in error",
  1052.                             ntoa(&peeraddr));
  1053.                         errflg = i;
  1054.                         break;
  1055.                     }
  1056.                     clock.haveflags |= CLK_HAVEVAL2;
  1057.                     break;
  1058.  
  1059.                 case CONF_FDG_FLAG1:
  1060.                 case CONF_FDG_FLAG2:
  1061.                 case CONF_FDG_FLAG3:
  1062.                 case CONF_FDG_FLAG4:
  1063.                     if (!atoint(tokens[++i], &peerkey)
  1064.                         || peerkey > 1) {
  1065.                         syslog(LOG_ERR,
  1066.                     "fudge %s flag value in error",
  1067.                             ntoa(&peeraddr));
  1068.                         errflg = i;
  1069.                         break;
  1070.                     }
  1071.                     switch(c) {
  1072.                     case CONF_FDG_FLAG1:
  1073.                         c = CLK_FLAG1;
  1074.                         clock.haveflags|=CLK_HAVEFLAG1;
  1075.                         break;
  1076.                     case CONF_FDG_FLAG2:
  1077.                         c = CLK_FLAG2;
  1078.                         clock.haveflags|=CLK_HAVEFLAG2;
  1079.                         break;
  1080.                     case CONF_FDG_FLAG3:
  1081.                         c = CLK_FLAG3;
  1082.                         clock.haveflags|=CLK_HAVEFLAG3;
  1083.                         break;
  1084.                     case CONF_FDG_FLAG4:
  1085.                         c = CLK_FLAG4;
  1086.                         clock.haveflags|=CLK_HAVEFLAG4;
  1087.                         break;
  1088.                     }
  1089.                     if (peerkey == 0)
  1090.                         clock.flags &= ~c;
  1091.                     else
  1092.                         clock.flags |= c;
  1093.                     break;
  1094.  
  1095.                 case CONFIG_UNKNOWN:
  1096.                     errflg = -1;
  1097.                     break;
  1098.                 }
  1099.             }
  1100.  
  1101. #ifdef REFCLOCK
  1102.             /*
  1103.              * If reference clock support isn't defined the
  1104.              * fudge line will still be accepted and syntax
  1105.              * checked, but will essentially do nothing.
  1106.              */
  1107.             if (!errflg) {
  1108.                 extern void refclock_control();
  1109.  
  1110.                 refclock_control(&peeraddr, &clock,
  1111.                     (struct refclockstat *)0);
  1112.             }
  1113. #endif
  1114.             break;
  1115.  
  1116.         case CONFIG_MAXSKEW:
  1117.             if (ntokens >= 2) {
  1118.                 l_fp tmp;
  1119.                 u_fp utmp;
  1120.  
  1121.                 if (!atolfp(tokens[1], &tmp)) {
  1122.                     syslog(LOG_ERR,
  1123.                      "maxskew value %s undecodable",
  1124.                         tokens[1]);
  1125.                 } else if (tmp.l_ui != 0) {
  1126.                     syslog(LOG_ERR,
  1127.                       "maxskew value %s is unlikely",
  1128.                         tokens[1]);
  1129.                 } else {
  1130.                     utmp = LFPTOFP(&tmp);
  1131.                     proto_config(PROTO_MAXSKEW, utmp);
  1132.                 }
  1133.             }
  1134.             break;
  1135.         
  1136.         case CONFIG_RESOLVER:
  1137.             if (ntokens >= 2) {
  1138.                 if (strlen(tokens[1]) >= MAXFILENAME) {
  1139.                     syslog(LOG_ERR,
  1140.     "resolver path name too long (>%d, sigh), no name resolution possible",
  1141.                         MAXFILENAME);
  1142.                     break;
  1143.                 }
  1144.                 strcpy(resolver_name, tokens[1]);
  1145.                 have_resolver = 1;
  1146. #ifdef RESOLVE_INTERNAL
  1147.                 resolve_internal = 0;
  1148. #endif
  1149.             }
  1150.             break;
  1151.  
  1152.         case CONFIG_SELECT:
  1153.             if (ntokens >= 2) {
  1154.                 i = atoi(tokens[1]);
  1155.                 if (i < SELECT_1 || i > SELECT_5)
  1156.                     syslog(LOG_ERR,
  1157.                 "invalid selection algorithm %s, line ignored",
  1158.                         tokens[1]);
  1159.                 else
  1160.                     proto_config(PROTO_SELECT, (long)i);
  1161.             }
  1162.             break;
  1163.  
  1164.         }
  1165.     }
  1166.     (void) fclose(fp);
  1167.  
  1168.     if (res_fp != NULL) {
  1169.         /*
  1170.          * Need name resolution
  1171.          */
  1172.         errflg = 0;
  1173. #ifdef RESOLVE_INTERNAL
  1174.         if (  resolve_internal )
  1175.             do_resolve_internal();
  1176.         else
  1177.           {
  1178. #endif
  1179.  
  1180.         if (info_auth_keyid == 0) {
  1181.             syslog(LOG_ERR,
  1182.         "no request key defined, peer name resolution not possible");
  1183.             errflg++;
  1184.         }
  1185.         if (!have_resolver) {
  1186.             syslog(LOG_ERR,
  1187.         "no resolver defined, peer name resolution not possible");
  1188.             errflg++;
  1189.         }
  1190.         if (!have_keyfile) {
  1191.             syslog(LOG_ERR,
  1192.         "no key file specified, peer name resolution not possible");
  1193.             errflg++;
  1194.         }
  1195.  
  1196.         if (!errflg)
  1197.  
  1198.             do_resolve(resolver_name, info_auth_keyid, keyfile);
  1199.         else
  1200.             abort_resolve();
  1201. #ifdef  RESOLVE_INTERNAL
  1202.           }
  1203. #endif
  1204.     }
  1205. }
  1206.  
  1207.  
  1208.  
  1209. /*
  1210.  * gettokens - read a line and return tokens
  1211.  */
  1212. static int
  1213. gettokens(fp, line, tokenlist, ntokens)
  1214.     FILE *fp;
  1215.     char *line;
  1216.     char **tokenlist;
  1217.     int *ntokens;
  1218. {
  1219.     register char *cp;
  1220.     register int eol;
  1221.     register int ntok;
  1222. #ifndef    __convex__
  1223.     static int matchkey();
  1224. #else    /* __convex__ */
  1225.     extern int matchkey();
  1226. #endif    /* __convex__ */
  1227.  
  1228.     /*
  1229.      * Find start of first token
  1230.      */
  1231. again:
  1232.     while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
  1233.         cp = line;
  1234.         while (ISSPACE(*cp))
  1235.             cp++;
  1236.         if (!ISEOL(*cp))
  1237.             break;
  1238.     }
  1239.     if (cp == NULL) {
  1240.         *ntokens = 0;
  1241.         return CONFIG_UNKNOWN;    /* hack.  Is recognized as EOF */
  1242.     }
  1243.  
  1244.     /*
  1245.      * Now separate out the tokens
  1246.      */
  1247.     eol = 0;
  1248.     ntok = 0;
  1249.     while (!eol) {
  1250.         tokenlist[ntok++] = cp;
  1251.         while (!ISEOL(*cp) && !ISSPACE(*cp))
  1252.             cp++;
  1253.         if (ISEOL(*cp)) {
  1254.             *cp = '\0';
  1255.             eol = 1;
  1256.         } else {        /* must be space */
  1257.             *cp++ = '\0';
  1258.             while (ISSPACE(*cp))
  1259.                 cp++;
  1260.             if (ISEOL(*cp))
  1261.                 eol = 1;
  1262.         }
  1263.         if (ntok == MAXTOKENS)
  1264.             eol = 1;
  1265.     }
  1266.  
  1267.     /*
  1268.      * Return the match
  1269.      */
  1270.     *ntokens = ntok;
  1271.     ntok = matchkey(tokenlist[0], keywords);
  1272.     if (ntok == CONFIG_UNKNOWN)
  1273.         goto again;
  1274.     return ntok;
  1275. }
  1276.  
  1277.  
  1278.  
  1279. /*
  1280.  * matchkey - match a keyword to a list
  1281.  */
  1282. static int
  1283. matchkey(word, keys)
  1284.     register char *word;
  1285.     register struct keyword *keys;
  1286. {
  1287.     for (;;) {
  1288.         if (keys->keytype == CONFIG_UNKNOWN) {
  1289.             syslog(LOG_ERR,
  1290.                 "configure: keyword \"%s\" unknown, line ignored",
  1291.                 word);
  1292.             return CONFIG_UNKNOWN;
  1293.         }
  1294.         if (STRSAME(word, keys->text))
  1295.             return keys->keytype;
  1296.         keys++;
  1297.     }
  1298. }
  1299.  
  1300.  
  1301. /*
  1302.  * getnetnum - return a net number (this is crude, but careful)
  1303.  */
  1304. static int
  1305. getnetnum(num, addr, complain)
  1306.     char *num;
  1307.     struct sockaddr_in *addr;
  1308.     int complain;
  1309. {
  1310.     register char *cp;
  1311.     register char *bp;
  1312.     register int i;
  1313.     register int temp;
  1314.     char buf[80];        /* will core dump on really stupid stuff */
  1315.     u_long netnum;
  1316. #ifdef DEBUG
  1317.     extern char *ntoa();
  1318. #endif
  1319.  
  1320.     cp = num;
  1321.     netnum = 0;
  1322.     for (i = 0; i < 4; i++) {
  1323.         bp = buf;
  1324.         while (isdigit(*cp))
  1325.             *bp++ = *cp++;
  1326.         if (bp == buf)
  1327.             break;
  1328.  
  1329.         if (i < 3) {
  1330.             if (*cp++ != '.')
  1331.                 break;
  1332.         } else if (*cp != '\0')
  1333.             break;
  1334.  
  1335.         *bp = '\0';
  1336.         temp = atoi(buf);
  1337.         if (temp > 255)
  1338.             break;
  1339.         netnum <<= 8;
  1340.         netnum += temp;
  1341. #ifdef DEBUG
  1342.     if (debug > 3)
  1343.         printf("getnetnum %s step %d buf %s temp %d netnum %d\n",
  1344.             num, i, buf, temp, netnum);
  1345. #endif
  1346.     }
  1347.  
  1348.     if (i < 4) {
  1349.         if (complain)
  1350.             syslog(LOG_ERR,
  1351.             "configure: \"%s\" not valid host number, line ignored",
  1352.                 num);
  1353.         return 0;
  1354.     }
  1355.  
  1356.     /*
  1357.      * make up socket address.  Clear it out for neatness.
  1358.      */
  1359.     bzero((char *)addr, sizeof(struct sockaddr_in));
  1360.     addr->sin_family = AF_INET;
  1361.     addr->sin_port = htons(NTP_PORT);
  1362.     addr->sin_addr.s_addr = htonl(netnum);
  1363. #ifdef DEBUG
  1364.     if (debug > 1)
  1365.         printf("getnetnum given %s, got %s (%x)\n",
  1366.             num, ntoa(addr), netnum);
  1367. #endif
  1368.     return 1;
  1369. }
  1370.  
  1371.  
  1372. /*
  1373.  * catchchild - receive the resolver's exit status
  1374.  */
  1375. static void
  1376. catchchild()
  1377. {
  1378.     /*
  1379.      * We only start up one child, and if we're here
  1380.      * it should have already exited.  Hence the following
  1381.      * shouldn't hang.  If it does, please tell me.
  1382.      */
  1383.     (void) wait(0);
  1384. }
  1385.  
  1386.  
  1387. /*
  1388.  * save_resolve - save configuration info into a file for later name resolution
  1389.  */
  1390. static void
  1391. save_resolve(name, mode, version, flags, keyid)
  1392.     char *name;
  1393.     int mode;
  1394.     int version;
  1395.     int flags;
  1396.     u_long keyid;
  1397. {
  1398.     extern char *mktemp();
  1399.  
  1400.     if (res_fp == NULL) {
  1401.         (void) strcpy(res_file, RES_TEMPFILE);
  1402.         (void) mktemp(res_file);
  1403.         res_fp = fopen(res_file, "w");
  1404.         if (res_fp == NULL) {
  1405.             syslog(LOG_ERR, "open failed for %s: %m", res_file);
  1406.             return;
  1407.         }
  1408.     }
  1409.  
  1410.     (void) fprintf(res_fp, "%s %d %d %d %lu\n", name, mode,
  1411.         version, flags, keyid);
  1412. }
  1413.  
  1414.  
  1415. /*
  1416.  * abort_resolve - terminate the resolver stuff and delete the file
  1417.  */
  1418. static void
  1419. abort_resolve()
  1420. {
  1421.     /*
  1422.      * In an ideal world we would might reread the file and
  1423.      * log the hosts which aren't getting configured.  Since
  1424.      * this is too much work, however, just close and delete
  1425.      * the temp file.
  1426.      */
  1427.     if (res_fp != NULL)
  1428.         (void) fclose(res_fp);
  1429.     res_fp = NULL;
  1430.  
  1431.     (void) unlink(res_file);
  1432. }
  1433.  
  1434.  
  1435. /*
  1436.  * do_resolve - start up the resolver program
  1437.  */
  1438. static void
  1439. do_resolve(program, auth_keyid, keyfile)
  1440.     char *program;
  1441.     u_long auth_keyid;
  1442.     char *keyfile;
  1443. {
  1444.     register int i;
  1445.     register char **ap;
  1446.     /* 1 progname + 5 -d's + 1 -r + keyid + keyfile + tempfile + 1 */
  1447.     char *argv[15];
  1448.     char numbuf[15];
  1449.     /*
  1450.      * Clean environment so the resolver is consistant
  1451.      */
  1452.     static char *resenv[] = {
  1453.         "HOME=/",
  1454.         "SHELL=/bin/sh",
  1455.         "TERM=dumb",
  1456.         "USER=root",
  1457.         NULL
  1458.     };
  1459.  
  1460.     if (res_fp == NULL) {
  1461.         /* belch */
  1462.         syslog(LOG_ERR, "internal error in do_resolve: res_fp == NULL");
  1463.         exit(1);
  1464.     }
  1465.     (void) fclose(res_fp);
  1466.     res_fp = NULL;
  1467.  
  1468.     ap = argv;
  1469.     *ap++ = program;
  1470.  
  1471.     /*
  1472.      * xntpres [-d ...] -r key# keyfile tempfile
  1473.      */
  1474. #ifdef DEBUG
  1475.     i = debug;
  1476.     if (i > 5)
  1477.         i = 5;
  1478.     while (i-- > 0)
  1479.         *ap++ = "-d";
  1480. #endif
  1481.     *ap++ = "-r";
  1482.  
  1483.     (void) sprintf(numbuf, "%lu", auth_keyid);
  1484.     *ap++ = numbuf;
  1485.     *ap++ = keyfile;
  1486.     *ap++ = res_file;
  1487.     *ap = NULL;
  1488.  
  1489.     (void) signal(SIGCHLD, catchchild);
  1490.  
  1491.     i = fork();
  1492.     if (i == 0) {
  1493.         /*
  1494.          * In child here, close up all descriptors and
  1495.          * exec the resolver program.  Close the syslog()
  1496.          * facility gracefully in case we must reopen it.
  1497.          */
  1498.         (void) signal(SIGCHLD, SIG_DFL);
  1499.         closelog();
  1500.         i = getdtablesize();
  1501. #ifdef DEBUG
  1502.         while (i-- > 2)
  1503. #else
  1504.         while (i-- > 0)
  1505. #endif
  1506.             (void) close(i);
  1507.         (void) execve(program, argv, resenv);
  1508.  
  1509.         /*
  1510.          * If we got here, the exec screwed up.  Open the log file
  1511.          * and print something so we don't die without complaint
  1512.          */
  1513. #ifndef    LOG_DAEMON
  1514.         openlog("xntpd", LOG_PID);
  1515. #else
  1516. #ifndef    LOG_NTP
  1517. #define    LOG_NTP    LOG_DAEMON
  1518. #endif
  1519.         openlog("xntpd", LOG_PID | LOG_NDELAY, LOG_NTP);
  1520. #endif    /* LOG_DAEMON */
  1521.         syslog(LOG_ERR, "exec of resolver %s failed!", program);
  1522.         abort_resolve();
  1523.         exit(1);
  1524.     }
  1525.  
  1526.     if (i == -1) {
  1527.         syslog(LOG_ERR, "fork() failed, can't start %s", program);
  1528.         (void) signal(SIGCHLD, SIG_DFL);
  1529.         abort_resolve();
  1530.     }
  1531. }
  1532.  
  1533.  
  1534. #ifdef RESOLVE_INTERNAL
  1535.  
  1536. #define    KEY_TYPE_ASCII    3
  1537.  
  1538. /*
  1539.  * do_resolve_internal - start up the resolver function (not program)
  1540.  */
  1541. static void
  1542. do_resolve_internal()
  1543. {
  1544.   int i;
  1545.  
  1546.   extern u_long req_keyid;    /* request keyid */
  1547.   extern char *req_file;    /* name of the file with configuration info */
  1548.  
  1549.   extern u_long info_auth_keyid;
  1550.  
  1551.  
  1552.   extern int authusekey();
  1553.  
  1554.   if (res_fp == NULL) {
  1555.     /* belch */
  1556.     syslog(LOG_ERR, "internal error in do_resolve_internal: res_fp == NULL");
  1557.     exit(1);
  1558.   }
  1559.  
  1560.   /* we are done with this now */
  1561.   (void) fclose(res_fp);
  1562.   res_fp = NULL;
  1563.  
  1564.   /* find a keyid */
  1565.   req_keyid = 65535;
  1566.  
  1567.   /* if doesn't exist, make up one at random */
  1568.   if ( ! authhavekey(req_keyid) )
  1569.     {
  1570.       char rankey[9];
  1571.       struct timeval now;
  1572.       extern int rand();
  1573.  
  1574.       /* generate random key */
  1575.       gettimeofday(&now, (struct timezone *)0);
  1576.       srand(now.tv_sec * now.tv_usec);
  1577.  
  1578.       for ( i = 0; i < 8; i++ )
  1579.     rankey[i] = (rand() % 255) + 1;
  1580.       rankey[8] = 0;
  1581.  
  1582.       authusekey(req_keyid, KEY_TYPE_ASCII, rankey);
  1583.     }
  1584.  
  1585.   /* save keyid so we will accept config requests with it */
  1586.   info_auth_keyid = req_keyid;
  1587.  
  1588.   req_file = res_file;    /* set up pointer to res file */
  1589.  
  1590.   (void) signal(SIGCHLD, catchchild);
  1591.  
  1592.   i = fork();
  1593.   if (i == 0) {
  1594.     /* this used to close everything
  1595.      * I don't think this is necessary */
  1596.     (void) signal(SIGCHLD, SIG_DFL);
  1597.  
  1598.     ntp_intres();
  1599.  
  1600.     /*
  1601.      * If we got here, the intres code screwed up.
  1602.      * Print something so we don't die without complaint
  1603.      */
  1604.     syslog(LOG_ERR, "call to ntp_intres lost");
  1605.     abort_resolve();
  1606.     exit(1);
  1607.   }
  1608.  
  1609.   if (i == -1) {
  1610.     syslog(LOG_ERR, "fork() failed, can't start ntp_intres");
  1611.     (void) signal(SIGCHLD, SIG_DFL);
  1612.     abort_resolve();
  1613.   }
  1614. }
  1615. #endif
  1616.