1 /* $OpenBSD: src/usr.sbin/ntpd/parse.y,v 1.22 2004/11/05 14:28:29 henning Exp $ */
4 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2001 Markus Friedl. All rights reserved.
6 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
7 * Copyright (c) 2001 Theo de Raadt. All rights reserved.
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
38 static struct ntpd_conf *conf;
39 static FILE *fin = NULL;
40 static int lineno = 1;
41 static int errors = 0;
44 int yyerror(const char *, ...);
46 int kw_cmp(const void *, const void *);
57 struct ntp_addr_wrap *addr;
67 %token <v.string> STRING
68 %type <v.addr> address
73 | grammar conf_main '\n'
74 | grammar error '\n' { errors++; }
77 conf_main : LISTEN ON address {
78 struct listen_addr *la;
79 struct ntp_addr *h, *next;
82 yyerror("cannot resolve \"%s\"", $3->name);
88 for (h = $3->a; h != NULL; h = next) {
90 if (h->ss.ss_family == AF_UNSPEC) {
95 la = calloc(1, sizeof(struct listen_addr));
97 fatal("listen on calloc");
99 memcpy(&la->sa, &h->ss,
100 sizeof(struct sockaddr_storage));
101 TAILQ_INSERT_TAIL(&conf->listen_addrs, la,
110 struct ntp_addr *h, *next;
116 if (h->ss.ss_family != AF_INET &&
117 h->ss.ss_family != AF_INET6) {
118 yyerror("IPv4 or IPv6 address "
119 "or hostname expected");
132 p->addr_head.pool = 1;
133 p->addr_head.name = strdup($2->name);
134 if (p->addr_head.name == NULL)
136 TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
146 struct ntp_addr *h, *next;
149 for (h = $2->a; h != NULL; h = next) {
151 if (h->ss.ss_family != AF_INET &&
152 h->ss.ss_family != AF_INET6) {
153 yyerror("IPv4 or IPv6 address "
154 "or hostname expected");
165 p->addr_head.a = p->addr;
166 p->addr_head.pool = 0;
167 p->addr_head.name = strdup($2->name);
168 if (p->addr_head.name == NULL)
170 TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
177 if (($$ = calloc(1, sizeof(struct ntp_addr_wrap))) ==
180 if (host($1, &$$->a) == -1) {
181 yyerror("could not parse address spec \"%s\"",
199 yyerror(const char *fmt, ...)
206 if (asprintf(&nfmt, "%s:%d: %s", infile, yylval.lineno, fmt) == -1)
207 fatalx("yyerror asprintf");
208 vlog(LOG_CRIT, nfmt, ap);
215 kw_cmp(const void *k, const void *e)
217 return (strcmp(k, ((const struct keywords *)e)->k_name));
223 /* this has to be sorted always */
224 static const struct keywords keywords[] = {
228 { "servers", SERVERS}
230 const struct keywords *p;
232 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
233 sizeof(keywords[0]), kw_cmp);
241 #define MAXPUSHBACK 128
245 char pushback_buffer[MAXPUSHBACK];
246 int pushback_index = 0;
254 /* Read character from the parsebuffer instead of input. */
255 if (parseindex >= 0) {
256 c = parsebuf[parseindex++];
265 return (pushback_buffer[--pushback_index]);
267 while ((c = getc(f)) == '\\') {
271 yyerror("whitespace after \\");
275 yylval.lineno = lineno;
278 if (c == '\t' || c == ' ') {
279 /* Compress blanks to a single space. */
282 } while (c == '\t' || c == ' ');
300 if (pushback_index < MAXPUSHBACK-1)
301 return (pushback_buffer[pushback_index++] = c);
314 /* skip to either EOF or the first real EOL */
336 while ((c = lgetc(fin)) == ' ')
339 yylval.lineno = lineno;
341 while ((c = lgetc(fin)) != '\n' && c != EOF)
349 if ((c = lgetc(fin)) == EOF)
359 if (p + 1 >= buf + sizeof(buf) - 1) {
360 yyerror("string too long");
365 yylval.v.string = strdup(buf);
366 if (yylval.v.string == NULL)
367 fatal("yylex: strdup");
371 #define allowed_in_string(x) \
372 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
373 x != '{' && x != '}' && x != '<' && x != '>' && \
374 x != '!' && x != '=' && x != '/' && x != '#' && \
377 if (isalnum(c) || c == ':' || c == '_' || c == '*') {
380 if ((unsigned)(p-buf) >= sizeof(buf)) {
381 yyerror("string too long");
384 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
387 if ((token = lookup(buf)) == STRING)
388 if ((yylval.v.string = strdup(buf)) == NULL)
389 fatal("yylex: strdup");
393 yylval.lineno = lineno;
402 parse_config(char *filename, struct ntpd_conf *xconf)
407 TAILQ_INIT(&conf->listen_addrs);
408 TAILQ_INIT(&conf->ntp_peers);
410 if ((fin = fopen(filename, "r")) == NULL) {
411 log_warn("%s", filename);
420 return (errors ? -1 : 0);