File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / ntp_intres.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 5 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>