GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/radiusd/radiusd/../parse.y Lines: 0 210 0.0 %
Date: 2017-11-07 Branches: 0 165 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: parse.y,v 1.4 2016/08/27 09:04:20 yasuoka Exp $	*/
2
3
/*
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.
8
 *
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.
12
 *
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.
20
 */
21
22
%{
23
#include <sys/types.h>
24
#include <sys/queue.h>
25
#include <sys/socket.h>
26
27
#include <ctype.h>
28
#include <errno.h>
29
#include <limits.h>
30
#include <netdb.h>
31
#include <stdarg.h>
32
#include <stdio.h>
33
#include <syslog.h>
34
35
#include "radiusd.h"
36
#include "radiusd_local.h"
37
#include "log.h"
38
39
static struct	 radiusd *conf;
40
static struct	 radiusd_authentication authen;
41
static struct	 radiusd_client client;
42
43
static struct	 radiusd_module *find_module (const char *);
44
static void	 free_str_l (void *);
45
static struct	 radiusd_module_ref *create_module_ref (const char *);
46
static void	 radiusd_authentication_init (struct radiusd_authentication *);
47
static void	 radiusd_client_init (struct radiusd_client *);
48
49
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
50
static struct file {
51
	TAILQ_ENTRY(file)	 entry;
52
	FILE			*stream;
53
	char			*name;
54
	int			 lineno;
55
	int			 errors;
56
} *file, *topfile;
57
struct file	*pushfile(const char *);
58
int		 popfile(void);
59
int		 yyparse(void);
60
int		 yylex(void);
61
int		 yyerror(const char *, ...);
62
int		 kw_cmp(const void *, const void *);
63
int		 lookup(char *);
64
int		 lgetc(int);
65
int		 lungetc(int);
66
int		 findeol(void);
67
68
typedef struct {
69
	union {
70
		int64_t				  number;
71
		char				 *string;
72
		struct radiusd_listen		  listen;
73
		int				  yesno;
74
		struct {
75
			char			**v;
76
			int			  c;
77
		} str_l;
78
		struct {
79
			int			 af;
80
			struct radiusd_addr	 addr;
81
			struct radiusd_addr	 mask;
82
		} prefix;
83
	} v;
84
	int lineno;
85
} YYSTYPE;
86
87
%}
88
89
%token	INCLUDE LISTEN ON PORT CLIENT SECRET LOAD MODULE MSGAUTH_REQUIRED
90
%token	AUTHENTICATE AUTHENTICATE_BY DECORATE_BY SET
91
%token	ERROR YES NO
92
%token	<v.string>		STRING
93
%token	<v.number>		NUMBER
94
%type	<v.number>		optport
95
%type	<v.listen>		listen_addr
96
%type	<v.str_l>		str_l
97
%type	<v.prefix>		prefix
98
%type	<v.yesno>		yesno
99
%type	<v.string>		strnum
100
%%
101
102
grammar		: /* empty */
103
		| grammar '\n'
104
		| grammar include '\n'
105
		| grammar listen '\n'
106
		| grammar client '\n'
107
		| grammar module '\n'
108
		| grammar authenticate '\n'
109
		| grammar error '\n'
110
		;
111
112
include		: INCLUDE STRING		{
113
			struct file	*nfile;
114
115
			if ((nfile = pushfile($2)) == NULL) {
116
				yyerror("failed to include file %s", $2);
117
				free($2);
118
				YYERROR;
119
			}
120
			free($2);
121
122
			file = nfile;
123
			lungetc('\n');
124
			nfile->lineno--;
125
		}
126
		;
127
listen		: LISTEN ON listen_addr {
128
			struct radiusd_listen *n;
129
130
			if ((n = malloc(sizeof(struct radiusd_listen)))
131
			    == NULL) {
132
outofmemory:
133
				yyerror("Out of memory: %s", strerror(errno));
134
				YYERROR;
135
			}
136
			*n = $3;
137
			TAILQ_INSERT_TAIL(&conf->listen, n, next);
138
		}
139
listen_addr	: STRING optport {
140
			int		 gai_errno;
141
			struct addrinfo hints, *res;
142
143
			memset(&hints, 0, sizeof(hints));
144
			hints.ai_family = PF_UNSPEC;
145
			hints.ai_socktype = SOCK_DGRAM;
146
			hints.ai_flags = AI_PASSIVE;
147
			hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
148
149
			if ((gai_errno =
150
				    getaddrinfo($1, NULL, &hints, &res)) != 0 ||
151
			    res->ai_addrlen > sizeof($$.addr)) {
152
				yyerror("Could not parse the address: %s: %s",
153
				    $1, gai_strerror(gai_errno));
154
				free($1);
155
				YYERROR;
156
			}
157
			free($1);
158
			$$.stype = res->ai_socktype;
159
			$$.sproto = res->ai_protocol;
160
			memcpy(&$$.addr, res->ai_addr, res->ai_addrlen);
161
			$$.addr.ipv4.sin_port = ($2 == 0)?
162
			    htons(RADIUS_DEFAULT_PORT) : htons($2);
163
			freeaddrinfo(res);
164
		}
165
optport		: { $$ = 0; }
166
		| PORT NUMBER	{ $$ = $2; }
167
		;
168
client		: CLIENT prefix optnl clientopts_b {
169
			struct radiusd_client *client0;
170
171
			client0 = calloc(1, sizeof(struct radiusd_client));
172
			if (client0 == NULL)
173
				goto outofmemory;
174
			strlcpy(client0->secret, client.secret,
175
			    sizeof(client0->secret));
176
			client0->msgauth_required = client.msgauth_required;
177
			client0->af = $2.af;
178
			client0->addr = $2.addr;
179
			client0->mask = $2.mask;
180
			TAILQ_INSERT_TAIL(&conf->client, client0, next);
181
			radiusd_client_init(&client);
182
		}
183
184
clientopts_b	: '{' optnl_l clientopts_l optnl_l '}'
185
		| '{' optnl_l '}'	/* allow empty block */
186
		;
187
188
clientopts_l	: clientopts_l nl clientopts
189
		| clientopts
190
		;
191
192
clientopts	: SECRET STRING {
193
			if (strlcpy(client.secret, $2, sizeof(client.secret))
194
			    >= sizeof(client.secret)) {
195
				yyerror("secret is too long");
196
				YYERROR;
197
			}
198
		}
199
		| MSGAUTH_REQUIRED yesno {
200
			client.msgauth_required = $2;
201
		}
202
		;
203
204
prefix		: STRING '/' NUMBER {
205
			int		 gai_errno, q, r;
206
			struct addrinfo	 hints, *res;
207
208
			memset(&hints, 0, sizeof(hints));
209
			hints.ai_family = PF_UNSPEC;
210
			hints.ai_socktype = SOCK_DGRAM;	/* dummy */
211
			hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
212
213
			if ((gai_errno = getaddrinfo($1, NULL, &hints, &res))
214
			    != 0) {
215
				yyerror("Could not parse the address: %s: %s",
216
				    $1, gai_strerror(gai_errno));
217
				free($1);
218
				YYERROR;
219
			}
220
			free($1);
221
			q = $3 >> 3;
222
			r = $3 & 7;
223
			switch (res->ai_family) {
224
			case AF_INET:
225
				if ($3 < 0 || 32 < $3) {
226
					yyerror("mask len %d is out of range",
227
					    $3);
228
					YYERROR;
229
				}
230
				$$.addr.addr.ipv4 = ((struct sockaddr_in *)
231
				    res->ai_addr)->sin_addr;
232
				$$.mask.addr.ipv4.s_addr = htonl((uint32_t)
233
				    ((0xffffffffffULL) << (32 - $3)));
234
				break;
235
			case AF_INET6:
236
				if ($3 < 0 || 128 < $3) {
237
					yyerror("mask len %d is out of range",
238
					    $3);
239
					YYERROR;
240
				}
241
				$$.addr.addr.ipv6 = ((struct sockaddr_in6 *)
242
				    res->ai_addr)->sin6_addr;
243
				memset(&$$.mask.addr.ipv6, 0,
244
				    sizeof($$.mask.addr.ipv6));
245
				if (q > 0)
246
					memset(&$$.mask.addr.ipv6, 0xff, q);
247
				if (r > 0)
248
					*((u_char *)&$$.mask.addr.ipv6 + q) =
249
					    (0xff00 >> r) & 0xff;
250
				break;
251
			}
252
			$$.af = res->ai_family;
253
			freeaddrinfo(res);
254
		}
255
		;
256
module		: MODULE LOAD STRING STRING {
257
			struct radiusd_module *module;
258
			if ((module = radiusd_module_load(conf, $4, $3))
259
			    == NULL) {
260
				free($3);
261
				free($4);
262
				YYERROR;
263
			}
264
			free($3);
265
			free($4);
266
			TAILQ_INSERT_TAIL(&conf->module, module, next);
267
		}
268
		| MODULE SET STRING STRING str_l {
269
			struct radiusd_module	*module;
270
271
			module = find_module($3);
272
			if (module == NULL) {
273
				yyerror("module `%s' is not found", $3);
274
				free($3);
275
				free($4);
276
				free_str_l(&$5);
277
				YYERROR;
278
			}
279
			if (radiusd_module_set(module, $4, $5.c, $5.v)) {
280
				yyerror("syntax error by module `%s'", $3);
281
				free($3);
282
				free($4);
283
				free_str_l(&$5);
284
				YYERROR;
285
			}
286
			free($3);
287
			free($4);
288
			free_str_l(&$5);
289
		}
290
		;
291
authenticate	: AUTHENTICATE str_l optnl authopts_b {
292
			struct radiusd_authentication *a;
293
294
			if ((a = calloc(1,
295
			    sizeof(struct radiusd_authentication))) == NULL) {
296
				free_str_l(&$2);
297
				goto outofmemory;
298
			}
299
			a->auth = authen.auth;
300
			a->deco = authen.deco;
301
			a->username = $2.v;
302
303
			TAILQ_INSERT_TAIL(&conf->authen, a, next);
304
			radiusd_authentication_init(&authen);
305
		}
306
		;
307
308
authopts_b	: '{' optnl_l authopts_l optnl_l '}'
309
		| '{' optnl_l '}'	/* empty options */
310
		;
311
312
authopts_l	: authopts_l nl authopts
313
		| authopts
314
		;
315
316
authopts	: AUTHENTICATE_BY STRING {
317
			struct radiusd_module_ref	*modref;
318
319
			modref = create_module_ref($2);
320
			free($2);
321
			if (modref == NULL)
322
				YYERROR;
323
			authen.auth = modref;
324
		}
325
		/* XXX decoration doesn't work for this moment.  */
326
		| DECORATE_BY str_l {
327
			int				 i;
328
			struct radiusd_module_ref	*modref;
329
330
			for (i = 0; i < $2.c; i++) {
331
				if ((modref = create_module_ref($2.v[i]))
332
				    == NULL) {
333
					free_str_l(&$2);
334
					YYERROR;
335
				}
336
				TAILQ_INSERT_TAIL(&authen.deco, modref, next);
337
			}
338
			free_str_l(&$2);
339
		}
340
		;
341
str_l		: str_l strnum {
342
			int	  i;
343
			char	**v;
344
			if ((v = calloc(sizeof(char **), $$.c + 2)) == NULL)
345
				goto outofmemory;
346
			for (i = 0; i < $$.c; i++)
347
				v[i] = $$.v[i];
348
			v[i++] = $2;
349
			v[i] = NULL;
350
			$$.c++;
351
			free($$.v);
352
			$$.v = v;
353
		}
354
		| strnum {
355
			if (($$.v = calloc(sizeof(char **), 2)) == NULL)
356
				goto outofmemory;
357
			$$.v[0] = $1;
358
			$$.v[1] = NULL;
359
			$$.c = 1;
360
		}
361
		;
362
strnum		: STRING	{ $$ = $1; }
363
		| NUMBER {
364
			/* Treat number as a string */
365
			asprintf(&($$), "%jd", (intmax_t)$1);
366
			if ($$ == NULL)
367
				goto outofmemory;
368
		}
369
		;
370
optnl		:
371
		| '\n'
372
		;
373
nl		: '\n' optnl		/* one new line or more */
374
		;
375
optnl_l		:
376
		| '\n' optnl_l
377
		;
378
yesno		: YES { $$ = true; }
379
		| NO  { $$ = false; }
380
		;
381
%%
382
383
struct keywords {
384
	const char	*k_name;
385
	int		 k_val;
386
};
387
388
int
389
yyerror(const char *fmt, ...)
390
{
391
	va_list		 ap;
392
	char		*msg;
393
394
	file->errors++;
395
	va_start(ap, fmt);
396
	if (vasprintf(&msg, fmt, ap) == -1)
397
		fatalx("yyerror vasprintf");
398
	va_end(ap);
399
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
400
	free(msg);
401
	return (0);
402
}
403
404
int
405
kw_cmp(const void *k, const void *e)
406
{
407
	return (strcmp(k, ((const struct keywords *)e)->k_name));
408
}
409
410
int
411
lookup(char *s)
412
{
413
	/* this has to be sorted always */
414
	static const struct keywords keywords[] = {
415
		{ "authenticate",		AUTHENTICATE},
416
		{ "authenticate-by",		AUTHENTICATE_BY},
417
		{ "client",			CLIENT},
418
		{ "decorate-by",		DECORATE_BY},
419
		{ "include",			INCLUDE},
420
		{ "listen",			LISTEN},
421
		{ "load",			LOAD},
422
		{ "module",			MODULE},
423
		{ "msgauth-required",		MSGAUTH_REQUIRED},
424
		{ "no",				NO},
425
		{ "on",				ON},
426
		{ "port",			PORT},
427
		{ "secret",			SECRET},
428
		{ "set",			SET},
429
		{ "yes",			YES},
430
	};
431
	const struct keywords	*p;
432
433
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
434
	    sizeof(keywords[0]), kw_cmp);
435
436
	if (p)
437
		return (p->k_val);
438
	else
439
		return (STRING);
440
}
441
442
#define MAXPUSHBACK	128
443
444
char	*parsebuf;
445
int	 parseindex;
446
char	 pushback_buffer[MAXPUSHBACK];
447
int	 pushback_index = 0;
448
449
int
450
lgetc(int quotec)
451
{
452
	int		c, next;
453
454
	if (parsebuf) {
455
		/* Read character from the parsebuffer instead of input. */
456
		if (parseindex >= 0) {
457
			c = parsebuf[parseindex++];
458
			if (c != '\0')
459
				return (c);
460
			parsebuf = NULL;
461
		} else
462
			parseindex++;
463
	}
464
465
	if (pushback_index)
466
		return (pushback_buffer[--pushback_index]);
467
468
	if (quotec) {
469
		if ((c = getc(file->stream)) == EOF) {
470
			yyerror("reached end of file while parsing "
471
			    "quoted string");
472
			if (file == topfile || popfile() == EOF)
473
				return (EOF);
474
			return (quotec);
475
		}
476
		return (c);
477
	}
478
479
	while ((c = getc(file->stream)) == '\\') {
480
		next = getc(file->stream);
481
		if (next != '\n') {
482
			c = next;
483
			break;
484
		}
485
		yylval.lineno = file->lineno;
486
		file->lineno++;
487
	}
488
489
	while (c == EOF) {
490
		if (file == topfile || popfile() == EOF)
491
			return (EOF);
492
		c = getc(file->stream);
493
	}
494
	return (c);
495
}
496
497
int
498
lungetc(int c)
499
{
500
	if (c == EOF)
501
		return (EOF);
502
	if (parsebuf) {
503
		parseindex--;
504
		if (parseindex >= 0)
505
			return (c);
506
	}
507
	if (pushback_index < MAXPUSHBACK-1)
508
		return (pushback_buffer[pushback_index++] = c);
509
	else
510
		return (EOF);
511
}
512
513
int
514
findeol(void)
515
{
516
	int	c;
517
518
	parsebuf = NULL;
519
520
	/* skip to either EOF or the first real EOL */
521
	while (1) {
522
		if (pushback_index)
523
			c = pushback_buffer[--pushback_index];
524
		else
525
			c = lgetc(0);
526
		if (c == '\n') {
527
			file->lineno++;
528
			break;
529
		}
530
		if (c == EOF)
531
			break;
532
	}
533
	return (ERROR);
534
}
535
536
int
537
yylex(void)
538
{
539
	char	 buf[8096];
540
	char	*p;
541
	int	 quotec, next, c;
542
	int	 token;
543
544
	p = buf;
545
	while ((c = lgetc(0)) == ' ' || c == '\t')
546
		; /* nothing */
547
548
	yylval.lineno = file->lineno;
549
	if (c == '#')
550
		while ((c = lgetc(0)) != '\n' && c != EOF)
551
			; /* nothing */
552
553
	switch (c) {
554
	case '\'':
555
	case '"':
556
		quotec = c;
557
		while (1) {
558
			if ((c = lgetc(quotec)) == EOF)
559
				return (0);
560
			if (c == '\n') {
561
				file->lineno++;
562
				continue;
563
			} else if (c == '\\') {
564
				if ((next = lgetc(quotec)) == EOF)
565
					return (0);
566
				if (next == quotec || c == ' ' || c == '\t')
567
					c = next;
568
				else if (next == '\n') {
569
					file->lineno++;
570
					continue;
571
				} else
572
					lungetc(next);
573
			} else if (c == quotec) {
574
				*p = '\0';
575
				break;
576
			} else if (c == '\0') {
577
				yyerror("syntax error");
578
				return (findeol());
579
			}
580
			if (p + 1 >= buf + sizeof(buf) - 1) {
581
				yyerror("string too long");
582
				return (findeol());
583
			}
584
			*p++ = (char)c;
585
		}
586
		yylval.v.string = strdup(buf);
587
		if (yylval.v.string == NULL)
588
			fatal("yylex: strdup");
589
		return (STRING);
590
	}
591
592
#define allowed_to_end_number(x) \
593
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
594
595
	if (c == '-' || isdigit(c)) {
596
		do {
597
			*p++ = c;
598
			if ((unsigned)(p-buf) >= sizeof(buf)) {
599
				yyerror("string too long");
600
				return (findeol());
601
			}
602
		} while ((c = lgetc(0)) != EOF && isdigit(c));
603
		lungetc(c);
604
		if (p == buf + 1 && buf[0] == '-')
605
			goto nodigits;
606
		if (c == EOF || allowed_to_end_number(c)) {
607
			const char *errstr = NULL;
608
609
			*p = '\0';
610
			yylval.v.number = strtonum(buf, LLONG_MIN,
611
			    LLONG_MAX, &errstr);
612
			if (errstr) {
613
				yyerror("\"%s\" invalid number: %s",
614
				    buf, errstr);
615
				return (findeol());
616
			}
617
			return (NUMBER);
618
		} else {
619
nodigits:
620
			while (p > buf + 1)
621
				lungetc(*--p);
622
			c = *--p;
623
			if (c == '-')
624
				return (c);
625
		}
626
	}
627
628
#define allowed_in_string(x) \
629
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
630
	x != '{' && x != '}' && x != '<' && x != '>' && \
631
	x != '!' && x != '=' && x != '/' && x != '#' && \
632
	x != ','))
633
634
	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
635
		do {
636
			*p++ = c;
637
			if ((unsigned)(p-buf) >= sizeof(buf)) {
638
				yyerror("string too long");
639
				return (findeol());
640
			}
641
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
642
		lungetc(c);
643
		*p = '\0';
644
		if ((token = lookup(buf)) == STRING)
645
			if ((yylval.v.string = strdup(buf)) == NULL)
646
				fatal("yylex: strdup");
647
		return (token);
648
	}
649
	if (c == '\n') {
650
		yylval.lineno = file->lineno;
651
		file->lineno++;
652
	}
653
	if (c == EOF)
654
		return (0);
655
	return (c);
656
}
657
658
struct file *
659
pushfile(const char *name)
660
{
661
	struct file	*nfile;
662
663
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
664
		log_warn("malloc");
665
		return (NULL);
666
	}
667
	if ((nfile->name = strdup(name)) == NULL) {
668
		log_warn("malloc");
669
		free(nfile);
670
		return (NULL);
671
	}
672
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
673
		log_warn("%s", nfile->name);
674
		free(nfile->name);
675
		free(nfile);
676
		return (NULL);
677
	}
678
	nfile->lineno = 1;
679
	TAILQ_INSERT_TAIL(&files, nfile, entry);
680
	return (nfile);
681
}
682
683
int
684
popfile(void)
685
{
686
	struct file	*prev;
687
688
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
689
		prev->errors += file->errors;
690
691
	TAILQ_REMOVE(&files, file, entry);
692
	fclose(file->stream);
693
	free(file->name);
694
	free(file);
695
	file = prev;
696
	return (file ? 0 : EOF);
697
}
698
699
int
700
parse_config(const char *filename, struct radiusd *radiusd)
701
{
702
	int				 errors = 0;
703
	struct radiusd_listen		*l;
704
	struct radiusd_module_ref	*m, *mt;
705
706
	conf = radiusd;
707
	radiusd_conf_init(conf);
708
	radiusd_authentication_init(&authen);
709
	radiusd_client_init(&client);
710
	authen.auth = NULL;
711
712
	if ((file = pushfile(filename)) == NULL) {
713
		errors++;
714
		goto out;
715
	}
716
	topfile = file;
717
718
	yyparse();
719
	errors = file->errors;
720
	popfile();
721
722
	if (TAILQ_EMPTY(&conf->listen)) {
723
		if ((l = malloc(sizeof(struct radiusd_listen))) == NULL) {
724
			log_warn("Out of memory");
725
			return (-1);
726
		}
727
		l->stype = SOCK_DGRAM;
728
		l->sproto = IPPROTO_UDP;
729
		l->addr.ipv4.sin_family = AF_INET;
730
		l->addr.ipv4.sin_len = sizeof(struct sockaddr_in);
731
		l->addr.ipv4.sin_addr.s_addr = htonl(0x7F000001L);
732
		l->addr.ipv4.sin_port = htons(RADIUS_DEFAULT_PORT);
733
		TAILQ_INSERT_TAIL(&conf->listen, l, next);
734
	}
735
	TAILQ_FOREACH(l, &conf->listen, next) {
736
		l->sock = -1;
737
	}
738
	if (authen.auth != NULL)
739
		free(authen.auth);
740
	TAILQ_FOREACH_SAFE(m, &authen.deco, next, mt) {
741
		TAILQ_REMOVE(&authen.deco, m, next);
742
		free(m);
743
	}
744
out:
745
	conf = NULL;
746
	return (errors ? -1 : 0);
747
}
748
749
static struct radiusd_module *
750
find_module(const char *name)
751
{
752
	struct radiusd_module	*module;
753
754
	TAILQ_FOREACH(module, &conf->module, next) {
755
		if (strcmp(name, module->name) == 0)
756
			return (module);
757
	}
758
759
	return (NULL);
760
}
761
762
static void
763
free_str_l(void *str_l0)
764
{
765
	int				  i;
766
	struct {
767
		char			**v;
768
		int			  c;
769
	}				 *str_l = str_l0;
770
771
	for (i = 0; i < str_l->c; i++)
772
		free(str_l->v[i]);
773
	free(str_l->v);
774
}
775
776
static struct radiusd_module_ref *
777
create_module_ref(const char *modulename)
778
{
779
	struct radiusd_module		*module;
780
	struct radiusd_module_ref	*modref;
781
782
	if ((module = find_module(modulename)) == NULL) {
783
		yyerror("module `%s' is not found", modulename);
784
		return (NULL);
785
	}
786
	if ((modref = calloc(1, sizeof(struct radiusd_module_ref))) == NULL) {
787
		yyerror("Out of memory: %s", strerror(errno));
788
		return (NULL);
789
	}
790
	modref->module = module;
791
792
	return (modref);
793
}
794
795
static void
796
radiusd_authentication_init(struct radiusd_authentication *auth)
797
{
798
	memset(auth, 0, sizeof(struct radiusd_authentication));
799
	TAILQ_INIT(&auth->deco);
800
}
801
802
static void
803
radiusd_client_init(struct radiusd_client *clnt)
804
{
805
	memset(clnt, 0, sizeof(struct radiusd_client));
806
	clnt->msgauth_required = true;
807
}