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.
19 * For special situations define the FORCE_DNSRETRY Macro
20 * to force retries even if it fails the lookup.
21 * Use with extreme caution since it will then retry forever.
28 #include "ntp_machine.h"
31 #include "ntp_request.h"
32 #include "ntp_stdlib.h"
33 #include "ntp_syslog.h"
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
43 #ifdef HAVE_SYS_PARAM_H
44 # include <sys/param.h> /* MAXHOSTNAMELEN (often) */
48 #include <isc/result.h>
50 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
53 * Each item we are to resolve and configure gets one of these
54 * structures defined for it.
57 struct conf_entry
*ce_next
;
58 char *ce_name
; /* name we are trying to resolve */
59 struct conf_peer ce_config
; /* configuration info for peer */
60 struct sockaddr_storage peer_store
; /* address info for both fams */
62 #define ce_peeraddr ce_config.peeraddr
63 #define ce_peeraddr6 ce_config.peeraddr6
64 #define ce_hmode ce_config.hmode
65 #define ce_version ce_config.version
66 #define ce_minpoll ce_config.minpoll
67 #define ce_maxpoll ce_config.maxpoll
68 #define ce_flags ce_config.flags
69 #define ce_ttl ce_config.ttl
70 #define ce_keyid ce_config.keyid
71 #define ce_keystr ce_config.keystr
74 * confentries is a pointer to the list of configuration entries
77 static struct conf_entry
*confentries
= NULL
;
80 * We take an interrupt every thirty seconds, at which time we decrement
81 * config_timer and resolve_timer. The former is set to 2, so we retry
82 * unsucessful reconfigurations every minute. The latter is set to
83 * an exponentially increasing value which starts at 2 and increases to
84 * 32. When this expires we retry failed name resolutions.
86 * We sleep SLEEPTIME seconds before doing anything, to give the server
87 * time to arrange itself.
95 static volatile int config_timer
= 0;
96 static volatile int resolve_timer
= 0;
98 static int resolve_value
; /* next value of resolve timer */
103 #define LOCALHOST 0x7f000001 /* 127.0.0.1, in hex, of course */
104 #define SKEWTIME 0x08000000 /* 0.03125 seconds as a l_fp fraction */
107 * Select time out. Set to 2 seconds. The server is on the local machine,
110 #define TIMEOUT_SEC 2
111 #define TIMEOUT_USEC 0
115 * Input processing. The data on each line in the configuration file
116 * is supposed to consist of entries in the following order
118 #define TOK_HOSTNAME 0
120 #define TOK_VERSION 2
121 #define TOK_MINPOLL 3
122 #define TOK_MAXPOLL 4
129 #define MAXLINESIZE 512
133 * File descriptor for ntp request code.
135 static SOCKET sockfd
= INVALID_SOCKET
; /* NT uses SOCKET */
137 /* stuff to be filled in by caller */
139 keyid_t req_keyid
; /* request keyid */
140 char *req_file
; /* name of the file with configuration info */
142 /* end stuff to be filled in */
145 static void checkparent
P((void));
146 static void removeentry
P((struct conf_entry
*));
147 static void addentry
P((char *, int, int, int, int, u_int
,
148 int, keyid_t
, char *));
149 static int findhostaddr
P((struct conf_entry
*));
150 static void openntp
P((void));
151 static int request
P((struct conf_peer
*));
152 static char * nexttoken
P((char **));
153 static void readconf
P((FILE *, char *));
154 static void doconfigure
P((int));
156 struct ntp_res_t_pkt
{ /* Tagged packet: */
157 void *tag
; /* For the caller */
158 u_int32 paddr
; /* IP to look up, or 0 */
159 char name
[MAXHOSTNAMELEN
]; /* Name to look up (if 1st byte is not 0) */
162 struct ntp_res_c_pkt
{ /* Control packet: */
163 char name
[MAXHOSTNAMELEN
];
172 u_char keystr
[MAXFILENAME
];
176 static void resolver_exit
P((int));
179 * Call here instead of just exiting
182 static void resolver_exit (int code
)
185 CloseHandle(ResolverEventHandle
);
186 ResolverEventHandle
= NULL
;
187 ExitThread(code
); /* Just to kill the thread not the process */
189 exit(code
); /* kill the forked process */
194 * ntp_res_recv: Process an answer from the resolver
201 We have data ready on our descriptor.
202 It may be an EOF, meaning the resolver process went away.
203 Otherwise, it will be an "answer".
211 * req_key(???), req_keyid, req_file valid
229 msyslog(LOG_INFO
, "NTP_INTRES running");
233 /* check out auth stuff */
234 if (sys_authenticate
) {
235 if (!authistrusted(req_keyid
)) {
236 msyslog(LOG_ERR
, "invalid request keyid %08x",
243 * Read the configuration info
244 * {this is bogus, since we are forked, but it is easier
245 * to keep this code - gdt}
247 if ((in
= fopen(req_file
, "r")) == NULL
) {
248 msyslog(LOG_ERR
, "can't open configuration file %s: %m",
252 readconf(in
, req_file
);
258 (void) unlink(req_file
);
261 * Set up the timers to do first shot immediately.
264 resolve_value
= MINRESOLVE
;
265 config_timer
= CONFIG_TIME
;
270 if (resolve_timer
== 0) {
272 * Sleep a little to make sure the network is completely up
277 /* prepare retry, in case there's more work to do */
278 resolve_timer
= resolve_value
;
281 msyslog(LOG_INFO
, "resolve_timer: 0->%d", resolve_timer
);
283 if (resolve_value
< MAXRESOLVE
)
286 config_timer
= CONFIG_TIME
;
287 } else if (config_timer
== 0) { /* MB: in which case would this be required ? */
289 /* MB: should we check now if we could exit, similar to the code above? */
290 config_timer
= CONFIG_TIME
;
293 msyslog(LOG_INFO
, "config_timer: 0->%d", config_timer
);
297 if (confentries
== NULL
)
298 resolver_exit(0); /* done */
301 rc
= WaitForSingleObject(ResolverEventHandle
, 1000 * ALARM_TIME
); /* in milliseconds */
303 if ( rc
== WAIT_OBJECT_0
) { /* signaled by the main thread */
304 resolve_timer
= 0; /* retry resolving immediately */
308 if ( rc
!= WAIT_TIMEOUT
) /* not timeout: error */
311 #else /* not SYS_WINNT */
312 tv
.tv_sec
= ALARM_TIME
;
315 FD_SET(resolver_pipe_fd
[0], &fdset
);
316 rc
= select(resolver_pipe_fd
[0] + 1, &fdset
, (fd_set
*)0, (fd_set
*)0, &tv
);
318 if (rc
> 0) { /* parent process has written to the pipe */
319 read(resolver_pipe_fd
[0], (char *)&rc
, sizeof(rc
)); /* make pipe empty */
320 resolve_timer
= 0; /* retry resolving immediately */
324 if ( rc
< 0 ) /* select() returned error */
328 /* normal timeout, keep on waiting */
329 if (config_timer
> 0)
331 if (resolve_timer
> 0)
339 * checkparent - see if our parent process is still running
341 * No need to worry in the Windows NT environment whether the
342 * main thread is still running, because if it goes
343 * down it takes the whole process down with it (in
344 * which case we won't be running this thread either)
345 * Turn function into NOP;
351 #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)
354 * If our parent (the server) has died we will have been
355 * inherited by init. If so, exit.
357 if (getppid() == 1) {
358 msyslog(LOG_INFO
, "parent died before we finished, exiting");
361 #endif /* SYS_WINNT && SYS_VXWORKS*/
367 * removeentry - we are done with an entry, remove it from the list
371 struct conf_entry
*entry
374 register struct conf_entry
*ce
;
378 confentries
= ce
->ce_next
;
383 if (ce
->ce_next
== entry
) {
384 ce
->ce_next
= entry
->ce_next
;
393 * addentry - add an entry to the configuration list
409 register struct conf_entry
*ce
;
415 "intres: <%s> %d %d %d %d %x %d %x %s\n", name
,
416 mode
, version
, minpoll
, maxpoll
, flags
, ttl
, keyid
,
419 len
= strlen(name
) + 1;
420 cp
= (char *)emalloc(len
);
421 memmove(cp
, name
, len
);
423 ce
= (struct conf_entry
*)emalloc(sizeof(struct conf_entry
));
426 #ifdef ISC_PLATFORM_HAVEIPV6
427 ce
->ce_peeraddr6
= in6addr_any
;
429 ANYSOCK(&ce
->peer_store
);
430 ce
->ce_hmode
= (u_char
)mode
;
431 ce
->ce_version
= (u_char
)version
;
432 ce
->ce_minpoll
= (u_char
)minpoll
;
433 ce
->ce_maxpoll
= (u_char
)maxpoll
;
434 ce
->ce_flags
= (u_char
)flags
;
435 ce
->ce_ttl
= (u_char
)ttl
;
436 ce
->ce_keyid
= keyid
;
437 strncpy((char *)ce
->ce_keystr
, keystr
, MAXFILENAME
);
440 if (confentries
== NULL
) {
443 register struct conf_entry
*cep
;
445 for (cep
= confentries
; cep
->ce_next
!= NULL
;
454 * findhostaddr - resolve a host name into an address (Or vice-versa)
456 * Given one of {ce_peeraddr,ce_name}, find the other one.
457 * It returns 1 for "success" and 0 for an uncorrectable failure.
458 * Note that "success" includes try again errors. You can tell that you
459 * got a "try again" since {ce_peeraddr,ce_name} will still be zero.
463 struct conf_entry
*entry
466 struct addrinfo
*addr
;
467 struct addrinfo hints
;
470 checkparent(); /* make sure our guy is still running */
472 if (entry
->ce_name
!= NULL
&& !SOCKNUL(&entry
->peer_store
)) {
474 msyslog(LOG_ERR
, "findhostaddr: both ce_name and ce_peeraddr are defined...");
478 if (entry
->ce_name
== NULL
&& SOCKNUL(&entry
->peer_store
)) {
479 msyslog(LOG_ERR
, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
483 if (entry
->ce_name
) {
486 msyslog(LOG_INFO
, "findhostaddr: Resolving <%s>",
490 memset(&hints
, 0, sizeof(hints
));
491 hints
.ai_family
= AF_UNSPEC
;
493 * If the IPv6 stack is not available look only for IPv4 addresses
495 if (isc_net_probeipv6() != ISC_R_SUCCESS
)
496 hints
.ai_family
= AF_INET
;
498 error
= getaddrinfo(entry
->ce_name
, NULL
, &hints
, &addr
);
500 entry
->peer_store
= *((struct sockaddr_storage
*)(addr
->ai_addr
));
501 if (entry
->peer_store
.ss_family
== AF_INET
) {
503 GET_INADDR(entry
->peer_store
);
504 entry
->ce_config
.v6_flag
= 0;
506 entry
->ce_peeraddr6
=
507 GET_INADDR6(entry
->peer_store
);
508 entry
->ce_config
.v6_flag
= 1;
511 else if (error
== EAI_NONAME
)
513 msyslog(LOG_ERR
, "host name not found: %s", entry
->ce_name
);
518 msyslog(LOG_INFO
, "findhostaddr: Resolving %s>",
519 stoa(&entry
->peer_store
));
521 entry
->ce_name
= emalloc(MAXHOSTNAMELEN
);
522 error
= getnameinfo((const struct sockaddr
*)&entry
->peer_store
,
523 SOCKLEN(&entry
->peer_store
),
524 (char *)&entry
->ce_name
, MAXHOSTNAMELEN
,
529 printf("intres: got error status of: %d\n", error
);
533 * If the resolver failed, see if the failure is
534 * temporary. If so, return success.
542 #ifndef FORCE_DNSRETRY
547 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
560 if (entry
->ce_name
) {
563 msyslog(LOG_INFO
, "findhostaddr: name resolved.");
568 msyslog(LOG_INFO
, "findhostaddr: address resolved.");
577 * openntp - open a socket to the ntp server
582 struct addrinfo hints
;
583 struct addrinfo
*addrResult
;
584 const char *localhost
= "127.0.0.1"; /* Use IPv6 loopback */
586 if (sockfd
!= INVALID_SOCKET
)
589 memset(&hints
, 0, sizeof(hints
));
592 * For now only bother with IPv4
594 hints
.ai_family
= AF_INET
;
596 hints
.ai_socktype
= SOCK_DGRAM
;
597 if (getaddrinfo(localhost
, "ntp", &hints
, &addrResult
)!=0) {
598 msyslog(LOG_ERR
, "getaddrinfo failed: %m");
601 sockfd
= socket(addrResult
->ai_family
, addrResult
->ai_socktype
, 0);
604 msyslog(LOG_ERR
, "socket() failed: %m");
609 * Make the socket non-blocking. We'll wait with select()
612 #if defined(O_NONBLOCK)
613 if (fcntl(sockfd
, F_SETFL
, O_NONBLOCK
) == -1) {
614 msyslog(LOG_ERR
, "fcntl(O_NONBLOCK) failed: %m");
619 if (fcntl(sockfd
, F_SETFL
, FNDELAY
) == -1) {
620 msyslog(LOG_ERR
, "fcntl(FNDELAY) failed: %m");
624 # include "Bletch: NEED NON BLOCKING IO"
625 #endif /* FNDDELAY */
626 #endif /* O_NONBLOCK */
627 #else /* SYS_WINNT */
630 if (ioctlsocket(sockfd
,FIONBIO
,(u_long
*) &on
) == SOCKET_ERROR
) {
631 msyslog(LOG_ERR
, "ioctlsocket(FIONBIO) fails: %m");
632 resolver_exit(1); /* Windows NT - set socket in non-blocking mode */
635 #endif /* SYS_WINNT */
636 if (connect(sockfd
, addrResult
->ai_addr
, addrResult
->ai_addrlen
) == -1) {
637 msyslog(LOG_ERR
, "openntp: connect() failed: %m");
640 freeaddrinfo(addrResult
);
645 * request - send a configuration request to the server, wait for a response
649 struct conf_peer
*conf
653 struct timeval tvout
;
654 struct req_pkt reqpkt
;
658 HANDLE hReadWriteEvent
= NULL
;
660 DWORD NumberOfBytesWritten
, NumberOfBytesRead
, dwWait
;
662 #endif /* SYS_WINNT */
664 checkparent(); /* make sure our guy is still running */
666 if (sockfd
== INVALID_SOCKET
)
670 hReadWriteEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
671 #endif /* SYS_WINNT */
674 * Try to clear out any previously received traffic so it
675 * doesn't fool us. Note the socket is nonblocking.
680 FD_SET(sockfd
, &fdset
);
681 while (select(sockfd
+ 1, &fdset
, (fd_set
*)0, (fd_set
*)0, &tvout
) >
683 recv(sockfd
, (char *)&reqpkt
, REQ_LEN_MAC
, 0);
685 FD_SET(sockfd
, &fdset
);
689 * Make up a request packet with the configuration info
691 memset((char *)&reqpkt
, 0, sizeof(reqpkt
));
693 reqpkt
.rm_vn_mode
= RM_VN_MODE(0, 0, 0);
694 reqpkt
.auth_seq
= AUTH_SEQ(1, 0); /* authenticated, no seq */
695 reqpkt
.implementation
= IMPL_XNTPD
; /* local implementation */
696 reqpkt
.request
= REQ_CONFIG
; /* configure a new peer */
697 reqpkt
.err_nitems
= ERR_NITEMS(0, 1); /* one item */
698 reqpkt
.mbz_itemsize
= MBZ_ITEMSIZE(sizeof(struct conf_peer
));
699 /* Make sure mbz_itemsize <= sizeof reqpkt.data */
700 if (sizeof(struct conf_peer
) > sizeof (reqpkt
.data
)) {
701 msyslog(LOG_ERR
, "Bletch: conf_peer is too big for reqpkt.data!");
704 memmove(reqpkt
.data
, (char *)conf
, sizeof(struct conf_peer
));
705 reqpkt
.keyid
= htonl(req_keyid
);
708 L_ADDUF(&ts
, SKEWTIME
);
709 HTONL_FP(&ts
, &reqpkt
.tstamp
);
711 if (sys_authenticate
)
712 n
= authencrypt(req_keyid
, (u_int32
*)&reqpkt
, REQ_LEN_NOMAC
);
718 n
= send(sockfd
, (char *)&reqpkt
, (unsigned)(REQ_LEN_NOMAC
+ n
), 0);
720 msyslog(LOG_ERR
, "send to NTP server failed: %m");
721 return 0; /* maybe should exit */
724 /* In the NT world, documentation seems to indicate that there
725 * exist _write and _read routines that can be used to do blocking
726 * I/O on sockets. Problem is these routines require a socket
727 * handle obtained through the _open_osf_handle C run-time API
728 * of which there is no explanation in the documentation. We need
729 * nonblocking write's and read's anyway for our purpose here.
730 * We're therefore forced to deviate a little bit from the Unix
731 * model here and use the ReadFile and WriteFile Win32 I/O API's
734 overlap
.Offset
= overlap
.OffsetHigh
= (DWORD
)0;
735 overlap
.hEvent
= hReadWriteEvent
;
736 ret
= WriteFile((HANDLE
)sockfd
, (char *)&reqpkt
, REQ_LEN_NOMAC
+ n
,
737 NULL
, (LPOVERLAPPED
)&overlap
);
738 if ((ret
== FALSE
) && (GetLastError() != ERROR_IO_PENDING
)) {
739 msyslog(LOG_ERR
, "send to NTP server failed: %m");
742 dwWait
= WaitForSingleObject(hReadWriteEvent
, (DWORD
) TIMEOUT_SEC
* 1000);
743 if ((dwWait
== WAIT_FAILED
) || (dwWait
== WAIT_TIMEOUT
)) {
744 if (dwWait
== WAIT_FAILED
)
745 msyslog(LOG_ERR
, "WaitForSingleObject failed: %m");
748 if (!GetOverlappedResult((HANDLE
)sockfd
, (LPOVERLAPPED
)&overlap
,
749 (LPDWORD
)&NumberOfBytesWritten
, FALSE
)) {
750 msyslog(LOG_ERR
, "GetOverlappedResult for WriteFile fails: %m");
753 #endif /* SYS_WINNT */
757 * Wait for a response. A weakness of the mode 7 protocol used
758 * is that there is no way to associate a response with a
759 * particular request, i.e. the response to this configuration
760 * request is indistinguishable from that to any other. I should
761 * fix this some day. In any event, the time out is fairly
762 * pessimistic to make sure that if an answer is coming back
767 FD_SET(sockfd
, &fdset
);
768 tvout
.tv_sec
= TIMEOUT_SEC
;
769 tvout
.tv_usec
= TIMEOUT_USEC
;
771 n
= select(sockfd
+ 1, &fdset
, (fd_set
*)0,
772 (fd_set
*)0, &tvout
);
777 msyslog(LOG_ERR
, "select() fails: %m");
784 msyslog(LOG_INFO
, "select() returned 0.");
790 n
= recv(sockfd
, (char *)&reqpkt
, REQ_LEN_MAC
, 0);
793 msyslog(LOG_ERR
, "recv() fails: %m");
798 #else /* Overlapped I/O used on non-blocking sockets on Windows NT */
799 ret
= ReadFile((HANDLE
)sockfd
, (char *)&reqpkt
, (DWORD
)REQ_LEN_MAC
,
800 NULL
, (LPOVERLAPPED
)&overlap
);
801 if ((ret
== FALSE
) && (GetLastError() != ERROR_IO_PENDING
)) {
802 msyslog(LOG_ERR
, "ReadFile() fails: %m");
805 dwWait
= WaitForSingleObject(hReadWriteEvent
, (DWORD
) TIMEOUT_SEC
* 1000);
806 if ((dwWait
== WAIT_FAILED
) || (dwWait
== WAIT_TIMEOUT
)) {
807 if (dwWait
== WAIT_FAILED
) {
808 msyslog(LOG_ERR
, "WaitForSingleObject for ReadFile fails: %m");
813 if (!GetOverlappedResult((HANDLE
)sockfd
, (LPOVERLAPPED
)&overlap
,
814 (LPDWORD
)&NumberOfBytesRead
, FALSE
)) {
815 msyslog(LOG_ERR
, "GetOverlappedResult fails: %m");
818 n
= NumberOfBytesRead
;
819 #endif /* SYS_WINNT */
822 * Got one. Check through to make sure it is what
825 if (n
< RESP_HEADER_SIZE
) {
826 msyslog(LOG_ERR
, "received runt response (%d octets)",
831 if (!ISRESPONSE(reqpkt
.rm_vn_mode
)) {
834 msyslog(LOG_INFO
, "received non-response packet");
839 if (ISMORE(reqpkt
.rm_vn_mode
)) {
842 msyslog(LOG_INFO
, "received fragmented packet");
847 if ( ( (INFO_VERSION(reqpkt
.rm_vn_mode
) < 2)
848 || (INFO_VERSION(reqpkt
.rm_vn_mode
) > NTP_VERSION
))
849 || INFO_MODE(reqpkt
.rm_vn_mode
) != MODE_PRIVATE
) {
853 "version (%d/%d) or mode (%d/%d) incorrect",
854 INFO_VERSION(reqpkt
.rm_vn_mode
),
856 INFO_MODE(reqpkt
.rm_vn_mode
),
862 if (INFO_SEQ(reqpkt
.auth_seq
) != 0) {
866 "nonzero sequence number (%d)",
867 INFO_SEQ(reqpkt
.auth_seq
));
872 if (reqpkt
.implementation
!= IMPL_XNTPD
||
873 reqpkt
.request
!= REQ_CONFIG
) {
877 "implementation (%d) or request (%d) incorrect",
878 reqpkt
.implementation
, reqpkt
.request
);
883 if (INFO_NITEMS(reqpkt
.err_nitems
) != 0 ||
884 INFO_MBZ(reqpkt
.mbz_itemsize
) != 0 ||
885 INFO_ITEMSIZE(reqpkt
.mbz_itemsize
) != 0) {
889 "nitems (%d) mbz (%d) or itemsize (%d) nonzero",
890 INFO_NITEMS(reqpkt
.err_nitems
),
891 INFO_MBZ(reqpkt
.mbz_itemsize
),
892 INFO_ITEMSIZE(reqpkt
.mbz_itemsize
));
897 n
= INFO_ERR(reqpkt
.err_nitems
);
905 "ntpd reports implementation mismatch!");
910 "ntpd says configuration request is unknown!");
915 "ntpd indicates a format error occurred!");
918 case INFO_ERR_NODATA
:
920 "ntpd indicates no data available!");
925 "ntpd returns a permission denied error!");
930 "ntpd returns unknown error code %d!", n
);
938 * nexttoken - return the next token from a line
946 register char *tstart
;
951 * Skip leading white space
953 while (*cp
== ' ' || *cp
== '\t')
957 * If this is the end of the line, return nothing.
959 if (*cp
== '\n' || *cp
== '\0') {
965 * Must be the start of a token. Record the pointer and look
969 while (*cp
!= ' ' && *cp
!= '\t' && *cp
!= '\n' && *cp
!= '\0')
973 * Terminate the token with a \0. If this isn't the end of the
974 * line, space to the next character.
976 if (*cp
== '\n' || *cp
== '\0')
987 * readconf - read the configuration information out of the file we
988 * were passed. Note that since the file is supposed to be
989 * machine generated, we bail out at the first sign of trouble.
999 u_long intval
[NUMTOK
];
1001 char buf
[MAXLINESIZE
];
1004 while (fgets(buf
, MAXLINESIZE
, fp
) != NULL
) {
1007 for (i
= 0; i
< NUMTOK
; i
++) {
1008 if ((token
[i
] = nexttoken(&bp
)) == NULL
) {
1010 "tokenizing error in file `%s', quitting",
1016 for (i
= 1; i
< NUMTOK
- 1; i
++) {
1017 if (!atouint(token
[i
], &intval
[i
])) {
1019 "format error for integer token `%s', file `%s', quitting",
1025 if (intval
[TOK_HMODE
] != MODE_ACTIVE
&&
1026 intval
[TOK_HMODE
] != MODE_CLIENT
&&
1027 intval
[TOK_HMODE
] != MODE_BROADCAST
) {
1028 msyslog(LOG_ERR
, "invalid mode (%ld) in file %s",
1029 intval
[TOK_HMODE
], name
);
1033 if (intval
[TOK_VERSION
] > NTP_VERSION
||
1034 intval
[TOK_VERSION
] < NTP_OLDVERSION
) {
1035 msyslog(LOG_ERR
, "invalid version (%ld) in file %s",
1036 intval
[TOK_VERSION
], name
);
1039 if (intval
[TOK_MINPOLL
] < NTP_MINPOLL
||
1040 intval
[TOK_MINPOLL
] > NTP_MAXPOLL
) {
1041 msyslog(LOG_ERR
, "invalid MINPOLL value (%ld) in file %s",
1042 intval
[TOK_MINPOLL
], name
);
1046 if (intval
[TOK_MAXPOLL
] < NTP_MINPOLL
||
1047 intval
[TOK_MAXPOLL
] > NTP_MAXPOLL
) {
1048 msyslog(LOG_ERR
, "invalid MAXPOLL value (%ld) in file %s",
1049 intval
[TOK_MAXPOLL
], name
);
1053 if ((intval
[TOK_FLAGS
] & ~(FLAG_AUTHENABLE
| FLAG_PREFER
|
1054 FLAG_NOSELECT
| FLAG_BURST
| FLAG_IBURST
| FLAG_SKEY
))
1056 msyslog(LOG_ERR
, "invalid flags (%ld) in file %s",
1057 intval
[TOK_FLAGS
], name
);
1062 if (intval
[TOK_FLAGS
] & FLAG_AUTHENABLE
)
1063 flags
|= CONF_FLAG_AUTHENABLE
;
1064 if (intval
[TOK_FLAGS
] & FLAG_PREFER
)
1065 flags
|= CONF_FLAG_PREFER
;
1066 if (intval
[TOK_FLAGS
] & FLAG_NOSELECT
)
1067 flags
|= CONF_FLAG_NOSELECT
;
1068 if (intval
[TOK_FLAGS
] & FLAG_BURST
)
1069 flags
|= CONF_FLAG_BURST
;
1070 if (intval
[TOK_FLAGS
] & FLAG_IBURST
)
1071 flags
|= CONF_FLAG_IBURST
;
1072 if (intval
[TOK_FLAGS
] & FLAG_SKEY
)
1073 flags
|= CONF_FLAG_SKEY
;
1076 * This is as good as we can check it. Add it in.
1078 addentry(token
[TOK_HOSTNAME
], (int)intval
[TOK_HMODE
],
1079 (int)intval
[TOK_VERSION
], (int)intval
[TOK_MINPOLL
],
1080 (int)intval
[TOK_MAXPOLL
], flags
, (int)intval
[TOK_TTL
],
1081 intval
[TOK_KEYID
], token
[TOK_KEYSTR
]);
1087 * doconfigure - attempt to resolve names and configure the server
1094 register struct conf_entry
*ce
;
1095 register struct conf_entry
*ceremove
;
1099 msyslog(LOG_INFO
, "Running doconfigure %s DNS",
1100 dores
? "with" : "without" );
1104 while (ce
!= NULL
) {
1108 "doconfigure: <%s> has peeraddr %s",
1109 ce
->ce_name
, stoa(&ce
->peer_store
));
1111 if (dores
&& SOCKNUL(&(ce
->peer_store
))) {
1112 if (!findhostaddr(ce
)) {
1114 "couldn't resolve `%s', giving up on it",
1117 ce
= ceremove
->ce_next
;
1118 removeentry(ceremove
);
1123 if (!SOCKNUL(&ce
->peer_store
)) {
1124 if (request(&ce
->ce_config
)) {
1126 ce
= ceremove
->ce_next
;
1127 removeentry(ceremove
);
1133 "doconfigure: request() FAILED, maybe next time.");