6 * What follows is a simplified version of the config parsing code
7 * in ntpd/ntp_config.c. We only parse a subset of the configuration
8 * syntax, and don't bother whining about things we don't understand.
19 #include "ntp_unixtime.h"
20 #include "ntp_filegen.h"
22 #include "ntp_syslog.h"
23 #include "ntp_stdlib.h"
30 * These routines are used to read the configuration file at
31 * startup time. An entry in the file must fit on a single line.
32 * Entries are processed as multiple tokens separated by white space
33 * Lines are considered terminated when a '#' is encountered. Blank
38 * Configuration file name
42 # define CONFIG_FILE "/etc/ntp.conf"
43 # else /* SYS_WINNT */
44 # define CONFIG_FILE "%windir%\\ntp.conf"
45 # define ALT_CONFIG_FILE "%windir%\\ntp.ini"
46 # endif /* SYS_WINNT */
47 #endif /* not CONFIG_FILE */
51 * We understand the following configuration entries and defaults.
53 * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
54 * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
58 #define CONFIG_UNKNOWN 0
61 #define CONFIG_SERVER 2
64 #define CONF_MOD_VERSION 1
65 #define CONF_MOD_KEY 2
66 #define CONF_MOD_MINPOLL 3
67 #define CONF_MOD_MAXPOLL 4
68 #define CONF_MOD_PREFER 5
69 #define CONF_MOD_BURST 6
70 #define CONF_MOD_SKEY 7
71 #define CONF_MOD_TTL 8
72 #define CONF_MOD_MODE 9
75 * Translation table - keywords to function index
85 static struct keyword keywords
[] = {
86 { "peer", CONFIG_PEER
},
87 { "server", CONFIG_SERVER
},
88 { "keys", CONFIG_KEYS
},
89 { "", CONFIG_UNKNOWN
}
93 * "peer", "server", "broadcast" modifier keywords
95 static struct keyword mod_keywords
[] = {
96 { "version", CONF_MOD_VERSION
},
97 { "key", CONF_MOD_KEY
},
98 { "minpoll", CONF_MOD_MINPOLL
},
99 { "maxpoll", CONF_MOD_MAXPOLL
},
100 { "prefer", CONF_MOD_PREFER
},
101 { "burst", CONF_MOD_BURST
},
102 { "autokey", CONF_MOD_SKEY
},
103 { "mode", CONF_MOD_MODE
}, /* reference clocks */
104 { "ttl", CONF_MOD_TTL
}, /* NTP peers */
105 { "", CONFIG_UNKNOWN
}
111 #define MAXTOKENS 20 /* 20 tokens on line */
112 #define MAXLINE 1024 /* maximum length of line */
113 #define MAXFILENAME 128 /* maximum length of a file name (alloca()?) */
116 * Miscellaneous macros
118 #define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
119 #define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
120 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
121 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
124 * Systemwide parameters and flags
126 extern struct server
**sys_servers
; /* the server list */
127 extern int sys_numservers
; /* number of servers to poll */
128 extern char *key_file
;
131 * Function prototypes
133 static int gettokens
P((FILE *, char *, char **, int *));
134 static int matchkey
P((char *, struct keyword
*));
135 static int getnetnum
P((const char *num
, struct sockaddr_in
*addr
,
140 * loadservers - load list of NTP servers from configuration file
154 /* u_long peerkey; */
156 struct sockaddr_in peeraddr
;
159 char *(tokens
[MAXTOKENS
]);
162 const char *config_file
;
164 char *alt_config_file
;
166 char config_file_storage
[MAX_PATH
];
167 char alt_config_file_storage
[MAX_PATH
];
168 #endif /* SYS_WINNT */
169 struct server
*server
, *srvlist
;
172 * Initialize, initialize
181 config_file
= cfgpath
? cfgpath
: CONFIG_FILE
;
184 config_file
= cfgpath
;
187 if (!ExpandEnvironmentStrings((LPCTSTR
)temp
, (LPTSTR
)config_file_storage
, (DWORD
)sizeof(config_file_storage
))) {
188 msyslog(LOG_ERR
, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
191 config_file
= config_file_storage
;
194 temp
= ALT_CONFIG_FILE
;
195 if (!ExpandEnvironmentStrings((LPCTSTR
)temp
, (LPTSTR
)alt_config_file_storage
, (DWORD
)sizeof(alt_config_file_storage
))) {
196 msyslog(LOG_ERR
, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
199 alt_config_file
= alt_config_file_storage
;
201 #endif /* SYS_WINNT */
203 if ((fp
= fopen(FindConfig(config_file
), "r")) == NULL
)
205 fprintf(stderr
, "getconfig: Couldn't open <%s>\n", FindConfig(config_file
));
206 msyslog(LOG_INFO
, "getconfig: Couldn't open <%s>", FindConfig(config_file
));
208 /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
210 if ((fp
= fopen(FindConfig(alt_config_file
), "r")) == NULL
) {
213 * Broadcast clients can sometimes run without
214 * a configuration file.
217 fprintf(stderr
, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file
));
218 msyslog(LOG_INFO
, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file
));
221 #else /* not SYS_WINNT */
223 #endif /* not SYS_WINNT */
226 while ((tok
= gettokens(fp
, line
, tokens
, &ntokens
))
234 "No address for %s, line ignored",
239 if (!getnetnum(tokens
[1], &peeraddr
, 1)) {
240 /* Resolve now, or lose! */
245 /* Shouldn't be able to specify multicast */
246 if (IN_CLASSD(ntohl(peeraddr
.sin_addr
.s_addr
))
247 || ISBADADR(&peeraddr
)) {
249 "attempt to configure invalid address %s",
255 peerversion
= NTP_VERSION
;
256 minpoll
= NTP_MINDPOLL
;
257 maxpoll
= NTP_MAXDPOLL
;
261 for (i
= 2; i
< ntokens
; i
++)
262 switch (matchkey(tokens
[i
], mod_keywords
)) {
263 case CONF_MOD_VERSION
:
264 if (i
>= ntokens
-1) {
266 "peer/server version requires an argument");
270 peerversion
= atoi(tokens
[++i
]);
271 if ((u_char
)peerversion
> NTP_VERSION
272 || (u_char
)peerversion
< NTP_OLDVERSION
) {
274 "inappropriate version number %s, line ignored",
281 if (i
>= ntokens
-1) {
283 "key: argument required");
288 /* peerkey = (int)atol(tokens[i]); */
289 peerflags
|= FLAG_AUTHENABLE
;
292 case CONF_MOD_MINPOLL
:
293 if (i
>= ntokens
-1) {
295 "minpoll: argument required");
299 minpoll
= atoi(tokens
[++i
]);
300 if (minpoll
< NTP_MINPOLL
)
301 minpoll
= NTP_MINPOLL
;
304 case CONF_MOD_MAXPOLL
:
305 if (i
>= ntokens
-1) {
307 "maxpoll: argument required"
312 maxpoll
= atoi(tokens
[++i
]);
313 if (maxpoll
> NTP_MAXPOLL
)
314 maxpoll
= NTP_MAXPOLL
;
317 case CONF_MOD_PREFER
:
318 peerflags
|= FLAG_PREFER
;
322 peerflags
|= FLAG_BURST
;
326 peerflags
|= FLAG_SKEY
| FLAG_AUTHENABLE
;
330 if (i
>= ntokens
-1) {
332 "ttl: argument required");
337 /* ttl = atoi(tokens[i]); */
341 if (i
>= ntokens
-1) {
343 "mode: argument required");
348 /* ttl = atoi(tokens[i]); */
355 if (minpoll
> maxpoll
) {
356 msyslog(LOG_ERR
, "config error: minpoll > maxpoll");
360 server
= (struct server
*)emalloc(sizeof(struct server
));
361 memset((char *)server
, 0, sizeof(struct server
));
362 server
->srcadr
= peeraddr
;
363 server
->version
= peerversion
;
364 server
->dispersion
= PEER_MAXDISP
;
365 server
->next_server
= srvlist
;
373 key_file
= (char *) emalloc(strlen(tokens
[1]) + 1);
374 strcpy(key_file
, tokens
[1]);
381 /* build final list */
382 sys_numservers
= srvcnt
;
383 sys_servers
= (struct server
**)
384 emalloc(sys_numservers
* sizeof(struct server
*));
385 for(i
=0;i
<sys_numservers
;i
++) {
386 sys_servers
[i
] = srvlist
;
387 srvlist
= srvlist
->next_server
;
394 * gettokens - read a line and return tokens
407 register int quoted
= 0;
410 * Find start of first token
413 while ((cp
= fgets(line
, MAXLINE
, fp
)) != NULL
) {
422 return CONFIG_UNKNOWN
; /* hack. Is recognized as EOF */
426 * Now separate out the tokens
431 tokenlist
[ntok
++] = cp
;
432 while (!ISEOL(*cp
) && (!ISSPACE(*cp
) || quoted
))
433 quoted
^= (*cp
++ == '"');
438 } else { /* must be space */
445 if (ntok
== MAXTOKENS
)
453 ntok
= matchkey(tokenlist
[0], keywords
);
454 if (ntok
== CONFIG_UNKNOWN
)
462 * matchkey - match a keyword to a list
467 register struct keyword
*keys
471 if (keys
->keytype
== CONFIG_UNKNOWN
) {
472 return CONFIG_UNKNOWN
;
474 if (STRSAME(word
, keys
->text
))
475 return keys
->keytype
;
482 * getnetnum - return a net number (this is crude, but careful)
487 struct sockaddr_in
*addr
,
491 register const char *cp
;
495 char buf
[80]; /* will core dump on really stupid stuff */
498 /* XXX ELIMINATE replace with decodenetnum */
501 for (i
= 0; i
< 4; i
++) {
503 while (isdigit((int)*cp
))
511 } else if (*cp
!= '\0')
522 printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
523 num
, i
, buf
, temp
, (u_long
)netnum
);
530 "getnetnum: \"%s\" invalid host number, line ignored",
535 "getnetnum: \"%s\" invalid host number, line ignored\n",
542 * make up socket address. Clear it out for neatness.
544 memset((void *)addr
, 0, sizeof(struct sockaddr_in
));
545 addr
->sin_family
= AF_INET
;
546 addr
->sin_port
= htons(NTP_PORT
);
547 addr
->sin_addr
.s_addr
= htonl(netnum
);
550 printf("getnetnum given %s, got %s (%lx)\n",
551 num
, ntoa(addr
), (u_long
)netnum
);