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_intres.c < prev    next >
C/C++ Source or Header  |  1992-08-04  |  16KB  |  758 lines

  1. /* 
  2.  * ripped off from ../xnptres/xntpres.c by gdt 4/2/92
  3.  * routine callable from xntpd, rather than separate program
  4.  * also, key info passed in via a global, so no key file needed.
  5.  */
  6.  
  7. /*
  8.  * xntpres - process configuration entries which require use of the resolver
  9.  *
  10.  * This is meant to be run by xntpd on the fly.  It is not guaranteed
  11.  * to work properly if run by hand.  This is actually a quick hack to
  12.  * stave off violence from people who hate using numbers in the
  13.  * configuration file (at least I hope the rest of the daemon is
  14.  * better than this).  Also might provide some ideas about how one
  15.  * might go about autoconfiguring an NTP distribution network.
  16.  *
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include <strings.h>
  21. #include <ctype.h>
  22. #include <sys/types.h>
  23. #include <sys/time.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <sys/file.h>
  27. #include <netdb.h>
  28. #include <syslog.h>
  29. #include <signal.h>
  30. #include <errno.h>
  31.  
  32. #include "ntp_fp.h"
  33. #include "ntp.h"
  34. #include "ntp_request.h"
  35.  
  36. #define    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
  37.  
  38. #ifndef FD_SET
  39. #define    NFDBITS        32
  40. #define    FD_SETSIZE    32
  41. #define    FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  42. #define    FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  43. #define    FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  44. #define FD_ZERO(p)    bzero((char *)(p), sizeof(*(p)))
  45. #endif
  46.  
  47. /*
  48.  * Each item we are to resolve and configure gets one of these
  49.  * structures defined for it.
  50.  */
  51. struct conf_entry {
  52.     struct conf_entry *ce_next;
  53.     char *ce_name;            /* name we are trying to resolve */
  54.     struct conf_peer ce_config;    /* configuration info for peer */
  55. };
  56. #define    ce_peeraddr    ce_config.peeraddr
  57. #define    ce_hmode    ce_config.hmode
  58. #define    ce_version    ce_config.version
  59. #define    ce_flags    ce_config.flags
  60. #define    ce_keyid    ce_config.keyid
  61.  
  62. /*
  63.  * confentries is a pointer to the list of configuration entries
  64.  * we have left to do.
  65.  */
  66. struct conf_entry *confentries = NULL;
  67.  
  68. /*
  69.  * We take an interrupt every thirty seconds, at which time we decrement
  70.  * config_timer and resolve_timer.  The former is set to 2, so we retry
  71.  * unsucessful reconfigurations every minute.  The latter is set to
  72.  * an exponentially increasing value which starts at 2 and increases to
  73.  * 32.  When this expires we retry failed name resolutions.
  74.  *
  75.  * We sleep SLEEPTIME seconds before doing anything, to give the server
  76.  * time to arrange itself.
  77.  */
  78. #define    MINRESOLVE    2
  79. #define    MAXRESOLVE    32
  80. #define    CONFIG_TIME    2
  81. #define    ALARM_TIME    30
  82.  
  83. #define    SLEEPTIME    2
  84.  
  85. int config_timer = 0;
  86. int resolve_timer = 0;
  87.  
  88. int resolve_value;    /* next value of resolve timer */
  89.  
  90. /*
  91.  * Big hack attack
  92.  */
  93. #define    LOCALHOST    0x7f000001    /* 127.0.0.1, in hex, of course */
  94. #define    SKEWTIME    0x08000000    /* 0.03125 seconds as a l_fp fraction */
  95.  
  96. /*
  97.  * Select time out.  Set to 2 seconds.  The server is on the local machine,
  98.  * after all.
  99.  */
  100. #define    TIMEOUT_SEC    2
  101. #define    TIMEOUT_USEC    0
  102.  
  103.  
  104. /*
  105.  * Input processing.  The data on each line in the configuration file
  106.  * is supposed to consist of entries in the following order
  107.  */
  108. #define    TOK_HOSTNAME    0
  109. #define    TOK_HMODE    1
  110. #define    TOK_VERSION    2
  111. #define    TOK_FLAGS    3
  112. #define    TOK_KEYID    4
  113. #define    NUMTOK        5
  114.  
  115. #define    MAXLINESIZE    512
  116.  
  117.  
  118. /*
  119.  * File descriptor for ntp request code.
  120.  */
  121. int sockfd = -1;
  122.  
  123.  
  124. /* stuff to be filled in by caller */
  125.  
  126. u_long req_keyid;    /* request keyid */
  127. char *req_file;        /* name of the file with configuration info */
  128.  
  129. /* end stuff to be filled in */
  130.  
  131.  
  132. extern int debug;        /* use global debug flag */
  133. extern int errno;
  134.  
  135. /*
  136.  * assumes:  req_key, req_keyid, conffile valid
  137.  *  syslog still open
  138.  */
  139. ntp_intres()
  140. {
  141.     int c;
  142.     int errflg = 0;
  143.     char *cp;
  144.     FILE *in;
  145.     void bong();
  146.     void readconf();
  147.     void doconfigure();
  148.     void checkparent();
  149.  
  150.     if ( debug )
  151.       syslog(LOG_INFO, "ntp_intres running");
  152.  
  153.  
  154.     /* check out auth stuff */
  155.     if (!authhavekey(req_keyid)) {
  156.         syslog(LOG_ERR, "request keyid %lu not found",
  157.             req_keyid );
  158.         exit(1);
  159.     }
  160.  
  161.     /*
  162.      * Read the configuration info
  163.      * {this is bogus, since we are forked, but it is easier
  164.      * to keep this code - gdt}
  165.      */
  166.     if ((in = fopen(req_file, "r")) == NULL) {
  167.         syslog(LOG_ERR, "can't open configuration file %s: %m",
  168.             req_file);
  169.         exit(1);
  170.     }
  171.     readconf(in, req_file);
  172.     (void) fclose(in);
  173.  
  174.     if ( ! debug )
  175.         (void) unlink(req_file);
  176.  
  177.     /*
  178.      * Sleep a little to make sure the server is completely up
  179.      */
  180.     sleep(SLEEPTIME);
  181.  
  182.     /*
  183.      * Make a first cut at resolving the bunch
  184.      */
  185.     doconfigure(1);
  186.     if (confentries == NULL)
  187.         exit(0);        /* done that quick */
  188.     
  189.     /*
  190.      * Here we've got some problem children.  Set up the timer
  191.      * and wait for it.
  192.      */
  193.     resolve_value = resolve_timer = MINRESOLVE;
  194.     config_timer = CONFIG_TIME;
  195.     (void) signal(SIGALRM, bong);
  196.     alarm(ALARM_TIME);
  197.  
  198.     for (;;) {
  199.         if (confentries == NULL)
  200.             exit(0);
  201.         checkparent();
  202.         if (resolve_timer == 0) {
  203.             if (resolve_value < MAXRESOLVE)
  204.                 resolve_value <<= 1;
  205.             resolve_timer = resolve_value;
  206.             config_timer = CONFIG_TIME;
  207.             doconfigure(1);
  208.             continue;
  209.         } else if (config_timer == 0) {
  210.             config_timer = CONFIG_TIME;
  211.             doconfigure(0);
  212.             continue;
  213.         }
  214.         /*
  215.          * There is a race in here.  Is okay, though, since
  216.          * all it does is delay things by 30 seconds.
  217.          */
  218.         (void) pause();
  219.     }
  220. }
  221.  
  222.  
  223. /*
  224.  * bong - service and reschedule an alarm() interrupt
  225.  */
  226. void
  227. bong()
  228. {
  229.     if (config_timer > 0)
  230.         config_timer--;
  231.     if (resolve_timer > 0)
  232.         resolve_timer--;
  233.     alarm(ALARM_TIME);
  234. }
  235.  
  236.  
  237. /*
  238.  * checkparent - see if our parent process is still running
  239.  */
  240. void
  241. checkparent()
  242. {
  243.     /*
  244.      * If our parent (the server) has died we will have been
  245.      * inherited by init.  If so, exit.
  246.      */
  247.     if (getppid() == 1) {
  248.         syslog(LOG_INFO, "parent died before we finished, exiting");
  249.         exit(0);
  250.     }
  251. }
  252.  
  253.  
  254. /*
  255.  * removeentry - we are done with an entry, remove it from the list
  256.  */
  257. void
  258. removeentry(entry)
  259.     struct conf_entry *entry;
  260. {
  261.     register struct conf_entry *ce;
  262.  
  263.     ce = confentries;
  264.     if (ce == entry) {
  265.         confentries = ce->ce_next;
  266.         return;
  267.     }
  268.  
  269.     while (ce != NULL) {
  270.         if (ce->ce_next == entry) {
  271.             ce->ce_next = entry->ce_next;
  272.             return;
  273.         }
  274.         ce = ce->ce_next;
  275.     }
  276. }
  277.  
  278.  
  279. /*
  280.  * addentry - add an entry to the configuration list
  281.  */
  282. void
  283. addentry(name, mode, version, flags, keyid)
  284.     char *name;
  285.     int mode;
  286.     int version;
  287.     int flags;
  288.     u_long keyid;
  289. {
  290.     register char *cp;
  291.     register struct conf_entry *ce;
  292.     int len;
  293.     extern char *emalloc();
  294.  
  295.     len = strlen(name) + 1;
  296.     cp = emalloc((unsigned)len);
  297.     bcopy(name, cp, len);
  298.  
  299.     ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
  300.     ce->ce_name = cp;
  301.     ce->ce_peeraddr = 0;
  302.     ce->ce_hmode = (u_char)mode;
  303.     ce->ce_version = (u_char)version;
  304.     ce->ce_flags = (u_char)flags;
  305.     ce->ce_keyid = htonl(keyid);
  306.     ce->ce_next = NULL;
  307.  
  308.     if (confentries == NULL) {
  309.         confentries = ce;
  310.     } else {
  311.         register struct conf_entry *cep;
  312.  
  313.         for (cep = confentries; cep->ce_next != NULL;
  314.             cep = cep->ce_next)
  315.             /* nothing */;
  316.         cep->ce_next = ce;
  317.     }
  318. }
  319.  
  320.  
  321. /*
  322.  * findhostaddr - resolve a host name into an address
  323.  *
  324.  * The routine sticks the address into the entry's ce_peeraddr if it
  325.  * gets one.  It returns 1 for "success" and 0 for an uncorrectable
  326.  * failure.  Note that "success" includes try again errors.  You can
  327.  * tell that you got a try again since ce_peeraddr will still be zero.
  328.  */
  329. int
  330. findhostaddr(entry)
  331.     struct conf_entry *entry;
  332. {
  333.     struct hostent *hp;
  334.  
  335.     checkparent();        /* make sure our guy is still running */
  336.  
  337.     hp = gethostbyname(entry->ce_name);
  338.  
  339.     if (hp == NULL) {
  340. #ifndef NODNS
  341.         /*
  342.          * If the resolver is in use, see if the failure is
  343.          * temporary.  If so, return success.
  344.          */
  345.         extern int h_errno;
  346.  
  347.         if (h_errno == TRY_AGAIN)
  348.             return 1;
  349. #endif
  350.         return 0;
  351.     }
  352.  
  353.     /*
  354.      * Use the first address.  We don't have any way to
  355.      * tell preferences and older gethostbyname() implementations
  356.      * only return one.
  357.      */
  358.     (void) bcopy(hp->h_addr, (char *)&(entry->ce_peeraddr),
  359.         sizeof(struct in_addr));
  360.     return 1;
  361. }
  362.  
  363.  
  364. /*
  365.  * openntp - open a socket to the ntp server
  366.  */
  367. void
  368. openntp()
  369. {
  370.     struct sockaddr_in saddr;
  371.  
  372.     if (sockfd >= 0)
  373.         return;
  374.     
  375.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  376.     if (sockfd == -1) {
  377.         syslog(LOG_ERR, "socket() failed: %m");
  378.         exit(1);
  379.     }
  380.  
  381.     bzero((char *)&saddr, sizeof(saddr));
  382.     saddr.sin_family = AF_INET;
  383.     saddr.sin_port = htons(NTP_PORT);        /* trash */
  384.     saddr.sin_addr.s_addr = htonl(LOCALHOST);    /* garbage */
  385.  
  386.  
  387.     /*
  388.      * Make the socket non-blocking.  We'll wait with select()
  389.      */
  390.     if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
  391.         syslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
  392.         exit(1);
  393.     }
  394.  
  395.     if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
  396.         syslog(LOG_ERR, "connect() failed: %m");
  397.         exit(1);
  398.     }
  399. }
  400.  
  401.  
  402. /*
  403.  * request - send a configuration request to the server, wait for a response
  404.  */
  405. int
  406. request(conf)
  407.     struct conf_peer *conf;
  408. {
  409.     fd_set fdset;
  410.     struct timeval tvout;
  411.     struct req_pkt reqpkt;
  412.     l_fp ts;
  413.     int n;
  414.  
  415.     checkparent();        /* make sure our guy is still running */
  416.  
  417.     if (sockfd < 0)
  418.         openntp();
  419.     
  420.     /*
  421.      * Try to clear out any previously received traffic so it
  422.      * doesn't fool us.  Note the socket is nonblocking.
  423.      */
  424.     while (read(sockfd, (char *)&reqpkt, REQ_LEN_MAC) > 0)
  425.         /* nothing */;
  426.  
  427.     /*
  428.      * Make up a request packet with the configuration info
  429.      */
  430.     bzero((char *)&reqpkt, sizeof(reqpkt));
  431.  
  432.     reqpkt.rm_vn_mode = RM_VN_MODE(0, 0);
  433.     reqpkt.auth_seq = AUTH_SEQ(1, 0);    /* authenticated, no seq */
  434.     reqpkt.implementation = IMPL_XNTPD;    /* local implementation */
  435.     reqpkt.request = REQ_CONFIG;        /* configure a new peer */
  436.     reqpkt.err_nitems = ERR_NITEMS(0, 1);    /* one item */
  437.     reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));
  438.     bcopy((char *)conf, reqpkt.data, sizeof(struct conf_peer));
  439.     reqpkt.keyid = htonl(req_keyid);
  440.  
  441.     auth1crypt(req_keyid, (u_long *)&reqpkt, REQ_LEN_NOMAC);
  442.     gettstamp(&ts);
  443.     M_ADDUF(ts.l_ui, ts.l_uf, SKEWTIME);
  444.     HTONL_FP(&ts, &reqpkt.tstamp);
  445.     n = auth2crypt(req_keyid, (u_long *)&reqpkt, REQ_LEN_NOMAC);
  446.  
  447.     /*
  448.      * Done.  Send it.
  449.      */
  450.     n = write(sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n);
  451.     if (n < 0) {
  452.         syslog(LOG_ERR, "send to NTP server failed: %m");
  453.         return 0;    /* maybe should exit */
  454.     }
  455.  
  456.     /*
  457.      * Wait for a response.  A weakness of the mode 7 protocol used
  458.      * is that there is no way to associate a response with a
  459.      * particular request, i.e. the response to this configuration
  460.      * request is indistinguishable from that to any other.  I should
  461.      * fix this some day.  In any event, the time out is fairly
  462.      * pessimistic to make sure that if an answer is coming back
  463.      * at all, we get it.
  464.      */
  465.     for (;;) {
  466.         FD_ZERO(&fdset);
  467.         FD_SET(sockfd, &fdset);
  468.         tvout.tv_sec = TIMEOUT_SEC;
  469.         tvout.tv_usec = TIMEOUT_USEC;
  470.  
  471.         n = select(sockfd + 1, &fdset, (fd_set *)0,
  472.             (fd_set *)0, &tvout);
  473.  
  474.         if (n <= 0) {
  475.             if (n < 0)
  476.                 syslog(LOG_ERR, "select() fails: %m");
  477.             return 0;
  478.         }
  479.  
  480.         n = read(sockfd, (char *)&reqpkt, REQ_LEN_MAC);
  481.         if (n <= 0) {
  482.             if (n < 0) {
  483.                 syslog(LOG_ERR, "read() fails: %m");
  484.                 return 0;
  485.             }
  486.             continue;
  487.         }
  488.  
  489.         /*
  490.          * Got one.  Check through to make sure it is what
  491.          * we expect.
  492.          */
  493.         if (n < RESP_HEADER_SIZE) {
  494.             syslog(LOG_ERR, "received runt response (%d octets)",
  495.                 n);
  496.             continue;
  497.         }
  498.  
  499.         if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
  500. #ifdef DEBUG
  501.             if (debug > 1)
  502.                 printf("received non-response packet\n");
  503. #endif
  504.             continue;
  505.         }
  506.  
  507.         if (ISMORE(reqpkt.rm_vn_mode)) {
  508. #ifdef DEBUG
  509.             if (debug > 1)
  510.                 printf("received fragmented packet\n");
  511. #endif
  512.             continue;
  513.         }
  514.  
  515.         if (INFO_VERSION(reqpkt.rm_vn_mode) != NTP_VERSION
  516.             || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
  517. #ifdef DEBUG
  518.             if (debug > 1)
  519.                 printf("version (%d) or mode (%d) incorrect\n",
  520.                     INFO_VERSION(reqpkt.rm_vn_mode),
  521.                     INFO_MODE(reqpkt.rm_vn_mode));
  522. #endif
  523.             continue;
  524.         }
  525.  
  526.         if (INFO_SEQ(reqpkt.auth_seq) != 0) {
  527. #ifdef DEBUG
  528.             if (debug > 1)
  529.                 printf("nonzero sequence number (%d)\n",
  530.                     INFO_SEQ(reqpkt.auth_seq));
  531. #endif
  532.             continue;
  533.         }
  534.  
  535.         if (reqpkt.implementation != IMPL_XNTPD ||
  536.             reqpkt.request != REQ_CONFIG) {
  537. #ifdef DEBUG
  538.             if (debug > 1)
  539.                 printf(
  540.                 "implementation (%d) or request (%d) incorrect\n",
  541.                     reqpkt.implementation, reqpkt.request);
  542. #endif
  543.             continue;
  544.         }
  545.  
  546.         if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
  547.             INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
  548.             INFO_ITEMSIZE(reqpkt.mbz_itemsize != 0)) {
  549. #ifdef DEBUG
  550.             if (debug > 1)
  551.                 printf(
  552.                 "nitems (%d) mbz (%d) or itemsize (%d) nonzero\n",
  553.                     INFO_NITEMS(reqpkt.err_nitems),
  554.                     INFO_MBZ(reqpkt.mbz_itemsize),
  555.                     INFO_ITEMSIZE(reqpkt.mbz_itemsize));
  556. #endif
  557.             continue;
  558.         }
  559.  
  560.         n = INFO_ERR(reqpkt.err_nitems);
  561.         switch (n) {
  562.         case INFO_OKAY:
  563.             /* success */
  564.             return 1;
  565.         
  566.         case INFO_ERR_IMPL:
  567.             syslog(LOG_ERR,
  568.                 "server reports implementation mismatch!!");
  569.             return 0;
  570.         
  571.         case INFO_ERR_REQ:
  572.             syslog(LOG_ERR,
  573.                 "server claims configuration request is unknown");
  574.             return 0;
  575.         
  576.         case INFO_ERR_FMT:
  577.             syslog(LOG_ERR,
  578.                 "server indicates a format error occured(!!)");
  579.             return 0;
  580.  
  581.         case INFO_ERR_NODATA:
  582.             syslog(LOG_ERR,
  583.         "server indicates no data available (shouldn't happen)");
  584.             return 0;
  585.         
  586.         case INFO_ERR_AUTH:
  587.             syslog(LOG_ERR,
  588.                 "server returns a permission denied error");
  589.             return 0;
  590.  
  591.         default:
  592.             syslog(LOG_ERR,
  593.                 "server returns unknown error code %d", n);
  594.             return 0;
  595.         }
  596.     }
  597. }
  598.  
  599.  
  600. /*
  601.  * nexttoken - return the next token from a line
  602.  */
  603. char *
  604. nexttoken(lptr)
  605.     char **lptr;
  606. {
  607.     register char *cp;
  608.     register char *tstart;
  609.  
  610.     cp = *lptr;
  611.  
  612.     /*
  613.      * Skip leading white space
  614.      */
  615.     while (*cp == ' ' || *cp == '\t')
  616.         cp++;
  617.     
  618.     /*
  619.      * If this is the end of the line, return nothing.
  620.      */
  621.     if (*cp == '\n' || *cp == '\0') {
  622.         *lptr = cp;
  623.         return NULL;
  624.     }
  625.     
  626.     /*
  627.      * Must be the start of a token.  Record the pointer and look
  628.      * for the end.
  629.      */
  630.     tstart = cp++;
  631.     while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')
  632.         cp++;
  633.     
  634.     /*
  635.      * Terminate the token with a \0.  If this isn't the end of the
  636.      * line, space to the next character.
  637.      */
  638.     if (*cp == '\n' || *cp == '\0')
  639.         *cp = '\0';
  640.     else
  641.         *cp++ = '\0';
  642.  
  643.     *lptr = cp;
  644.     return tstart;
  645. }
  646.  
  647.  
  648. /*
  649.  * readconf - read the configuration information out of the file we
  650.  *          were passed.  Note that since the file is supposed to be
  651.  *          machine generated, we bail out at the first sign of trouble.
  652.  */
  653. void
  654. readconf(fp, name)
  655.     FILE *fp;
  656.     char *name;
  657. {
  658.     register int i;
  659.     char *token[NUMTOK];
  660.     u_long intval[NUMTOK];
  661.     int flags;
  662.     char buf[MAXLINESIZE];
  663.     char *bp;
  664.  
  665.     while (fgets(buf, MAXLINESIZE, fp) != NULL) {
  666.  
  667.         bp = buf;
  668.         for (i = 0; i < NUMTOK; i++) {
  669.             if ((token[i] = nexttoken(&bp)) == NULL) {
  670.                 syslog(LOG_ERR,
  671.                     "tokenizing error in file `%s', quitting",
  672.                     name);
  673.                 exit(1);
  674.             }
  675.         }
  676.  
  677.         for (i = 1; i < NUMTOK; i++) {
  678.             if (!atouint(token[i], &intval[i])) {
  679.                 syslog(LOG_ERR,
  680.          "format error for integer token `%s', file `%s', quitting",
  681.                     token[i], name);
  682.                 exit(1);
  683.             }
  684.         }
  685.  
  686.         if (intval[TOK_HMODE] != MODE_ACTIVE &&
  687.             intval[TOK_HMODE] != MODE_CLIENT &&
  688.             intval[TOK_HMODE] != MODE_BROADCAST) {
  689.             syslog(LOG_ERR, "invalid mode (%d) in file %s",
  690.                 intval[TOK_HMODE], name);
  691.             exit(1);
  692.         }
  693.  
  694.         if (intval[TOK_VERSION] > NTP_VERSION ||
  695.             intval[TOK_VERSION] < NTP_OLDVERSION) {
  696.             syslog(LOG_ERR, "invalid version (%d) in file %s",
  697.                 intval[TOK_VERSION], name);
  698.             exit(1);
  699.         }
  700.  
  701.         if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE|FLAG_MINPOLL))
  702.             != 0) {
  703.             syslog(LOG_ERR, "invalid flags (%d) in file %s",
  704.                 intval[TOK_FLAGS], name);
  705.             exit(1);
  706.         }
  707.  
  708.         flags = 0;
  709.         if (intval[TOK_FLAGS] & FLAG_AUTHENABLE)
  710.             flags |= CONF_FLAG_AUTHENABLE;
  711.         if (intval[TOK_FLAGS] & FLAG_MINPOLL)
  712.             flags |= CONF_FLAG_MINPOLL;
  713.         
  714.         /*
  715.          * This is as good as we can check it.  Add it in.
  716.          */
  717.         addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
  718.             (int)intval[TOK_VERSION], flags, intval[TOK_KEYID]);
  719.     }
  720. }
  721.  
  722.  
  723. /*
  724.  * doconfigure - attempt to resolve names and configure the server
  725.  */
  726. void
  727. doconfigure(dores)
  728.     int dores;
  729. {
  730.     register struct conf_entry *ce;
  731.     register struct conf_entry *ceremove;
  732.  
  733.     ce = confentries;
  734.     while (ce != NULL) {
  735.         if (dores && ce->ce_peeraddr == 0) {
  736.             if (!findhostaddr(ce)) {
  737.                 syslog(LOG_ERR,
  738.                     "couldn't resolve `%s', giving up on it",
  739.                     ce->ce_name);
  740.                 ceremove = ce;
  741.                 ce = ceremove->ce_next;
  742.                 removeentry(ceremove);
  743.                 continue;
  744.             }
  745.         }
  746.  
  747.         if (ce->ce_peeraddr != 0) {
  748.             if (request(&ce->ce_config)) {
  749.                 ceremove = ce;
  750.                 ce = ceremove->ce_next;
  751.                 removeentry(ceremove);
  752.                 continue;
  753.             }
  754.         }
  755.         ce = ce->ce_next;
  756.     }
  757. }
  758.