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

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#define YYBYACC 1
4
#define YYMAJOR 1
5
#define YYMINOR 9
6
#define YYLEX yylex()
7
#define YYEMPTY -1
8
#define yyclearin (yychar=(YYEMPTY))
9
#define yyerrok (yyerrflag=0)
10
#define YYRECOVERING() (yyerrflag!=0)
11
#define YYPREFIX "yy"
12
#line 23 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
13
#include <sys/types.h>
14
#include <sys/queue.h>
15
#include <sys/socket.h>
16
17
#include <ctype.h>
18
#include <errno.h>
19
#include <limits.h>
20
#include <netdb.h>
21
#include <stdarg.h>
22
#include <stdio.h>
23
#include <syslog.h>
24
25
#include "radiusd.h"
26
#include "radiusd_local.h"
27
#include "log.h"
28
29
static struct	 radiusd *conf;
30
static struct	 radiusd_authentication authen;
31
static struct	 radiusd_client client;
32
33
static struct	 radiusd_module *find_module (const char *);
34
static void	 free_str_l (void *);
35
static struct	 radiusd_module_ref *create_module_ref (const char *);
36
static void	 radiusd_authentication_init (struct radiusd_authentication *);
37
static void	 radiusd_client_init (struct radiusd_client *);
38
39
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
40
static struct file {
41
	TAILQ_ENTRY(file)	 entry;
42
	FILE			*stream;
43
	char			*name;
44
	int			 lineno;
45
	int			 errors;
46
} *file, *topfile;
47
struct file	*pushfile(const char *);
48
int		 popfile(void);
49
int		 yyparse(void);
50
int		 yylex(void);
51
int		 yyerror(const char *, ...);
52
int		 kw_cmp(const void *, const void *);
53
int		 lookup(char *);
54
int		 lgetc(int);
55
int		 lungetc(int);
56
int		 findeol(void);
57
58
typedef struct {
59
	union {
60
		int64_t				  number;
61
		char				 *string;
62
		struct radiusd_listen		  listen;
63
		int				  yesno;
64
		struct {
65
			char			**v;
66
			int			  c;
67
		} str_l;
68
		struct {
69
			int			 af;
70
			struct radiusd_addr	 addr;
71
			struct radiusd_addr	 mask;
72
		} prefix;
73
	} v;
74
	int lineno;
75
} YYSTYPE;
76
77
#line 78 "parse.c"
78
#define INCLUDE 257
79
#define LISTEN 258
80
#define ON 259
81
#define PORT 260
82
#define CLIENT 261
83
#define SECRET 262
84
#define LOAD 263
85
#define MODULE 264
86
#define MSGAUTH_REQUIRED 265
87
#define AUTHENTICATE 266
88
#define AUTHENTICATE_BY 267
89
#define DECORATE_BY 268
90
#define SET 269
91
#define ERROR 270
92
#define YES 271
93
#define NO 272
94
#define STRING 273
95
#define NUMBER 274
96
#define YYERRCODE 256
97
const short yylhs[] =
98
	{                                        -1,
99
    0,    0,    0,    0,    0,    0,    0,    0,    7,    8,
100
    2,    1,    1,    9,   13,   13,   15,   15,   17,   17,
101
    4,   10,   10,   11,   18,   18,   19,   19,   20,   20,
102
    3,    3,    6,    6,   12,   12,   16,   14,   14,    5,
103
    5,
104
};
105
const short yylen[] =
106
	{                                         2,
107
    0,    2,    3,    3,    3,    3,    3,    3,    2,    3,
108
    2,    0,    2,    4,    5,    3,    3,    1,    2,    2,
109
    3,    4,    5,    4,    5,    3,    3,    1,    2,    2,
110
    2,    1,    1,    1,    0,    1,    2,    0,    2,    1,
111
    1,
112
};
113
const short yydefred[] =
114
	{                                      1,
115
    0,    0,    0,    0,    0,    0,    0,    2,    0,    0,
116
    0,    0,    0,    8,    9,    0,    0,    0,    0,    0,
117
   33,   34,    0,   32,    3,    4,    5,    6,    7,    0,
118
   10,    0,   36,    0,    0,    0,   31,    0,    0,   11,
119
   21,    0,   14,   22,    0,    0,   24,   13,    0,    0,
120
    0,    0,   39,    0,    0,   16,    0,   18,    0,    0,
121
   26,    0,   28,   19,   40,   41,   20,    0,    0,    0,
122
   29,    0,    0,    0,    0,   37,   15,   17,   25,   27,
123
};
124
const short yydgoto[] =
125
	{                                       1,
126
   40,   31,   23,   18,   67,   24,    9,   10,   11,   12,
127
   13,   34,   43,   53,   57,   70,   58,   47,   62,   63,
128
};
129
const short yysindex[] =
130
	{                                      0,
131
   -9,   -3, -257, -229, -242, -252, -254,    0,   23,   24,
132
   25,   26,   27,    0,    0, -235,   -8,   30, -232, -231,
133
    0,    0,  -10,    0,    0,    0,    0,    0,    0, -217,
134
    0, -230,    0,  -78, -227, -226,    0,  -75, -225,    0,
135
    0,   41,    0,    0, -254,   41,    0,    0,   41, -104,
136
 -254, -113,    0, -221, -246,    0,   44,    0, -218, -254,
137
    0,   44,    0,    0,    0,    0,    0,   46,  -68, -247,
138
    0, -254,  -67, -240,   41,    0,    0,    0,    0,    0,};
139
const short yyrindex[] =
140
	{                                      0,
141
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
142
    0,    0,    0,    0,    0,    0,    0,  -64,    0,    0,
143
    0,    0,  -64,    0,    0,    0,    0,    0,    0,   50,
144
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
145
    0, -103,    0,    0,    0, -111,    0,    0, -123,    0,
146
   51,    0,    0,    0,    0,    0,  -63,    0,    0,    0,
147
    0,  -63,    0,    0,    0,    0,    0, -119,    0,    0,
148
    0,   -7,    0,    0, -115,    0,    0,    0,    0,    0,};
149
const short yygindex[] =
150
	{                                      0,
151
    0,    0,  -37,    0,    0,  -19,    0,    0,    0,    0,
152
    0,  -18,    0,  -33,    0,    1,   -6,    0,    0,   -5,
153
};
154
#define YYTABLESIZE 264
155
const short yytable[] =
156
	{                                      33,
157
    8,   38,   30,   37,   38,   38,   14,   51,   50,   38,
158
   19,   61,   52,   38,   54,   15,   20,   55,   21,   22,
159
   56,   38,   72,   69,   65,   66,   59,   60,   73,   16,
160
   17,   37,   25,   26,   27,   28,   29,   30,   32,   33,
161
   35,   36,   39,   41,   42,   44,   45,   46,   48,   76,
162
   49,   64,   37,   68,   71,   75,   77,   79,   35,   12,
163
   23,   38,   74,   78,    0,    0,    0,    0,   80,    0,
164
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
165
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
166
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
167
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
168
    0,    0,    0,    0,    0,    0,    0,   30,    0,    0,
169
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
170
    0,    0,    0,    0,    0,    0,    0,    0,   38,    0,
171
    0,   38,   35,   38,   38,   35,   36,   35,   35,   36,
172
    0,   36,   36,   59,   60,   38,   38,   54,   38,    0,
173
   55,   38,    0,    0,    0,    0,    0,    0,    0,    0,
174
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
175
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
176
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
177
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
178
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
179
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
180
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
181
    0,    0,    0,    0,    0,    0,    2,    3,    4,    0,
182
    0,    5,    0,    0,    6,    0,    7,    0,    0,    0,
183
    0,    0,   21,   22,
184
};
185
const short yycheck[] =
186
	{                                      10,
187
   10,  125,   10,   23,   23,  125,   10,   45,   42,  125,
188
  263,  125,   46,  125,  262,  273,  269,  265,  273,  274,
189
  125,  125,   60,   57,  271,  272,  267,  268,   62,  259,
190
  273,   51,   10,   10,   10,   10,   10,  273,   47,   10,
191
  273,  273,  260,  274,  123,  273,  273,  123,  274,   68,
192
   10,  273,   72,   10,  273,   10,  125,  125,  123,   10,
193
   10,  125,   62,   70,   -1,   -1,   -1,   -1,   74,   -1,
194
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
195
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
196
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
197
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
198
   -1,   -1,   -1,   -1,   -1,   -1,   -1,  125,   -1,   -1,
199
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
200
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  262,   -1,
201
   -1,  265,  262,  267,  268,  265,  262,  267,  268,  265,
202
   -1,  267,  268,  267,  268,  267,  268,  262,  262,   -1,
203
  265,  265,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
204
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
205
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
206
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
207
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
208
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
209
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
210
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
211
   -1,   -1,   -1,   -1,   -1,   -1,  256,  257,  258,   -1,
212
   -1,  261,   -1,   -1,  264,   -1,  266,   -1,   -1,   -1,
213
   -1,   -1,  273,  274,
214
};
215
#define YYFINAL 1
216
#ifndef YYDEBUG
217
#define YYDEBUG 0
218
#endif
219
#define YYMAXTOKEN 274
220
#if YYDEBUG
221
const char * const yyname[] =
222
	{
223
"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,
224
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,
225
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,0,
226
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,
227
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,0,
228
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,0,
229
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,"INCLUDE",
230
"LISTEN","ON","PORT","CLIENT","SECRET","LOAD","MODULE","MSGAUTH_REQUIRED",
231
"AUTHENTICATE","AUTHENTICATE_BY","DECORATE_BY","SET","ERROR","YES","NO",
232
"STRING","NUMBER",
233
};
234
const char * const yyrule[] =
235
	{"$accept : grammar",
236
"grammar :",
237
"grammar : grammar '\\n'",
238
"grammar : grammar include '\\n'",
239
"grammar : grammar listen '\\n'",
240
"grammar : grammar client '\\n'",
241
"grammar : grammar module '\\n'",
242
"grammar : grammar authenticate '\\n'",
243
"grammar : grammar error '\\n'",
244
"include : INCLUDE STRING",
245
"listen : LISTEN ON listen_addr",
246
"listen_addr : STRING optport",
247
"optport :",
248
"optport : PORT NUMBER",
249
"client : CLIENT prefix optnl clientopts_b",
250
"clientopts_b : '{' optnl_l clientopts_l optnl_l '}'",
251
"clientopts_b : '{' optnl_l '}'",
252
"clientopts_l : clientopts_l nl clientopts",
253
"clientopts_l : clientopts",
254
"clientopts : SECRET STRING",
255
"clientopts : MSGAUTH_REQUIRED yesno",
256
"prefix : STRING '/' NUMBER",
257
"module : MODULE LOAD STRING STRING",
258
"module : MODULE SET STRING STRING str_l",
259
"authenticate : AUTHENTICATE str_l optnl authopts_b",
260
"authopts_b : '{' optnl_l authopts_l optnl_l '}'",
261
"authopts_b : '{' optnl_l '}'",
262
"authopts_l : authopts_l nl authopts",
263
"authopts_l : authopts",
264
"authopts : AUTHENTICATE_BY STRING",
265
"authopts : DECORATE_BY str_l",
266
"str_l : str_l strnum",
267
"str_l : strnum",
268
"strnum : STRING",
269
"strnum : NUMBER",
270
"optnl :",
271
"optnl : '\\n'",
272
"nl : '\\n' optnl",
273
"optnl_l :",
274
"optnl_l : '\\n' optnl_l",
275
"yesno : YES",
276
"yesno : NO",
277
};
278
#endif
279
#ifdef YYSTACKSIZE
280
#undef YYMAXDEPTH
281
#define YYMAXDEPTH YYSTACKSIZE
282
#else
283
#ifdef YYMAXDEPTH
284
#define YYSTACKSIZE YYMAXDEPTH
285
#else
286
#define YYSTACKSIZE 10000
287
#define YYMAXDEPTH 10000
288
#endif
289
#endif
290
#define YYINITSTACKSIZE 200
291
/* LINTUSED */
292
int yydebug;
293
int yynerrs;
294
int yyerrflag;
295
int yychar;
296
short *yyssp;
297
YYSTYPE *yyvsp;
298
YYSTYPE yyval;
299
YYSTYPE yylval;
300
short *yyss;
301
short *yysslim;
302
YYSTYPE *yyvs;
303
unsigned int yystacksize;
304
int yyparse(void);
305
#line 382 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
306
307
struct keywords {
308
	const char	*k_name;
309
	int		 k_val;
310
};
311
312
int
313
yyerror(const char *fmt, ...)
314
{
315
	va_list		 ap;
316
	char		*msg;
317
318
	file->errors++;
319
	va_start(ap, fmt);
320
	if (vasprintf(&msg, fmt, ap) == -1)
321
		fatalx("yyerror vasprintf");
322
	va_end(ap);
323
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
324
	free(msg);
325
	return (0);
326
}
327
328
int
329
kw_cmp(const void *k, const void *e)
330
{
331
	return (strcmp(k, ((const struct keywords *)e)->k_name));
332
}
333
334
int
335
lookup(char *s)
336
{
337
	/* this has to be sorted always */
338
	static const struct keywords keywords[] = {
339
		{ "authenticate",		AUTHENTICATE},
340
		{ "authenticate-by",		AUTHENTICATE_BY},
341
		{ "client",			CLIENT},
342
		{ "decorate-by",		DECORATE_BY},
343
		{ "include",			INCLUDE},
344
		{ "listen",			LISTEN},
345
		{ "load",			LOAD},
346
		{ "module",			MODULE},
347
		{ "msgauth-required",		MSGAUTH_REQUIRED},
348
		{ "no",				NO},
349
		{ "on",				ON},
350
		{ "port",			PORT},
351
		{ "secret",			SECRET},
352
		{ "set",			SET},
353
		{ "yes",			YES},
354
	};
355
	const struct keywords	*p;
356
357
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
358
	    sizeof(keywords[0]), kw_cmp);
359
360
	if (p)
361
		return (p->k_val);
362
	else
363
		return (STRING);
364
}
365
366
#define MAXPUSHBACK	128
367
368
char	*parsebuf;
369
int	 parseindex;
370
char	 pushback_buffer[MAXPUSHBACK];
371
int	 pushback_index = 0;
372
373
int
374
lgetc(int quotec)
375
{
376
	int		c, next;
377
378
	if (parsebuf) {
379
		/* Read character from the parsebuffer instead of input. */
380
		if (parseindex >= 0) {
381
			c = parsebuf[parseindex++];
382
			if (c != '\0')
383
				return (c);
384
			parsebuf = NULL;
385
		} else
386
			parseindex++;
387
	}
388
389
	if (pushback_index)
390
		return (pushback_buffer[--pushback_index]);
391
392
	if (quotec) {
393
		if ((c = getc(file->stream)) == EOF) {
394
			yyerror("reached end of file while parsing "
395
			    "quoted string");
396
			if (file == topfile || popfile() == EOF)
397
				return (EOF);
398
			return (quotec);
399
		}
400
		return (c);
401
	}
402
403
	while ((c = getc(file->stream)) == '\\') {
404
		next = getc(file->stream);
405
		if (next != '\n') {
406
			c = next;
407
			break;
408
		}
409
		yylval.lineno = file->lineno;
410
		file->lineno++;
411
	}
412
413
	while (c == EOF) {
414
		if (file == topfile || popfile() == EOF)
415
			return (EOF);
416
		c = getc(file->stream);
417
	}
418
	return (c);
419
}
420
421
int
422
lungetc(int c)
423
{
424
	if (c == EOF)
425
		return (EOF);
426
	if (parsebuf) {
427
		parseindex--;
428
		if (parseindex >= 0)
429
			return (c);
430
	}
431
	if (pushback_index < MAXPUSHBACK-1)
432
		return (pushback_buffer[pushback_index++] = c);
433
	else
434
		return (EOF);
435
}
436
437
int
438
findeol(void)
439
{
440
	int	c;
441
442
	parsebuf = NULL;
443
444
	/* skip to either EOF or the first real EOL */
445
	while (1) {
446
		if (pushback_index)
447
			c = pushback_buffer[--pushback_index];
448
		else
449
			c = lgetc(0);
450
		if (c == '\n') {
451
			file->lineno++;
452
			break;
453
		}
454
		if (c == EOF)
455
			break;
456
	}
457
	return (ERROR);
458
}
459
460
int
461
yylex(void)
462
{
463
	char	 buf[8096];
464
	char	*p;
465
	int	 quotec, next, c;
466
	int	 token;
467
468
	p = buf;
469
	while ((c = lgetc(0)) == ' ' || c == '\t')
470
		; /* nothing */
471
472
	yylval.lineno = file->lineno;
473
	if (c == '#')
474
		while ((c = lgetc(0)) != '\n' && c != EOF)
475
			; /* nothing */
476
477
	switch (c) {
478
	case '\'':
479
	case '"':
480
		quotec = c;
481
		while (1) {
482
			if ((c = lgetc(quotec)) == EOF)
483
				return (0);
484
			if (c == '\n') {
485
				file->lineno++;
486
				continue;
487
			} else if (c == '\\') {
488
				if ((next = lgetc(quotec)) == EOF)
489
					return (0);
490
				if (next == quotec || c == ' ' || c == '\t')
491
					c = next;
492
				else if (next == '\n') {
493
					file->lineno++;
494
					continue;
495
				} else
496
					lungetc(next);
497
			} else if (c == quotec) {
498
				*p = '\0';
499
				break;
500
			} else if (c == '\0') {
501
				yyerror("syntax error");
502
				return (findeol());
503
			}
504
			if (p + 1 >= buf + sizeof(buf) - 1) {
505
				yyerror("string too long");
506
				return (findeol());
507
			}
508
			*p++ = (char)c;
509
		}
510
		yylval.v.string = strdup(buf);
511
		if (yylval.v.string == NULL)
512
			fatal("yylex: strdup");
513
		return (STRING);
514
	}
515
516
#define allowed_to_end_number(x) \
517
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
518
519
	if (c == '-' || isdigit(c)) {
520
		do {
521
			*p++ = c;
522
			if ((unsigned)(p-buf) >= sizeof(buf)) {
523
				yyerror("string too long");
524
				return (findeol());
525
			}
526
		} while ((c = lgetc(0)) != EOF && isdigit(c));
527
		lungetc(c);
528
		if (p == buf + 1 && buf[0] == '-')
529
			goto nodigits;
530
		if (c == EOF || allowed_to_end_number(c)) {
531
			const char *errstr = NULL;
532
533
			*p = '\0';
534
			yylval.v.number = strtonum(buf, LLONG_MIN,
535
			    LLONG_MAX, &errstr);
536
			if (errstr) {
537
				yyerror("\"%s\" invalid number: %s",
538
				    buf, errstr);
539
				return (findeol());
540
			}
541
			return (NUMBER);
542
		} else {
543
nodigits:
544
			while (p > buf + 1)
545
				lungetc(*--p);
546
			c = *--p;
547
			if (c == '-')
548
				return (c);
549
		}
550
	}
551
552
#define allowed_in_string(x) \
553
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
554
	x != '{' && x != '}' && x != '<' && x != '>' && \
555
	x != '!' && x != '=' && x != '/' && x != '#' && \
556
	x != ','))
557
558
	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
559
		do {
560
			*p++ = c;
561
			if ((unsigned)(p-buf) >= sizeof(buf)) {
562
				yyerror("string too long");
563
				return (findeol());
564
			}
565
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
566
		lungetc(c);
567
		*p = '\0';
568
		if ((token = lookup(buf)) == STRING)
569
			if ((yylval.v.string = strdup(buf)) == NULL)
570
				fatal("yylex: strdup");
571
		return (token);
572
	}
573
	if (c == '\n') {
574
		yylval.lineno = file->lineno;
575
		file->lineno++;
576
	}
577
	if (c == EOF)
578
		return (0);
579
	return (c);
580
}
581
582
struct file *
583
pushfile(const char *name)
584
{
585
	struct file	*nfile;
586
587
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
588
		log_warn("malloc");
589
		return (NULL);
590
	}
591
	if ((nfile->name = strdup(name)) == NULL) {
592
		log_warn("malloc");
593
		free(nfile);
594
		return (NULL);
595
	}
596
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
597
		log_warn("%s", nfile->name);
598
		free(nfile->name);
599
		free(nfile);
600
		return (NULL);
601
	}
602
	nfile->lineno = 1;
603
	TAILQ_INSERT_TAIL(&files, nfile, entry);
604
	return (nfile);
605
}
606
607
int
608
popfile(void)
609
{
610
	struct file	*prev;
611
612
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
613
		prev->errors += file->errors;
614
615
	TAILQ_REMOVE(&files, file, entry);
616
	fclose(file->stream);
617
	free(file->name);
618
	free(file);
619
	file = prev;
620
	return (file ? 0 : EOF);
621
}
622
623
int
624
parse_config(const char *filename, struct radiusd *radiusd)
625
{
626
	int				 errors = 0;
627
	struct radiusd_listen		*l;
628
	struct radiusd_module_ref	*m, *mt;
629
630
	conf = radiusd;
631
	radiusd_conf_init(conf);
632
	radiusd_authentication_init(&authen);
633
	radiusd_client_init(&client);
634
	authen.auth = NULL;
635
636
	if ((file = pushfile(filename)) == NULL) {
637
		errors++;
638
		goto out;
639
	}
640
	topfile = file;
641
642
	yyparse();
643
	errors = file->errors;
644
	popfile();
645
646
	if (TAILQ_EMPTY(&conf->listen)) {
647
		if ((l = malloc(sizeof(struct radiusd_listen))) == NULL) {
648
			log_warn("Out of memory");
649
			return (-1);
650
		}
651
		l->stype = SOCK_DGRAM;
652
		l->sproto = IPPROTO_UDP;
653
		l->addr.ipv4.sin_family = AF_INET;
654
		l->addr.ipv4.sin_len = sizeof(struct sockaddr_in);
655
		l->addr.ipv4.sin_addr.s_addr = htonl(0x7F000001L);
656
		l->addr.ipv4.sin_port = htons(RADIUS_DEFAULT_PORT);
657
		TAILQ_INSERT_TAIL(&conf->listen, l, next);
658
	}
659
	TAILQ_FOREACH(l, &conf->listen, next) {
660
		l->sock = -1;
661
	}
662
	if (authen.auth != NULL)
663
		free(authen.auth);
664
	TAILQ_FOREACH_SAFE(m, &authen.deco, next, mt) {
665
		TAILQ_REMOVE(&authen.deco, m, next);
666
		free(m);
667
	}
668
out:
669
	conf = NULL;
670
	return (errors ? -1 : 0);
671
}
672
673
static struct radiusd_module *
674
find_module(const char *name)
675
{
676
	struct radiusd_module	*module;
677
678
	TAILQ_FOREACH(module, &conf->module, next) {
679
		if (strcmp(name, module->name) == 0)
680
			return (module);
681
	}
682
683
	return (NULL);
684
}
685
686
static void
687
free_str_l(void *str_l0)
688
{
689
	int				  i;
690
	struct {
691
		char			**v;
692
		int			  c;
693
	}				 *str_l = str_l0;
694
695
	for (i = 0; i < str_l->c; i++)
696
		free(str_l->v[i]);
697
	free(str_l->v);
698
}
699
700
static struct radiusd_module_ref *
701
create_module_ref(const char *modulename)
702
{
703
	struct radiusd_module		*module;
704
	struct radiusd_module_ref	*modref;
705
706
	if ((module = find_module(modulename)) == NULL) {
707
		yyerror("module `%s' is not found", modulename);
708
		return (NULL);
709
	}
710
	if ((modref = calloc(1, sizeof(struct radiusd_module_ref))) == NULL) {
711
		yyerror("Out of memory: %s", strerror(errno));
712
		return (NULL);
713
	}
714
	modref->module = module;
715
716
	return (modref);
717
}
718
719
static void
720
radiusd_authentication_init(struct radiusd_authentication *auth)
721
{
722
	memset(auth, 0, sizeof(struct radiusd_authentication));
723
	TAILQ_INIT(&auth->deco);
724
}
725
726
static void
727
radiusd_client_init(struct radiusd_client *clnt)
728
{
729
	memset(clnt, 0, sizeof(struct radiusd_client));
730
	clnt->msgauth_required = true;
731
}
732
#line 725 "parse.c"
733
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
734
static int yygrowstack(void)
735
{
736
    unsigned int newsize;
737
    long sslen;
738
    short *newss;
739
    YYSTYPE *newvs;
740
741
    if ((newsize = yystacksize) == 0)
742
        newsize = YYINITSTACKSIZE;
743
    else if (newsize >= YYMAXDEPTH)
744
        return -1;
745
    else if ((newsize *= 2) > YYMAXDEPTH)
746
        newsize = YYMAXDEPTH;
747
    sslen = yyssp - yyss;
748
#ifdef SIZE_MAX
749
#define YY_SIZE_MAX SIZE_MAX
750
#else
751
#define YY_SIZE_MAX 0xffffffffU
752
#endif
753
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
754
        goto bail;
755
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
756
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
757
    if (newss == NULL)
758
        goto bail;
759
    yyss = newss;
760
    yyssp = newss + sslen;
761
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
762
        goto bail;
763
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
764
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
765
    if (newvs == NULL)
766
        goto bail;
767
    yyvs = newvs;
768
    yyvsp = newvs + sslen;
769
    yystacksize = newsize;
770
    yysslim = yyss + newsize - 1;
771
    return 0;
772
bail:
773
    if (yyss)
774
            free(yyss);
775
    if (yyvs)
776
            free(yyvs);
777
    yyss = yyssp = NULL;
778
    yyvs = yyvsp = NULL;
779
    yystacksize = 0;
780
    return -1;
781
}
782
783
#define YYABORT goto yyabort
784
#define YYREJECT goto yyabort
785
#define YYACCEPT goto yyaccept
786
#define YYERROR goto yyerrlab
787
int
788
yyparse(void)
789
{
790
    int yym, yyn, yystate;
791
#if YYDEBUG
792
    const char *yys;
793
794
    if ((yys = getenv("YYDEBUG")))
795
    {
796
        yyn = *yys;
797
        if (yyn >= '0' && yyn <= '9')
798
            yydebug = yyn - '0';
799
    }
800
#endif /* YYDEBUG */
801
802
    yynerrs = 0;
803
    yyerrflag = 0;
804
    yychar = (-1);
805
806
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
807
    yyssp = yyss;
808
    yyvsp = yyvs;
809
    *yyssp = yystate = 0;
810
811
yyloop:
812
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
813
    if (yychar < 0)
814
    {
815
        if ((yychar = yylex()) < 0) yychar = 0;
816
#if YYDEBUG
817
        if (yydebug)
818
        {
819
            yys = 0;
820
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
821
            if (!yys) yys = "illegal-symbol";
822
            printf("%sdebug: state %d, reading %d (%s)\n",
823
                    YYPREFIX, yystate, yychar, yys);
824
        }
825
#endif
826
    }
827
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
828
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
829
    {
830
#if YYDEBUG
831
        if (yydebug)
832
            printf("%sdebug: state %d, shifting to state %d\n",
833
                    YYPREFIX, yystate, yytable[yyn]);
834
#endif
835
        if (yyssp >= yysslim && yygrowstack())
836
        {
837
            goto yyoverflow;
838
        }
839
        *++yyssp = yystate = yytable[yyn];
840
        *++yyvsp = yylval;
841
        yychar = (-1);
842
        if (yyerrflag > 0)  --yyerrflag;
843
        goto yyloop;
844
    }
845
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
846
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
847
    {
848
        yyn = yytable[yyn];
849
        goto yyreduce;
850
    }
851
    if (yyerrflag) goto yyinrecovery;
852
#if defined(__GNUC__)
853
    goto yynewerror;
854
#endif
855
yynewerror:
856
    yyerror("syntax error");
857
#if defined(__GNUC__)
858
    goto yyerrlab;
859
#endif
860
yyerrlab:
861
    ++yynerrs;
862
yyinrecovery:
863
    if (yyerrflag < 3)
864
    {
865
        yyerrflag = 3;
866
        for (;;)
867
        {
868
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
869
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
870
            {
871
#if YYDEBUG
872
                if (yydebug)
873
                    printf("%sdebug: state %d, error recovery shifting\
874
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
875
#endif
876
                if (yyssp >= yysslim && yygrowstack())
877
                {
878
                    goto yyoverflow;
879
                }
880
                *++yyssp = yystate = yytable[yyn];
881
                *++yyvsp = yylval;
882
                goto yyloop;
883
            }
884
            else
885
            {
886
#if YYDEBUG
887
                if (yydebug)
888
                    printf("%sdebug: error recovery discarding state %d\n",
889
                            YYPREFIX, *yyssp);
890
#endif
891
                if (yyssp <= yyss) goto yyabort;
892
                --yyssp;
893
                --yyvsp;
894
            }
895
        }
896
    }
897
    else
898
    {
899
        if (yychar == 0) goto yyabort;
900
#if YYDEBUG
901
        if (yydebug)
902
        {
903
            yys = 0;
904
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
905
            if (!yys) yys = "illegal-symbol";
906
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
907
                    YYPREFIX, yystate, yychar, yys);
908
        }
909
#endif
910
        yychar = (-1);
911
        goto yyloop;
912
    }
913
yyreduce:
914
#if YYDEBUG
915
    if (yydebug)
916
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
917
                YYPREFIX, yystate, yyn, yyrule[yyn]);
918
#endif
919
    yym = yylen[yyn];
920
    if (yym)
921
        yyval = yyvsp[1-yym];
922
    else
923
        memset(&yyval, 0, sizeof yyval);
924
    switch (yyn)
925
    {
926
case 9:
927
#line 112 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
928
{
929
			struct file	*nfile;
930
931
			if ((nfile = pushfile(yyvsp[0].v.string)) == NULL) {
932
				yyerror("failed to include file %s", yyvsp[0].v.string);
933
				free(yyvsp[0].v.string);
934
				YYERROR;
935
			}
936
			free(yyvsp[0].v.string);
937
938
			file = nfile;
939
			lungetc('\n');
940
			nfile->lineno--;
941
		}
942
break;
943
case 10:
944
#line 127 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
945
{
946
			struct radiusd_listen *n;
947
948
			if ((n = malloc(sizeof(struct radiusd_listen)))
949
			    == NULL) {
950
outofmemory:
951
				yyerror("Out of memory: %s", strerror(errno));
952
				YYERROR;
953
			}
954
			*n = yyvsp[0].v.listen;
955
			TAILQ_INSERT_TAIL(&conf->listen, n, next);
956
		}
957
break;
958
case 11:
959
#line 139 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
960
{
961
			int		 gai_errno;
962
			struct addrinfo hints, *res;
963
964
			memset(&hints, 0, sizeof(hints));
965
			hints.ai_family = PF_UNSPEC;
966
			hints.ai_socktype = SOCK_DGRAM;
967
			hints.ai_flags = AI_PASSIVE;
968
			hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
969
970
			if ((gai_errno =
971
				    getaddrinfo(yyvsp[-1].v.string, NULL, &hints, &res)) != 0 ||
972
			    res->ai_addrlen > sizeof(yyval.v.listen.addr)) {
973
				yyerror("Could not parse the address: %s: %s",
974
				    yyvsp[-1].v.string, gai_strerror(gai_errno));
975
				free(yyvsp[-1].v.string);
976
				YYERROR;
977
			}
978
			free(yyvsp[-1].v.string);
979
			yyval.v.listen.stype = res->ai_socktype;
980
			yyval.v.listen.sproto = res->ai_protocol;
981
			memcpy(&yyval.v.listen.addr, res->ai_addr, res->ai_addrlen);
982
			yyval.v.listen.addr.ipv4.sin_port = (yyvsp[0].v.number == 0)?
983
			    htons(RADIUS_DEFAULT_PORT) : htons(yyvsp[0].v.number);
984
			freeaddrinfo(res);
985
		}
986
break;
987
case 12:
988
#line 165 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
989
{ yyval.v.number = 0; }
990
break;
991
case 13:
992
#line 166 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
993
{ yyval.v.number = yyvsp[0].v.number; }
994
break;
995
case 14:
996
#line 168 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
997
{
998
			struct radiusd_client *client0;
999
1000
			client0 = calloc(1, sizeof(struct radiusd_client));
1001
			if (client0 == NULL)
1002
				goto outofmemory;
1003
			strlcpy(client0->secret, client.secret,
1004
			    sizeof(client0->secret));
1005
			client0->msgauth_required = client.msgauth_required;
1006
			client0->af = yyvsp[-2].v.prefix.af;
1007
			client0->addr = yyvsp[-2].v.prefix.addr;
1008
			client0->mask = yyvsp[-2].v.prefix.mask;
1009
			TAILQ_INSERT_TAIL(&conf->client, client0, next);
1010
			radiusd_client_init(&client);
1011
		}
1012
break;
1013
case 19:
1014
#line 192 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1015
{
1016
			if (strlcpy(client.secret, yyvsp[0].v.string, sizeof(client.secret))
1017
			    >= sizeof(client.secret)) {
1018
				yyerror("secret is too long");
1019
				YYERROR;
1020
			}
1021
		}
1022
break;
1023
case 20:
1024
#line 199 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1025
{
1026
			client.msgauth_required = yyvsp[0].v.yesno;
1027
		}
1028
break;
1029
case 21:
1030
#line 204 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1031
{
1032
			int		 gai_errno, q, r;
1033
			struct addrinfo	 hints, *res;
1034
1035
			memset(&hints, 0, sizeof(hints));
1036
			hints.ai_family = PF_UNSPEC;
1037
			hints.ai_socktype = SOCK_DGRAM;	/* dummy */
1038
			hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
1039
1040
			if ((gai_errno = getaddrinfo(yyvsp[-2].v.string, NULL, &hints, &res))
1041
			    != 0) {
1042
				yyerror("Could not parse the address: %s: %s",
1043
				    yyvsp[-2].v.string, gai_strerror(gai_errno));
1044
				free(yyvsp[-2].v.string);
1045
				YYERROR;
1046
			}
1047
			free(yyvsp[-2].v.string);
1048
			q = yyvsp[0].v.number >> 3;
1049
			r = yyvsp[0].v.number & 7;
1050
			switch (res->ai_family) {
1051
			case AF_INET:
1052
				if (yyvsp[0].v.number < 0 || 32 < yyvsp[0].v.number) {
1053
					yyerror("mask len %d is out of range",
1054
					    yyvsp[0].v.number);
1055
					YYERROR;
1056
				}
1057
				yyval.v.prefix.addr.addr.ipv4 = ((struct sockaddr_in *)
1058
				    res->ai_addr)->sin_addr;
1059
				yyval.v.prefix.mask.addr.ipv4.s_addr = htonl((uint32_t)
1060
				    ((0xffffffffffULL) << (32 - yyvsp[0].v.number)));
1061
				break;
1062
			case AF_INET6:
1063
				if (yyvsp[0].v.number < 0 || 128 < yyvsp[0].v.number) {
1064
					yyerror("mask len %d is out of range",
1065
					    yyvsp[0].v.number);
1066
					YYERROR;
1067
				}
1068
				yyval.v.prefix.addr.addr.ipv6 = ((struct sockaddr_in6 *)
1069
				    res->ai_addr)->sin6_addr;
1070
				memset(&yyval.v.prefix.mask.addr.ipv6, 0,
1071
				    sizeof(yyval.v.prefix.mask.addr.ipv6));
1072
				if (q > 0)
1073
					memset(&yyval.v.prefix.mask.addr.ipv6, 0xff, q);
1074
				if (r > 0)
1075
					*((u_char *)&yyval.v.prefix.mask.addr.ipv6 + q) =
1076
					    (0xff00 >> r) & 0xff;
1077
				break;
1078
			}
1079
			yyval.v.prefix.af = res->ai_family;
1080
			freeaddrinfo(res);
1081
		}
1082
break;
1083
case 22:
1084
#line 256 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1085
{
1086
			struct radiusd_module *module;
1087
			if ((module = radiusd_module_load(conf, yyvsp[0].v.string, yyvsp[-1].v.string))
1088
			    == NULL) {
1089
				free(yyvsp[-1].v.string);
1090
				free(yyvsp[0].v.string);
1091
				YYERROR;
1092
			}
1093
			free(yyvsp[-1].v.string);
1094
			free(yyvsp[0].v.string);
1095
			TAILQ_INSERT_TAIL(&conf->module, module, next);
1096
		}
1097
break;
1098
case 23:
1099
#line 268 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1100
{
1101
			struct radiusd_module	*module;
1102
1103
			module = find_module(yyvsp[-2].v.string);
1104
			if (module == NULL) {
1105
				yyerror("module `%s' is not found", yyvsp[-2].v.string);
1106
				free(yyvsp[-2].v.string);
1107
				free(yyvsp[-1].v.string);
1108
				free_str_l(&yyvsp[0].v.str_l);
1109
				YYERROR;
1110
			}
1111
			if (radiusd_module_set(module, yyvsp[-1].v.string, yyvsp[0].v.str_l.c, yyvsp[0].v.str_l.v)) {
1112
				yyerror("syntax error by module `%s'", yyvsp[-2].v.string);
1113
				free(yyvsp[-2].v.string);
1114
				free(yyvsp[-1].v.string);
1115
				free_str_l(&yyvsp[0].v.str_l);
1116
				YYERROR;
1117
			}
1118
			free(yyvsp[-2].v.string);
1119
			free(yyvsp[-1].v.string);
1120
			free_str_l(&yyvsp[0].v.str_l);
1121
		}
1122
break;
1123
case 24:
1124
#line 291 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1125
{
1126
			struct radiusd_authentication *a;
1127
1128
			if ((a = calloc(1,
1129
			    sizeof(struct radiusd_authentication))) == NULL) {
1130
				free_str_l(&yyvsp[-2].v.str_l);
1131
				goto outofmemory;
1132
			}
1133
			a->auth = authen.auth;
1134
			a->deco = authen.deco;
1135
			a->username = yyvsp[-2].v.str_l.v;
1136
1137
			TAILQ_INSERT_TAIL(&conf->authen, a, next);
1138
			radiusd_authentication_init(&authen);
1139
		}
1140
break;
1141
case 29:
1142
#line 316 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1143
{
1144
			struct radiusd_module_ref	*modref;
1145
1146
			modref = create_module_ref(yyvsp[0].v.string);
1147
			free(yyvsp[0].v.string);
1148
			if (modref == NULL)
1149
				YYERROR;
1150
			authen.auth = modref;
1151
		}
1152
break;
1153
case 30:
1154
#line 326 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1155
{
1156
			int				 i;
1157
			struct radiusd_module_ref	*modref;
1158
1159
			for (i = 0; i < yyvsp[0].v.str_l.c; i++) {
1160
				if ((modref = create_module_ref(yyvsp[0].v.str_l.v[i]))
1161
				    == NULL) {
1162
					free_str_l(&yyvsp[0].v.str_l);
1163
					YYERROR;
1164
				}
1165
				TAILQ_INSERT_TAIL(&authen.deco, modref, next);
1166
			}
1167
			free_str_l(&yyvsp[0].v.str_l);
1168
		}
1169
break;
1170
case 31:
1171
#line 341 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1172
{
1173
			int	  i;
1174
			char	**v;
1175
			if ((v = calloc(sizeof(char **), yyval.v.str_l.c + 2)) == NULL)
1176
				goto outofmemory;
1177
			for (i = 0; i < yyval.v.str_l.c; i++)
1178
				v[i] = yyval.v.str_l.v[i];
1179
			v[i++] = yyvsp[0].v.string;
1180
			v[i] = NULL;
1181
			yyval.v.str_l.c++;
1182
			free(yyval.v.str_l.v);
1183
			yyval.v.str_l.v = v;
1184
		}
1185
break;
1186
case 32:
1187
#line 354 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1188
{
1189
			if ((yyval.v.str_l.v = calloc(sizeof(char **), 2)) == NULL)
1190
				goto outofmemory;
1191
			yyval.v.str_l.v[0] = yyvsp[0].v.string;
1192
			yyval.v.str_l.v[1] = NULL;
1193
			yyval.v.str_l.c = 1;
1194
		}
1195
break;
1196
case 33:
1197
#line 362 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1198
{ yyval.v.string = yyvsp[0].v.string; }
1199
break;
1200
case 34:
1201
#line 363 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1202
{
1203
			/* Treat number as a string */
1204
			asprintf(&(yyval.v.string), "%jd", (intmax_t)yyvsp[0].v.number);
1205
			if (yyval.v.string == NULL)
1206
				goto outofmemory;
1207
		}
1208
break;
1209
case 40:
1210
#line 378 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1211
{ yyval.v.yesno = true; }
1212
break;
1213
case 41:
1214
#line 379 "/usr/src/usr.sbin/radiusd/radiusd/../parse.y"
1215
{ yyval.v.yesno = false; }
1216
break;
1217
#line 1210 "parse.c"
1218
    }
1219
    yyssp -= yym;
1220
    yystate = *yyssp;
1221
    yyvsp -= yym;
1222
    yym = yylhs[yyn];
1223
    if (yystate == 0 && yym == 0)
1224
    {
1225
#if YYDEBUG
1226
        if (yydebug)
1227
            printf("%sdebug: after reduction, shifting from state 0 to\
1228
 state %d\n", YYPREFIX, YYFINAL);
1229
#endif
1230
        yystate = YYFINAL;
1231
        *++yyssp = YYFINAL;
1232
        *++yyvsp = yyval;
1233
        if (yychar < 0)
1234
        {
1235
            if ((yychar = yylex()) < 0) yychar = 0;
1236
#if YYDEBUG
1237
            if (yydebug)
1238
            {
1239
                yys = 0;
1240
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1241
                if (!yys) yys = "illegal-symbol";
1242
                printf("%sdebug: state %d, reading %d (%s)\n",
1243
                        YYPREFIX, YYFINAL, yychar, yys);
1244
            }
1245
#endif
1246
        }
1247
        if (yychar == 0) goto yyaccept;
1248
        goto yyloop;
1249
    }
1250
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1251
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1252
        yystate = yytable[yyn];
1253
    else
1254
        yystate = yydgoto[yym];
1255
#if YYDEBUG
1256
    if (yydebug)
1257
        printf("%sdebug: after reduction, shifting from state %d \
1258
to state %d\n", YYPREFIX, *yyssp, yystate);
1259
#endif
1260
    if (yyssp >= yysslim && yygrowstack())
1261
    {
1262
        goto yyoverflow;
1263
    }
1264
    *++yyssp = yystate;
1265
    *++yyvsp = yyval;
1266
    goto yyloop;
1267
yyoverflow:
1268
    yyerror("yacc stack overflow");
1269
yyabort:
1270
    if (yyss)
1271
            free(yyss);
1272
    if (yyvs)
1273
            free(yyvs);
1274
    yyss = yyssp = NULL;
1275
    yyvs = yyvsp = NULL;
1276
    yystacksize = 0;
1277
    return (1);
1278
yyaccept:
1279
    if (yyss)
1280
            free(yyss);
1281
    if (yyvs)
1282
            free(yyvs);
1283
    yyss = yyssp = NULL;
1284
    yyvs = yyvsp = NULL;
1285
    yystacksize = 0;
1286
    return (0);
1287
}