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.
8 * ntpres - process configuration entries which require use of the resolver
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.
23 #include "ntp_machine.h"
26 #include "ntp_request.h"
27 #include "ntp_stdlib.h"
28 #include "ntp_syslog.h"
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
39 #ifdef HAVE_SYS_PARAM_H
40 # include <sys/param.h> /* MAXHOSTNAMELEN (often) */
44 #include <isc/result.h>
46 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
49 * Each item we are to resolve and configure gets one of these
50 * structures defined for it.
53 struct conf_entry *ce_next;
54 char *ce_name; /* name we are trying to resolve */
55 struct conf_peer ce_config; /* configuration info for peer */
56 struct sockaddr_storage peer_store; /* address info for both fams */
58 #define ce_peeraddr ce_config.peeraddr
59 #define ce_peeraddr6 ce_config.peeraddr6
60 #define ce_hmode ce_config.hmode
61 #define ce_version ce_config.version
62 #define ce_minpoll ce_config.minpoll
63 #define ce_maxpoll ce_config.maxpoll
64 #define ce_flags ce_config.flags
65 #define ce_ttl ce_config.ttl
66 #define ce_keyid ce_config.keyid
67 #define ce_keystr ce_config.keystr
70 * confentries is a pointer to the list of configuration entries
73 static struct conf_entry *confentries = NULL;
76 * We take an interrupt every thirty seconds, at which time we decrement
77 * config_timer and resolve_timer. The former is set to 2, so we retry
78 * unsucessful reconfigurations every minute. The latter is set to
79 * an exponentially increasing value which starts at 2 and increases to
80 * 32. When this expires we retry failed name resolutions.
82 * We sleep SLEEPTIME seconds before doing anything, to give the server
83 * time to arrange itself.
91 static volatile int config_timer = 0;
92 static volatile int resolve_timer = 0;
94 static int resolve_value; /* next value of resolve timer */
99 #define LOCALHOST 0x7f000001 /* 127.0.0.1, in hex, of course */
100 #define SKEWTIME 0x08000000 /* 0.03125 seconds as a l_fp fraction */
103 * Select time out. Set to 2 seconds. The server is on the local machine,
106 #define TIMEOUT_SEC 2
107 #define TIMEOUT_USEC 0
111 * Input processing. The data on each line in the configuration file
112 * is supposed to consist of entries in the following order
114 #define TOK_HOSTNAME 0
117 #define TOK_VERSION 3
118 #define TOK_MINPOLL 4
119 #define TOK_MAXPOLL 5
126 #define MAXLINESIZE 512
130 * File descriptor for ntp request code.
132 static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */
134 /* stuff to be filled in by caller */
136 keyid_t req_keyid; /* request keyid */
137 char *req_file; /* name of the file with configuration info */
139 /* end stuff to be filled in */
142 static void checkparent P((void));
143 static void removeentry P((struct conf_entry *));
144 static void addentry P((char *, int, int, int, int, u_int,
145 int, keyid_t, char *, u_char));
146 static int findhostaddr P((struct conf_entry *));
147 static void openntp P((void));
148 static int request P((struct conf_peer *));
149 static char * nexttoken P((char **));
150 static void readconf P((FILE *, char *));
151 static void doconfigure P((int));
153 struct ntp_res_t_pkt { /* Tagged packet: */
154 void *tag; /* For the caller */
155 u_int32 paddr; /* IP to look up, or 0 */
156 char name[MAXHOSTNAMELEN]; /* Name to look up (if 1st byte is not 0) */
159 struct ntp_res_c_pkt { /* Control packet: */
160 char name[MAXHOSTNAMELEN];
169 u_char keystr[MAXFILENAME];
173 static void resolver_exit P((int));
176 * Call here instead of just exiting
179 static void resolver_exit (int code)
182 CloseHandle(ResolverEventHandle);
183 ResolverEventHandle = NULL;
184 ExitThread(code); /* Just to kill the thread not the process */
186 exit(code); /* kill the forked process */
191 * ntp_res_recv: Process an answer from the resolver
198 We have data ready on our descriptor.
199 It may be an EOF, meaning the resolver process went away.
200 Otherwise, it will be an "answer".
208 * req_key(???), req_keyid, req_file valid
226 msyslog(LOG_INFO, "NTP_INTRES running");
230 /* check out auth stuff */
231 if (sys_authenticate) {
232 if (!authistrusted(req_keyid)) {
233 msyslog(LOG_ERR, "invalid request keyid %08x",
240 * Read the configuration info
241 * {this is bogus, since we are forked, but it is easier
242 * to keep this code - gdt}
244 if ((in = fopen(req_file, "r")) == NULL) {
245 msyslog(LOG_ERR, "can't open configuration file %s: %m",
249 readconf(in, req_file);
255 (void) unlink(req_file);
258 * Set up the timers to do first shot immediately.
261 resolve_value = MINRESOLVE;
262 config_timer = CONFIG_TIME;
267 if (resolve_timer == 0) {
269 * Sleep a little to make sure the network is completely up
274 /* prepare retry, in case there's more work to do */
275 resolve_timer = resolve_value;
278 msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
280 if (resolve_value < MAXRESOLVE)
283 config_timer = CONFIG_TIME;
284 } else if (config_timer == 0) { /* MB: in which case would this be required ? */
286 /* MB: should we check now if we could exit, similar to the code above? */
287 config_timer = CONFIG_TIME;
290 msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
294 if (confentries == NULL)
295 resolver_exit(0); /* done */
298 rc = WaitForSingleObject(ResolverEventHandle, 1000 * ALARM_TIME); /* in milliseconds */
300 if ( rc == WAIT_OBJECT_0 ) { /* signaled by the main thread */
301 resolve_timer = 0; /* retry resolving immediately */
305 if ( rc != WAIT_TIMEOUT ) /* not timeout: error */
308 #else /* not SYS_WINNT */
309 tv.tv_sec = ALARM_TIME;
312 FD_SET(resolver_pipe_fd[0], &fdset);
313 rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
315 if (rc > 0) { /* parent process has written to the pipe */
316 read(resolver_pipe_fd[0], (char *)&rc, sizeof(rc)); /* make pipe empty */
317 resolve_timer = 0; /* retry resolving immediately */
321 if ( rc < 0 ) /* select() returned error */
325 /* normal timeout, keep on waiting */
326 if (config_timer > 0)
328 if (resolve_timer > 0)
336 * checkparent - see if our parent process is still running
338 * No need to worry in the Windows NT environment whether the
339 * main thread is still running, because if it goes
340 * down it takes the whole process down with it (in
341 * which case we won't be running this thread either)
342 * Turn function into NOP;
348 #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)
351 * If our parent (the server) has died we will have been
352 * inherited by init. If so, exit.
354 if (getppid() == 1) {
355 msyslog(LOG_INFO, "parent died before we finished, exiting");
358 #endif /* SYS_WINNT && SYS_VXWORKS*/
364 * removeentry - we are done with an entry, remove it from the list
368 struct conf_entry *entry
371 register struct conf_entry *ce;
375 confentries = ce->ce_next;
380 if (ce->ce_next == entry) {
381 ce->ce_next = entry->ce_next;
390 * addentry - add an entry to the configuration list
407 register struct conf_entry *ce;
413 "intres: <%s> %u %d %d %d %d %x %d %x %s\n", name, peeraf,
414 mode, version, minpoll, maxpoll, flags, ttl, keyid,
417 len = strlen(name) + 1;
418 cp = (char *)emalloc(len);
419 memmove(cp, name, len);
421 ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
424 #ifdef ISC_PLATFORM_HAVEIPV6
425 ce->ce_peeraddr6 = in6addr_any;
427 ANYSOCK(&ce->peer_store);
428 ce->peer_store.ss_family = peeraf; /* Save AF for getaddrinfo hints. */
429 ce->ce_hmode = (u_char)mode;
430 ce->ce_version = (u_char)version;
431 ce->ce_minpoll = (u_char)minpoll;
432 ce->ce_maxpoll = (u_char)maxpoll;
433 ce->ce_flags = (u_char)flags;
434 ce->ce_ttl = (u_char)ttl;
435 ce->ce_keyid = keyid;
436 strncpy((char *)ce->ce_keystr, keystr, MAXFILENAME);
439 if (confentries == NULL) {
442 register struct conf_entry *cep;
444 for (cep = confentries; cep->ce_next != NULL;
453 * findhostaddr - resolve a host name into an address (Or vice-versa)
455 * Given one of {ce_peeraddr,ce_name}, find the other one.
456 * It returns 1 for "success" and 0 for an uncorrectable failure.
457 * Note that "success" includes try again errors. You can tell that you
458 * got a "try again" since {ce_peeraddr,ce_name} will still be zero.
462 struct conf_entry *entry
465 static int eai_again_seen = 0;
466 struct addrinfo *addr;
467 struct addrinfo hints;
471 checkparent(); /* make sure our guy is still running */
473 if (entry->ce_name != NULL && !SOCKNUL(&entry->peer_store)) {
475 msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
479 if (entry->ce_name == NULL && SOCKNUL(&entry->peer_store)) {
480 msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
484 if (entry->ce_name) {
485 DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
488 memset(&hints, 0, sizeof(hints));
489 hints.ai_family = entry->peer_store.ss_family;
490 hints.ai_socktype = SOCK_DGRAM;
492 * If the IPv6 stack is not available look only for IPv4 addresses
494 if (isc_net_probeipv6() != ISC_R_SUCCESS)
495 hints.ai_family = AF_INET;
497 error = getaddrinfo(entry->ce_name, NULL, &hints, &addr);
499 entry->peer_store = *((struct sockaddr_storage*)(addr->ai_addr));
500 if (entry->peer_store.ss_family == AF_INET) {
502 GET_INADDR(entry->peer_store);
503 entry->ce_config.v6_flag = 0;
505 entry->ce_peeraddr6 =
506 GET_INADDR6(entry->peer_store);
507 entry->ce_config.v6_flag = 1;
511 DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
512 stoa(&entry->peer_store)));
514 entry->ce_name = emalloc(MAXHOSTNAMELEN);
515 error = getnameinfo((const struct sockaddr *)&entry->peer_store,
516 SOCKLEN(&entry->peer_store),
517 (char *)&entry->ce_name, MAXHOSTNAMELEN,
523 /* again is our return value, for success it is 1 */
526 DPRINTF(2, ("findhostaddr: %s resolved.\n",
527 (entry->ce_name) ? "name" : "address"));
530 * If the resolver failed, see if the failure is
531 * temporary. If so, return success.
547 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
550 msyslog(LOG_ERR, "host name not found%s%s: %s",
551 (EAI_NONAME == error) ? "" : " EAI_NODATA",
552 (eai_again_seen) ? " (permanent)" : "",
554 again = !eai_again_seen;
560 * EAI_SYSTEM means the real error is in errno. We should be more
561 * discriminating about which errno values require retrying, but
562 * this matches existing behavior.
565 DPRINTF(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n",
566 errno, strerror(errno)));
571 /* do this here to avoid perturbing errno earlier */
572 DPRINTF(2, ("intres: got error status of: %d\n", error));
580 * openntp - open a socket to the ntp server
585 const char *localhost = "127.0.0.1"; /* Use IPv4 loopback */
586 struct addrinfo hints;
587 struct addrinfo *addr;
591 if (sockfd != INVALID_SOCKET)
594 memset(&hints, 0, sizeof(hints));
597 * For now only bother with IPv4
599 hints.ai_family = AF_INET;
600 hints.ai_socktype = SOCK_DGRAM;
602 err = getaddrinfo(localhost, "ntp", &hints, &addr);
606 if (EAI_SYSTEM == err)
607 msyslog(LOG_ERR, "getaddrinfo(%s) failed: %m",
611 msyslog(LOG_ERR, "getaddrinfo(%s) failed: %s",
612 localhost, gai_strerror(err));
616 sockfd = socket(addr->ai_family, addr->ai_socktype, 0);
618 if (INVALID_SOCKET == sockfd) {
619 msyslog(LOG_ERR, "socket() failed: %m");
625 * On Windows only the count of sockets must be less than
626 * FD_SETSIZE. On Unix each descriptor's value must be less
627 * than FD_SETSIZE, as fd_set is a bit array.
629 if (sockfd >= FD_SETSIZE) {
630 msyslog(LOG_ERR, "socket fd %d too large, FD_SETSIZE %d",
631 (int)sockfd, FD_SETSIZE);
636 * Make the socket non-blocking. We'll wait with select()
637 * Unix: fcntl(O_NONBLOCK) or fcntl(FNDELAY)
640 if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
641 msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
646 if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
647 msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
651 # include "Bletch: NEED NON BLOCKING IO"
652 # endif /* FNDDELAY */
653 # endif /* O_NONBLOCK */
654 (void)on; /* quiet unused warning */
655 #else /* !SYS_WINNT above */
657 * Make the socket non-blocking. We'll wait with select()
658 * Windows: ioctlsocket(FIONBIO)
661 err = ioctlsocket(sockfd, FIONBIO, &on);
662 if (SOCKET_ERROR == err) {
663 msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
666 #endif /* SYS_WINNT */
668 err = connect(sockfd, addr->ai_addr, addr->ai_addrlen);
669 if (SOCKET_ERROR == err) {
670 msyslog(LOG_ERR, "openntp: connect() failed: %m");
679 * request - send a configuration request to the server, wait for a response
683 struct conf_peer *conf
687 struct timeval tvout;
688 struct req_pkt reqpkt;
692 HANDLE hReadWriteEvent = NULL;
694 DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait;
696 #endif /* SYS_WINNT */
698 checkparent(); /* make sure our guy is still running */
700 if (sockfd == INVALID_SOCKET)
704 hReadWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
705 #endif /* SYS_WINNT */
708 * Try to clear out any previously received traffic so it
709 * doesn't fool us. Note the socket is nonblocking.
714 FD_SET(sockfd, &fdset);
715 while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) >
717 recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
719 FD_SET(sockfd, &fdset);
723 * Make up a request packet with the configuration info
725 memset((char *)&reqpkt, 0, sizeof(reqpkt));
727 reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
728 reqpkt.auth_seq = AUTH_SEQ(1, 0); /* authenticated, no seq */
729 reqpkt.implementation = IMPL_XNTPD; /* local implementation */
730 reqpkt.request = REQ_CONFIG; /* configure a new peer */
731 reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */
732 reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));
733 /* Make sure mbz_itemsize <= sizeof reqpkt.data */
734 if (sizeof(struct conf_peer) > sizeof (reqpkt.data)) {
735 msyslog(LOG_ERR, "Bletch: conf_peer is too big for reqpkt.data!");
738 memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));
739 reqpkt.keyid = htonl(req_keyid);
742 L_ADDUF(&ts, SKEWTIME);
743 HTONL_FP(&ts, &reqpkt.tstamp);
745 if (sys_authenticate)
746 n = authencrypt(req_keyid, (u_int32 *)&reqpkt, REQ_LEN_NOMAC);
752 n = send(sockfd, (char *)&reqpkt, (unsigned)(REQ_LEN_NOMAC + n), 0);
754 msyslog(LOG_ERR, "send to NTP server failed: %m");
755 return 0; /* maybe should exit */
758 /* In the NT world, documentation seems to indicate that there
759 * exist _write and _read routines that can be used to do blocking
760 * I/O on sockets. Problem is these routines require a socket
761 * handle obtained through the _open_osf_handle C run-time API
762 * of which there is no explanation in the documentation. We need
763 * nonblocking write's and read's anyway for our purpose here.
764 * We're therefore forced to deviate a little bit from the Unix
765 * model here and use the ReadFile and WriteFile Win32 I/O API's
768 overlap.Offset = overlap.OffsetHigh = (DWORD)0;
769 overlap.hEvent = hReadWriteEvent;
770 ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n,
771 NULL, (LPOVERLAPPED)&overlap);
772 if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
773 msyslog(LOG_ERR, "send to NTP server failed: %m");
776 dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
777 if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
778 if (dwWait == WAIT_FAILED)
779 msyslog(LOG_ERR, "WaitForSingleObject failed: %m");
782 if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
783 (LPDWORD)&NumberOfBytesWritten, FALSE)) {
784 msyslog(LOG_ERR, "GetOverlappedResult for WriteFile fails: %m");
787 #endif /* SYS_WINNT */
791 * Wait for a response. A weakness of the mode 7 protocol used
792 * is that there is no way to associate a response with a
793 * particular request, i.e. the response to this configuration
794 * request is indistinguishable from that to any other. I should
795 * fix this some day. In any event, the time out is fairly
796 * pessimistic to make sure that if an answer is coming back
801 FD_SET(sockfd, &fdset);
802 tvout.tv_sec = TIMEOUT_SEC;
803 tvout.tv_usec = TIMEOUT_USEC;
805 n = select(sockfd + 1, &fdset, (fd_set *)0,
806 (fd_set *)0, &tvout);
811 msyslog(LOG_ERR, "select() fails: %m");
818 msyslog(LOG_INFO, "select() returned 0.");
824 n = recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
827 msyslog(LOG_ERR, "recv() fails: %m");
832 #else /* Overlapped I/O used on non-blocking sockets on Windows NT */
833 ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, (DWORD)REQ_LEN_MAC,
834 NULL, (LPOVERLAPPED)&overlap);
835 if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
836 msyslog(LOG_ERR, "ReadFile() fails: %m");
839 dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
840 if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
841 if (dwWait == WAIT_FAILED) {
842 msyslog(LOG_ERR, "WaitForSingleObject for ReadFile fails: %m");
847 if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
848 (LPDWORD)&NumberOfBytesRead, FALSE)) {
849 msyslog(LOG_ERR, "GetOverlappedResult fails: %m");
852 n = NumberOfBytesRead;
853 #endif /* SYS_WINNT */
856 * Got one. Check through to make sure it is what
859 if (n < RESP_HEADER_SIZE) {
860 msyslog(LOG_ERR, "received runt response (%d octets)",
865 if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
868 msyslog(LOG_INFO, "received non-response packet");
873 if (ISMORE(reqpkt.rm_vn_mode)) {
876 msyslog(LOG_INFO, "received fragmented packet");
881 if ( ( (INFO_VERSION(reqpkt.rm_vn_mode) < 2)
882 || (INFO_VERSION(reqpkt.rm_vn_mode) > NTP_VERSION))
883 || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
887 "version (%d/%d) or mode (%d/%d) incorrect",
888 INFO_VERSION(reqpkt.rm_vn_mode),
890 INFO_MODE(reqpkt.rm_vn_mode),
896 if (INFO_SEQ(reqpkt.auth_seq) != 0) {
900 "nonzero sequence number (%d)",
901 INFO_SEQ(reqpkt.auth_seq));
906 if (reqpkt.implementation != IMPL_XNTPD ||
907 reqpkt.request != REQ_CONFIG) {
911 "implementation (%d) or request (%d) incorrect",
912 reqpkt.implementation, reqpkt.request);
917 if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
918 INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
919 INFO_ITEMSIZE(reqpkt.mbz_itemsize) != 0) {
923 "nitems (%d) mbz (%d) or itemsize (%d) nonzero",
924 INFO_NITEMS(reqpkt.err_nitems),
925 INFO_MBZ(reqpkt.mbz_itemsize),
926 INFO_ITEMSIZE(reqpkt.mbz_itemsize));
931 n = INFO_ERR(reqpkt.err_nitems);
939 "ntpd reports implementation mismatch!");
944 "ntpd says configuration request is unknown!");
949 "ntpd indicates a format error occurred!");
952 case INFO_ERR_NODATA:
954 "ntpd indicates no data available!");
959 "ntpd returns a permission denied error!");
964 "ntpd returns unknown error code %d!", n);
972 * nexttoken - return the next token from a line
980 register char *tstart;
985 * Skip leading white space
987 while (*cp == ' ' || *cp == '\t')
991 * If this is the end of the line, return nothing.
993 if (*cp == '\n' || *cp == '\0') {
999 * Must be the start of a token. Record the pointer and look
1003 while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')
1007 * Terminate the token with a \0. If this isn't the end of the
1008 * line, space to the next character.
1010 if (*cp == '\n' || *cp == '\0')
1021 * readconf - read the configuration information out of the file we
1022 * were passed. Note that since the file is supposed to be
1023 * machine generated, we bail out at the first sign of trouble.
1032 char *token[NUMTOK];
1033 u_long intval[NUMTOK];
1035 char buf[MAXLINESIZE];
1038 while (fgets(buf, MAXLINESIZE, fp) != NULL) {
1041 for (i = 0; i < NUMTOK; i++) {
1042 if ((token[i] = nexttoken(&bp)) == NULL) {
1044 "tokenizing error in file `%s', quitting",
1050 for (i = 1; i < NUMTOK - 1; i++) {
1051 if (!atouint(token[i], &intval[i])) {
1053 "format error for integer token `%s', file `%s', quitting",
1059 if (intval[TOK_PEERAF] != AF_UNSPEC && intval[TOK_PEERAF] !=
1060 AF_INET && intval[TOK_PEERAF] != AF_INET6) {
1061 msyslog(LOG_ERR, "invalid peer address family (%u) in "
1062 "file %s", intval[TOK_PEERAF], name);
1066 if (intval[TOK_HMODE] != MODE_ACTIVE &&
1067 intval[TOK_HMODE] != MODE_CLIENT &&
1068 intval[TOK_HMODE] != MODE_BROADCAST) {
1069 msyslog(LOG_ERR, "invalid mode (%ld) in file %s",
1070 intval[TOK_HMODE], name);
1074 if (intval[TOK_VERSION] > NTP_VERSION ||
1075 intval[TOK_VERSION] < NTP_OLDVERSION) {
1076 msyslog(LOG_ERR, "invalid version (%ld) in file %s",
1077 intval[TOK_VERSION], name);
1080 if (intval[TOK_MINPOLL] < NTP_MINPOLL ||
1081 intval[TOK_MINPOLL] > NTP_MAXPOLL) {
1082 msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",
1083 intval[TOK_MINPOLL], name);
1087 if (intval[TOK_MAXPOLL] < NTP_MINPOLL ||
1088 intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
1089 msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",
1090 intval[TOK_MAXPOLL], name);
1094 if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE | FLAG_PREFER |
1095 FLAG_NOSELECT | FLAG_BURST | FLAG_IBURST | FLAG_SKEY))
1097 msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
1098 intval[TOK_FLAGS], name);
1103 if (intval[TOK_FLAGS] & FLAG_AUTHENABLE)
1104 flags |= CONF_FLAG_AUTHENABLE;
1105 if (intval[TOK_FLAGS] & FLAG_PREFER)
1106 flags |= CONF_FLAG_PREFER;
1107 if (intval[TOK_FLAGS] & FLAG_NOSELECT)
1108 flags |= CONF_FLAG_NOSELECT;
1109 if (intval[TOK_FLAGS] & FLAG_BURST)
1110 flags |= CONF_FLAG_BURST;
1111 if (intval[TOK_FLAGS] & FLAG_IBURST)
1112 flags |= CONF_FLAG_IBURST;
1113 if (intval[TOK_FLAGS] & FLAG_SKEY)
1114 flags |= CONF_FLAG_SKEY;
1117 * This is as good as we can check it. Add it in.
1119 addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
1120 (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
1121 (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
1122 intval[TOK_KEYID], token[TOK_KEYSTR], (u_char)intval[TOK_PEERAF]);
1128 * doconfigure - attempt to resolve names and configure the server
1135 register struct conf_entry *ce;
1136 register struct conf_entry *ceremove;
1140 msyslog(LOG_INFO, "Running doconfigure %s DNS",
1141 dores ? "with" : "without" );
1144 if (dores) /* Reload /etc/resolv.conf - bug 1226 */
1148 while (ce != NULL) {
1152 "doconfigure: <%s> has peeraddr %s",
1153 ce->ce_name, stoa(&ce->peer_store));
1155 if (dores && SOCKNUL(&(ce->peer_store))) {
1156 if (!findhostaddr(ce)) {
1157 #ifndef IGNORE_DNS_ERRORS
1159 "couldn't resolve `%s', giving up on it",
1162 ce = ceremove->ce_next;
1163 removeentry(ceremove);
1169 if (!SOCKNUL(&ce->peer_store)) {
1170 if (request(&ce->ce_config)) {
1172 ce = ceremove->ce_next;
1173 removeentry(ceremove);
1179 "doconfigure: request() FAILED, maybe next time.");