1*cf9537f6Sflorian /* $OpenBSD: parse.y,v 1.29 2021/10/22 15:03:28 florian Exp $ */
258b5b9b8Sflorian
358b5b9b8Sflorian /*
458b5b9b8Sflorian * Copyright (c) 2018 Florian Obser <florian@openbsd.org>
558b5b9b8Sflorian * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
658b5b9b8Sflorian * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
758b5b9b8Sflorian * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
858b5b9b8Sflorian * Copyright (c) 2001 Markus Friedl. All rights reserved.
958b5b9b8Sflorian * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
1058b5b9b8Sflorian * Copyright (c) 2001 Theo de Raadt. All rights reserved.
1158b5b9b8Sflorian *
1258b5b9b8Sflorian * Permission to use, copy, modify, and distribute this software for any
1358b5b9b8Sflorian * purpose with or without fee is hereby granted, provided that the above
1458b5b9b8Sflorian * copyright notice and this permission notice appear in all copies.
1558b5b9b8Sflorian *
1658b5b9b8Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1758b5b9b8Sflorian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1858b5b9b8Sflorian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1958b5b9b8Sflorian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2058b5b9b8Sflorian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2158b5b9b8Sflorian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2258b5b9b8Sflorian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2358b5b9b8Sflorian */
2458b5b9b8Sflorian
2558b5b9b8Sflorian %{
2658b5b9b8Sflorian #include <sys/queue.h>
2758b5b9b8Sflorian #include <sys/socket.h>
2858b5b9b8Sflorian #include <sys/stat.h>
2958b5b9b8Sflorian #include <sys/types.h>
3058b5b9b8Sflorian
3158b5b9b8Sflorian #include <ctype.h>
3258b5b9b8Sflorian #include <err.h>
3358b5b9b8Sflorian #include <errno.h>
3458b5b9b8Sflorian #include <limits.h>
3558b5b9b8Sflorian #include <netdb.h>
3658b5b9b8Sflorian #include <stdarg.h>
3758b5b9b8Sflorian #include <stdint.h>
3858b5b9b8Sflorian #include <stdio.h>
3958b5b9b8Sflorian #include <syslog.h>
4058b5b9b8Sflorian #include <unistd.h>
4158b5b9b8Sflorian
4258b5b9b8Sflorian #include "log.h"
4358b5b9b8Sflorian #include "unwind.h"
4458b5b9b8Sflorian
4558b5b9b8Sflorian TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
4658b5b9b8Sflorian static struct file {
4758b5b9b8Sflorian TAILQ_ENTRY(file) entry;
4858b5b9b8Sflorian FILE *stream;
4958b5b9b8Sflorian char *name;
5058b5b9b8Sflorian size_t ungetpos;
5158b5b9b8Sflorian size_t ungetsize;
5258b5b9b8Sflorian u_char *ungetbuf;
5358b5b9b8Sflorian int eof_reached;
5458b5b9b8Sflorian int lineno;
5558b5b9b8Sflorian int errors;
5658b5b9b8Sflorian } *file, *topfile;
5758b5b9b8Sflorian struct file *pushfile(const char *, int);
5858b5b9b8Sflorian int popfile(void);
5958b5b9b8Sflorian int check_file_secrecy(int, const char *);
6058b5b9b8Sflorian int yyparse(void);
6158b5b9b8Sflorian int yylex(void);
6258b5b9b8Sflorian int yyerror(const char *, ...)
6358b5b9b8Sflorian __attribute__((__format__ (printf, 1, 2)))
6458b5b9b8Sflorian __attribute__((__nonnull__ (1)));
6558b5b9b8Sflorian int kw_cmp(const void *, const void *);
6658b5b9b8Sflorian int lookup(char *);
6758b5b9b8Sflorian int igetc(void);
6858b5b9b8Sflorian int lgetc(int);
6958b5b9b8Sflorian void lungetc(int);
7058b5b9b8Sflorian int findeol(void);
7158b5b9b8Sflorian
7258b5b9b8Sflorian TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
7358b5b9b8Sflorian struct sym {
7458b5b9b8Sflorian TAILQ_ENTRY(sym) entry;
7558b5b9b8Sflorian int used;
7658b5b9b8Sflorian int persist;
7758b5b9b8Sflorian char *nam;
7858b5b9b8Sflorian char *val;
7958b5b9b8Sflorian };
8058b5b9b8Sflorian
8158b5b9b8Sflorian int symset(const char *, const char *, int);
8258b5b9b8Sflorian char *symget(const char *);
83fd873f7fSflorian int check_pref_uniq(enum uw_resolver_type);
8458b5b9b8Sflorian
8558b5b9b8Sflorian static struct uw_conf *conf;
8658b5b9b8Sflorian static int errors;
8758b5b9b8Sflorian
8858b5b9b8Sflorian void clear_config(struct uw_conf *xconf);
8958b5b9b8Sflorian struct sockaddr_storage *host_ip(const char *);
9058b5b9b8Sflorian
9158b5b9b8Sflorian typedef struct {
9258b5b9b8Sflorian union {
9358b5b9b8Sflorian int64_t number;
9458b5b9b8Sflorian char *string;
95dd16127bSotto struct force_tree force;
9658b5b9b8Sflorian } v;
9758b5b9b8Sflorian int lineno;
9858b5b9b8Sflorian } YYSTYPE;
9958b5b9b8Sflorian
10058b5b9b8Sflorian %}
10158b5b9b8Sflorian
102f3ea9bf1Sflorian %token INCLUDE ERROR
10356fed3e1Skn %token FORWARDER DOT PORT ODOT_FORWARDER ODOT_AUTOCONF ODOT_DHCP
10456fed3e1Skn %token AUTHENTICATION NAME PREFERENCE RECURSOR AUTOCONF DHCP STUB
105dd16127bSotto %token BLOCK LIST LOG FORCE ACCEPT BOGUS
10658b5b9b8Sflorian
10758b5b9b8Sflorian %token <v.string> STRING
10858b5b9b8Sflorian %token <v.number> NUMBER
109dd16127bSotto %type <v.number> port dot prefopt log acceptbogus
1101463ff3cSotto %type <v.string> string authname
111dd16127bSotto %type <v.force> force_list
11258b5b9b8Sflorian
11358b5b9b8Sflorian %%
11458b5b9b8Sflorian
11558b5b9b8Sflorian grammar : /* empty */
11658b5b9b8Sflorian | grammar include '\n'
11758b5b9b8Sflorian | grammar '\n'
11858b5b9b8Sflorian | grammar varset '\n'
119fd873f7fSflorian | grammar uw_pref '\n'
12058b5b9b8Sflorian | grammar uw_forwarder '\n'
1212d988276Sflorian | grammar block_list '\n'
122dd16127bSotto | grammar force '\n'
12358b5b9b8Sflorian | grammar error '\n' { file->errors++; }
12458b5b9b8Sflorian ;
12558b5b9b8Sflorian
12658b5b9b8Sflorian include : INCLUDE STRING {
12758b5b9b8Sflorian struct file *nfile;
12858b5b9b8Sflorian
12958b5b9b8Sflorian if ((nfile = pushfile($2, 0)) == NULL) {
13058b5b9b8Sflorian yyerror("failed to include file %s", $2);
13158b5b9b8Sflorian free($2);
13258b5b9b8Sflorian YYERROR;
13358b5b9b8Sflorian }
13458b5b9b8Sflorian free($2);
13558b5b9b8Sflorian
13658b5b9b8Sflorian file = nfile;
13758b5b9b8Sflorian lungetc('\n');
13858b5b9b8Sflorian }
13958b5b9b8Sflorian ;
14058b5b9b8Sflorian
14158b5b9b8Sflorian string : string STRING {
14258b5b9b8Sflorian if (asprintf(&$$, "%s %s", $1, $2) == -1) {
14358b5b9b8Sflorian free($1);
14458b5b9b8Sflorian free($2);
14558b5b9b8Sflorian yyerror("string: asprintf");
14658b5b9b8Sflorian YYERROR;
14758b5b9b8Sflorian }
14858b5b9b8Sflorian free($1);
14958b5b9b8Sflorian free($2);
15058b5b9b8Sflorian }
15158b5b9b8Sflorian | STRING
15258b5b9b8Sflorian ;
15358b5b9b8Sflorian
15458b5b9b8Sflorian varset : STRING '=' string {
15558b5b9b8Sflorian char *s = $1;
15658b5b9b8Sflorian if (cmd_opts & OPT_VERBOSE)
15758b5b9b8Sflorian printf("%s = \"%s\"\n", $1, $3);
15858b5b9b8Sflorian while (*s++) {
15958b5b9b8Sflorian if (isspace((unsigned char)*s)) {
16058b5b9b8Sflorian yyerror("macro name cannot contain "
16158b5b9b8Sflorian "whitespace");
162570434efSotto free($1);
163570434efSotto free($3);
16458b5b9b8Sflorian YYERROR;
16558b5b9b8Sflorian }
16658b5b9b8Sflorian }
16758b5b9b8Sflorian if (symset($1, $3, 0) == -1)
16858b5b9b8Sflorian fatal("cannot store variable");
16958b5b9b8Sflorian free($1);
17058b5b9b8Sflorian free($3);
17158b5b9b8Sflorian }
17258b5b9b8Sflorian ;
17358b5b9b8Sflorian
17458b5b9b8Sflorian
17558b5b9b8Sflorian optnl : '\n' optnl /* zero or more newlines */
17658b5b9b8Sflorian | /*empty*/
17758b5b9b8Sflorian ;
17858b5b9b8Sflorian
179ac71ec8eSflorian block_list : BLOCK LIST STRING log {
1802d988276Sflorian if (conf->blocklist_file != NULL) {
1812d988276Sflorian yyerror("block list already "
1822d988276Sflorian "configured");
1832d988276Sflorian free($3);
1842d988276Sflorian YYERROR;
1852d988276Sflorian } else {
1862d988276Sflorian conf->blocklist_file = strdup($3);
1872d988276Sflorian if (conf->blocklist_file == NULL)
1882d988276Sflorian err(1, "strdup");
1892d988276Sflorian free($3);
190ac71ec8eSflorian conf->blocklist_log = $4;
1912d988276Sflorian }
1922d988276Sflorian }
1932d988276Sflorian ;
1942d988276Sflorian
19561b17b6aSflorian uw_pref : PREFERENCE {
19661b17b6aSflorian conf->res_pref.len = 0;
19761b17b6aSflorian memset(conf->enabled_resolvers, 0,
19861b17b6aSflorian sizeof(conf->enabled_resolvers));
19961b17b6aSflorian } pref_block
200fd873f7fSflorian ;
201fd873f7fSflorian
202fd873f7fSflorian pref_block : '{' optnl prefopts_l '}'
203fd873f7fSflorian | prefoptsl
204fd873f7fSflorian ;
205fd873f7fSflorian
206fd873f7fSflorian prefopts_l : prefopts_l prefoptsl optnl
207fd873f7fSflorian | prefoptsl optnl
208fd873f7fSflorian ;
209fd873f7fSflorian
210eb720a37Sotto prefoptsl : prefopt {
211eb720a37Sotto if (!check_pref_uniq($1))
212fd873f7fSflorian YYERROR;
213d032132bSflorian if (conf->res_pref.len >= UW_RES_NONE) {
214fd873f7fSflorian yyerror("preference list too long");
215fd873f7fSflorian YYERROR;
216fd873f7fSflorian }
217d032132bSflorian conf->res_pref.types[conf->res_pref.len++] = $1;
21861b17b6aSflorian conf->enabled_resolvers[$1] = 1;
219fd873f7fSflorian }
220eb720a37Sotto ;
221eb720a37Sotto
222eb720a37Sotto prefopt : DOT { $$ = UW_RES_DOT; }
223eb720a37Sotto | FORWARDER { $$ = UW_RES_FORWARDER; }
22415fe126bSflorian | ODOT_FORWARDER { $$ = UW_RES_ODOT_FORWARDER; }
225eb720a37Sotto | RECURSOR { $$ = UW_RES_RECURSOR; }
22656fed3e1Skn | AUTOCONF { $$ = UW_RES_AUTOCONF; }
22756fed3e1Skn | DHCP { $$ = UW_RES_AUTOCONF; }
22856fed3e1Skn | ODOT_AUTOCONF { $$ = UW_RES_ODOT_AUTOCONF; }
22956fed3e1Skn | ODOT_DHCP { $$ = UW_RES_ODOT_AUTOCONF; }
230217b4d33Sflorian | STUB { $$ = UW_RES_ASR; }
231fd873f7fSflorian ;
232fd873f7fSflorian
23358b5b9b8Sflorian uw_forwarder : FORWARDER forwarder_block
23458b5b9b8Sflorian ;
23558b5b9b8Sflorian
23658b5b9b8Sflorian forwarder_block : '{' optnl forwarderopts_l '}'
23758b5b9b8Sflorian | forwarderoptsl
23858b5b9b8Sflorian ;
23958b5b9b8Sflorian
24058b5b9b8Sflorian forwarderopts_l : forwarderopts_l forwarderoptsl optnl
24158b5b9b8Sflorian | forwarderoptsl optnl
24258b5b9b8Sflorian ;
24358b5b9b8Sflorian
2441463ff3cSotto forwarderoptsl : STRING port authname dot {
245c4d4ad74Sotto struct uw_forwarder *uw_fwd;
24658b5b9b8Sflorian struct sockaddr_storage *ss;
247c4d4ad74Sotto
24858b5b9b8Sflorian if ((ss = host_ip($1)) == NULL) {
24958b5b9b8Sflorian yyerror("%s is not an ip-address", $1);
25058b5b9b8Sflorian free($1);
25158b5b9b8Sflorian YYERROR;
25258b5b9b8Sflorian }
25358b5b9b8Sflorian free(ss);
25458b5b9b8Sflorian
255838215f8Sflorian if ((uw_fwd = calloc(1, sizeof(*uw_fwd))) ==
256838215f8Sflorian NULL)
257838215f8Sflorian err(1, NULL);
258838215f8Sflorian
2591463ff3cSotto if ($2 < 0 || $2 > (int)USHRT_MAX) {
2601463ff3cSotto yyerror("invalid port: %lld", $2);
2611463ff3cSotto free($1);
262838215f8Sflorian free(uw_fwd);
2631463ff3cSotto YYERROR;
2641463ff3cSotto }
2651463ff3cSotto if ($2 == 0)
266838215f8Sflorian uw_fwd->port = $4 == DOT ? 853 : 53;
2671463ff3cSotto else
268838215f8Sflorian uw_fwd->port = $2;
2691463ff3cSotto
270c4d4ad74Sotto if ($3 != NULL && $4 == 0) {
271c4d4ad74Sotto yyerror("authentication name can only "
272c4d4ad74Sotto "be used with DoT");
273c4d4ad74Sotto free($1);
274838215f8Sflorian free(uw_fwd);
275c4d4ad74Sotto YYERROR;
276c4d4ad74Sotto }
277c4d4ad74Sotto
278838215f8Sflorian if (strlcpy(uw_fwd->ip, $1, sizeof(uw_fwd->ip))
279838215f8Sflorian >= sizeof(uw_fwd->ip)) {
280c4d4ad74Sotto free(uw_fwd);
28158b5b9b8Sflorian yyerror("forwarder %s too long", $1);
28258b5b9b8Sflorian free($1);
28358b5b9b8Sflorian YYERROR;
28458b5b9b8Sflorian }
28558b5b9b8Sflorian
286838215f8Sflorian if ($4 == DOT && $3 != NULL) {
287838215f8Sflorian if (strlcpy(uw_fwd->auth_name, $3,
288838215f8Sflorian sizeof(uw_fwd->auth_name))
289838215f8Sflorian >= sizeof(uw_fwd->auth_name)) {
290838215f8Sflorian free(uw_fwd);
291838215f8Sflorian yyerror("authentication name "
292838215f8Sflorian "%s too long", $3);
293838215f8Sflorian free($1);
294838215f8Sflorian YYERROR;
295838215f8Sflorian }
296838215f8Sflorian }
297838215f8Sflorian
2981463ff3cSotto if ($4 == DOT)
2997d055805Sflorian TAILQ_INSERT_TAIL(
3001463ff3cSotto &conf->uw_dot_forwarder_list,
301c4d4ad74Sotto uw_fwd, entry);
302c4d4ad74Sotto else {
3037d055805Sflorian TAILQ_INSERT_TAIL(
3041463ff3cSotto &conf->uw_forwarder_list,
305c4d4ad74Sotto uw_fwd, entry);
306c4d4ad74Sotto }
307c4d4ad74Sotto free($1);
30858b5b9b8Sflorian }
3091463ff3cSotto ;
31058b5b9b8Sflorian
3111463ff3cSotto port : PORT NUMBER { $$ = $2; }
3121463ff3cSotto | /* empty */ { $$ = 0; }
3131463ff3cSotto ;
31458b5b9b8Sflorian
3151463ff3cSotto authname: AUTHENTICATION NAME STRING { $$ = $3; }
3161463ff3cSotto | /* empty */ { $$ = NULL; }
3171463ff3cSotto ;
31858b5b9b8Sflorian
3191463ff3cSotto dot : DOT { $$ = DOT; }
3201463ff3cSotto | /* empty */ { $$ = 0; }
32158b5b9b8Sflorian ;
322ac71ec8eSflorian
323ac71ec8eSflorian log : LOG { $$ = 1; }
324ac71ec8eSflorian | /* empty */ { $$ = 0; }
325ac71ec8eSflorian ;
326dd16127bSotto
327dd16127bSotto force : FORCE acceptbogus prefopt '{' force_list optnl '}' {
328dd16127bSotto struct force_tree_entry *n, *nxt;
329dd16127bSotto int error = 0;
330dd16127bSotto
3313bcff273Stb RB_FOREACH_SAFE(n, force_tree, &$5, nxt) {
332dd16127bSotto n->acceptbogus = $2;
333dd16127bSotto n->type = $3;
334dd16127bSotto RB_REMOVE(force_tree, &$5, n);
335dd16127bSotto if (RB_INSERT(force_tree, &conf->force,
336dd16127bSotto n)) {
337dd16127bSotto yyerror("%s already in an force "
338dd16127bSotto "list", n->domain);
339dd16127bSotto error = 1;
340dd16127bSotto }
341dd16127bSotto }
342dd16127bSotto if (error)
343dd16127bSotto YYERROR;
344dd16127bSotto }
345dd16127bSotto ;
346dd16127bSotto
347dd16127bSotto acceptbogus: ACCEPT BOGUS { $$ = 1; }
348dd16127bSotto | /* empty */ { $$ = 0; }
349dd16127bSotto ;
350dd16127bSotto
351dd16127bSotto force_list: force_list optnl STRING {
352dd16127bSotto struct force_tree_entry *e;
353dd16127bSotto size_t len;
354dd16127bSotto
355dd16127bSotto len = strlen($3);
356dd16127bSotto e = malloc(sizeof(*e));
357dd16127bSotto if (e == NULL)
358dd16127bSotto err(1, NULL);
359dd16127bSotto if (strlcpy(e->domain, $3, sizeof(e->domain)) >=
360dd16127bSotto sizeof(e->domain)) {
361dd16127bSotto yyerror("force %s too long", $3);
362dd16127bSotto free($3);
363dd16127bSotto YYERROR;
364dd16127bSotto }
365dd16127bSotto free($3);
366dd16127bSotto if (len == 0 || e->domain[len-1] != '.') {
367dd16127bSotto if (strlcat(e->domain, ".",
368dd16127bSotto sizeof((e->domain))) >=
369dd16127bSotto sizeof((e->domain))) {
370dd16127bSotto yyerror("force %s too long", $3);
371dd16127bSotto YYERROR;
372dd16127bSotto }
373dd16127bSotto }
374dbebd753Stb if (RB_INSERT(force_tree, &$$, e) != NULL) {
375dbebd753Stb log_warnx("duplicate force %s", e->domain);
376dbebd753Stb free(e);
377dbebd753Stb }
378dd16127bSotto }
379dd16127bSotto | /* empty */ {
380dd16127bSotto RB_INIT(&$$);
381dd16127bSotto }
382dd16127bSotto ;
383dd16127bSotto
38458b5b9b8Sflorian %%
38558b5b9b8Sflorian
38658b5b9b8Sflorian struct keywords {
38758b5b9b8Sflorian const char *k_name;
38858b5b9b8Sflorian int k_val;
38958b5b9b8Sflorian };
39058b5b9b8Sflorian
39158b5b9b8Sflorian int
yyerror(const char * fmt,...)39258b5b9b8Sflorian yyerror(const char *fmt, ...)
39358b5b9b8Sflorian {
39458b5b9b8Sflorian va_list ap;
39558b5b9b8Sflorian char *msg;
39658b5b9b8Sflorian
39758b5b9b8Sflorian file->errors++;
39858b5b9b8Sflorian va_start(ap, fmt);
39958b5b9b8Sflorian if (vasprintf(&msg, fmt, ap) == -1)
40058b5b9b8Sflorian fatalx("yyerror vasprintf");
40158b5b9b8Sflorian va_end(ap);
40258b5b9b8Sflorian logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
40358b5b9b8Sflorian free(msg);
40458b5b9b8Sflorian return (0);
40558b5b9b8Sflorian }
40658b5b9b8Sflorian
40758b5b9b8Sflorian int
kw_cmp(const void * k,const void * e)40858b5b9b8Sflorian kw_cmp(const void *k, const void *e)
40958b5b9b8Sflorian {
41058b5b9b8Sflorian return (strcmp(k, ((const struct keywords *)e)->k_name));
41158b5b9b8Sflorian }
41258b5b9b8Sflorian
41358b5b9b8Sflorian int
lookup(char * s)41458b5b9b8Sflorian lookup(char *s)
41558b5b9b8Sflorian {
41658b5b9b8Sflorian /* This has to be sorted always. */
41758b5b9b8Sflorian static const struct keywords keywords[] = {
41858b5b9b8Sflorian {"DoT", DOT},
419dd16127bSotto {"accept", ACCEPT},
4203461bfbeSflorian {"authentication", AUTHENTICATION},
42156fed3e1Skn {"autoconf", AUTOCONF},
4222d988276Sflorian {"block", BLOCK},
423dd16127bSotto {"bogus", BOGUS},
424fd873f7fSflorian {"dhcp", DHCP},
42558b5b9b8Sflorian {"dot", DOT},
426dd16127bSotto {"force", FORCE},
42758b5b9b8Sflorian {"forwarder", FORWARDER},
42858b5b9b8Sflorian {"include", INCLUDE},
4292d988276Sflorian {"list", LIST},
430ac71ec8eSflorian {"log", LOG},
4313461bfbeSflorian {"name", NAME},
43256fed3e1Skn {"oDoT-autoconf", ODOT_AUTOCONF},
43315fe126bSflorian {"oDoT-dhcp", ODOT_DHCP},
43415fe126bSflorian {"oDoT-forwarder", ODOT_FORWARDER},
43558b5b9b8Sflorian {"port", PORT},
436fd873f7fSflorian {"preference", PREFERENCE},
437fd873f7fSflorian {"recursor", RECURSOR},
438217b4d33Sflorian {"stub", STUB},
43958b5b9b8Sflorian {"tls", DOT},
44058b5b9b8Sflorian };
44158b5b9b8Sflorian const struct keywords *p;
44258b5b9b8Sflorian
44358b5b9b8Sflorian p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
44458b5b9b8Sflorian sizeof(keywords[0]), kw_cmp);
44558b5b9b8Sflorian
44658b5b9b8Sflorian if (p)
44758b5b9b8Sflorian return (p->k_val);
44858b5b9b8Sflorian else
44958b5b9b8Sflorian return (STRING);
45058b5b9b8Sflorian }
45158b5b9b8Sflorian
45258b5b9b8Sflorian #define START_EXPAND 1
45358b5b9b8Sflorian #define DONE_EXPAND 2
45458b5b9b8Sflorian
45558b5b9b8Sflorian static int expanding;
45658b5b9b8Sflorian
45758b5b9b8Sflorian int
igetc(void)45858b5b9b8Sflorian igetc(void)
45958b5b9b8Sflorian {
46058b5b9b8Sflorian int c;
46158b5b9b8Sflorian
46258b5b9b8Sflorian while (1) {
46358b5b9b8Sflorian if (file->ungetpos > 0)
46458b5b9b8Sflorian c = file->ungetbuf[--file->ungetpos];
46558b5b9b8Sflorian else
46658b5b9b8Sflorian c = getc(file->stream);
46758b5b9b8Sflorian
46858b5b9b8Sflorian if (c == START_EXPAND)
46958b5b9b8Sflorian expanding = 1;
47058b5b9b8Sflorian else if (c == DONE_EXPAND)
47158b5b9b8Sflorian expanding = 0;
47258b5b9b8Sflorian else
47358b5b9b8Sflorian break;
47458b5b9b8Sflorian }
47558b5b9b8Sflorian return (c);
47658b5b9b8Sflorian }
47758b5b9b8Sflorian
47858b5b9b8Sflorian int
lgetc(int quotec)47958b5b9b8Sflorian lgetc(int quotec)
48058b5b9b8Sflorian {
48158b5b9b8Sflorian int c, next;
48258b5b9b8Sflorian
48358b5b9b8Sflorian if (quotec) {
48458b5b9b8Sflorian if ((c = igetc()) == EOF) {
48558b5b9b8Sflorian yyerror("reached end of file while parsing "
48658b5b9b8Sflorian "quoted string");
48758b5b9b8Sflorian if (file == topfile || popfile() == EOF)
48858b5b9b8Sflorian return (EOF);
48958b5b9b8Sflorian return (quotec);
49058b5b9b8Sflorian }
49158b5b9b8Sflorian return (c);
49258b5b9b8Sflorian }
49358b5b9b8Sflorian
49458b5b9b8Sflorian while ((c = igetc()) == '\\') {
49558b5b9b8Sflorian next = igetc();
49658b5b9b8Sflorian if (next != '\n') {
49758b5b9b8Sflorian c = next;
49858b5b9b8Sflorian break;
49958b5b9b8Sflorian }
50058b5b9b8Sflorian yylval.lineno = file->lineno;
50158b5b9b8Sflorian file->lineno++;
50258b5b9b8Sflorian }
50358b5b9b8Sflorian
50458b5b9b8Sflorian if (c == EOF) {
50558b5b9b8Sflorian /*
50658b5b9b8Sflorian * Fake EOL when hit EOF for the first time. This gets line
50758b5b9b8Sflorian * count right if last line in included file is syntactically
50858b5b9b8Sflorian * invalid and has no newline.
50958b5b9b8Sflorian */
51058b5b9b8Sflorian if (file->eof_reached == 0) {
51158b5b9b8Sflorian file->eof_reached = 1;
51258b5b9b8Sflorian return ('\n');
51358b5b9b8Sflorian }
51458b5b9b8Sflorian while (c == EOF) {
51558b5b9b8Sflorian if (file == topfile || popfile() == EOF)
51658b5b9b8Sflorian return (EOF);
51758b5b9b8Sflorian c = igetc();
51858b5b9b8Sflorian }
51958b5b9b8Sflorian }
52058b5b9b8Sflorian return (c);
52158b5b9b8Sflorian }
52258b5b9b8Sflorian
52358b5b9b8Sflorian void
lungetc(int c)52458b5b9b8Sflorian lungetc(int c)
52558b5b9b8Sflorian {
52658b5b9b8Sflorian if (c == EOF)
52758b5b9b8Sflorian return;
52858b5b9b8Sflorian
52958b5b9b8Sflorian if (file->ungetpos >= file->ungetsize) {
53058b5b9b8Sflorian void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
53158b5b9b8Sflorian if (p == NULL)
53258b5b9b8Sflorian err(1, "lungetc");
53358b5b9b8Sflorian file->ungetbuf = p;
53458b5b9b8Sflorian file->ungetsize *= 2;
53558b5b9b8Sflorian }
53658b5b9b8Sflorian file->ungetbuf[file->ungetpos++] = c;
53758b5b9b8Sflorian }
53858b5b9b8Sflorian
53958b5b9b8Sflorian int
findeol(void)54058b5b9b8Sflorian findeol(void)
54158b5b9b8Sflorian {
54258b5b9b8Sflorian int c;
54358b5b9b8Sflorian
54458b5b9b8Sflorian /* Skip to either EOF or the first real EOL. */
54558b5b9b8Sflorian while (1) {
54658b5b9b8Sflorian c = lgetc(0);
54758b5b9b8Sflorian if (c == '\n') {
54858b5b9b8Sflorian file->lineno++;
54958b5b9b8Sflorian break;
55058b5b9b8Sflorian }
55158b5b9b8Sflorian if (c == EOF)
55258b5b9b8Sflorian break;
55358b5b9b8Sflorian }
55458b5b9b8Sflorian return (ERROR);
55558b5b9b8Sflorian }
55658b5b9b8Sflorian
55758b5b9b8Sflorian int
yylex(void)55858b5b9b8Sflorian yylex(void)
55958b5b9b8Sflorian {
56008f6ba19Snaddy char buf[8096];
56108f6ba19Snaddy char *p, *val;
56258b5b9b8Sflorian int quotec, next, c;
56358b5b9b8Sflorian int token;
56458b5b9b8Sflorian
56558b5b9b8Sflorian top:
56658b5b9b8Sflorian p = buf;
56758b5b9b8Sflorian while ((c = lgetc(0)) == ' ' || c == '\t')
56858b5b9b8Sflorian ; /* nothing */
56958b5b9b8Sflorian
57058b5b9b8Sflorian yylval.lineno = file->lineno;
57158b5b9b8Sflorian if (c == '#')
57258b5b9b8Sflorian while ((c = lgetc(0)) != '\n' && c != EOF)
57358b5b9b8Sflorian ; /* nothing */
57458b5b9b8Sflorian if (c == '$' && !expanding) {
57558b5b9b8Sflorian while (1) {
57658b5b9b8Sflorian if ((c = lgetc(0)) == EOF)
57758b5b9b8Sflorian return (0);
57858b5b9b8Sflorian
57958b5b9b8Sflorian if (p + 1 >= buf + sizeof(buf) - 1) {
58058b5b9b8Sflorian yyerror("string too long");
58158b5b9b8Sflorian return (findeol());
58258b5b9b8Sflorian }
58358b5b9b8Sflorian if (isalnum(c) || c == '_') {
58458b5b9b8Sflorian *p++ = c;
58558b5b9b8Sflorian continue;
58658b5b9b8Sflorian }
58758b5b9b8Sflorian *p = '\0';
58858b5b9b8Sflorian lungetc(c);
58958b5b9b8Sflorian break;
59058b5b9b8Sflorian }
59158b5b9b8Sflorian val = symget(buf);
59258b5b9b8Sflorian if (val == NULL) {
59358b5b9b8Sflorian yyerror("macro '%s' not defined", buf);
59458b5b9b8Sflorian return (findeol());
59558b5b9b8Sflorian }
59658b5b9b8Sflorian p = val + strlen(val) - 1;
59758b5b9b8Sflorian lungetc(DONE_EXPAND);
59858b5b9b8Sflorian while (p >= val) {
59908f6ba19Snaddy lungetc((unsigned char)*p);
60058b5b9b8Sflorian p--;
60158b5b9b8Sflorian }
60258b5b9b8Sflorian lungetc(START_EXPAND);
60358b5b9b8Sflorian goto top;
60458b5b9b8Sflorian }
60558b5b9b8Sflorian
60658b5b9b8Sflorian switch (c) {
60758b5b9b8Sflorian case '\'':
60858b5b9b8Sflorian case '"':
60958b5b9b8Sflorian quotec = c;
61058b5b9b8Sflorian while (1) {
61158b5b9b8Sflorian if ((c = lgetc(quotec)) == EOF)
61258b5b9b8Sflorian return (0);
61358b5b9b8Sflorian if (c == '\n') {
61458b5b9b8Sflorian file->lineno++;
61558b5b9b8Sflorian continue;
61658b5b9b8Sflorian } else if (c == '\\') {
61758b5b9b8Sflorian if ((next = lgetc(quotec)) == EOF)
61858b5b9b8Sflorian return (0);
61958b5b9b8Sflorian if (next == quotec || next == ' ' ||
62058b5b9b8Sflorian next == '\t')
62158b5b9b8Sflorian c = next;
62258b5b9b8Sflorian else if (next == '\n') {
62358b5b9b8Sflorian file->lineno++;
62458b5b9b8Sflorian continue;
62558b5b9b8Sflorian } else
62658b5b9b8Sflorian lungetc(next);
62758b5b9b8Sflorian } else if (c == quotec) {
62858b5b9b8Sflorian *p = '\0';
62958b5b9b8Sflorian break;
63058b5b9b8Sflorian } else if (c == '\0') {
63158b5b9b8Sflorian yyerror("syntax error");
63258b5b9b8Sflorian return (findeol());
63358b5b9b8Sflorian }
63458b5b9b8Sflorian if (p + 1 >= buf + sizeof(buf) - 1) {
63558b5b9b8Sflorian yyerror("string too long");
63658b5b9b8Sflorian return (findeol());
63758b5b9b8Sflorian }
63858b5b9b8Sflorian *p++ = c;
63958b5b9b8Sflorian }
64058b5b9b8Sflorian yylval.v.string = strdup(buf);
64158b5b9b8Sflorian if (yylval.v.string == NULL)
64258b5b9b8Sflorian err(1, "yylex: strdup");
64358b5b9b8Sflorian return (STRING);
64458b5b9b8Sflorian }
64558b5b9b8Sflorian
64658b5b9b8Sflorian #define allowed_to_end_number(x) \
64758b5b9b8Sflorian (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
64858b5b9b8Sflorian
64958b5b9b8Sflorian if (c == '-' || isdigit(c)) {
65058b5b9b8Sflorian do {
65158b5b9b8Sflorian *p++ = c;
65258b5b9b8Sflorian if ((size_t)(p-buf) >= sizeof(buf)) {
65358b5b9b8Sflorian yyerror("string too long");
65458b5b9b8Sflorian return (findeol());
65558b5b9b8Sflorian }
65658b5b9b8Sflorian } while ((c = lgetc(0)) != EOF && isdigit(c));
65758b5b9b8Sflorian lungetc(c);
65858b5b9b8Sflorian if (p == buf + 1 && buf[0] == '-')
65958b5b9b8Sflorian goto nodigits;
66058b5b9b8Sflorian if (c == EOF || allowed_to_end_number(c)) {
66158b5b9b8Sflorian const char *errstr = NULL;
66258b5b9b8Sflorian
66358b5b9b8Sflorian *p = '\0';
66458b5b9b8Sflorian yylval.v.number = strtonum(buf, LLONG_MIN,
66558b5b9b8Sflorian LLONG_MAX, &errstr);
66658b5b9b8Sflorian if (errstr) {
66758b5b9b8Sflorian yyerror("\"%s\" invalid number: %s",
66858b5b9b8Sflorian buf, errstr);
66958b5b9b8Sflorian return (findeol());
67058b5b9b8Sflorian }
67158b5b9b8Sflorian return (NUMBER);
67258b5b9b8Sflorian } else {
67358b5b9b8Sflorian nodigits:
67458b5b9b8Sflorian while (p > buf + 1)
67508f6ba19Snaddy lungetc((unsigned char)*--p);
67608f6ba19Snaddy c = (unsigned char)*--p;
67758b5b9b8Sflorian if (c == '-')
67858b5b9b8Sflorian return (c);
67958b5b9b8Sflorian }
68058b5b9b8Sflorian }
68158b5b9b8Sflorian
68258b5b9b8Sflorian #define allowed_in_string(x) \
68358b5b9b8Sflorian (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
68458b5b9b8Sflorian x != '{' && x != '}' && \
68558b5b9b8Sflorian x != '!' && x != '=' && x != '#' && \
68658b5b9b8Sflorian x != ','))
68758b5b9b8Sflorian
68858b5b9b8Sflorian if (isalnum(c) || c == ':' || c == '_') {
68958b5b9b8Sflorian do {
69058b5b9b8Sflorian *p++ = c;
69158b5b9b8Sflorian if ((size_t)(p-buf) >= sizeof(buf)) {
69258b5b9b8Sflorian yyerror("string too long");
69358b5b9b8Sflorian return (findeol());
69458b5b9b8Sflorian }
69558b5b9b8Sflorian } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
69658b5b9b8Sflorian lungetc(c);
69758b5b9b8Sflorian *p = '\0';
69858b5b9b8Sflorian if ((token = lookup(buf)) == STRING)
69958b5b9b8Sflorian if ((yylval.v.string = strdup(buf)) == NULL)
70058b5b9b8Sflorian err(1, "yylex: strdup");
70158b5b9b8Sflorian return (token);
70258b5b9b8Sflorian }
70358b5b9b8Sflorian if (c == '\n') {
70458b5b9b8Sflorian yylval.lineno = file->lineno;
70558b5b9b8Sflorian file->lineno++;
70658b5b9b8Sflorian }
70758b5b9b8Sflorian if (c == EOF)
70858b5b9b8Sflorian return (0);
70958b5b9b8Sflorian return (c);
71058b5b9b8Sflorian }
71158b5b9b8Sflorian
71258b5b9b8Sflorian int
check_file_secrecy(int fd,const char * fname)71358b5b9b8Sflorian check_file_secrecy(int fd, const char *fname)
71458b5b9b8Sflorian {
71558b5b9b8Sflorian struct stat st;
71658b5b9b8Sflorian
71758b5b9b8Sflorian if (fstat(fd, &st)) {
71858b5b9b8Sflorian log_warn("cannot stat %s", fname);
71958b5b9b8Sflorian return (-1);
72058b5b9b8Sflorian }
72158b5b9b8Sflorian if (st.st_uid != 0 && st.st_uid != getuid()) {
72258b5b9b8Sflorian log_warnx("%s: owner not root or current user", fname);
72358b5b9b8Sflorian return (-1);
72458b5b9b8Sflorian }
72558b5b9b8Sflorian if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
72658b5b9b8Sflorian log_warnx("%s: group writable or world read/writable", fname);
72758b5b9b8Sflorian return (-1);
72858b5b9b8Sflorian }
72958b5b9b8Sflorian return (0);
73058b5b9b8Sflorian }
73158b5b9b8Sflorian
73258b5b9b8Sflorian struct file *
pushfile(const char * name,int secret)73358b5b9b8Sflorian pushfile(const char *name, int secret)
73458b5b9b8Sflorian {
73558b5b9b8Sflorian struct file *nfile;
73658b5b9b8Sflorian
73758b5b9b8Sflorian if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
73858b5b9b8Sflorian log_warn("calloc");
73958b5b9b8Sflorian return (NULL);
74058b5b9b8Sflorian }
74158b5b9b8Sflorian if ((nfile->name = strdup(name)) == NULL) {
74258b5b9b8Sflorian log_warn("strdup");
74358b5b9b8Sflorian free(nfile);
74458b5b9b8Sflorian return (NULL);
74558b5b9b8Sflorian }
74658b5b9b8Sflorian if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
74758b5b9b8Sflorian free(nfile->name);
74858b5b9b8Sflorian free(nfile);
74958b5b9b8Sflorian return (NULL);
75058b5b9b8Sflorian } else if (secret &&
75158b5b9b8Sflorian check_file_secrecy(fileno(nfile->stream), nfile->name)) {
75258b5b9b8Sflorian fclose(nfile->stream);
75358b5b9b8Sflorian free(nfile->name);
75458b5b9b8Sflorian free(nfile);
75558b5b9b8Sflorian return (NULL);
75658b5b9b8Sflorian }
75758b5b9b8Sflorian nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
75858b5b9b8Sflorian nfile->ungetsize = 16;
75958b5b9b8Sflorian nfile->ungetbuf = malloc(nfile->ungetsize);
76058b5b9b8Sflorian if (nfile->ungetbuf == NULL) {
76158b5b9b8Sflorian log_warn("malloc");
76258b5b9b8Sflorian fclose(nfile->stream);
76358b5b9b8Sflorian free(nfile->name);
76458b5b9b8Sflorian free(nfile);
76558b5b9b8Sflorian return (NULL);
76658b5b9b8Sflorian }
76758b5b9b8Sflorian TAILQ_INSERT_TAIL(&files, nfile, entry);
76858b5b9b8Sflorian return (nfile);
76958b5b9b8Sflorian }
77058b5b9b8Sflorian
77158b5b9b8Sflorian int
popfile(void)77258b5b9b8Sflorian popfile(void)
77358b5b9b8Sflorian {
77458b5b9b8Sflorian struct file *prev;
77558b5b9b8Sflorian
77658b5b9b8Sflorian if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
77758b5b9b8Sflorian prev->errors += file->errors;
77858b5b9b8Sflorian
77958b5b9b8Sflorian TAILQ_REMOVE(&files, file, entry);
78058b5b9b8Sflorian fclose(file->stream);
78158b5b9b8Sflorian free(file->name);
78258b5b9b8Sflorian free(file->ungetbuf);
78358b5b9b8Sflorian free(file);
78458b5b9b8Sflorian file = prev;
78558b5b9b8Sflorian return (file ? 0 : EOF);
78658b5b9b8Sflorian }
78758b5b9b8Sflorian
78858b5b9b8Sflorian struct uw_conf *
parse_config(char * filename)789572e5ac0Skn parse_config(char *filename)
79058b5b9b8Sflorian {
791*cf9537f6Sflorian static enum uw_resolver_type default_res_pref[] = {
792*cf9537f6Sflorian UW_RES_DOT,
793*cf9537f6Sflorian UW_RES_ODOT_FORWARDER,
794*cf9537f6Sflorian UW_RES_FORWARDER,
795*cf9537f6Sflorian UW_RES_RECURSOR,
796*cf9537f6Sflorian UW_RES_ODOT_AUTOCONF,
797*cf9537f6Sflorian UW_RES_AUTOCONF,
798*cf9537f6Sflorian UW_RES_ASR};
79958b5b9b8Sflorian struct sym *sym, *next;
800*cf9537f6Sflorian int i;
80158b5b9b8Sflorian
80258b5b9b8Sflorian conf = config_new_empty();
80358b5b9b8Sflorian
804*cf9537f6Sflorian memcpy(&conf->res_pref.types, &default_res_pref,
805*cf9537f6Sflorian sizeof(default_res_pref));
806*cf9537f6Sflorian conf->res_pref.len = nitems(default_res_pref);
807*cf9537f6Sflorian for (i = 0; i < conf->res_pref.len; i++)
808*cf9537f6Sflorian conf->enabled_resolvers[conf->res_pref.types[i]] = 1;
809*cf9537f6Sflorian
810ee5be195Sflorian file = pushfile(filename != NULL ? filename : _PATH_CONF_FILE, 0);
81158b5b9b8Sflorian if (file == NULL) {
812572e5ac0Skn /* no default config file is fine */
813572e5ac0Skn if (errno == ENOENT && filename == NULL)
81458b5b9b8Sflorian return (conf);
81558b5b9b8Sflorian log_warn("%s", filename);
81658b5b9b8Sflorian free(conf);
81758b5b9b8Sflorian return (NULL);
81858b5b9b8Sflorian }
81958b5b9b8Sflorian topfile = file;
82058b5b9b8Sflorian
82158b5b9b8Sflorian yyparse();
82258b5b9b8Sflorian errors = file->errors;
82358b5b9b8Sflorian popfile();
82458b5b9b8Sflorian
82558b5b9b8Sflorian /* Free macros and check which have not been used. */
82658b5b9b8Sflorian TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
82758b5b9b8Sflorian if ((cmd_opts & OPT_VERBOSE2) && !sym->used)
82858b5b9b8Sflorian fprintf(stderr, "warning: macro '%s' not used\n",
82958b5b9b8Sflorian sym->nam);
83058b5b9b8Sflorian if (!sym->persist) {
83158b5b9b8Sflorian free(sym->nam);
83258b5b9b8Sflorian free(sym->val);
83358b5b9b8Sflorian TAILQ_REMOVE(&symhead, sym, entry);
83458b5b9b8Sflorian free(sym);
83558b5b9b8Sflorian }
83658b5b9b8Sflorian }
83758b5b9b8Sflorian
83858b5b9b8Sflorian if (errors) {
83958b5b9b8Sflorian clear_config(conf);
84058b5b9b8Sflorian return (NULL);
84158b5b9b8Sflorian }
84258b5b9b8Sflorian
84358b5b9b8Sflorian return (conf);
84458b5b9b8Sflorian }
84558b5b9b8Sflorian
84658b5b9b8Sflorian int
symset(const char * nam,const char * val,int persist)84758b5b9b8Sflorian symset(const char *nam, const char *val, int persist)
84858b5b9b8Sflorian {
84958b5b9b8Sflorian struct sym *sym;
85058b5b9b8Sflorian
85158b5b9b8Sflorian TAILQ_FOREACH(sym, &symhead, entry) {
85258b5b9b8Sflorian if (strcmp(nam, sym->nam) == 0)
85358b5b9b8Sflorian break;
85458b5b9b8Sflorian }
85558b5b9b8Sflorian
85658b5b9b8Sflorian if (sym != NULL) {
85758b5b9b8Sflorian if (sym->persist == 1)
85858b5b9b8Sflorian return (0);
85958b5b9b8Sflorian else {
86058b5b9b8Sflorian free(sym->nam);
86158b5b9b8Sflorian free(sym->val);
86258b5b9b8Sflorian TAILQ_REMOVE(&symhead, sym, entry);
86358b5b9b8Sflorian free(sym);
86458b5b9b8Sflorian }
86558b5b9b8Sflorian }
86658b5b9b8Sflorian if ((sym = calloc(1, sizeof(*sym))) == NULL)
86758b5b9b8Sflorian return (-1);
86858b5b9b8Sflorian
86958b5b9b8Sflorian sym->nam = strdup(nam);
87058b5b9b8Sflorian if (sym->nam == NULL) {
87158b5b9b8Sflorian free(sym);
87258b5b9b8Sflorian return (-1);
87358b5b9b8Sflorian }
87458b5b9b8Sflorian sym->val = strdup(val);
87558b5b9b8Sflorian if (sym->val == NULL) {
87658b5b9b8Sflorian free(sym->nam);
87758b5b9b8Sflorian free(sym);
87858b5b9b8Sflorian return (-1);
87958b5b9b8Sflorian }
88058b5b9b8Sflorian sym->used = 0;
88158b5b9b8Sflorian sym->persist = persist;
88258b5b9b8Sflorian TAILQ_INSERT_TAIL(&symhead, sym, entry);
88358b5b9b8Sflorian return (0);
88458b5b9b8Sflorian }
88558b5b9b8Sflorian
88658b5b9b8Sflorian int
cmdline_symset(char * s)88758b5b9b8Sflorian cmdline_symset(char *s)
88858b5b9b8Sflorian {
88958b5b9b8Sflorian char *sym, *val;
89058b5b9b8Sflorian int ret;
89158b5b9b8Sflorian
89258b5b9b8Sflorian if ((val = strrchr(s, '=')) == NULL)
89358b5b9b8Sflorian return (-1);
89458b5b9b8Sflorian sym = strndup(s, val - s);
89558b5b9b8Sflorian if (sym == NULL)
89658b5b9b8Sflorian errx(1, "%s: strndup", __func__);
89758b5b9b8Sflorian ret = symset(sym, val + 1, 1);
89858b5b9b8Sflorian free(sym);
89958b5b9b8Sflorian
90058b5b9b8Sflorian return (ret);
90158b5b9b8Sflorian }
90258b5b9b8Sflorian
90358b5b9b8Sflorian char *
symget(const char * nam)90458b5b9b8Sflorian symget(const char *nam)
90558b5b9b8Sflorian {
90658b5b9b8Sflorian struct sym *sym;
90758b5b9b8Sflorian
90858b5b9b8Sflorian TAILQ_FOREACH(sym, &symhead, entry) {
90958b5b9b8Sflorian if (strcmp(nam, sym->nam) == 0) {
91058b5b9b8Sflorian sym->used = 1;
91158b5b9b8Sflorian return (sym->val);
91258b5b9b8Sflorian }
91358b5b9b8Sflorian }
91458b5b9b8Sflorian return (NULL);
91558b5b9b8Sflorian }
91658b5b9b8Sflorian
91758b5b9b8Sflorian void
clear_config(struct uw_conf * xconf)91858b5b9b8Sflorian clear_config(struct uw_conf *xconf)
91958b5b9b8Sflorian {
920c4d4ad74Sotto struct uw_forwarder *uw_forwarder;
921c4d4ad74Sotto
9227d055805Sflorian while ((uw_forwarder = TAILQ_FIRST(&xconf->uw_forwarder_list)) !=
92358b5b9b8Sflorian NULL) {
9247d055805Sflorian TAILQ_REMOVE(&xconf->uw_forwarder_list, uw_forwarder, entry);
92558b5b9b8Sflorian free(uw_forwarder);
92658b5b9b8Sflorian }
9277d055805Sflorian while ((uw_forwarder = TAILQ_FIRST(&xconf->uw_dot_forwarder_list)) !=
92858b5b9b8Sflorian NULL) {
9297d055805Sflorian TAILQ_REMOVE(&xconf->uw_dot_forwarder_list, uw_forwarder,
9307d055805Sflorian entry);
93158b5b9b8Sflorian free(uw_forwarder);
93258b5b9b8Sflorian }
93358b5b9b8Sflorian
93458b5b9b8Sflorian free(xconf);
93558b5b9b8Sflorian }
93658b5b9b8Sflorian
93758b5b9b8Sflorian struct sockaddr_storage *
host_ip(const char * s)93858b5b9b8Sflorian host_ip(const char *s)
93958b5b9b8Sflorian {
94058b5b9b8Sflorian struct addrinfo hints, *res;
94158b5b9b8Sflorian struct sockaddr_storage *ss = NULL;
94258b5b9b8Sflorian
94358b5b9b8Sflorian memset(&hints, 0, sizeof(hints));
94458b5b9b8Sflorian hints.ai_family = AF_UNSPEC;
94558b5b9b8Sflorian hints.ai_socktype = SOCK_DGRAM; /*dummy*/
94658b5b9b8Sflorian hints.ai_flags = AI_NUMERICHOST;
94758b5b9b8Sflorian if (getaddrinfo(s, "0", &hints, &res) == 0) {
94858b5b9b8Sflorian if (res->ai_family == AF_INET ||
94958b5b9b8Sflorian res->ai_family == AF_INET6) {
95058b5b9b8Sflorian if ((ss = calloc(1, sizeof(*ss))) == NULL)
95158b5b9b8Sflorian fatal(NULL);
95258b5b9b8Sflorian memcpy(ss, res->ai_addr, res->ai_addrlen);
95358b5b9b8Sflorian }
95458b5b9b8Sflorian freeaddrinfo(res);
95558b5b9b8Sflorian }
95658b5b9b8Sflorian
95758b5b9b8Sflorian return (ss);
95858b5b9b8Sflorian }
959fd873f7fSflorian
960fd873f7fSflorian int
check_pref_uniq(enum uw_resolver_type type)961fd873f7fSflorian check_pref_uniq(enum uw_resolver_type type)
962fd873f7fSflorian {
963fd873f7fSflorian int i;
964fd873f7fSflorian
965d032132bSflorian for (i = 0; i < conf->res_pref.len; i++)
966d032132bSflorian if (conf->res_pref.types[i] == type) {
967fd873f7fSflorian yyerror("%s is already in the preference list",
968fd873f7fSflorian uw_resolver_type_str[type]);
969fd873f7fSflorian return (0);
970fd873f7fSflorian }
971fd873f7fSflorian
972fd873f7fSflorian return (1);
973fd873f7fSflorian }
974