1 /* $OpenBSD: src/usr.sbin/ntpd/parse.y,v 1.24 2004/11/25 06:27:41 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
;
81 if
((h
= $3->a
) == NULL
&&
82 (host_dns
($3->name
, &h
) == -1 ||
!h
)) {
83 yyerror("could not resolve \"%s\"", $3->name
);
89 for
(; h
!= NULL
; h
= next
) {
91 if
(h
->ss.ss_family
== AF_UNSPEC
) {
96 la
= calloc
(1, sizeof
(struct listen_addr
));
98 fatal
("listen on calloc");
100 memcpy
(&la
->sa
, &h
->ss
,
101 sizeof
(struct sockaddr_storage
));
102 TAILQ_INSERT_TAIL
(&conf
->listen_addrs
, la
,
111 struct ntp_addr
*h
, *next
;
117 if
(h
->ss.ss_family
!= AF_INET
&&
118 h
->ss.ss_family
!= AF_INET6
) {
119 yyerror("IPv4 or IPv6 address "
120 "or hostname expected");
133 p
->addr_head.pool
= 1;
134 p
->addr_head.name
= strdup
($2->name
);
135 if
(p
->addr_head.name
== NULL
)
137 TAILQ_INSERT_TAIL
(&conf
->ntp_peers
, p
, entry
);
147 struct ntp_addr
*h
, *next
;
150 for
(h
= $2->a
; h
!= NULL
; h
= next
) {
152 if
(h
->ss.ss_family
!= AF_INET
&&
153 h
->ss.ss_family
!= AF_INET6
) {
154 yyerror("IPv4 or IPv6 address "
155 "or hostname expected");
166 p
->addr_head.a
= p
->addr
;
167 p
->addr_head.pool
= 0;
168 p
->addr_head.name
= strdup
($2->name
);
169 if
(p
->addr_head.name
== NULL
)
171 TAILQ_INSERT_TAIL
(&conf
->ntp_peers
, p
, entry
);
178 if
(($$
= calloc
(1, sizeof
(struct ntp_addr_wrap
))) ==
181 if
(host
($1, &$$
->a
) == -1) {
182 yyerror("could not parse address spec \"%s\"",
200 yyerror(const char *fmt
, ...
)
207 if
(asprintf
(&nfmt
, "%s:%d: %s", infile
, yylval.lineno
, fmt
) == -1)
208 fatalx
("yyerror asprintf");
209 vlog
(LOG_CRIT
, nfmt
, ap
);
216 kw_cmp
(const void *k
, const void *e
)
218 return
(strcmp
(k
, ((const struct keywords
*)e
)->k_name
));
224 /* this has to be sorted always */
225 static const struct keywords keywords
[] = {
229 { "servers", SERVERS
}
231 const struct keywords
*p
;
233 p
= bsearch
(s
, keywords
, sizeof
(keywords
)/sizeof
(keywords
[0]),
234 sizeof
(keywords
[0]), kw_cmp
);
242 #define MAXPUSHBACK 128
246 char pushback_buffer
[MAXPUSHBACK
];
247 int pushback_index
= 0;
255 /* Read character from the parsebuffer instead of input. */
256 if
(parseindex
>= 0) {
257 c
= parsebuf
[parseindex
++];
266 return
(pushback_buffer
[--pushback_index
]);
268 while
((c
= getc
(f
)) == '\\') {
272 yyerror("whitespace after \\");
276 yylval.lineno
= lineno
;
279 if
(c
== '\t' || c
== ' ') {
280 /* Compress blanks to a single space. */
283 } while
(c
== '\t' || c
== ' ');
301 if
(pushback_index
< MAXPUSHBACK
-1)
302 return
(pushback_buffer
[pushback_index
++] = c
);
315 /* skip to either EOF or the first real EOL */
337 while
((c
= lgetc
(fin
)) == ' ')
340 yylval.lineno
= lineno
;
342 while
((c
= lgetc
(fin
)) != '\n' && c
!= EOF
)
350 if
((c
= lgetc
(fin
)) == EOF
)
360 if
(p
+ 1 >= buf
+ sizeof
(buf
) - 1) {
361 yyerror("string too long");
366 yylval.v.
string = strdup
(buf
);
367 if
(yylval.v.
string == NULL
)
368 fatal
("yylex: strdup");
372 #define allowed_in_string(x) \
373 (isalnum
(x
) ||
(ispunct
(x
) && x
!= '(' && x
!= ')' && \
374 x
!= '{' && x
!= '}' && x
!= '<' && x
!= '>' && \
375 x
!= '!' && x
!= '=' && x
!= '/' && x
!= '#' && \
378 if
(isalnum
(c
) || c
== ':' || c
== '_' || c
== '*') {
381 if
((unsigned)(p
-buf
) >= sizeof
(buf
)) {
382 yyerror("string too long");
385 } while
((c
= lgetc
(fin
)) != EOF
&& (allowed_in_string
(c
)));
388 if
((token
= lookup
(buf
)) == STRING
)
389 if
((yylval.v.
string = strdup
(buf
)) == NULL
)
390 fatal
("yylex: strdup");
394 yylval.lineno
= lineno
;
403 parse_config
(const char *filename
, struct ntpd_conf
*xconf
)
408 TAILQ_INIT
(&conf
->listen_addrs
);
409 TAILQ_INIT
(&conf
->ntp_peers
);
411 if
((fin
= fopen
(filename
, "r")) == NULL
) {
412 log_warn
("%s", filename
);
421 return
(errors ?
-1 : 0);