Bug Summary

File:src/sbin/unwind/obj/parse.c
Warning:line 971, column 13
Attempt to free released memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name parse.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/unwind/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/unwind -I /usr/src/sbin/unwind -I /usr/src/sbin/unwind/libunbound/libunbound -I /usr/src/sbin/unwind/libunbound -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/unwind/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c parse.c
1#include <stdlib.h>
2#include <string.h>
3#define YYBYACC1 1
4#define YYMAJOR1 1
5#define YYMINOR9 9
6#define YYLEXyylex() yylex()
7#define YYEMPTY-1 -1
8#define yyclearin(yychar=(-1)) (yychar=(YYEMPTY-1))
9#define yyerrok(yyerrflag=0) (yyerrflag=0)
10#define YYRECOVERING()(yyerrflag!=0) (yyerrflag!=0)
11#define YYPREFIX"yy" "yy"
12#line 26 "/usr/src/sbin/unwind/parse.y"
13#include <sys/queue.h>
14#include <sys/socket.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17
18#include <ctype.h>
19#include <err.h>
20#include <errno(*__errno()).h>
21#include <limits.h>
22#include <netdb.h>
23#include <stdarg.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <syslog.h>
27#include <unistd.h>
28
29#include "log.h"
30#include "unwind.h"
31
32TAILQ_HEAD(files, file)struct files { struct file *tqh_first; struct file **tqh_last
; }
files = TAILQ_HEAD_INITIALIZER(files){ ((void *)0), &(files).tqh_first };
33static struct file {
34 TAILQ_ENTRY(file)struct { struct file *tqe_next; struct file **tqe_prev; } entry;
35 FILE *stream;
36 char *name;
37 size_t ungetpos;
38 size_t ungetsize;
39 u_char *ungetbuf;
40 int eof_reached;
41 int lineno;
42 int errors;
43} *file, *topfile;
44struct file *pushfile(const char *, int);
45int popfile(void);
46int check_file_secrecy(int, const char *);
47int yyparse(void);
48int yylex(void);
49int yyerror(const char *, ...)
50 __attribute__((__format__ (printf, 1, 2)))
51 __attribute__((__nonnull__ (1)));
52int kw_cmp(const void *, const void *);
53int lookup(char *);
54int igetc(void);
55int lgetc(int);
56void lungetc(int);
57int findeol(void);
58
59TAILQ_HEAD(symhead, sym)struct symhead { struct sym *tqh_first; struct sym **tqh_last
; }
symhead = TAILQ_HEAD_INITIALIZER(symhead){ ((void *)0), &(symhead).tqh_first };
60struct sym {
61 TAILQ_ENTRY(sym)struct { struct sym *tqe_next; struct sym **tqe_prev; } entry;
62 int used;
63 int persist;
64 char *nam;
65 char *val;
66};
67
68int symset(const char *, const char *, int);
69char *symget(const char *);
70int check_pref_uniq(enum uw_resolver_type);
71
72static struct uw_conf *conf;
73static int errors;
74
75void clear_config(struct uw_conf *xconf);
76struct sockaddr_storage *host_ip(const char *);
77
78typedef struct {
79 union {
80 int64_t number;
81 char *string;
82 struct force_tree force;
83 } v;
84 int lineno;
85} YYSTYPE;
86
87#line 88 "parse.c"
88#define INCLUDE257 257
89#define ERROR258 258
90#define FORWARDER259 259
91#define DOT260 260
92#define PORT261 261
93#define ODOT_FORWARDER262 262
94#define ODOT_AUTOCONF263 263
95#define ODOT_DHCP264 264
96#define AUTHENTICATION265 265
97#define NAME266 266
98#define PREFERENCE267 267
99#define RECURSOR268 268
100#define AUTOCONF269 269
101#define DHCP270 270
102#define STUB271 271
103#define BLOCK272 272
104#define LIST273 273
105#define LOG274 274
106#define FORCE275 275
107#define ACCEPT276 276
108#define BOGUS277 277
109#define STRING278 278
110#define NUMBER279 279
111#define YYERRCODE256 256
112const short yylhs[] =
113 { -1,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
115 6, 6, 10, 15, 15, 13, 17, 11, 16, 16,
116 18, 18, 19, 3, 3, 3, 3, 3, 3, 3,
117 3, 3, 12, 20, 20, 21, 21, 22, 1, 1,
118 7, 7, 2, 2, 4, 4, 14, 5, 5, 8,
119 8,
120};
121const short yylen[] =
122 { 2,
123 0, 3, 2, 3, 3, 3, 3, 3, 3, 2,
124 2, 1, 3, 2, 0, 4, 0, 3, 4, 1,
125 3, 2, 1, 1, 1, 1, 1, 1, 1, 1,
126 1, 1, 2, 4, 1, 3, 2, 4, 2, 0,
127 3, 0, 1, 0, 1, 0, 7, 2, 0, 3,
128 0,
129};
130const short yydefred[] =
131 { 1,
132 0, 0, 0, 0, 17, 0, 0, 0, 3, 0,
133 0, 0, 0, 0, 0, 9, 10, 0, 0, 33,
134 35, 0, 0, 0, 0, 0, 2, 4, 5, 6,
135 7, 8, 0, 0, 0, 0, 25, 24, 26, 30,
136 31, 27, 28, 29, 32, 0, 23, 18, 20, 0,
137 48, 0, 12, 0, 39, 0, 0, 14, 0, 0,
138 0, 45, 16, 51, 11, 0, 43, 38, 34, 0,
139 37, 0, 0, 0, 41, 36, 19, 0, 22, 0,
140 21, 50, 47,
141};
142const short yydgoto[] =
143 { 1,
144 34, 68, 47, 63, 25, 54, 57, 74, 10, 11,
145 12, 13, 14, 15, 36, 48, 22, 72, 49, 20,
146 59, 21,
147};
148const short yysindex[] =
149 { 0,
150 -10, 8, -259, -119, 0, -241, -238, -22, 0, 30,
151 33, 36, 43, 44, 50, 0, 0, -200, 52, 0,
152 0, -96, -215, -213, -248, -211, 0, 0, 0, 0,
153 0, 0, -214, -199, 52, -210, 0, 0, 0, 0,
154 0, 0, 0, 0, 0, 52, 0, 0, 0, -205,
155 0, -53, 0, -207, 0, -194, -187, 0, -118, 52,
156 -248, 0, 0, 0, 0, -204, 0, 0, 0, 52,
157 0, -83, 52, 52, 0, 0, 0, 52, 0, -117,
158 0, 0, 0,};
159const short yyrindex[] =
160 { 0,
161 0, 0, 0, 0, 0, 0, -234, 0, 0, 0,
162 0, 0, 0, 0, 0, 0, 0, -9, -203, 0,
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0, -8, -120, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, -212, 0, 0, 0, 66,
166 0, 0, 0, 67, 0, 0, -7, 0, 0, -116,
167 0, 0, 0, 0, 0, 0, 0, 0, 0, -116,
168 0, 0, -70, -116, 0, 0, 0, -70, 0, 0,
169 0, 0, 0,};
170const short yygindex[] =
171 { 0,
172 0, 0, 53, 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, -29, 0, 0, 0, -48, 0,
174 0, -26,
175};
176#define YYTABLESIZE271 271
177const short yytable[] =
178 { 9,
179 40, 42, 44, 19, 15, 58, 69, 83, 15, 60,
180 37, 38, 73, 39, 40, 41, 61, 16, 17, 42,
181 43, 44, 45, 78, 49, 49, 46, 49, 49, 49,
182 71, 23, 70, 49, 49, 49, 49, 24, 26, 27,
183 76, 77, 28, 79, 80, 29, 15, 15, 81, 15,
184 15, 15, 30, 31, 15, 15, 15, 15, 15, 32,
185 33, 35, 50, 51, 55, 56, 53, 18, 62, 64,
186 65, 66, 67, 75, 15, 46, 13, 52, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190 0, 0, 0, 0, 0, 40, 42, 44, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
193 0, 15, 15, 15, 0, 0, 0, 15, 15, 15,
194 15, 0, 0, 0, 0, 0, 0, 15, 18, 18,
195 82, 15, 37, 38, 0, 39, 40, 41, 0, 0,
196 0, 42, 43, 44, 45, 37, 38, 0, 39, 40,
197 41, 0, 0, 0, 42, 43, 44, 45, 15, 15,
198 0, 15, 15, 15, 0, 0, 0, 15, 15, 15,
199 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 2, 3, 0, 4, 0,
204 40, 42, 0, 0, 0, 40, 5, 0, 0, 0,
205 0, 6, 0, 0, 7, 0, 0, 8, 40, 42,
206 44,
207};
208const short yycheck[] =
209 { 10,
210 10, 10, 10, 123, 125, 35, 125, 125, 125, 36,
211 259, 260, 61, 262, 263, 264, 46, 10, 278, 268,
212 269, 270, 271, 72, 259, 260, 123, 262, 263, 264,
213 60, 273, 59, 268, 269, 270, 271, 276, 61, 10,
214 70, 125, 10, 73, 74, 10, 259, 260, 78, 262,
215 263, 264, 10, 10, 125, 268, 269, 270, 271, 10,
216 261, 10, 278, 277, 279, 265, 278, 278, 274, 123,
217 278, 266, 260, 278, 278, 10, 10, 25, -1, -1,
218 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
220 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
221 -1, -1, -1, -1, -1, 125, 125, 125, -1, -1,
222 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
223 -1, -1, -1, -1, -1, -1, -1, -1, 259, 260,
224 -1, 262, 263, 264, -1, -1, -1, 268, 269, 270,
225 271, -1, -1, -1, -1, -1, -1, 278, 278, 278,
226 278, 278, 259, 260, -1, 262, 263, 264, -1, -1,
227 -1, 268, 269, 270, 271, 259, 260, -1, 262, 263,
228 264, -1, -1, -1, 268, 269, 270, 271, 259, 260,
229 -1, 262, 263, 264, -1, -1, -1, 268, 269, 270,
230 271, -1, -1, -1, -1, -1, -1, -1, -1, -1,
231 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
232 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
233 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234 -1, -1, -1, -1, -1, 256, 257, -1, 259, -1,
235 260, 260, -1, -1, -1, 265, 267, -1, -1, -1,
236 -1, 272, -1, -1, 275, -1, -1, 278, 278, 278,
237 278,
238};
239#define YYFINAL1 1
240#ifndef YYDEBUG0
241#define YYDEBUG0 0
242#endif
243#define YYMAXTOKEN279 279
244#if YYDEBUG0
245const char * const yyname[] =
246 {
247"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'='",0,0,0,0,0,0,0,
2490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2500,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2510,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2520,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INCLUDE",
254"ERROR","FORWARDER","DOT","PORT","ODOT_FORWARDER","ODOT_AUTOCONF","ODOT_DHCP",
255"AUTHENTICATION","NAME","PREFERENCE","RECURSOR","AUTOCONF","DHCP","STUB",
256"BLOCK","LIST","LOG","FORCE","ACCEPT","BOGUS","STRING","NUMBER",
257};
258const char * const yyrule[] =
259 {"$accept : grammar",
260"grammar :",
261"grammar : grammar include '\\n'",
262"grammar : grammar '\\n'",
263"grammar : grammar varset '\\n'",
264"grammar : grammar uw_pref '\\n'",
265"grammar : grammar uw_forwarder '\\n'",
266"grammar : grammar block_list '\\n'",
267"grammar : grammar force '\\n'",
268"grammar : grammar error '\\n'",
269"include : INCLUDE STRING",
270"string : string STRING",
271"string : STRING",
272"varset : STRING '=' string",
273"optnl : '\\n' optnl",
274"optnl :",
275"block_list : BLOCK LIST STRING log",
276"$$1 :",
277"uw_pref : PREFERENCE $$1 pref_block",
278"pref_block : '{' optnl prefopts_l '}'",
279"pref_block : prefoptsl",
280"prefopts_l : prefopts_l prefoptsl optnl",
281"prefopts_l : prefoptsl optnl",
282"prefoptsl : prefopt",
283"prefopt : DOT",
284"prefopt : FORWARDER",
285"prefopt : ODOT_FORWARDER",
286"prefopt : RECURSOR",
287"prefopt : AUTOCONF",
288"prefopt : DHCP",
289"prefopt : ODOT_AUTOCONF",
290"prefopt : ODOT_DHCP",
291"prefopt : STUB",
292"uw_forwarder : FORWARDER forwarder_block",
293"forwarder_block : '{' optnl forwarderopts_l '}'",
294"forwarder_block : forwarderoptsl",
295"forwarderopts_l : forwarderopts_l forwarderoptsl optnl",
296"forwarderopts_l : forwarderoptsl optnl",
297"forwarderoptsl : STRING port authname dot",
298"port : PORT NUMBER",
299"port :",
300"authname : AUTHENTICATION NAME STRING",
301"authname :",
302"dot : DOT",
303"dot :",
304"log : LOG",
305"log :",
306"force : FORCE acceptbogus prefopt '{' force_list optnl '}'",
307"acceptbogus : ACCEPT BOGUS",
308"acceptbogus :",
309"force_list : force_list optnl STRING",
310"force_list :",
311};
312#endif
313#ifdef YYSTACKSIZE10000
314#undef YYMAXDEPTH10000
315#define YYMAXDEPTH10000 YYSTACKSIZE10000
316#else
317#ifdef YYMAXDEPTH10000
318#define YYSTACKSIZE10000 YYMAXDEPTH10000
319#else
320#define YYSTACKSIZE10000 10000
321#define YYMAXDEPTH10000 10000
322#endif
323#endif
324#define YYINITSTACKSIZE200 200
325/* LINTUSED */
326int yydebug;
327int yynerrs;
328int yyerrflag;
329int yychar;
330short *yyssp;
331YYSTYPE *yyvsp;
332YYSTYPE yyval;
333YYSTYPE yylval;
334short *yyss;
335short *yysslim;
336YYSTYPE *yyvs;
337unsigned int yystacksize;
338int yyparse(void);
339#line 385 "/usr/src/sbin/unwind/parse.y"
340
341struct keywords {
342 const char *k_name;
343 int k_val;
344};
345
346int
347yyerror(const char *fmt, ...)
348{
349 va_list ap;
350 char *msg;
351
352 file->errors++;
353 va_start(ap, fmt)__builtin_va_start(ap, fmt);
354 if (vasprintf(&msg, fmt, ap) == -1)
355 fatalx("yyerror vasprintf");
356 va_end(ap)__builtin_va_end(ap);
357 logit(LOG_CRIT2, "%s:%d: %s", file->name, yylval.lineno, msg);
358 free(msg);
359 return (0);
360}
361
362int
363kw_cmp(const void *k, const void *e)
364{
365 return (strcmp(k, ((const struct keywords *)e)->k_name));
366}
367
368int
369lookup(char *s)
370{
371 /* This has to be sorted always. */
372 static const struct keywords keywords[] = {
373 {"DoT", DOT260},
374 {"accept", ACCEPT276},
375 {"authentication", AUTHENTICATION265},
376 {"autoconf", AUTOCONF269},
377 {"block", BLOCK272},
378 {"bogus", BOGUS277},
379 {"dhcp", DHCP270},
380 {"dot", DOT260},
381 {"force", FORCE275},
382 {"forwarder", FORWARDER259},
383 {"include", INCLUDE257},
384 {"list", LIST273},
385 {"log", LOG274},
386 {"name", NAME266},
387 {"oDoT-autoconf", ODOT_AUTOCONF263},
388 {"oDoT-dhcp", ODOT_DHCP264},
389 {"oDoT-forwarder", ODOT_FORWARDER262},
390 {"port", PORT261},
391 {"preference", PREFERENCE267},
392 {"recursor", RECURSOR268},
393 {"stub", STUB271},
394 {"tls", DOT260},
395 };
396 const struct keywords *p;
397
398 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
399 sizeof(keywords[0]), kw_cmp);
400
401 if (p)
402 return (p->k_val);
403 else
404 return (STRING278);
405}
406
407#define START_EXPAND1 1
408#define DONE_EXPAND2 2
409
410static int expanding;
411
412int
413igetc(void)
414{
415 int c;
416
417 while (1) {
418 if (file->ungetpos > 0)
419 c = file->ungetbuf[--file->ungetpos];
420 else
421 c = getc(file->stream)(!__isthreaded ? (--(file->stream)->_r < 0 ? __srget
(file->stream) : (int)(*(file->stream)->_p++)) : (getc
)(file->stream))
;
422
423 if (c == START_EXPAND1)
424 expanding = 1;
425 else if (c == DONE_EXPAND2)
426 expanding = 0;
427 else
428 break;
429 }
430 return (c);
431}
432
433int
434lgetc(int quotec)
435{
436 int c, next;
437
438 if (quotec) {
439 if ((c = igetc()) == EOF(-1)) {
440 yyerror("reached end of file while parsing "
441 "quoted string");
442 if (file == topfile || popfile() == EOF(-1))
443 return (EOF(-1));
444 return (quotec);
445 }
446 return (c);
447 }
448
449 while ((c = igetc()) == '\\') {
450 next = igetc();
451 if (next != '\n') {
452 c = next;
453 break;
454 }
455 yylval.lineno = file->lineno;
456 file->lineno++;
457 }
458
459 if (c == EOF(-1)) {
460 /*
461 * Fake EOL when hit EOF for the first time. This gets line
462 * count right if last line in included file is syntactically
463 * invalid and has no newline.
464 */
465 if (file->eof_reached == 0) {
466 file->eof_reached = 1;
467 return ('\n');
468 }
469 while (c == EOF(-1)) {
470 if (file == topfile || popfile() == EOF(-1))
471 return (EOF(-1));
472 c = igetc();
473 }
474 }
475 return (c);
476}
477
478void
479lungetc(int c)
480{
481 if (c == EOF(-1))
482 return;
483
484 if (file->ungetpos >= file->ungetsize) {
485 void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
486 if (p == NULL((void *)0))
487 err(1, "lungetc");
488 file->ungetbuf = p;
489 file->ungetsize *= 2;
490 }
491 file->ungetbuf[file->ungetpos++] = c;
492}
493
494int
495findeol(void)
496{
497 int c;
498
499 /* Skip to either EOF or the first real EOL. */
500 while (1) {
501 c = lgetc(0);
502 if (c == '\n') {
503 file->lineno++;
504 break;
505 }
506 if (c == EOF(-1))
507 break;
508 }
509 return (ERROR258);
510}
511
512int
513yylex(void)
514{
515 char buf[8096];
516 char *p, *val;
517 int quotec, next, c;
518 int token;
519
520top:
521 p = buf;
522 while ((c = lgetc(0)) == ' ' || c == '\t')
523 ; /* nothing */
524
525 yylval.lineno = file->lineno;
526 if (c == '#')
527 while ((c = lgetc(0)) != '\n' && c != EOF(-1))
528 ; /* nothing */
529 if (c == '$' && !expanding) {
530 while (1) {
531 if ((c = lgetc(0)) == EOF(-1))
532 return (0);
533
534 if (p + 1 >= buf + sizeof(buf) - 1) {
535 yyerror("string too long");
536 return (findeol());
537 }
538 if (isalnum(c) || c == '_') {
539 *p++ = c;
540 continue;
541 }
542 *p = '\0';
543 lungetc(c);
544 break;
545 }
546 val = symget(buf);
547 if (val == NULL((void *)0)) {
548 yyerror("macro '%s' not defined", buf);
549 return (findeol());
550 }
551 p = val + strlen(val) - 1;
552 lungetc(DONE_EXPAND2);
553 while (p >= val) {
554 lungetc((unsigned char)*p);
555 p--;
556 }
557 lungetc(START_EXPAND1);
558 goto top;
559 }
560
561 switch (c) {
562 case '\'':
563 case '"':
564 quotec = c;
565 while (1) {
566 if ((c = lgetc(quotec)) == EOF(-1))
567 return (0);
568 if (c == '\n') {
569 file->lineno++;
570 continue;
571 } else if (c == '\\') {
572 if ((next = lgetc(quotec)) == EOF(-1))
573 return (0);
574 if (next == quotec || next == ' ' ||
575 next == '\t')
576 c = next;
577 else if (next == '\n') {
578 file->lineno++;
579 continue;
580 } else
581 lungetc(next);
582 } else if (c == quotec) {
583 *p = '\0';
584 break;
585 } else if (c == '\0') {
586 yyerror("syntax error");
587 return (findeol());
588 }
589 if (p + 1 >= buf + sizeof(buf) - 1) {
590 yyerror("string too long");
591 return (findeol());
592 }
593 *p++ = c;
594 }
595 yylval.v.string = strdup(buf);
596 if (yylval.v.string == NULL((void *)0))
597 err(1, "yylex: strdup");
598 return (STRING278);
599 }
600
601#define allowed_to_end_number(x)(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' ||
x == '=')
\
602 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
603
604 if (c == '-' || isdigit(c)) {
605 do {
606 *p++ = c;
607 if ((size_t)(p-buf) >= sizeof(buf)) {
608 yyerror("string too long");
609 return (findeol());
610 }
611 } while ((c = lgetc(0)) != EOF(-1) && isdigit(c));
612 lungetc(c);
613 if (p == buf + 1 && buf[0] == '-')
614 goto nodigits;
615 if (c == EOF(-1) || allowed_to_end_number(c)(isspace(c) || c == ')' || c ==',' || c == '/' || c == '}' ||
c == '=')
) {
616 const char *errstr = NULL((void *)0);
617
618 *p = '\0';
619 yylval.v.number = strtonum(buf, LLONG_MIN(-9223372036854775807LL -1LL),
620 LLONG_MAX9223372036854775807LL, &errstr);
621 if (errstr) {
622 yyerror("\"%s\" invalid number: %s",
623 buf, errstr);
624 return (findeol());
625 }
626 return (NUMBER279);
627 } else {
628nodigits:
629 while (p > buf + 1)
630 lungetc((unsigned char)*--p);
631 c = (unsigned char)*--p;
632 if (c == '-')
633 return (c);
634 }
635 }
636
637#define allowed_in_string(x)(isalnum(x) || (ispunct(x) && x != '(' && x !=
')' && x != '{' && x != '}' && x != '!'
&& x != '=' && x != '#' && x != ',')
)
\
638 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
639 x != '{' && x != '}' && \
640 x != '!' && x != '=' && x != '#' && \
641 x != ','))
642
643 if (isalnum(c) || c == ':' || c == '_') {
644 do {
645 *p++ = c;
646 if ((size_t)(p-buf) >= sizeof(buf)) {
647 yyerror("string too long");
648 return (findeol());
649 }
650 } while ((c = lgetc(0)) != EOF(-1) && (allowed_in_string(c)(isalnum(c) || (ispunct(c) && c != '(' && c !=
')' && c != '{' && c != '}' && c != '!'
&& c != '=' && c != '#' && c != ',')
)
));
651 lungetc(c);
652 *p = '\0';
653 if ((token = lookup(buf)) == STRING278)
654 if ((yylval.v.string = strdup(buf)) == NULL((void *)0))
655 err(1, "yylex: strdup");
656 return (token);
657 }
658 if (c == '\n') {
659 yylval.lineno = file->lineno;
660 file->lineno++;
661 }
662 if (c == EOF(-1))
663 return (0);
664 return (c);
665}
666
667int
668check_file_secrecy(int fd, const char *fname)
669{
670 struct stat st;
671
672 if (fstat(fd, &st)) {
673 log_warn("cannot stat %s", fname)uw_log_warn("cannot stat %s", fname);
674 return (-1);
675 }
676 if (st.st_uid != 0 && st.st_uid != getuid()) {
677 log_warnx("%s: owner not root or current user", fname);
678 return (-1);
679 }
680 if (st.st_mode & (S_IWGRP0000020 | S_IXGRP0000010 | S_IRWXO0000007)) {
681 log_warnx("%s: group writable or world read/writable", fname);
682 return (-1);
683 }
684 return (0);
685}
686
687struct file *
688pushfile(const char *name, int secret)
689{
690 struct file *nfile;
691
692 if ((nfile = calloc(1, sizeof(struct file))) == NULL((void *)0)) {
693 log_warn("calloc")uw_log_warn("calloc");
694 return (NULL((void *)0));
695 }
696 if ((nfile->name = strdup(name)) == NULL((void *)0)) {
697 log_warn("strdup")uw_log_warn("strdup");
698 free(nfile);
699 return (NULL((void *)0));
700 }
701 if ((nfile->stream = fopen(nfile->name, "r")) == NULL((void *)0)) {
702 free(nfile->name);
703 free(nfile);
704 return (NULL((void *)0));
705 } else if (secret &&
706 check_file_secrecy(fileno(nfile->stream)(!__isthreaded ? ((nfile->stream)->_file) : (fileno)(nfile
->stream))
, nfile->name)) {
707 fclose(nfile->stream);
708 free(nfile->name);
709 free(nfile);
710 return (NULL((void *)0));
711 }
712 nfile->lineno = TAILQ_EMPTY(&files)(((&files)->tqh_first) == ((void *)0)) ? 1 : 0;
713 nfile->ungetsize = 16;
714 nfile->ungetbuf = malloc(nfile->ungetsize);
715 if (nfile->ungetbuf == NULL((void *)0)) {
716 log_warn("malloc")uw_log_warn("malloc");
717 fclose(nfile->stream);
718 free(nfile->name);
719 free(nfile);
720 return (NULL((void *)0));
721 }
722 TAILQ_INSERT_TAIL(&files, nfile, entry)do { (nfile)->entry.tqe_next = ((void *)0); (nfile)->entry
.tqe_prev = (&files)->tqh_last; *(&files)->tqh_last
= (nfile); (&files)->tqh_last = &(nfile)->entry
.tqe_next; } while (0)
;
723 return (nfile);
724}
725
726int
727popfile(void)
728{
729 struct file *prev;
730
731 if ((prev = TAILQ_PREV(file, files, entry)(*(((struct files *)((file)->entry.tqe_prev))->tqh_last
))
) != NULL((void *)0))
732 prev->errors += file->errors;
733
734 TAILQ_REMOVE(&files, file, entry)do { if (((file)->entry.tqe_next) != ((void *)0)) (file)->
entry.tqe_next->entry.tqe_prev = (file)->entry.tqe_prev
; else (&files)->tqh_last = (file)->entry.tqe_prev;
*(file)->entry.tqe_prev = (file)->entry.tqe_next; ; ; }
while (0)
;
735 fclose(file->stream);
736 free(file->name);
737 free(file->ungetbuf);
738 free(file);
739 file = prev;
740 return (file ? 0 : EOF(-1));
741}
742
743struct uw_conf *
744parse_config(char *filename)
745{
746 static enum uw_resolver_type default_res_pref[] = {
747 UW_RES_DOT,
748 UW_RES_ODOT_FORWARDER,
749 UW_RES_FORWARDER,
750 UW_RES_RECURSOR,
751 UW_RES_ODOT_AUTOCONF,
752 UW_RES_AUTOCONF,
753 UW_RES_ASR};
754 struct sym *sym, *next;
755 int i;
756
757 conf = config_new_empty();
758
759 memcpy(&conf->res_pref.types, &default_res_pref,
760 sizeof(default_res_pref));
761 conf->res_pref.len = nitems(default_res_pref)(sizeof((default_res_pref)) / sizeof((default_res_pref)[0]));
762 for (i = 0; i < conf->res_pref.len; i++)
763 conf->enabled_resolvers[conf->res_pref.types[i]] = 1;
764
765 file = pushfile(filename != NULL((void *)0) ? filename : _PATH_CONF_FILE"/etc/unwind.conf", 0);
766 if (file == NULL((void *)0)) {
767 /* no default config file is fine */
768 if (errno(*__errno()) == ENOENT2 && filename == NULL((void *)0))
769 return (conf);
770 log_warn("%s", filename)uw_log_warn("%s", filename);
771 free(conf);
772 return (NULL((void *)0));
773 }
774 topfile = file;
775
776 yyparse();
777 errors = file->errors;
778 popfile();
779
780 /* Free macros and check which have not been used. */
781 TAILQ_FOREACH_SAFE(sym, &symhead, entry, next)for ((sym) = ((&symhead)->tqh_first); (sym) != ((void *
)0) && ((next) = ((sym)->entry.tqe_next), 1); (sym
) = (next))
{
782 if ((cmd_opts & OPT_VERBOSE20x00000002) && !sym->used)
783 fprintf(stderr(&__sF[2]), "warning: macro '%s' not used\n",
784 sym->nam);
785 if (!sym->persist) {
786 free(sym->nam);
787 free(sym->val);
788 TAILQ_REMOVE(&symhead, sym, entry)do { if (((sym)->entry.tqe_next) != ((void *)0)) (sym)->
entry.tqe_next->entry.tqe_prev = (sym)->entry.tqe_prev;
else (&symhead)->tqh_last = (sym)->entry.tqe_prev;
*(sym)->entry.tqe_prev = (sym)->entry.tqe_next; ; ; } while
(0)
;
789 free(sym);
790 }
791 }
792
793 if (errors) {
794 clear_config(conf);
795 return (NULL((void *)0));
796 }
797
798 return (conf);
799}
800
801int
802symset(const char *nam, const char *val, int persist)
803{
804 struct sym *sym;
805
806 TAILQ_FOREACH(sym, &symhead, entry)for((sym) = ((&symhead)->tqh_first); (sym) != ((void *
)0); (sym) = ((sym)->entry.tqe_next))
{
807 if (strcmp(nam, sym->nam) == 0)
808 break;
809 }
810
811 if (sym != NULL((void *)0)) {
812 if (sym->persist == 1)
813 return (0);
814 else {
815 free(sym->nam);
816 free(sym->val);
817 TAILQ_REMOVE(&symhead, sym, entry)do { if (((sym)->entry.tqe_next) != ((void *)0)) (sym)->
entry.tqe_next->entry.tqe_prev = (sym)->entry.tqe_prev;
else (&symhead)->tqh_last = (sym)->entry.tqe_prev;
*(sym)->entry.tqe_prev = (sym)->entry.tqe_next; ; ; } while
(0)
;
818 free(sym);
819 }
820 }
821 if ((sym = calloc(1, sizeof(*sym))) == NULL((void *)0))
822 return (-1);
823
824 sym->nam = strdup(nam);
825 if (sym->nam == NULL((void *)0)) {
826 free(sym);
827 return (-1);
828 }
829 sym->val = strdup(val);
830 if (sym->val == NULL((void *)0)) {
831 free(sym->nam);
832 free(sym);
833 return (-1);
834 }
835 sym->used = 0;
836 sym->persist = persist;
837 TAILQ_INSERT_TAIL(&symhead, sym, entry)do { (sym)->entry.tqe_next = ((void *)0); (sym)->entry.
tqe_prev = (&symhead)->tqh_last; *(&symhead)->tqh_last
= (sym); (&symhead)->tqh_last = &(sym)->entry.
tqe_next; } while (0)
;
838 return (0);
839}
840
841int
842cmdline_symset(char *s)
843{
844 char *sym, *val;
845 int ret;
846
847 if ((val = strrchr(s, '=')) == NULL((void *)0))
848 return (-1);
849 sym = strndup(s, val - s);
850 if (sym == NULL((void *)0))
851 errx(1, "%s: strndup", __func__);
852 ret = symset(sym, val + 1, 1);
853 free(sym);
854
855 return (ret);
856}
857
858char *
859symget(const char *nam)
860{
861 struct sym *sym;
862
863 TAILQ_FOREACH(sym, &symhead, entry)for((sym) = ((&symhead)->tqh_first); (sym) != ((void *
)0); (sym) = ((sym)->entry.tqe_next))
{
864 if (strcmp(nam, sym->nam) == 0) {
865 sym->used = 1;
866 return (sym->val);
867 }
868 }
869 return (NULL((void *)0));
870}
871
872void
873clear_config(struct uw_conf *xconf)
874{
875 struct uw_forwarder *uw_forwarder;
876
877 while ((uw_forwarder = TAILQ_FIRST(&xconf->uw_forwarder_list)((&xconf->uw_forwarder_list)->tqh_first)) !=
878 NULL((void *)0)) {
879 TAILQ_REMOVE(&xconf->uw_forwarder_list, uw_forwarder, entry)do { if (((uw_forwarder)->entry.tqe_next) != ((void *)0)) (
uw_forwarder)->entry.tqe_next->entry.tqe_prev = (uw_forwarder
)->entry.tqe_prev; else (&xconf->uw_forwarder_list)
->tqh_last = (uw_forwarder)->entry.tqe_prev; *(uw_forwarder
)->entry.tqe_prev = (uw_forwarder)->entry.tqe_next; ; ;
} while (0)
;
880 free(uw_forwarder);
881 }
882 while ((uw_forwarder = TAILQ_FIRST(&xconf->uw_dot_forwarder_list)((&xconf->uw_dot_forwarder_list)->tqh_first)) !=
883 NULL((void *)0)) {
884 TAILQ_REMOVE(&xconf->uw_dot_forwarder_list, uw_forwarder,do { if (((uw_forwarder)->entry.tqe_next) != ((void *)0)) (
uw_forwarder)->entry.tqe_next->entry.tqe_prev = (uw_forwarder
)->entry.tqe_prev; else (&xconf->uw_dot_forwarder_list
)->tqh_last = (uw_forwarder)->entry.tqe_prev; *(uw_forwarder
)->entry.tqe_prev = (uw_forwarder)->entry.tqe_next; ; ;
} while (0)
885 entry)do { if (((uw_forwarder)->entry.tqe_next) != ((void *)0)) (
uw_forwarder)->entry.tqe_next->entry.tqe_prev = (uw_forwarder
)->entry.tqe_prev; else (&xconf->uw_dot_forwarder_list
)->tqh_last = (uw_forwarder)->entry.tqe_prev; *(uw_forwarder
)->entry.tqe_prev = (uw_forwarder)->entry.tqe_next; ; ;
} while (0)
;
886 free(uw_forwarder);
887 }
888
889 free(xconf);
890}
891
892struct sockaddr_storage *
893host_ip(const char *s)
894{
895 struct addrinfo hints, *res;
896 struct sockaddr_storage *ss = NULL((void *)0);
897
898 memset(&hints, 0, sizeof(hints));
899 hints.ai_family = AF_UNSPEC0;
900 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
901 hints.ai_flags = AI_NUMERICHOST4;
902 if (getaddrinfo(s, "0", &hints, &res) == 0) {
903 if (res->ai_family == AF_INET2 ||
904 res->ai_family == AF_INET624) {
905 if ((ss = calloc(1, sizeof(*ss))) == NULL((void *)0))
906 fatal(NULL((void *)0));
907 memcpy(ss, res->ai_addr, res->ai_addrlen);
908 }
909 freeaddrinfo(res);
910 }
911
912 return (ss);
913}
914
915int
916check_pref_uniq(enum uw_resolver_type type)
917{
918 int i;
919
920 for (i = 0; i < conf->res_pref.len; i++)
921 if (conf->res_pref.types[i] == type) {
922 yyerror("%s is already in the preference list",
923 uw_resolver_type_str[type]);
924 return (0);
925 }
926
927 return (1);
928}
929#line 922 "parse.c"
930/* allocate initial stack or double stack size, up to YYMAXDEPTH */
931static int yygrowstack(void)
932{
933 unsigned int newsize;
934 long sslen;
935 short *newss;
936 YYSTYPE *newvs;
937
938 if ((newsize = yystacksize) == 0)
3
Assuming the condition is false
4
Taking false branch
939 newsize = YYINITSTACKSIZE200;
940 else if (newsize >= YYMAXDEPTH10000)
5
Assuming 'newsize' is < YYMAXDEPTH
6
Taking false branch
941 return -1;
942 else if ((newsize *= 2) > YYMAXDEPTH10000)
7
Assuming the condition is false
8
Taking false branch
943 newsize = YYMAXDEPTH10000;
944 sslen = yyssp - yyss;
945#ifdef SIZE_MAX0xffffffffffffffffUL
946#define YY_SIZE_MAX0xffffffffffffffffUL SIZE_MAX0xffffffffffffffffUL
947#else
948#define YY_SIZE_MAX0xffffffffffffffffUL 0xffffffffU
949#endif
950 if (newsize && YY_SIZE_MAX0xffffffffffffffffUL / newsize < sizeof *newss)
9
Assuming 'newsize' is 0
951 goto bail;
952 newss = (short *)realloc(yyss, newsize * sizeof *newss);
953 if (newss == NULL((void *)0))
10
Assuming 'newss' is not equal to NULL
11
Taking false branch
954 goto bail;
955 yyss = newss;
956 yyssp = newss + sslen;
957 if (newsize
11.1
'newsize' is 0
&& YY_SIZE_MAX0xffffffffffffffffUL / newsize < sizeof *newvs)
958 goto bail;
959 newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs);
12
Memory is released
960 if (newvs == NULL((void *)0))
13
Assuming 'newvs' is equal to NULL
14
Taking true branch
961 goto bail;
15
Control jumps to line 968
962 yyvs = newvs;
963 yyvsp = newvs + sslen;
964 yystacksize = newsize;
965 yysslim = yyss + newsize - 1;
966 return 0;
967bail:
968 if (yyss
15.1
'yyss' is non-null
)
16
Taking true branch
969 free(yyss);
970 if (yyvs)
17
Assuming 'yyvs' is non-null
18
Taking true branch
971 free(yyvs);
19
Attempt to free released memory
972 yyss = yyssp = NULL((void *)0);
973 yyvs = yyvsp = NULL((void *)0);
974 yystacksize = 0;
975 return -1;
976}
977
978#define YYABORTgoto yyabort goto yyabort
979#define YYREJECTgoto yyabort goto yyabort
980#define YYACCEPTgoto yyaccept goto yyaccept
981#define YYERRORgoto yyerrlab goto yyerrlab
982int
983yyparse(void)
984{
985 int yym, yyn, yystate;
986#if YYDEBUG0
987 const char *yys;
988
989 if ((yys = getenv("YYDEBUG")))
990 {
991 yyn = *yys;
992 if (yyn >= '0' && yyn <= '9')
993 yydebug = yyn - '0';
994 }
995#endif /* YYDEBUG */
996
997 yynerrs = 0;
998 yyerrflag = 0;
999 yychar = (-1);
1000
1001 if (yyss == NULL((void *)0) && yygrowstack()) goto yyoverflow;
1
Assuming 'yyss' is equal to NULL
2
Calling 'yygrowstack'
1002 yyssp = yyss;
1003 yyvsp = yyvs;
1004 *yyssp = yystate = 0;
1005
1006yyloop:
1007 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1008 if (yychar < 0)
1009 {
1010 if ((yychar = yylex()) < 0) yychar = 0;
1011#if YYDEBUG0
1012 if (yydebug)
1013 {
1014 yys = 0;
1015 if (yychar <= YYMAXTOKEN279) yys = yyname[yychar];
1016 if (!yys) yys = "illegal-symbol";
1017 printf("%sdebug: state %d, reading %d (%s)\n",
1018 YYPREFIX"yy", yystate, yychar, yys);
1019 }
1020#endif
1021 }
1022 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1023 yyn <= YYTABLESIZE271 && yycheck[yyn] == yychar)
1024 {
1025#if YYDEBUG0
1026 if (yydebug)
1027 printf("%sdebug: state %d, shifting to state %d\n",
1028 YYPREFIX"yy", yystate, yytable[yyn]);
1029#endif
1030 if (yyssp >= yysslim && yygrowstack())
1031 {
1032 goto yyoverflow;
1033 }
1034 *++yyssp = yystate = yytable[yyn];
1035 *++yyvsp = yylval;
1036 yychar = (-1);
1037 if (yyerrflag > 0) --yyerrflag;
1038 goto yyloop;
1039 }
1040 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1041 yyn <= YYTABLESIZE271 && yycheck[yyn] == yychar)
1042 {
1043 yyn = yytable[yyn];
1044 goto yyreduce;
1045 }
1046 if (yyerrflag) goto yyinrecovery;
1047#if defined(__GNUC__4)
1048 goto yynewerror;
1049#endif
1050yynewerror:
1051 yyerror("syntax error");
1052#if defined(__GNUC__4)
1053 goto yyerrlab;
1054#endif
1055yyerrlab:
1056 ++yynerrs;
1057yyinrecovery:
1058 if (yyerrflag < 3)
1059 {
1060 yyerrflag = 3;
1061 for (;;)
1062 {
1063 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE256) >= 0 &&
1064 yyn <= YYTABLESIZE271 && yycheck[yyn] == YYERRCODE256)
1065 {
1066#if YYDEBUG0
1067 if (yydebug)
1068 printf("%sdebug: state %d, error recovery shifting\
1069 to state %d\n", YYPREFIX"yy", *yyssp, yytable[yyn]);
1070#endif
1071 if (yyssp >= yysslim && yygrowstack())
1072 {
1073 goto yyoverflow;
1074 }
1075 *++yyssp = yystate = yytable[yyn];
1076 *++yyvsp = yylval;
1077 goto yyloop;
1078 }
1079 else
1080 {
1081#if YYDEBUG0
1082 if (yydebug)
1083 printf("%sdebug: error recovery discarding state %d\n",
1084 YYPREFIX"yy", *yyssp);
1085#endif
1086 if (yyssp <= yyss) goto yyabort;
1087 --yyssp;
1088 --yyvsp;
1089 }
1090 }
1091 }
1092 else
1093 {
1094 if (yychar == 0) goto yyabort;
1095#if YYDEBUG0
1096 if (yydebug)
1097 {
1098 yys = 0;
1099 if (yychar <= YYMAXTOKEN279) yys = yyname[yychar];
1100 if (!yys) yys = "illegal-symbol";
1101 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1102 YYPREFIX"yy", yystate, yychar, yys);
1103 }
1104#endif
1105 yychar = (-1);
1106 goto yyloop;
1107 }
1108yyreduce:
1109#if YYDEBUG0
1110 if (yydebug)
1111 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1112 YYPREFIX"yy", yystate, yyn, yyrule[yyn]);
1113#endif
1114 yym = yylen[yyn];
1115 if (yym)
1116 yyval = yyvsp[1-yym];
1117 else
1118 memset(&yyval, 0, sizeof yyval);
1119 switch (yyn)
1120 {
1121case 9:
1122#line 123 "/usr/src/sbin/unwind/parse.y"
1123{ file->errors++; }
1124break;
1125case 10:
1126#line 126 "/usr/src/sbin/unwind/parse.y"
1127{
1128 struct file *nfile;
1129
1130 if ((nfile = pushfile(yyvsp[0].v.string, 0)) == NULL((void *)0)) {
1131 yyerror("failed to include file %s", yyvsp[0].v.string);
1132 free(yyvsp[0].v.string);
1133 YYERRORgoto yyerrlab;
1134 }
1135 free(yyvsp[0].v.string);
1136
1137 file = nfile;
1138 lungetc('\n');
1139 }
1140break;
1141case 11:
1142#line 141 "/usr/src/sbin/unwind/parse.y"
1143{
1144 if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
1145 free(yyvsp[-1].v.string);
1146 free(yyvsp[0].v.string);
1147 yyerror("string: asprintf");
1148 YYERRORgoto yyerrlab;
1149 }
1150 free(yyvsp[-1].v.string);
1151 free(yyvsp[0].v.string);
1152 }
1153break;
1154case 13:
1155#line 154 "/usr/src/sbin/unwind/parse.y"
1156{
1157 char *s = yyvsp[-2].v.string;
1158 if (cmd_opts & OPT_VERBOSE0x00000001)
1159 printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
1160 while (*s++) {
1161 if (isspace((unsigned char)*s)) {
1162 yyerror("macro name cannot contain "
1163 "whitespace");
1164 free(yyvsp[-2].v.string);
1165 free(yyvsp[0].v.string);
1166 YYERRORgoto yyerrlab;
1167 }
1168 }
1169 if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1170 fatal("cannot store variable");
1171 free(yyvsp[-2].v.string);
1172 free(yyvsp[0].v.string);
1173 }
1174break;
1175case 16:
1176#line 179 "/usr/src/sbin/unwind/parse.y"
1177{
1178 if (conf->blocklist_file != NULL((void *)0)) {
1179 yyerror("block list already "
1180 "configured");
1181 free(yyvsp[-1].v.string);
1182 YYERRORgoto yyerrlab;
1183 } else {
1184 conf->blocklist_file = strdup(yyvsp[-1].v.string);
1185 if (conf->blocklist_file == NULL((void *)0))
1186 err(1, "strdup");
1187 free(yyvsp[-1].v.string);
1188 conf->blocklist_log = yyvsp[0].v.number;
1189 }
1190 }
1191break;
1192case 17:
1193#line 195 "/usr/src/sbin/unwind/parse.y"
1194{
1195 conf->res_pref.len = 0;
1196 memset(conf->enabled_resolvers, 0,
1197 sizeof(conf->enabled_resolvers));
1198 }
1199break;
1200case 23:
1201#line 210 "/usr/src/sbin/unwind/parse.y"
1202{
1203 if (!check_pref_uniq(yyvsp[0].v.number))
1204 YYERRORgoto yyerrlab;
1205 if (conf->res_pref.len >= UW_RES_NONE) {
1206 yyerror("preference list too long");
1207 YYERRORgoto yyerrlab;
1208 }
1209 conf->res_pref.types[conf->res_pref.len++] = yyvsp[0].v.number;
1210 conf->enabled_resolvers[yyvsp[0].v.number] = 1;
1211 }
1212break;
1213case 24:
1214#line 222 "/usr/src/sbin/unwind/parse.y"
1215{ yyval.v.number = UW_RES_DOT; }
1216break;
1217case 25:
1218#line 223 "/usr/src/sbin/unwind/parse.y"
1219{ yyval.v.number = UW_RES_FORWARDER; }
1220break;
1221case 26:
1222#line 224 "/usr/src/sbin/unwind/parse.y"
1223{ yyval.v.number = UW_RES_ODOT_FORWARDER; }
1224break;
1225case 27:
1226#line 225 "/usr/src/sbin/unwind/parse.y"
1227{ yyval.v.number = UW_RES_RECURSOR; }
1228break;
1229case 28:
1230#line 226 "/usr/src/sbin/unwind/parse.y"
1231{ yyval.v.number = UW_RES_AUTOCONF; }
1232break;
1233case 29:
1234#line 227 "/usr/src/sbin/unwind/parse.y"
1235{ yyval.v.number = UW_RES_AUTOCONF; }
1236break;
1237case 30:
1238#line 228 "/usr/src/sbin/unwind/parse.y"
1239{ yyval.v.number = UW_RES_ODOT_AUTOCONF; }
1240break;
1241case 31:
1242#line 229 "/usr/src/sbin/unwind/parse.y"
1243{ yyval.v.number = UW_RES_ODOT_AUTOCONF; }
1244break;
1245case 32:
1246#line 230 "/usr/src/sbin/unwind/parse.y"
1247{ yyval.v.number = UW_RES_ASR; }
1248break;
1249case 38:
1250#line 244 "/usr/src/sbin/unwind/parse.y"
1251{
1252 struct uw_forwarder *uw_fwd;
1253 struct sockaddr_storage *ss;
1254
1255 if ((ss = host_ip(yyvsp[-3].v.string)) == NULL((void *)0)) {
1256 yyerror("%s is not an ip-address", yyvsp[-3].v.string);
1257 free(yyvsp[-3].v.string);
1258 YYERRORgoto yyerrlab;
1259 }
1260 free(ss);
1261
1262 if ((uw_fwd = calloc(1, sizeof(*uw_fwd))) ==
1263 NULL((void *)0))
1264 err(1, NULL((void *)0));
1265
1266 if (yyvsp[-2].v.number < 0 || yyvsp[-2].v.number > (int)USHRT_MAX(32767 *2 +1)) {
1267 yyerror("invalid port: %lld", yyvsp[-2].v.number);
1268 free(yyvsp[-3].v.string);
1269 free(uw_fwd);
1270 YYERRORgoto yyerrlab;
1271 }
1272 if (yyvsp[-2].v.number == 0)
1273 uw_fwd->port = yyvsp[0].v.number == DOT260 ? 853 : 53;
1274 else
1275 uw_fwd->port = yyvsp[-2].v.number;
1276
1277 if (yyvsp[-1].v.string != NULL((void *)0) && yyvsp[0].v.number == 0) {
1278 yyerror("authentication name can only "
1279 "be used with DoT");
1280 free(yyvsp[-3].v.string);
1281 free(uw_fwd);
1282 YYERRORgoto yyerrlab;
1283 }
1284
1285 if (strlcpy(uw_fwd->ip, yyvsp[-3].v.string, sizeof(uw_fwd->ip))
1286 >= sizeof(uw_fwd->ip)) {
1287 free(uw_fwd);
1288 yyerror("forwarder %s too long", yyvsp[-3].v.string);
1289 free(yyvsp[-3].v.string);
1290 YYERRORgoto yyerrlab;
1291 }
1292
1293 if (yyvsp[0].v.number == DOT260 && yyvsp[-1].v.string != NULL((void *)0)) {
1294 if (strlcpy(uw_fwd->auth_name, yyvsp[-1].v.string,
1295 sizeof(uw_fwd->auth_name))
1296 >= sizeof(uw_fwd->auth_name)) {
1297 free(uw_fwd);
1298 yyerror("authentication name "
1299 "%s too long", yyvsp[-1].v.string);
1300 free(yyvsp[-3].v.string);
1301 YYERRORgoto yyerrlab;
1302 }
1303 }
1304
1305 if (yyvsp[0].v.number == DOT260)
1306 TAILQ_INSERT_TAIL(do { (uw_fwd)->entry.tqe_next = ((void *)0); (uw_fwd)->
entry.tqe_prev = (&conf->uw_dot_forwarder_list)->tqh_last
; *(&conf->uw_dot_forwarder_list)->tqh_last = (uw_fwd
); (&conf->uw_dot_forwarder_list)->tqh_last = &
(uw_fwd)->entry.tqe_next; } while (0)
1307 &conf->uw_dot_forwarder_list,do { (uw_fwd)->entry.tqe_next = ((void *)0); (uw_fwd)->
entry.tqe_prev = (&conf->uw_dot_forwarder_list)->tqh_last
; *(&conf->uw_dot_forwarder_list)->tqh_last = (uw_fwd
); (&conf->uw_dot_forwarder_list)->tqh_last = &
(uw_fwd)->entry.tqe_next; } while (0)
1308 uw_fwd, entry)do { (uw_fwd)->entry.tqe_next = ((void *)0); (uw_fwd)->
entry.tqe_prev = (&conf->uw_dot_forwarder_list)->tqh_last
; *(&conf->uw_dot_forwarder_list)->tqh_last = (uw_fwd
); (&conf->uw_dot_forwarder_list)->tqh_last = &
(uw_fwd)->entry.tqe_next; } while (0)
;
1309 else {
1310 TAILQ_INSERT_TAIL(do { (uw_fwd)->entry.tqe_next = ((void *)0); (uw_fwd)->
entry.tqe_prev = (&conf->uw_forwarder_list)->tqh_last
; *(&conf->uw_forwarder_list)->tqh_last = (uw_fwd);
(&conf->uw_forwarder_list)->tqh_last = &(uw_fwd
)->entry.tqe_next; } while (0)
1311 &conf->uw_forwarder_list,do { (uw_fwd)->entry.tqe_next = ((void *)0); (uw_fwd)->
entry.tqe_prev = (&conf->uw_forwarder_list)->tqh_last
; *(&conf->uw_forwarder_list)->tqh_last = (uw_fwd);
(&conf->uw_forwarder_list)->tqh_last = &(uw_fwd
)->entry.tqe_next; } while (0)
1312 uw_fwd, entry)do { (uw_fwd)->entry.tqe_next = ((void *)0); (uw_fwd)->
entry.tqe_prev = (&conf->uw_forwarder_list)->tqh_last
; *(&conf->uw_forwarder_list)->tqh_last = (uw_fwd);
(&conf->uw_forwarder_list)->tqh_last = &(uw_fwd
)->entry.tqe_next; } while (0)
;
1313 }
1314 free(yyvsp[-3].v.string);
1315 }
1316break;
1317case 39:
1318#line 311 "/usr/src/sbin/unwind/parse.y"
1319{ yyval.v.number = yyvsp[0].v.number; }
1320break;
1321case 40:
1322#line 312 "/usr/src/sbin/unwind/parse.y"
1323{ yyval.v.number = 0; }
1324break;
1325case 41:
1326#line 315 "/usr/src/sbin/unwind/parse.y"
1327{ yyval.v.string = yyvsp[0].v.string; }
1328break;
1329case 42:
1330#line 316 "/usr/src/sbin/unwind/parse.y"
1331{ yyval.v.string = NULL((void *)0); }
1332break;
1333case 43:
1334#line 319 "/usr/src/sbin/unwind/parse.y"
1335{ yyval.v.number = DOT260; }
1336break;
1337case 44:
1338#line 320 "/usr/src/sbin/unwind/parse.y"
1339{ yyval.v.number = 0; }
1340break;
1341case 45:
1342#line 323 "/usr/src/sbin/unwind/parse.y"
1343{ yyval.v.number = 1; }
1344break;
1345case 46:
1346#line 324 "/usr/src/sbin/unwind/parse.y"
1347{ yyval.v.number = 0; }
1348break;
1349case 47:
1350#line 327 "/usr/src/sbin/unwind/parse.y"
1351{
1352 struct force_tree_entry *n, *nxt;
1353 int error = 0;
1354
1355 RB_FOREACH_SAFE(n, force_tree, &yyvsp[-2].v.force, nxt)for ((n) = force_tree_RB_MINMAX(&yyvsp[-2].v.force, -1); (
(n) != ((void *)0)) && ((nxt) = force_tree_RB_NEXT(n)
, 1); (n) = (nxt))
{
1356 n->acceptbogus = yyvsp[-5].v.number;
1357 n->type = yyvsp[-4].v.number;
1358 RB_REMOVE(force_tree, &yyvsp[-2].v.force, n)force_tree_RB_REMOVE(&yyvsp[-2].v.force, n);
1359 if (RB_INSERT(force_tree, &conf->force,force_tree_RB_INSERT(&conf->force, n)
1360 n)force_tree_RB_INSERT(&conf->force, n)) {
1361 yyerror("%s already in an force "
1362 "list", n->domain);
1363 error = 1;
1364 }
1365 }
1366 if (error)
1367 YYERRORgoto yyerrlab;
1368 }
1369break;
1370case 48:
1371#line 347 "/usr/src/sbin/unwind/parse.y"
1372{ yyval.v.number = 1; }
1373break;
1374case 49:
1375#line 348 "/usr/src/sbin/unwind/parse.y"
1376{ yyval.v.number = 0; }
1377break;
1378case 50:
1379#line 351 "/usr/src/sbin/unwind/parse.y"
1380{
1381 struct force_tree_entry *e;
1382 size_t len;
1383
1384 len = strlen(yyvsp[0].v.string);
1385 e = malloc(sizeof(*e));
1386 if (e == NULL((void *)0))
1387 err(1, NULL((void *)0));
1388 if (strlcpy(e->domain, yyvsp[0].v.string, sizeof(e->domain)) >=
1389 sizeof(e->domain)) {
1390 yyerror("force %s too long", yyvsp[0].v.string);
1391 free(yyvsp[0].v.string);
1392 YYERRORgoto yyerrlab;
1393 }
1394 free(yyvsp[0].v.string);
1395 if (len == 0 || e->domain[len-1] != '.') {
1396 if (strlcat(e->domain, ".",
1397 sizeof((e->domain))) >=
1398 sizeof((e->domain))) {
1399 yyerror("force %s too long", yyvsp[0].v.string);
1400 YYERRORgoto yyerrlab;
1401 }
1402 }
1403 if (RB_INSERT(force_tree, &yyval.v.force, e)force_tree_RB_INSERT(&yyval.v.force, e) != NULL((void *)0)) {
1404 log_warnx("duplicate force %s", e->domain);
1405 free(e);
1406 }
1407 }
1408break;
1409case 51:
1410#line 379 "/usr/src/sbin/unwind/parse.y"
1411{
1412 RB_INIT(&yyval.v.force)do { (&yyval.v.force)->rbh_root = ((void *)0); } while
(0)
;
1413 }
1414break;
1415#line 1408 "parse.c"
1416 }
1417 yyssp -= yym;
1418 yystate = *yyssp;
1419 yyvsp -= yym;
1420 yym = yylhs[yyn];
1421 if (yystate == 0 && yym == 0)
1422 {
1423#if YYDEBUG0
1424 if (yydebug)
1425 printf("%sdebug: after reduction, shifting from state 0 to\
1426 state %d\n", YYPREFIX"yy", YYFINAL1);
1427#endif
1428 yystate = YYFINAL1;
1429 *++yyssp = YYFINAL1;
1430 *++yyvsp = yyval;
1431 if (yychar < 0)
1432 {
1433 if ((yychar = yylex()) < 0) yychar = 0;
1434#if YYDEBUG0
1435 if (yydebug)
1436 {
1437 yys = 0;
1438 if (yychar <= YYMAXTOKEN279) yys = yyname[yychar];
1439 if (!yys) yys = "illegal-symbol";
1440 printf("%sdebug: state %d, reading %d (%s)\n",
1441 YYPREFIX"yy", YYFINAL1, yychar, yys);
1442 }
1443#endif
1444 }
1445 if (yychar == 0) goto yyaccept;
1446 goto yyloop;
1447 }
1448 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1449 yyn <= YYTABLESIZE271 && yycheck[yyn] == yystate)
1450 yystate = yytable[yyn];
1451 else
1452 yystate = yydgoto[yym];
1453#if YYDEBUG0
1454 if (yydebug)
1455 printf("%sdebug: after reduction, shifting from state %d \
1456to state %d\n", YYPREFIX"yy", *yyssp, yystate);
1457#endif
1458 if (yyssp >= yysslim && yygrowstack())
1459 {
1460 goto yyoverflow;
1461 }
1462 *++yyssp = yystate;
1463 *++yyvsp = yyval;
1464 goto yyloop;
1465yyoverflow:
1466 yyerror("yacc stack overflow");
1467yyabort:
1468 if (yyss)
1469 free(yyss);
1470 if (yyvs)
1471 free(yyvs);
1472 yyss = yyssp = NULL((void *)0);
1473 yyvs = yyvsp = NULL((void *)0);
1474 yystacksize = 0;
1475 return (1);
1476yyaccept:
1477 if (yyss)
1478 free(yyss);
1479 if (yyvs)
1480 free(yyvs);
1481 yyss = yyssp = NULL((void *)0);
1482 yyvs = yyvsp = NULL((void *)0);
1483 yystacksize = 0;
1484 return (0);
1485}