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