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

1.1       misho       1: /*
                      2:  * ripped off from ../ntpres/ntpres.c by Greg Troxel 4/2/92
                      3:  * routine callable from ntpd, rather than separate program
                      4:  * also, key info passed in via a global, so no key file needed.
                      5:  */
                      6: 
                      7: /*
                      8:  * ntpres - process configuration entries which require use of the resolver
                      9:  *
                     10:  * This is meant to be run by ntpd 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: #ifdef HAVE_CONFIG_H
                     20: # include <config.h>
                     21: #endif
                     22: 
                     23: #include "ntp_intres.h"
                     24: 
                     25: #ifndef NO_INTRES
                     26: 
                     27: #include <stdio.h>
                     28: #include <ctype.h>
                     29: #include <signal.h>
                     30: 
                     31: /**/
                     32: #ifdef HAVE_SYS_TYPES_H
                     33: # include <sys/types.h>
                     34: #endif
                     35: #ifdef HAVE_NETINET_IN_H
                     36: #include <netinet/in.h>
                     37: #endif
                     38: #include <arpa/inet.h>
                     39: /**/
                     40: #ifdef HAVE_SYS_PARAM_H
                     41: # include <sys/param.h>                /* MAXHOSTNAMELEN (often) */
                     42: #endif
                     43: 
                     44: #if !defined(HAVE_RES_INIT) && defined(HAVE___RES_INIT)
                     45: # define HAVE_RES_INIT
                     46: #endif
                     47: 
                     48: #if defined(HAVE_RESOLV_H) && defined(HAVE_RES_INIT)
                     49: # ifdef HAVE_ARPA_NAMESER_H
                     50: #  include <arpa/nameser.h> /* DNS HEADER struct */
                     51: # endif
                     52: # ifdef HAVE_NETDB_H
                     53: #  include <netdb.h>
                     54: # endif
                     55: # include <resolv.h>
                     56: #endif
                     57: 
                     58: #ifdef RES_TIMEOUT
                     59: #undef RES_TIMEOUT     /* resolv.h has one, we want ours */
                     60: #endif
                     61: 
                     62: #include "ntp_machine.h"
                     63: #include "ntpd.h"
                     64: #include "ntp_io.h"
                     65: #include "ntp_request.h"
                     66: #include "ntp_stdlib.h"
                     67: #include "ntp_syslog.h"
                     68: #include "ntp_config.h"
                     69: 
                     70: #include <isc/net.h>
                     71: #include <isc/result.h>
                     72: 
                     73: #define        STREQ(a, b)     (*(a) == *(b) && strcmp((a), (b)) == 0)
                     74: 
                     75: /*
                     76:  * Each item we are to resolve and configure gets one of these
                     77:  * structures defined for it.
                     78:  */
                     79: struct conf_entry {
                     80:        struct conf_entry *ce_next;
                     81:        char *ce_name;                  /* name to resolve */
                     82:        struct conf_peer ce_config;     /* config info for peer */
                     83:        int no_needed;                  /* number of addresses needed (pool) */
                     84:        /*  no_needed isn't used yet: It's needed to fix bug-975 */
                     85:        int type;                       /* -4 and -6 flags */
                     86:        sockaddr_u peer_store;          /* address info for both fams */
                     87: };
                     88: #define        ce_peeraddr     ce_config.peeraddr
                     89: #define        ce_peeraddr6    ce_config.peeraddr6
                     90: #define        ce_hmode        ce_config.hmode
                     91: #define        ce_version      ce_config.version
                     92: #define ce_minpoll     ce_config.minpoll
                     93: #define ce_maxpoll     ce_config.maxpoll
                     94: #define        ce_flags        ce_config.flags
                     95: #define ce_ttl         ce_config.ttl
                     96: #define        ce_keyid        ce_config.keyid
                     97: #define ce_keystr      ce_config.keystr
                     98: 
                     99: /*
                    100:  * confentries is a pointer to the list of configuration entries
                    101:  * we have left to do.
                    102:  */
                    103: static struct conf_entry *confentries = NULL;
                    104: 
                    105: /*
                    106:  * We take an interrupt every thirty seconds, at which time we decrement
                    107:  * config_timer and resolve_timer.  The former is set to 2, so we retry
                    108:  * unsucessful reconfigurations every minute.  The latter is set to
                    109:  * an exponentially increasing value which starts at 2 and increases to
                    110:  * 32.  When this expires we retry failed name resolutions.
                    111:  *
                    112:  * We sleep SLEEPTIME seconds before doing anything, to give the server
                    113:  * time to arrange itself.
                    114:  */
                    115: #define        MINRESOLVE      2
                    116: #define        MAXRESOLVE      32
                    117: #define        CONFIG_TIME     2
                    118: #define        ALARM_TIME      30
                    119: #define        SLEEPTIME       2
                    120: 
                    121: static volatile int config_timer = 0;
                    122: static volatile int resolve_timer = 0;
                    123: 
                    124: static int resolve_value;      /* next value of resolve timer */
                    125: 
                    126: /*
                    127:  * Big hack attack
                    128:  */
                    129: #define        SKEWTIME        0x08000000      /* 0.03125 seconds as a l_fp fraction */
                    130: 
                    131: /*
                    132:  * Select time out.  Set to 2 seconds.  The server is on the local machine,
                    133:  * after all.
                    134:  */
                    135: #define        TIMEOUT_SEC     2
                    136: #define        TIMEOUT_USEC    0
                    137: 
                    138: 
                    139: /*
                    140:  * Input processing.  The data on each line in the configuration file
                    141:  * is supposed to consist of entries in the following order
                    142:  */
                    143: #define        TOK_HOSTNAME    0
                    144: #define        TOK_NEEDED      1
                    145: #define        TOK_TYPE        2
                    146: #define        TOK_HMODE       3
                    147: #define        TOK_VERSION     4
                    148: #define        TOK_MINPOLL     5
                    149: #define        TOK_MAXPOLL     6
                    150: #define        TOK_FLAGS       7
                    151: #define        TOK_TTL         8
                    152: #define        TOK_KEYID       9
                    153: #define        TOK_KEYSTR      10
                    154: #define        NUMTOK          11
                    155: 
                    156: #define        MAXLINESIZE     512
                    157: 
                    158: 
                    159: /*
                    160:  * File descriptor for ntp request code.
                    161:  */
                    162: static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */
                    163: 
                    164: /* stuff to be filled in by caller */
                    165: 
                    166: keyid_t req_keyid;     /* request keyid */
                    167: int    req_keytype;    /* OpenSSL NID such as NID_md5 */
                    168: size_t req_hashlen;    /* digest size for req_keytype */
                    169: char *req_file;                /* name of the file with configuration info */
                    170: 
                    171: /* end stuff to be filled in */
                    172: 
                    173: 
                    174: static void    checkparent     (void);
                    175: static struct conf_entry *
                    176:                removeentry     (struct conf_entry *);
                    177: static void    addentry        (char *, int, int, int, int, int, int, u_int,
                    178:                                   int, keyid_t, char *);
                    179: static int     findhostaddr    (struct conf_entry *);
                    180: static void    openntp         (void);
                    181: static int     request         (struct conf_peer *);
                    182: static char *  nexttoken       (char **);
                    183: static void    readconf        (FILE *, char *);
                    184: static void    doconfigure     (int);
                    185: 
                    186: struct ntp_res_t_pkt {         /* Tagged packet: */
                    187:        void *tag;              /* For the caller */
                    188:        u_int32 paddr;          /* IP to look up, or 0 */
                    189:        char name[MAXHOSTNAMELEN]; /* Name to look up (if 1st byte is not 0) */
                    190: };
                    191: 
                    192: struct ntp_res_c_pkt {         /* Control packet: */
                    193:        char name[MAXHOSTNAMELEN];
                    194:        u_int32 paddr;
                    195:        int mode;
                    196:        int version;
                    197:        int minpoll;
                    198:        int maxpoll;
                    199:        u_int flags;
                    200:        int ttl;
                    201:        keyid_t keyid;
                    202:        u_char keystr[MAXFILENAME];
                    203: };
                    204: 
                    205: 
                    206: static void    resolver_exit (int);
                    207: 
                    208: /*
                    209:  * Call here instead of just exiting
                    210:  */
                    211: 
                    212: static void resolver_exit (int code)
                    213: {
                    214: #ifdef SYS_WINNT
                    215:        CloseHandle(ResolverEventHandle);
                    216:        ResolverEventHandle = NULL;
                    217:        _endthreadex(code);     /* Just to kill the thread not the process */
                    218: #else
                    219:        exit(code);             /* kill the forked process */
                    220: #endif
                    221: }
                    222: 
                    223: /*
                    224:  * ntp_res_recv: Process an answer from the resolver
                    225:  */
                    226: 
                    227: void
                    228: ntp_res_recv(void)
                    229: {
                    230:        /*
                    231:          We have data ready on our descriptor.
                    232:          It may be an EOF, meaning the resolver process went away.
                    233:          Otherwise, it will be an "answer".
                    234:        */
                    235: }
                    236: 
                    237: 
                    238: /*
                    239:  * ntp_intres needs;
                    240:  *
                    241:  *     req_key(???), req_keyid, req_file valid
                    242:  *     syslog still open
                    243:  */
                    244: 
                    245: void
                    246: ntp_intres(void)
                    247: {
                    248:        FILE *in;
                    249: #ifdef SYS_WINNT
                    250:        DWORD rc;
                    251: #else
                    252:        int     rc;
                    253:        struct  timeval tv;
                    254:        fd_set  fdset;
                    255:        int     time_left;
                    256: #endif
                    257: 
                    258: #ifdef DEBUG
                    259:        if (debug > 1) {
                    260:                msyslog(LOG_INFO, "NTP_INTRES running");
                    261:        }
                    262: #endif
                    263: 
                    264:        /* check out auth stuff */
                    265:        if (sys_authenticate) {
                    266:                if (!authistrusted(req_keyid)) {
                    267:                        msyslog(LOG_ERR, "invalid request keyid %08x",
                    268:                            req_keyid );
                    269:                        resolver_exit(1);
                    270:                }
                    271:        }
                    272: 
                    273:        /*
                    274:         * Read the configuration info
                    275:         * {this is bogus, since we are forked, but it is easier
                    276:         * to keep this code - gdt}
                    277:         */
                    278:        if ((in = fopen(req_file, "r")) == NULL) {
                    279:                msyslog(LOG_ERR, "can't open configuration file %s: %m",
                    280:                        req_file);
                    281:                resolver_exit(1);
                    282:        }
                    283:        readconf(in, req_file);
                    284:        (void) fclose(in);
                    285: 
                    286: #ifdef DEBUG
                    287:        if (!debug)
                    288: #endif
                    289:                if (unlink(req_file))
                    290:                        msyslog(LOG_WARNING,
                    291:                                "unable to remove intres request file %s, %m",
                    292:                                req_file);
                    293: 
                    294:        /*
                    295:         * Set up the timers to do first shot immediately.
                    296:         */
                    297:        resolve_timer = 0;
                    298:        resolve_value = MINRESOLVE;
                    299:        config_timer = CONFIG_TIME;
                    300: 
                    301:        for (;;) {
                    302:                checkparent();
                    303: 
                    304:                if (resolve_timer == 0) {
                    305:                        /*
                    306:                         * Sleep a little to make sure the network is completely up
                    307:                         */
                    308:                        sleep(SLEEPTIME);
                    309:                        doconfigure(1);
                    310: 
                    311:                        /* prepare retry, in case there's more work to do */
                    312:                        resolve_timer = resolve_value;
                    313: #ifdef DEBUG
                    314:                        if (debug > 2)
                    315:                                msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
                    316: #endif
                    317:                        if (resolve_value < MAXRESOLVE)
                    318:                                resolve_value <<= 1;
                    319: 
                    320:                        config_timer = CONFIG_TIME;
                    321:                } else if (config_timer == 0) {  /* MB: in which case would this be required ? */
                    322:                        doconfigure(0);
                    323:                        /* MB: should we check now if we could exit, similar to the code above? */
                    324:                        config_timer = CONFIG_TIME;
                    325: #ifdef DEBUG
                    326:                        if (debug > 2)
                    327:                                msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
                    328: #endif
                    329:                }
                    330: 
                    331:                if (confentries == NULL)
                    332:                        resolver_exit(0);   /* done */
                    333: 
                    334: #ifdef SYS_WINNT
                    335:                rc = WaitForSingleObject(ResolverEventHandle, 1000 * ALARM_TIME);  /* in milliseconds */
                    336: 
                    337:                if ( rc == WAIT_OBJECT_0 ) { /* signaled by the main thread */
                    338:                        resolve_timer = 0;         /* retry resolving immediately */
                    339:                        continue;
                    340:                }
                    341: 
                    342:                if ( rc != WAIT_TIMEOUT ) /* not timeout: error */
                    343:                        resolver_exit(1);
                    344: 
                    345: #else  /* not SYS_WINNT */
                    346:                /* Bug 1386: fork() in NetBSD leaves timers running. */
                    347:                /* So we need to retry select on EINTR */
                    348:                time_left = ALARM_TIME;
                    349:                while (time_left > 0) {
                    350:                    tv.tv_sec = time_left;
                    351:                    tv.tv_usec = 0;
                    352:                    FD_ZERO(&fdset);
                    353:                    FD_SET(resolver_pipe_fd[0], &fdset);
                    354:                    rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
                    355: 
                    356:                    if (rc == 0)                /* normal timeout */
                    357:                        break;
                    358: 
                    359:                    if (rc > 0) {  /* parent process has written to the pipe */
                    360:                        read(resolver_pipe_fd[0], (char *)&rc, sizeof(rc));  /* make pipe empty */
                    361:                        resolve_timer = 0;   /* retry resolving immediately */
                    362:                        break;
                    363:                    }
                    364: 
                    365:                    if ( rc < 0 ) {             /* select() returned error */
                    366:                        if (errno == EINTR) {   /* Timer went off */
                    367:                            time_left -= (1<<EVENT_TIMEOUT);
                    368:                            continue;           /* try again */
                    369:                        }
                    370:                        msyslog(LOG_ERR, "ntp_intres: Error from select: %s",
                    371:                            strerror(errno));
                    372:                        resolver_exit(1);
                    373:                    }
                    374:                }
                    375: #endif
                    376: 
                    377:                /* normal timeout, keep on waiting */
                    378:                if (config_timer > 0)
                    379:                        config_timer--;
                    380:                if (resolve_timer > 0)
                    381:                        resolve_timer--;
                    382:        }
                    383: }
                    384: 
                    385: 
                    386: #ifdef SYS_WINNT
                    387: /*
                    388:  * ntp_intres_thread wraps the slightly different interface of Windows
                    389:  * thread functions and ntp_intres
                    390:  */
                    391: unsigned WINAPI
                    392: ntp_intres_thread(void *UnusedThreadArg)
                    393: {
                    394:        UNUSED_ARG(UnusedThreadArg);
                    395: 
                    396:        ntp_intres();
                    397:        return 0;
                    398: }
                    399: #endif /* SYS_WINNT */
                    400: 
                    401: 
                    402: /*
                    403:  * checkparent - see if our parent process is still running
                    404:  *
                    405:  * No need to worry in the Windows NT environment whether the
                    406:  * main thread is still running, because if it goes
                    407:  * down it takes the whole process down with it (in
                    408:  * which case we won't be running this thread either)
                    409:  * Turn function into NOP;
                    410:  */
                    411: 
                    412: static void
                    413: checkparent(void)
                    414: {
                    415: #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)
                    416: 
                    417:        /*
                    418:         * If our parent (the server) has died we will have been
                    419:         * inherited by init.  If so, exit.
                    420:         */
                    421:        if (getppid() == 1) {
                    422:                msyslog(LOG_INFO, "parent died before we finished, exiting");
                    423:                resolver_exit(0);
                    424:        }
                    425: #endif /* SYS_WINNT && SYS_VXWORKS*/
                    426: }
                    427: 
                    428: 
                    429: 
                    430: /*
                    431:  * removeentry - we are done with an entry, remove it from the list
                    432:  */
                    433: static struct conf_entry *
                    434: removeentry(
                    435:        struct conf_entry *entry
                    436:        )
                    437: {
                    438:        register struct conf_entry *ce;
                    439:        struct conf_entry *next_ce;
                    440: 
                    441:        ce = confentries;
                    442:        if (ce == entry)
                    443:                confentries = ce->ce_next;
                    444:        else
                    445:                while (ce != NULL) {
                    446:                        if (ce->ce_next == entry) {
                    447:                                ce->ce_next = entry->ce_next;
                    448:                                break;
                    449:                        }
                    450:                        ce = ce->ce_next;
                    451:                }
                    452: 
                    453:        next_ce = entry->ce_next;
                    454:        if (entry->ce_name != NULL)
                    455:                free(entry->ce_name);
                    456:        free(entry);
                    457: 
                    458:        return next_ce;
                    459: }
                    460: 
                    461: 
                    462: /*
                    463:  * addentry - add an entry to the configuration list
                    464:  */
                    465: static void
                    466: addentry(
                    467:        char *name,
                    468:        int no_needed,
                    469:        int type,
                    470:        int mode,
                    471:        int version,
                    472:        int minpoll,
                    473:        int maxpoll,
                    474:        u_int flags,
                    475:        int ttl,
                    476:        keyid_t keyid,
                    477:        char *keystr
                    478:        )
                    479: {
                    480:        register struct conf_entry *ce;
                    481: 
                    482: #ifdef DEBUG
                    483:        if (debug > 1)
                    484:                msyslog(LOG_INFO, 
                    485:                    "intres: <%s> %d %d %d %d %d %d %x %d %x %s",
                    486:                    name, no_needed, type, mode, version,
                    487:                    minpoll, maxpoll, flags, ttl, keyid, keystr);
                    488: #endif
                    489:        ce = emalloc(sizeof(*ce));
                    490:        ce->ce_name = estrdup(name);
                    491:        ce->ce_peeraddr = 0;
                    492: #ifdef ISC_PLATFORM_HAVEIPV6
                    493:        ce->ce_peeraddr6 = in6addr_any;
                    494: #endif
                    495:        ZERO_SOCK(&ce->peer_store);
                    496:        ce->ce_hmode = (u_char)mode;
                    497:        ce->ce_version = (u_char)version;
                    498:        ce->ce_minpoll = (u_char)minpoll;
                    499:        ce->ce_maxpoll = (u_char)maxpoll;
                    500:        ce->no_needed = no_needed;      /* Not used after here. */
                    501:                                        /* Start of fixing bug-975 */
                    502:        ce->type = type;
                    503:        ce->ce_flags = (u_char)flags;
                    504:        ce->ce_ttl = (u_char)ttl;
                    505:        ce->ce_keyid = keyid;
                    506:        strncpy(ce->ce_keystr, keystr, sizeof(ce->ce_keystr) - 1);
                    507:        ce->ce_keystr[sizeof(ce->ce_keystr) - 1] = 0;
                    508:        ce->ce_next = NULL;
                    509: 
                    510:        if (confentries == NULL) {
                    511:                confentries = ce;
                    512:        } else {
                    513:                register struct conf_entry *cep;
                    514: 
                    515:                for (cep = confentries; cep->ce_next != NULL;
                    516:                     cep = cep->ce_next)
                    517:                    /* nothing */;
                    518:                cep->ce_next = ce;
                    519:        }
                    520: }
                    521: 
                    522: 
                    523: /*
                    524:  * findhostaddr - resolve a host name into an address (Or vice-versa)
                    525:  *
                    526:  * Given one of {ce_peeraddr,ce_name}, find the other one.
                    527:  * It returns 1 for "success" and 0 for an uncorrectable failure.
                    528:  * Note that "success" includes try again errors.  You can tell that you
                    529:  *  got a "try again" since {ce_peeraddr,ce_name} will still be zero.
                    530:  */
                    531: static int
                    532: findhostaddr(
                    533:        struct conf_entry *entry
                    534:        )
                    535: {
                    536:        static int eai_again_seen = 0;
                    537:        struct addrinfo *addr;
                    538:        struct addrinfo hints;
                    539:        int again;
                    540:        int error;
                    541: 
                    542:        checkparent();          /* make sure our guy is still running */
                    543: 
                    544:        if (entry->ce_name != NULL && !SOCK_UNSPEC(&entry->peer_store)) {
                    545:                /* HMS: Squawk? */
                    546:                msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
                    547:                return 1;
                    548:        }
                    549: 
                    550:        if (entry->ce_name == NULL && SOCK_UNSPEC(&entry->peer_store)) {
                    551:                msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
                    552:                return 0;
                    553:        }
                    554: 
                    555:        if (entry->ce_name) {
                    556:                DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
                    557:                        entry->ce_name));
                    558: 
                    559:                memset(&hints, 0, sizeof(hints));
                    560:                hints.ai_family = entry->type;
                    561:                hints.ai_socktype = SOCK_DGRAM;
                    562:                hints.ai_protocol = IPPROTO_UDP;
                    563:                /*
                    564:                 * If IPv6 is not available look only for v4 addresses
                    565:                 */
                    566:                if (!ipv6_works)
                    567:                        hints.ai_family = AF_INET;
                    568:                error = getaddrinfo(entry->ce_name, NULL, &hints, &addr);
                    569:                if (error == 0) {
                    570:                        entry->peer_store = *((sockaddr_u *)(addr->ai_addr));
                    571:                        if (IS_IPV4(&entry->peer_store)) {
                    572:                                entry->ce_peeraddr =
                    573:                                    NSRCADR(&entry->peer_store);
                    574:                                entry->ce_config.v6_flag = 0;
                    575:                        } else {
                    576:                                entry->ce_peeraddr6 =
                    577:                                    SOCK_ADDR6(&entry->peer_store);
                    578:                                entry->ce_config.v6_flag = 1;
                    579:                        }
                    580:                        freeaddrinfo(addr);
                    581:                }
                    582:        } else {
                    583:                DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
                    584:                        stoa(&entry->peer_store)));
                    585: 
                    586:                entry->ce_name = emalloc(MAXHOSTNAMELEN);
                    587:                error = getnameinfo((const struct sockaddr *)&entry->peer_store,
                    588:                                   SOCKLEN(&entry->peer_store),
                    589:                                   (char *)&entry->ce_name, MAXHOSTNAMELEN,
                    590:                                   NULL, 0, 0);
                    591:        }
                    592: 
                    593:        if (0 == error) {
                    594: 
                    595:                /* again is our return value, for success it is 1 */
                    596:                again = 1;
                    597: 
                    598:                DPRINTF(2, ("findhostaddr: %s resolved.\n", 
                    599:                        (entry->ce_name) ? "name" : "address"));
                    600:        } else {
                    601:                /*
                    602:                 * If the resolver failed, see if the failure is
                    603:                 * temporary. If so, return success.
                    604:                 */
                    605:                again = 0;
                    606: 
                    607:                switch (error) {
                    608: 
                    609:                case EAI_FAIL:
                    610:                        again = 1;
                    611:                        break;
                    612: 
                    613:                case EAI_AGAIN:
                    614:                        again = 1;
                    615:                        eai_again_seen = 1;
                    616:                        break;
                    617: 
                    618:                case EAI_NONAME:
                    619: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
                    620:                case EAI_NODATA:
                    621: #endif
                    622:                        msyslog(LOG_ERR, "host name not found%s%s: %s",
                    623:                                (EAI_NONAME == error) ? "" : " EAI_NODATA",
                    624:                                (eai_again_seen) ? " (permanent)" : "",
                    625:                                entry->ce_name);
                    626:                        again = !eai_again_seen;
                    627:                        break;
                    628: 
                    629: #ifdef EAI_SYSTEM
                    630:                case EAI_SYSTEM:
                    631:                        /* 
                    632:                         * EAI_SYSTEM means the real error is in errno.  We should be more
                    633:                         * discriminating about which errno values require retrying, but
                    634:                         * this matches existing behavior.
                    635:                         */
                    636:                        again = 1;
                    637:                        DPRINTF(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n",
                    638:                                errno, strerror(errno)));
                    639:                        break;
                    640: #endif
                    641:                }
                    642: 
                    643:                /* do this here to avoid perturbing errno earlier */
                    644:                DPRINTF(2, ("intres: got error status of: %d\n", error));
                    645:        }
                    646: 
                    647:        return again;
                    648: }
                    649: 
                    650: 
                    651: /*
                    652:  * openntp - open a socket to the ntp server
                    653:  */
                    654: static void
                    655: openntp(void)
                    656: {
                    657:        const char      *localhost = "127.0.0.1";       /* Use IPv4 loopback */
                    658:        struct addrinfo hints;
                    659:        struct addrinfo *addr;
                    660:        u_long          on;
                    661:        int             err;
                    662: 
                    663:        if (sockfd != INVALID_SOCKET)
                    664:                return;
                    665: 
                    666:        memset(&hints, 0, sizeof(hints));
                    667: 
                    668:        /*
                    669:         * For now only bother with IPv4
                    670:         */
                    671:        hints.ai_family = AF_INET;
                    672:        hints.ai_socktype = SOCK_DGRAM;
                    673: 
                    674:        err = getaddrinfo(localhost, "ntp", &hints, &addr);
                    675: 
                    676:        if (err) {
                    677: #ifdef EAI_SYSTEM
                    678:                if (EAI_SYSTEM == err)
                    679:                        msyslog(LOG_ERR, "getaddrinfo(%s) failed: %m",
                    680:                                localhost);
                    681:                else
                    682: #endif
                    683:                        msyslog(LOG_ERR, "getaddrinfo(%s) failed: %s",
                    684:                                localhost, gai_strerror(err));
                    685:                resolver_exit(1);
                    686:        }
                    687: 
                    688:        sockfd = socket(addr->ai_family, addr->ai_socktype, 0);
                    689: 
                    690:        if (INVALID_SOCKET == sockfd) {
                    691:                msyslog(LOG_ERR, "socket() failed: %m");
                    692:                resolver_exit(1);
                    693:        }
                    694: 
                    695: #ifndef SYS_WINNT
                    696:        /*
                    697:         * On Windows only the count of sockets must be less than
                    698:         * FD_SETSIZE. On Unix each descriptor's value must be less
                    699:         * than FD_SETSIZE, as fd_set is a bit array.
                    700:         */
                    701:        if (sockfd >= FD_SETSIZE) {
                    702:                msyslog(LOG_ERR, "socket fd %d too large, FD_SETSIZE %d",
                    703:                        (int)sockfd, FD_SETSIZE);
                    704:                resolver_exit(1);
                    705:        }
                    706: 
                    707:        /*
                    708:         * Make the socket non-blocking.  We'll wait with select()
                    709:         * Unix: fcntl(O_NONBLOCK) or fcntl(FNDELAY)
                    710:         */
                    711: # ifdef O_NONBLOCK
                    712:        if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
                    713:                msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
                    714:                resolver_exit(1);
                    715:        }
                    716: # else
                    717: #  ifdef FNDELAY
                    718:        if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
                    719:                msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
                    720:                resolver_exit(1);
                    721:        }
                    722: #  else
                    723: #   include "Bletch: NEED NON BLOCKING IO"
                    724: #  endif       /* FNDDELAY */
                    725: # endif        /* O_NONBLOCK */
                    726:        (void)on;       /* quiet unused warning */
                    727: #else  /* !SYS_WINNT above */
                    728:        /*
                    729:         * Make the socket non-blocking.  We'll wait with select()
                    730:         * Windows: ioctlsocket(FIONBIO)
                    731:         */
                    732:        on = 1;
                    733:        err = ioctlsocket(sockfd, FIONBIO, &on);
                    734:        if (SOCKET_ERROR == err) {
                    735:                msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
                    736:                resolver_exit(1);
                    737:        }
                    738: #endif /* SYS_WINNT */
                    739: 
                    740:        err = connect(sockfd, addr->ai_addr, addr->ai_addrlen);
                    741:        if (SOCKET_ERROR == err) {
                    742:                msyslog(LOG_ERR, "openntp: connect() failed: %m");
                    743:                resolver_exit(1);
                    744:        }
                    745: 
                    746:        freeaddrinfo(addr);
                    747: }
                    748: 
                    749: 
                    750: /*
                    751:  * request - send a configuration request to the server, wait for a response
                    752:  */
                    753: static int
                    754: request(
                    755:        struct conf_peer *conf
                    756:        )
                    757: {
                    758:        struct sock_timeval tvout;
                    759:        struct req_pkt reqpkt;
                    760:        size_t  req_len;
                    761:        size_t  total_len;      /* req_len plus keyid & digest */
                    762:        fd_set  fdset;
                    763:        l_fp    ts;
                    764:        char *  pch;
                    765:        char *  pchEnd;
                    766:        l_fp *  pts;
                    767:        keyid_t *pkeyid;
                    768:        int n;
                    769: #ifdef SYS_WINNT
                    770:        HANDLE  hReadWriteEvent = NULL;
                    771:        BOOL    ret;
                    772:        DWORD   NumberOfBytesWritten, NumberOfBytesRead, dwWait;
                    773:        OVERLAPPED overlap;
                    774: #endif /* SYS_WINNT */
                    775: 
                    776:        checkparent();          /* make sure our guy is still running */
                    777: 
                    778:        if (sockfd == INVALID_SOCKET)
                    779:                openntp();
                    780:        
                    781: #ifdef SYS_WINNT
                    782:        hReadWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
                    783: #endif /* SYS_WINNT */
                    784: 
                    785:        /*
                    786:         * Try to clear out any previously received traffic so it
                    787:         * doesn't fool us.  Note the socket is nonblocking.
                    788:         */
                    789:        tvout.tv_sec =  0;
                    790:        tvout.tv_usec = 0;
                    791:        FD_ZERO(&fdset);
                    792:        FD_SET(sockfd, &fdset);
                    793:        while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) >
                    794:               0) {
                    795:                recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0);
                    796:                FD_ZERO(&fdset);
                    797:                FD_SET(sockfd, &fdset);
                    798:        }
                    799: 
                    800:        /*
                    801:         * Make up a request packet with the configuration info
                    802:         */
                    803:        memset(&reqpkt, 0, sizeof(reqpkt));
                    804: 
                    805:        reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
                    806:        reqpkt.auth_seq = AUTH_SEQ(1, 0);       /* authenticated, no seq */
                    807:        reqpkt.implementation = IMPL_XNTPD;     /* local implementation */
                    808:        reqpkt.request = REQ_CONFIG;            /* configure a new peer */
                    809:        reqpkt.err_nitems = ERR_NITEMS(0, 1);   /* one item */
                    810:        reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(*conf));
                    811:        /* Make sure mbz_itemsize <= sizeof reqpkt.data */
                    812:        if (sizeof(*conf) > sizeof(reqpkt.data)) {
                    813:                msyslog(LOG_ERR,
                    814:                        "Bletch: conf_peer is too big for reqpkt.data!");
                    815:                resolver_exit(1);
                    816:        }
                    817:        memcpy(reqpkt.data, conf, sizeof(*conf));
                    818: 
                    819:        if (sys_authenticate && req_hashlen > 16) {
                    820:                pch = reqpkt.data; 
                    821:                /* 32-bit alignment */
                    822:                pch += (sizeof(*conf) + 3) & ~3;
                    823:                pts = (void *)pch;
                    824:                pkeyid = (void *)(pts + 1);
                    825:                pchEnd = (void *)pkeyid;
                    826:                req_len = pchEnd - (char *)&reqpkt;
                    827:                pchEnd = (void *)(pkeyid + 1);
                    828:                pchEnd += req_hashlen;
                    829:                total_len = pchEnd - (char *)&reqpkt;
                    830:                if (total_len > sizeof(reqpkt)) {
                    831:                        msyslog(LOG_ERR,
                    832:                                "intres total_len %lu limit is %lu (%lu octet digest)\n",
                    833:                                (u_long)total_len,
                    834:                                (u_long)sizeof(reqpkt),
                    835:                                (u_long)req_hashlen);
                    836:                        resolver_exit(1);
                    837:                }
                    838:        } else {
                    839:                pts = &reqpkt.tstamp;
                    840:                pkeyid = &reqpkt.keyid;
                    841:                req_len = REQ_LEN_NOMAC;
                    842:        }
                    843: 
                    844:        *pkeyid = htonl(req_keyid);
                    845:        get_systime(&ts);
                    846:        L_ADDUF(&ts, SKEWTIME);
                    847:        HTONL_FP(&ts, pts);
                    848:        if (sys_authenticate) {
                    849:                n = authencrypt(req_keyid, (void *)&reqpkt, req_len);
                    850:                if ((size_t)n != req_hashlen + sizeof(reqpkt.keyid)) {
                    851:                        msyslog(LOG_ERR,
                    852:                                "intres maclen %d expected %lu\n",
                    853:                                n, (u_long)(req_hashlen +
                    854:                                sizeof(reqpkt.keyid)));
                    855:                        resolver_exit(1);
                    856:                }
                    857:                req_len += n;
                    858:        }
                    859: 
                    860:        /*
                    861:         * Done.  Send it.
                    862:         */
                    863: #ifndef SYS_WINNT
                    864:        n = send(sockfd, (char *)&reqpkt, req_len, 0);
                    865:        if (n < 0) {
                    866:                msyslog(LOG_ERR, "send to NTP server failed: %m");
                    867:                return 0;       /* maybe should exit */
                    868:        }
                    869: #else
                    870:        /* In the NT world, documentation seems to indicate that there
                    871:         * exist _write and _read routines that can be used to do blocking
                    872:         * I/O on sockets. Problem is these routines require a socket
                    873:         * handle obtained through the _open_osf_handle C run-time API
                    874:         * of which there is no explanation in the documentation. We need
                    875:         * nonblocking write's and read's anyway for our purpose here.
                    876:         * We're therefore forced to deviate a little bit from the Unix
                    877:         * model here and use the ReadFile and WriteFile Win32 I/O API's
                    878:         * on the socket
                    879:         */
                    880:        overlap.Offset = overlap.OffsetHigh = (DWORD)0;
                    881:        overlap.hEvent = hReadWriteEvent;
                    882:        ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, req_len,
                    883:                        NULL, (LPOVERLAPPED)&overlap);
                    884:        if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
                    885:                msyslog(LOG_ERR, "send to NTP server failed: %m");
                    886:                return 0;
                    887:        }
                    888:        dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
                    889:        if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
                    890:                if (dwWait == WAIT_FAILED)
                    891:                    msyslog(LOG_ERR, "WaitForSingleObject failed: %m");
                    892:                return 0;
                    893:        }
                    894:        if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
                    895:                                (LPDWORD)&NumberOfBytesWritten, FALSE)) {
                    896:                msyslog(LOG_ERR, "GetOverlappedResult for WriteFile fails: %m");
                    897:                return 0;
                    898:        }
                    899: #endif /* SYS_WINNT */
                    900: 
                    901: 
                    902:        /*
                    903:         * Wait for a response.  A weakness of the mode 7 protocol used
                    904:         * is that there is no way to associate a response with a
                    905:         * particular request, i.e. the response to this configuration
                    906:         * request is indistinguishable from that to any other.  I should
                    907:         * fix this some day.  In any event, the time out is fairly
                    908:         * pessimistic to make sure that if an answer is coming back
                    909:         * at all, we get it.
                    910:         */
                    911:        for (;;) {
                    912:                FD_ZERO(&fdset);
                    913:                FD_SET(sockfd, &fdset);
                    914:                tvout.tv_sec = TIMEOUT_SEC;
                    915:                tvout.tv_usec = TIMEOUT_USEC;
                    916: 
                    917:                n = select(sockfd + 1, &fdset, (fd_set *)0,
                    918:                           (fd_set *)0, &tvout);
                    919: 
                    920:                if (n < 0) {
                    921:                        if (errno != EINTR)
                    922:                                msyslog(LOG_ERR, "select() fails: %m");
                    923:                        return 0;
                    924:                } else if (n == 0) {
                    925: #ifdef DEBUG
                    926:                        if (debug)
                    927:                                msyslog(LOG_INFO, "ntp_intres select() returned 0.");
                    928: #endif
                    929:                        return 0;
                    930:                }
                    931: 
                    932: #ifndef SYS_WINNT
                    933:                n = recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0);
                    934:                if (n <= 0) {
                    935:                        if (n < 0) {
                    936:                                msyslog(LOG_ERR, "recv() fails: %m");
                    937:                                return 0;
                    938:                        }
                    939:                        continue;
                    940:                }
                    941: #else /* Overlapped I/O used on non-blocking sockets on Windows NT */
                    942:                ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, sizeof(reqpkt),
                    943:                               NULL, (LPOVERLAPPED)&overlap);
                    944:                if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
                    945:                        msyslog(LOG_ERR, "ReadFile() fails: %m");
                    946:                        return 0;
                    947:                }
                    948:                dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
                    949:                if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
                    950:                        if (dwWait == WAIT_FAILED) {
                    951:                                msyslog(LOG_ERR, "WaitForSingleObject for ReadFile fails: %m");
                    952:                                return 0;
                    953:                        }
                    954:                        continue;
                    955:                }
                    956:                if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
                    957:                                        (LPDWORD)&NumberOfBytesRead, FALSE)) {
                    958:                        msyslog(LOG_ERR, "GetOverlappedResult fails: %m");
                    959:                        return 0;
                    960:                }
                    961:                n = NumberOfBytesRead;
                    962: #endif /* SYS_WINNT */
                    963: 
                    964:                /*
                    965:                 * Got one.  Check through to make sure it is what
                    966:                 * we expect.
                    967:                 */
                    968:                if (n < RESP_HEADER_SIZE) {
                    969:                        msyslog(LOG_ERR, "received runt response (%d octets)",
                    970:                                n);
                    971:                        continue;
                    972:                }
                    973: 
                    974:                if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
                    975: #ifdef DEBUG
                    976:                        if (debug > 1)
                    977:                            msyslog(LOG_INFO, "received non-response packet");
                    978: #endif
                    979:                        continue;
                    980:                }
                    981: 
                    982:                if (ISMORE(reqpkt.rm_vn_mode)) {
                    983: #ifdef DEBUG
                    984:                        if (debug > 1)
                    985:                            msyslog(LOG_INFO, "received fragmented packet");
                    986: #endif
                    987:                        continue;
                    988:                }
                    989: 
                    990:                if ( ( (INFO_VERSION(reqpkt.rm_vn_mode) < 2)
                    991:                       || (INFO_VERSION(reqpkt.rm_vn_mode) > NTP_VERSION))
                    992:                     || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
                    993: #ifdef DEBUG
                    994:                        if (debug > 1)
                    995:                            msyslog(LOG_INFO,
                    996:                                    "version (%d/%d) or mode (%d/%d) incorrect",
                    997:                                    INFO_VERSION(reqpkt.rm_vn_mode),
                    998:                                    NTP_VERSION,
                    999:                                    INFO_MODE(reqpkt.rm_vn_mode),
                   1000:                                    MODE_PRIVATE);
                   1001: #endif
                   1002:                        continue;
                   1003:                }
                   1004: 
                   1005:                if (INFO_SEQ(reqpkt.auth_seq) != 0) {
                   1006: #ifdef DEBUG
                   1007:                        if (debug > 1)
                   1008:                            msyslog(LOG_INFO,
                   1009:                                    "nonzero sequence number (%d)",
                   1010:                                    INFO_SEQ(reqpkt.auth_seq));
                   1011: #endif
                   1012:                        continue;
                   1013:                }
                   1014: 
                   1015:                if (reqpkt.implementation != IMPL_XNTPD ||
                   1016:                    reqpkt.request != REQ_CONFIG) {
                   1017: #ifdef DEBUG
                   1018:                        if (debug > 1)
                   1019:                            msyslog(LOG_INFO,
                   1020:                                    "implementation (%d) or request (%d) incorrect",
                   1021:                                    reqpkt.implementation, reqpkt.request);
                   1022: #endif
                   1023:                        continue;
                   1024:                }
                   1025: 
                   1026:                if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
                   1027:                    INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
                   1028:                    INFO_ITEMSIZE(reqpkt.mbz_itemsize) != 0) {
                   1029: #ifdef DEBUG
                   1030:                        if (debug > 1)
                   1031:                            msyslog(LOG_INFO,
                   1032:                                    "nitems (%d) mbz (%d) or itemsize (%d) nonzero",
                   1033:                                    INFO_NITEMS(reqpkt.err_nitems),
                   1034:                                    INFO_MBZ(reqpkt.mbz_itemsize),
                   1035:                                    INFO_ITEMSIZE(reqpkt.mbz_itemsize));
                   1036: #endif
                   1037:                        continue;
                   1038:                }
                   1039: 
                   1040:                n = INFO_ERR(reqpkt.err_nitems);
                   1041:                switch (n) {
                   1042:                    case INFO_OKAY:
                   1043:                        /* success */
                   1044:                        return 1;
                   1045:                
                   1046:                    case INFO_ERR_NODATA:
                   1047:                        /*
                   1048:                         * newpeer() refused duplicate association, no
                   1049:                         * point in retrying so call it success.
                   1050:                         */
                   1051:                        return 1;
                   1052:                
                   1053:                    case INFO_ERR_IMPL:
                   1054:                        msyslog(LOG_ERR,
                   1055:                                "ntp_intres.request: implementation mismatch");
                   1056:                        return 0;
                   1057:                
                   1058:                    case INFO_ERR_REQ:
                   1059:                        msyslog(LOG_ERR,
                   1060:                                "ntp_intres.request: request unknown");
                   1061:                        return 0;
                   1062:                
                   1063:                    case INFO_ERR_FMT:
                   1064:                        msyslog(LOG_ERR,
                   1065:                                "ntp_intres.request: format error");
                   1066:                        return 0;
                   1067: 
                   1068:                    case INFO_ERR_AUTH:
                   1069:                        msyslog(LOG_ERR,
                   1070:                                "ntp_intres.request: permission denied");
                   1071:                        return 0;
                   1072: 
                   1073:                    default:
                   1074:                        msyslog(LOG_ERR,
                   1075:                                "ntp_intres.request: unknown error code %d", n);
                   1076:                        return 0;
                   1077:                }
                   1078:        }
                   1079: }
                   1080: 
                   1081: 
                   1082: /*
                   1083:  * nexttoken - return the next token from a line
                   1084:  */
                   1085: static char *
                   1086: nexttoken(
                   1087:        char **lptr
                   1088:        )
                   1089: {
                   1090:        register char *cp;
                   1091:        register char *tstart;
                   1092: 
                   1093:        cp = *lptr;
                   1094: 
                   1095:        /*
                   1096:         * Skip leading white space
                   1097:         */
                   1098:        while (*cp == ' ' || *cp == '\t')
                   1099:            cp++;
                   1100:        
                   1101:        /*
                   1102:         * If this is the end of the line, return nothing.
                   1103:         */
                   1104:        if (*cp == '\n' || *cp == '\0') {
                   1105:                *lptr = cp;
                   1106:                return NULL;
                   1107:        }
                   1108:        
                   1109:        /*
                   1110:         * Must be the start of a token.  Record the pointer and look
                   1111:         * for the end.
                   1112:         */
                   1113:        tstart = cp++;
                   1114:        while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')
                   1115:            cp++;
                   1116:        
                   1117:        /*
                   1118:         * Terminate the token with a \0.  If this isn't the end of the
                   1119:         * line, space to the next character.
                   1120:         */
                   1121:        if (*cp == '\n' || *cp == '\0')
                   1122:            *cp = '\0';
                   1123:        else
                   1124:            *cp++ = '\0';
                   1125: 
                   1126:        *lptr = cp;
                   1127:        return tstart;
                   1128: }
                   1129: 
                   1130: 
                   1131: /*
                   1132:  * readconf - read the configuration information out of the file we
                   1133:  *           were passed.  Note that since the file is supposed to be
                   1134:  *           machine generated, we bail out at the first sign of trouble.
                   1135:  */
                   1136: static void
                   1137: readconf(
                   1138:        FILE *fp,
                   1139:        char *name
                   1140:        )
                   1141: {
                   1142:        register int i;
                   1143:        char *token[NUMTOK];
                   1144:        u_long intval[NUMTOK];
                   1145:        u_int flags;
                   1146:        char buf[MAXLINESIZE];
                   1147:        char *bp;
                   1148: 
                   1149:        while (fgets(buf, MAXLINESIZE, fp) != NULL) {
                   1150: 
                   1151:                bp = buf;
                   1152:                for (i = 0; i < NUMTOK; i++) {
                   1153:                        if ((token[i] = nexttoken(&bp)) == NULL) {
                   1154:                                msyslog(LOG_ERR,
                   1155:                                        "tokenizing error in file `%s', quitting",
                   1156:                                        name);
                   1157:                                resolver_exit(1);
                   1158:                        }
                   1159:                }
                   1160: 
                   1161:                for (i = 1; i < NUMTOK - 1; i++) {
                   1162:                        if (!atouint(token[i], &intval[i])) {
                   1163:                                msyslog(LOG_ERR,
                   1164:                                        "format error for integer token `%s', file `%s', quitting",
                   1165:                                        token[i], name);
                   1166:                                resolver_exit(1);
                   1167:                        }
                   1168:                }
                   1169: 
                   1170: #if 0 /* paranoid checking - these are done in newpeer() */
                   1171:                if (intval[TOK_HMODE] != MODE_ACTIVE &&
                   1172:                    intval[TOK_HMODE] != MODE_CLIENT &&
                   1173:                    intval[TOK_HMODE] != MODE_BROADCAST) {
                   1174:                        msyslog(LOG_ERR, "invalid mode (%ld) in file %s",
                   1175:                                intval[TOK_HMODE], name);
                   1176:                        resolver_exit(1);
                   1177:                }
                   1178: 
                   1179:                if (intval[TOK_VERSION] > NTP_VERSION ||
                   1180:                    intval[TOK_VERSION] < NTP_OLDVERSION) {
                   1181:                        msyslog(LOG_ERR, "invalid version (%ld) in file %s",
                   1182:                                intval[TOK_VERSION], name);
                   1183:                        resolver_exit(1);
                   1184:                }
                   1185:                if (intval[TOK_MINPOLL] < ntp_minpoll ||
                   1186:                    intval[TOK_MINPOLL] > NTP_MAXPOLL) {
                   1187: 
                   1188:                        msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",
                   1189:                                intval[TOK_MINPOLL], name);
                   1190:                        resolver_exit(1);
                   1191:                }
                   1192: 
                   1193:                if (intval[TOK_MAXPOLL] < ntp_minpoll ||
                   1194:                    intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
                   1195:                        msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",
                   1196:                                intval[TOK_MAXPOLL], name);
                   1197:                        resolver_exit(1);
                   1198:                }
                   1199: 
                   1200:                if ((intval[TOK_FLAGS] & ~(FLAG_PREFER | FLAG_NOSELECT |
                   1201:                    FLAG_BURST | FLAG_IBURST | FLAG_SKEY)) != 0) {
                   1202:                        msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
                   1203:                                intval[TOK_FLAGS], name);
                   1204:                        resolver_exit(1);
                   1205:                }
                   1206: #endif /* end paranoid checking */
                   1207: 
                   1208:                flags = 0;
                   1209:                if (intval[TOK_FLAGS] & FLAG_PREFER)
                   1210:                    flags |= CONF_FLAG_PREFER;
                   1211:                if (intval[TOK_FLAGS] & FLAG_NOSELECT)
                   1212:                    flags |= CONF_FLAG_NOSELECT;
                   1213:                if (intval[TOK_FLAGS] & FLAG_BURST)
                   1214:                    flags |= CONF_FLAG_BURST;
                   1215:                if (intval[TOK_FLAGS] & FLAG_IBURST)
                   1216:                    flags |= CONF_FLAG_IBURST;
                   1217: 
                   1218: #ifdef OPENSSL
                   1219:                if (intval[TOK_FLAGS] & FLAG_SKEY)
                   1220:                    flags |= CONF_FLAG_SKEY;
                   1221: #endif /* OPENSSL */
                   1222: 
                   1223:                /*
                   1224:                 * This is as good as we can check it.  Add it in.
                   1225:                 */
                   1226:                addentry(token[TOK_HOSTNAME],
                   1227:                         (int)intval[TOK_NEEDED], (int)intval[TOK_TYPE],
                   1228:                         (int)intval[TOK_HMODE], (int)intval[TOK_VERSION],
                   1229:                         (int)intval[TOK_MINPOLL], (int)intval[TOK_MAXPOLL],
                   1230:                         flags, (int)intval[TOK_TTL],
                   1231:                         intval[TOK_KEYID], token[TOK_KEYSTR]);
                   1232:        }
                   1233: }
                   1234: 
                   1235: 
                   1236: /*
                   1237:  * doconfigure - attempt to resolve names and configure the server
                   1238:  */
                   1239: static void
                   1240: doconfigure(
                   1241:        int dores
                   1242:        )
                   1243: {
                   1244:        register struct conf_entry *ce;
                   1245: 
                   1246: #ifdef DEBUG
                   1247:                if (debug > 1)
                   1248:                        msyslog(LOG_INFO, "Running doconfigure %s DNS",
                   1249:                            dores ? "with" : "without" );
                   1250: #endif
                   1251: 
                   1252: #if defined(HAVE_RES_INIT)
                   1253:        if (dores)         /* Reload /etc/resolv.conf - bug 1226 */
                   1254:                res_init();
                   1255: #endif
                   1256:        ce = confentries;
                   1257:        while (ce != NULL) {
                   1258: #ifdef DEBUG
                   1259:                if (debug > 1)
                   1260:                        msyslog(LOG_INFO,
                   1261:                            "doconfigure: <%s> has peeraddr %s",
                   1262:                            ce->ce_name, stoa(&ce->peer_store));
                   1263: #endif
                   1264:                if (dores && SOCK_UNSPEC(&ce->peer_store)) {
                   1265:                        if (!findhostaddr(ce)) {
                   1266: #ifndef IGNORE_DNS_ERRORS
                   1267:                                msyslog(LOG_ERR,
                   1268:                                        "couldn't resolve `%s', giving up on it",
                   1269:                                        ce->ce_name);
                   1270:                                ce = removeentry(ce);
                   1271:                                continue;
                   1272: #endif
                   1273:                        } else if (!SOCK_UNSPEC(&ce->peer_store))
                   1274:                                msyslog(LOG_INFO,
                   1275:                                        "DNS %s -> %s", ce->ce_name,
                   1276:                                        stoa(&ce->peer_store));
                   1277:                }
                   1278: 
                   1279:                if (!SOCK_UNSPEC(&ce->peer_store)) {
                   1280:                        if (request(&ce->ce_config)) {
                   1281:                                ce = removeentry(ce);
                   1282:                                continue;
                   1283:                        }
                   1284:                        /* 
                   1285:                         * Failed case.  Should bump counter and give 
                   1286:                         * up.
                   1287:                         */
                   1288: #ifdef DEBUG
                   1289:                        if (debug > 1) {
                   1290:                                msyslog(LOG_INFO,
                   1291:                                    "doconfigure: request() FAILED, maybe next time.");
                   1292:                        }
                   1293: #endif
                   1294:                }
                   1295:                ce = ce->ce_next;
                   1296:        }
                   1297: }
                   1298: 
                   1299: #else  /* NO_INTRES follows */
                   1300: int ntp_intres_nonempty_compilation_unit;
                   1301: #endif

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