GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/snmpd/parse.c Lines: 186 350 53.1 %
Date: 2017-11-07 Branches: 105 249 42.2 %

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 26 "parse.y"
13
#include <sys/types.h>
14
#include <sys/socket.h>
15
#include <sys/stat.h>
16
#include <sys/queue.h>
17
#include <sys/tree.h>
18
19
#include <netinet/in.h>
20
#include <net/if.h>
21
22
#include <arpa/inet.h>
23
#include <arpa/nameser.h>
24
25
#include <ctype.h>
26
#include <unistd.h>
27
#include <err.h>
28
#include <errno.h>
29
#include <event.h>
30
#include <limits.h>
31
#include <stdint.h>
32
#include <stdarg.h>
33
#include <stdio.h>
34
#include <netdb.h>
35
#include <string.h>
36
#include <syslog.h>
37
38
#include "snmpd.h"
39
#include "mib.h"
40
41
enum socktype {
42
	SOCK_TYPE_RESTRICTED = 1,
43
	SOCK_TYPE_AGENTX = 2
44
};
45
46
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
47
static struct file {
48
	TAILQ_ENTRY(file)	 entry;
49
	FILE			*stream;
50
	char			*name;
51
	int			 lineno;
52
	int			 errors;
53
} *file, *topfile;
54
struct file	*pushfile(const char *, int);
55
int		 popfile(void);
56
int		 check_file_secrecy(int, const char *);
57
int		 yyparse(void);
58
int		 yylex(void);
59
int		 yyerror(const char *, ...)
60
    __attribute__((__format__ (printf, 1, 2)))
61
    __attribute__((__nonnull__ (1)));
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
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
69
struct sym {
70
	TAILQ_ENTRY(sym)	 entry;
71
	int			 used;
72
	int			 persist;
73
	char			*nam;
74
	char			*val;
75
};
76
int		 symset(const char *, const char *, int);
77
char		*symget(const char *);
78
79
struct snmpd			*conf = NULL;
80
static int			 errors = 0;
81
static struct addresslist	*hlist;
82
static struct usmuser		*user = NULL;
83
static int			 nctlsocks = 0;
84
85
struct address	*host_v4(const char *);
86
struct address	*host_v6(const char *);
87
int		 host_dns(const char *, struct addresslist *,
88
		    int, in_port_t, struct ber_oid *, char *,
89
		    struct address *);
90
int		 host(const char *, struct addresslist *,
91
		    int, in_port_t, struct ber_oid *, char *, char *);
92
93
typedef struct {
94
	union {
95
		int64_t		 number;
96
		char		*string;
97
		struct host	*host;
98
		struct timeval	 tv;
99
		struct ber_oid	*oid;
100
		struct {
101
			int		 type;
102
			void		*data;
103
			long long	 value;
104
		}		 data;
105
		enum usmauth	 auth;
106
		enum usmpriv	 enc;
107
	} v;
108
	int lineno;
109
} YYSTYPE;
110
111
#line 112 "parse.c"
112
#define INCLUDE 257
113
#define LISTEN 258
114
#define ON 259
115
#define SYSTEM 260
116
#define CONTACT 261
117
#define DESCR 262
118
#define LOCATION 263
119
#define NAME 264
120
#define OBJECTID 265
121
#define SERVICES 266
122
#define RTFILTER 267
123
#define READONLY 268
124
#define READWRITE 269
125
#define OCTETSTRING 270
126
#define INTEGER 271
127
#define COMMUNITY 272
128
#define TRAP 273
129
#define RECEIVER 274
130
#define SECLEVEL 275
131
#define NONE 276
132
#define AUTH 277
133
#define ENC 278
134
#define USER 279
135
#define AUTHKEY 280
136
#define ENCKEY 281
137
#define ERROR 282
138
#define DISABLED 283
139
#define SOCKET 284
140
#define RESTRICTED 285
141
#define AGENTX 286
142
#define HANDLE 287
143
#define DEFAULT 288
144
#define SRCADDR 289
145
#define STRING 290
146
#define NUMBER 291
147
#define YYERRCODE 256
148
const short yylhs[] =
149
	{                                        -1,
150
    0,    0,    0,    0,    0,    0,    0,    0,   14,   15,
151
    4,   16,   16,   16,   16,   16,   20,   16,   16,   16,
152
   16,   22,   16,   16,   17,   23,   23,   23,   23,   23,
153
   23,   18,    7,    7,    3,    3,    9,   11,   11,   10,
154
   10,    1,    1,    2,    2,   24,   25,   25,   19,   19,
155
   26,   26,    5,    5,    5,   21,   21,   27,   27,   27,
156
   27,   12,   13,    6,    6,    6,    8,
157
};
158
const short yylen[] =
159
	{                                         2,
160
    0,    3,    2,    3,    3,    3,    3,    3,    2,    3,
161
    1,    3,    3,    3,    2,    3,    0,    4,    5,    2,
162
    2,    0,    4,    3,    2,    2,    2,    2,    2,    2,
163
    2,    6,    2,    2,    1,    1,    1,    1,    1,    0,
164
    2,    0,    2,    0,    2,    4,    0,    3,    1,    3,
165
    0,    1,    1,    1,    1,    0,    2,    2,    2,    2,
166
    2,    1,    1,    1,    1,    0,    1,
167
};
168
const short yydefred[] =
169
	{                                      1,
170
16
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
171
208
    0,    0,    0,    0,    3,    0,    0,    0,    0,    0,
172
176
    8,    9,    0,    0,    0,    0,    0,    0,    0,   25,
173
   37,    0,   11,   20,    0,    0,   15,    0,   17,    0,
174
   53,   54,   55,   21,   22,    0,    0,    2,    4,    5,
175
    6,    7,   12,   26,   27,   28,   29,   30,   31,    0,
176
   13,   14,   16,    0,    0,    0,   56,   64,   65,   24,
177
   10,    0,    0,   47,   18,   49,   43,   39,   38,    0,
178
16
    0,   35,   36,    0,    0,    0,    0,   67,   19,    0,
179
    0,    0,    0,   57,    0,    0,   32,   41,    0,   50,
180
16
   52,    0,   62,   59,   63,   61,   58,   60,   34,   33,
181
16
    0,   46,   48,   45,
182
16
};
183
const short yydgoto[] =
184
	{                                       1,
185
   66,  112,   84,   34,   44,   70,   97,   89,   32,   86,
186
   80,  104,  106,   16,   17,   18,   19,   20,   75,   64,
187
   81,   67,   30,   76,   87,  102,   94,
188
};
189
const short yysindex[] =
190
	{                                      0,
191
  -10,    6, -256, -224, -251, -248, -247, -235, -264, -265,
192
 -253, -245, -244,  -14,    0,   38,   39,   40,   41,   42,
193
    0,    0, -237, -234, -233, -232, -231, -248, -229,    0,
194
    0, -210,    0,    0, -226, -225,    0, -223,    0, -217,
195
    0,    0,    0,    0,    0, -255, -222,    0,    0,    0,
196
    0,    0,    0,    0,    0,    0,    0,    0,    0, -221,
197
    0,    0,    0, -122, -220, -262,    0,    0,    0,    0,
198
    0, -236, -205,    0,    0,    0,    0,    0,    0, -219,
199
 -260,    0,    0, -230, -248, -217,  -41,    0,    0, -218,
200
 -216, -215, -214,    0, -213, -212,    0,    0, -228,    0,
201
32
    0, -209,    0,    0,    0,    0,    0,    0,    0,    0,
202
16
 -208,    0,    0,    0,};
203
const short yyrindex[] =
204
	{                                      0,
205
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
206
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
207
16
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
208
    0,    0,    0,    0,    0,    0,    0,    0,    0, -261,
209
16
    0,    0,    0,    0,    0,   56,    0,    0,    0,    0,
210
8
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
211
4
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
212
    0,    0,   -8,    0,    0,    0,    0,    0,    0,    0,
213
   63,    0,    0,    0,    0,   -6, -207,    0,    0,    0,
214
    0,    0,    0,    0,    0,    0,    0,    0,   -5,    0,
215
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
216
    0,    0,    0,    0,};
217
4
const short yygindex[] =
218
	{                                      0,
219
4
   -1,    0,    0,    0,    0,    0,    0,    0,  -22,    0,
220
8
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
221
4
    0,    0,    0,  -24,    0,    0,    0,
222
};
223
#define YYTABLESIZE 285
224
const short yytable[] =
225
	{                                      15,
226
   74,   40,  101,   42,   44,   58,   38,   36,   39,   24,
227
4
   25,   26,   27,   28,   29,   21,   90,   91,   37,   92,
228
   93,   40,   41,   42,   43,   78,   42,   31,   42,   68,
229
4
   69,   82,   83,   22,   23,   40,   35,   42,   44,   95,
230
   96,   31,   33,   79,   45,   46,   47,   48,   49,   50,
231
   51,   52,   53,   60,   65,   54,   55,   56,   57,   85,
232
  111,   59,   98,   61,   62,   66,   63,   71,   72,   77,
233
   88,  103,   23,  105,  107,  108,  109,  113,  110,    0,
234
   73,  114,   51,  100,   99,    0,    0,    0,    0,    0,
235
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
236
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
237
    0,    0,    0,    0,    0,    0,   40,    0,   42,   44,
238
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
239
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
240
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
241
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
242
    0,    0,    0,    0,    0,    0,    0,   73,    0,    0,
243
4
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
244
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
245
8
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
246
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
247
4
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
248
4
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
249
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
250
4
    0,    0,    0,    0,    0,    2,    3,    4,    0,    5,
251
    0,    0,    0,    0,    6,    0,    7,    8,    9,    0,
252
4
    0,    0,   10,   40,   11,    0,    0,    0,   12,    0,
253
    0,    0,    0,   13,    0,    0,    0,    0,    0,   14,
254
   40,   40,   42,   42,   44,
255
};
256
const short yycheck[] =
257
	{                                      10,
258
4
  123,   10,   44,   10,   10,   28,  272,  272,  274,  261,
259
4
  262,  263,  264,  265,  266,   10,  277,  278,  283,  280,
260
  281,  287,  276,  277,  278,  288,  288,  290,  290,  285,
261
  286,  268,  269,  290,  259,   44,  272,   44,   44,  270,
262
  271,  290,  290,   66,  290,  290,   61,   10,   10,   10,
263
   10,   10,  290,  264,  272,  290,  290,  290,  290,  265,
264
  289,  291,   85,  290,  290,   10,  290,  290,  290,  290,
265
  290,  290,   10,  290,  290,  290,  290,  102,  291,   -1,
266
  290,  290,  290,  125,   86,   -1,   -1,   -1,   -1,   -1,
267
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
268
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
269
   -1,   -1,   -1,   -1,   -1,   -1,  125,   -1,  125,  125,
270
8
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
271
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
272
8
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
273
8
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
274
8
   -1,   -1,   -1,   -1,   -1,   -1,   -1,  290,   -1,   -1,
275
8
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
276
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
277
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
278
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
279
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
280
16
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
281
8
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
282
8
   -1,   -1,   -1,   -1,   -1,  256,  257,  258,   -1,  260,
283
   -1,   -1,   -1,   -1,  265,   -1,  267,  268,  269,   -1,
284
   -1,   -1,  273,  272,  275,   -1,   -1,   -1,  279,   -1,
285
   -1,   -1,   -1,  284,   -1,   -1,   -1,   -1,   -1,  290,
286
8
  289,  290,  289,  290,  290,
287
16
};
288
#define YYFINAL 1
289
#ifndef YYDEBUG
290
#define YYDEBUG 0
291
#endif
292
#define YYMAXTOKEN 291
293
#if YYDEBUG
294
const char * const yyname[] =
295
	{
296
"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,
297
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,
298
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,
299
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,
300
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,
301
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,
302
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,"INCLUDE",
303
"LISTEN","ON","SYSTEM","CONTACT","DESCR","LOCATION","NAME","OBJECTID",
304
"SERVICES","RTFILTER","READONLY","READWRITE","OCTETSTRING","INTEGER",
305
"COMMUNITY","TRAP","RECEIVER","SECLEVEL","NONE","AUTH","ENC","USER","AUTHKEY",
306
"ENCKEY","ERROR","DISABLED","SOCKET","RESTRICTED","AGENTX","HANDLE","DEFAULT",
307
"SRCADDR","STRING","NUMBER",
308
};
309
const char * const yyrule[] =
310
	{"$accept : grammar",
311
"grammar :",
312
"grammar : grammar include '\\n'",
313
"grammar : grammar '\\n'",
314
"grammar : grammar varset '\\n'",
315
"grammar : grammar main '\\n'",
316
"grammar : grammar system '\\n'",
317
"grammar : grammar mib '\\n'",
318
"grammar : grammar error '\\n'",
319
"include : INCLUDE STRING",
320
"varset : STRING '=' STRING",
321
"yesno : STRING",
322
"main : LISTEN ON STRING",
323
"main : READONLY COMMUNITY STRING",
324
"main : READWRITE COMMUNITY STRING",
325
"main : READWRITE DISABLED",
326
"main : TRAP COMMUNITY STRING",
327
"$$1 :",
328
"main : TRAP RECEIVER $$1 host",
329
"main : TRAP HANDLE hostcmn trapoid cmd",
330
"main : RTFILTER yesno",
331
"main : SECLEVEL seclevel",
332
"$$2 :",
333
"main : USER STRING $$2 userspecs",
334
"main : SOCKET STRING socktype",
335
"system : SYSTEM sysmib",
336
"sysmib : CONTACT STRING",
337
"sysmib : DESCR STRING",
338
"sysmib : LOCATION STRING",
339
"sysmib : NAME STRING",
340
"sysmib : OBJECTID oid",
341
"sysmib : SERVICES NUMBER",
342
"mib : OBJECTID oid NAME STRING optwrite objtype",
343
"objtype : INTEGER NUMBER",
344
"objtype : OCTETSTRING STRING",
345
"optwrite : READONLY",
346
16
"optwrite : READWRITE",
347
16
"oid : STRING",
348
"trapoid : oid",
349
"trapoid : DEFAULT",
350
"hostoid :",
351
"hostoid : OBJECTID oid",
352
"hostcmn :",
353
"hostcmn : COMMUNITY STRING",
354
16
"srcaddr :",
355
16
"srcaddr : SRCADDR STRING",
356
16
"hostdef : STRING hostoid hostcmn srcaddr",
357
16
"hostlist :",
358
16
"hostlist : hostlist comma hostdef",
359
16
"host : hostdef",
360
16
"host : '{' hostlist '}'",
361
"comma :",
362
4
"comma : ','",
363
"seclevel : NONE",
364
4
"seclevel : AUTH",
365
"seclevel : ENC",
366
4
"userspecs :",
367
"userspecs : userspecs userspec",
368
4
"userspec : AUTHKEY STRING",
369
"userspec : AUTH auth",
370
16
"userspec : ENCKEY STRING",
371
8
"userspec : ENC enc",
372
"auth : STRING",
373
"enc : STRING",
374
8
"socktype : RESTRICTED",
375
"socktype : AGENTX",
376
"socktype :",
377
"cmd : STRING",
378
};
379
#endif
380
8
#ifdef YYSTACKSIZE
381
#undef YYMAXDEPTH
382
#define YYMAXDEPTH YYSTACKSIZE
383
#else
384
4
#ifdef YYMAXDEPTH
385
4
#define YYSTACKSIZE YYMAXDEPTH
386
4
#else
387
#define YYSTACKSIZE 10000
388
4
#define YYMAXDEPTH 10000
389
4
#endif
390
4
#endif
391
4
#define YYINITSTACKSIZE 200
392
/* LINTUSED */
393
4
int yydebug;
394
int yynerrs;
395
8
int yyerrflag;
396
8
int yychar;
397
short *yyssp;
398
YYSTYPE *yyvsp;
399
YYSTYPE yyval;
400
YYSTYPE yylval;
401
12
short *yyss;
402
12
short *yysslim;
403
YYSTYPE *yyvs;
404
unsigned int yystacksize;
405
int yyparse(void);
406
#line 574 "parse.y"
407
12
408
struct keywords {
409
	const char	*k_name;
410
	int		 k_val;
411
};
412
413
12
int
414
12
yyerror(const char *fmt, ...)
415
12
{
416
	va_list		 ap;
417
	char		*msg;
418
4
419
4
	file->errors++;
420
	va_start(ap, fmt);
421
	if (vasprintf(&msg, fmt, ap) == -1)
422
		fatalx("yyerror vasprintf");
423
	va_end(ap);
424
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
425
	free(msg);
426
	return (0);
427
}
428
429
int
430
kw_cmp(const void *k, const void *e)
431
4
{
432
4
	return (strcmp(k, ((const struct keywords *)e)->k_name));
433
}
434
435
8
int
436
8
lookup(char *s)
437
{
438
	/* this has to be sorted always */
439
4
	static const struct keywords keywords[] = {
440
4
		{ "agentx",		AGENTX },
441
		{ "auth",		AUTH },
442
		{ "authkey",		AUTHKEY },
443
		{ "community",		COMMUNITY },
444
12
		{ "contact",		CONTACT },
445
8
		{ "default",		DEFAULT },
446
		{ "description",	DESCR },
447
		{ "disabled",		DISABLED},
448
		{ "enc",		ENC },
449
		{ "enckey",		ENCKEY },
450
4
		{ "filter-routes",	RTFILTER },
451
		{ "handle",		HANDLE },
452
4
		{ "include",		INCLUDE },
453
		{ "integer",		INTEGER },
454
		{ "listen",		LISTEN },
455
		{ "location",		LOCATION },
456
		{ "name",		NAME },
457
		{ "none",		NONE },
458
		{ "oid",		OBJECTID },
459
		{ "on",			ON },
460
		{ "read-only",		READONLY },
461
		{ "read-write",		READWRITE },
462
		{ "receiver",		RECEIVER },
463
		{ "restricted",		RESTRICTED },
464
		{ "seclevel",		SECLEVEL },
465
		{ "services",		SERVICES },
466
		{ "socket",		SOCKET },
467
4
		{ "source-address",	SRCADDR },
468
8
		{ "string",		OCTETSTRING },
469
4
		{ "system",		SYSTEM },
470
		{ "trap",		TRAP },
471
		{ "user",		USER }
472
	};
473
	const struct keywords	*p;
474
475
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
476
8
	    sizeof(keywords[0]), kw_cmp);
477
478
8
	if (p)
479
		return (p->k_val);
480
	else
481
		return (STRING);
482
4
}
483
484
4
#define MAXPUSHBACK	128
485
4
486
u_char	*parsebuf;
487
4
int	 parseindex;
488
u_char	 pushback_buffer[MAXPUSHBACK];
489
int	 pushback_index = 0;
490
491
int
492
lgetc(int quotec)
493
{
494
	int		c, next;
495
496
	if (parsebuf) {
497
		/* Read character from the parsebuffer instead of input. */
498
		if (parseindex >= 0) {
499
			c = parsebuf[parseindex++];
500
			if (c != '\0')
501
				return (c);
502
			parsebuf = NULL;
503
		} else
504
			parseindex++;
505
	}
506

8
507
4
	if (pushback_index)
508
		return (pushback_buffer[--pushback_index]);
509

4
510
	if (quotec) {
511
		if ((c = getc(file->stream)) == EOF) {
512
			yyerror("reached end of file while parsing quoted string");
513
			if (file == topfile || popfile() == EOF)
514
				return (EOF);
515
			return (quotec);
516
		}
517
4
		return (c);
518
	}
519
520
4
	while ((c = getc(file->stream)) == '\\') {
521
		next = getc(file->stream);
522
		if (next != '\n') {
523
			c = next;
524
			break;
525
		}
526
		yylval.lineno = file->lineno;
527
		file->lineno++;
528
	}
529
	if (c == '\t' || c == ' ') {
530
		/* Compress blanks to a single space. */
531
		do {
532
			c = getc(file->stream);
533

8
		} while (c == '\t' || c == ' ');
534
4
		ungetc(c, file->stream);
535
		c = ' ';
536
	}
537
538
	while (c == EOF) {
539
		if (file == topfile || popfile() == EOF)
540
4
			return (EOF);
541
4
		c = getc(file->stream);
542
	}
543

32
	return (c);
544
8
}
545
8
546
8
int
547
8
lungetc(int c)
548
{
549
	if (c == EOF)
550
		return (EOF);
551
	if (parsebuf) {
552
		parseindex--;
553
8
		if (parseindex >= 0)
554
8
			return (c);
555
	}
556
	if (pushback_index < MAXPUSHBACK-1)
557
		return (pushback_buffer[pushback_index++] = c);
558
	else
559
		return (EOF);
560
}
561
562
int
563
findeol(void)
564
{
565
8
	int	c;
566
567
4
	parsebuf = NULL;
568
4
569
4
	/* skip to either EOF or the first real EOL */
570
4
	while (1) {
571
		if (pushback_index)
572
			c = pushback_buffer[--pushback_index];
573
		else
574
			c = lgetc(0);
575
		if (c == '\n') {
576
			file->lineno++;
577
			break;
578
		}
579
		if (c == EOF)
580
			break;
581
	}
582
	return (ERROR);
583
}
584
585
int
586
yylex(void)
587
{
588
	u_char	 buf[8096];
589
	u_char	*p, *val;
590
	int	 quotec, next, c;
591
	int	 token;
592
593
top:
594
	p = buf;
595
	while ((c = lgetc(0)) == ' ' || c == '\t')
596
		; /* nothing */
597
598
	yylval.lineno = file->lineno;
599
	if (c == '#')
600
		while ((c = lgetc(0)) != '\n' && c != EOF)
601
			; /* nothing */
602
	if (c == '$' && parsebuf == NULL) {
603
		while (1) {
604
			if ((c = lgetc(0)) == EOF)
605
				return (0);
606
607
			if (p + 1 >= buf + sizeof(buf) - 1) {
608
				yyerror("string too long");
609
				return (findeol());
610
			}
611
			if (isalnum(c) || c == '_') {
612
				*p++ = c;
613
				continue;
614
			}
615
			*p = '\0';
616
			lungetc(c);
617
			break;
618
		}
619
		val = symget(buf);
620
		if (val == NULL) {
621
			yyerror("macro '%s' not defined", buf);
622
			return (findeol());
623
		}
624
		parsebuf = val;
625
		parseindex = 0;
626
		goto top;
627
	}
628
629
	switch (c) {
630
	case '\'':
631
	case '"':
632
		quotec = c;
633
		while (1) {
634
			if ((c = lgetc(quotec)) == EOF)
635
				return (0);
636
			if (c == '\n') {
637
				file->lineno++;
638
				continue;
639
			} else if (c == '\\') {
640
				if ((next = lgetc(quotec)) == EOF)
641
					return (0);
642
				if (next == quotec || c == ' ' || c == '\t')
643
					c = next;
644
				else if (next == '\n') {
645
					file->lineno++;
646
					continue;
647
				} else
648
					lungetc(next);
649
			} else if (c == quotec) {
650
				*p = '\0';
651
				break;
652
			} else if (c == '\0') {
653
				yyerror("syntax error");
654
				return (findeol());
655
			}
656
			if (p + 1 >= buf + sizeof(buf) - 1) {
657
				yyerror("string too long");
658
				return (findeol());
659
			}
660
			*p++ = c;
661
		}
662
		yylval.v.string = strdup(buf);
663
		if (yylval.v.string == NULL)
664
			err(1, "yylex: strdup");
665
		return (STRING);
666
	}
667
668
#define allowed_to_end_number(x) \
669
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
670
671
	if (c == '-' || isdigit(c)) {
672
		do {
673
			*p++ = c;
674
			if ((unsigned)(p-buf) >= sizeof(buf)) {
675
				yyerror("string too long");
676
				return (findeol());
677
			}
678
		} while ((c = lgetc(0)) != EOF && isdigit(c));
679
		lungetc(c);
680
		if (p == buf + 1 && buf[0] == '-')
681
			goto nodigits;
682
		if (c == EOF || allowed_to_end_number(c)) {
683
			const char *errstr = NULL;
684
685
			*p = '\0';
686
			yylval.v.number = strtonum(buf, LLONG_MIN,
687
			    LLONG_MAX, &errstr);
688
			if (errstr) {
689
				yyerror("\"%s\" invalid number: %s",
690
				    buf, errstr);
691
				return (findeol());
692
			}
693
			return (NUMBER);
694
		} else {
695
nodigits:
696
			while (p > buf + 1)
697
				lungetc(*--p);
698
			c = *--p;
699
			if (c == '-')
700
				return (c);
701
		}
702
	}
703
704
#define allowed_in_string(x) \
705
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
706
	x != '{' && x != '}' && \
707
	x != '!' && x != '=' && x != '#' && \
708
	x != ','))
709
710
	if (isalnum(c) || c == ':' || c == '_') {
711
		do {
712
			*p++ = c;
713
			if ((unsigned)(p-buf) >= sizeof(buf)) {
714
				yyerror("string too long");
715
				return (findeol());
716
			}
717
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
718
		lungetc(c);
719
		*p = '\0';
720
		if ((token = lookup(buf)) == STRING)
721
			if ((yylval.v.string = strdup(buf)) == NULL)
722
				err(1, "yylex: strdup");
723
		return (token);
724
	}
725
	if (c == '\n') {
726
		yylval.lineno = file->lineno;
727
		file->lineno++;
728
	}
729
	if (c == EOF)
730
		return (0);
731
	return (c);
732
}
733
734
int
735
check_file_secrecy(int fd, const char *fname)
736
{
737
	struct stat	st;
738
739
	if (fstat(fd, &st)) {
740
		log_warn("cannot stat %s", fname);
741
		return (-1);
742
	}
743
	if (st.st_uid != 0 && st.st_uid != getuid()) {
744
		log_warnx("%s: owner not root or current user", fname);
745
		return (-1);
746
	}
747
	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
748
		log_warnx("%s: group writable or world read/writable", fname);
749
		return (-1);
750
	}
751
	return (0);
752
}
753
754
struct file *
755
pushfile(const char *name, int secret)
756
{
757
	struct file	*nfile;
758
759
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
760
		log_warn("malloc");
761
		return (NULL);
762
	}
763
	if ((nfile->name = strdup(name)) == NULL) {
764
		log_warn("malloc");
765
		free(nfile);
766
		return (NULL);
767
	}
768
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
769
		log_warn("%s", nfile->name);
770
		free(nfile->name);
771
		free(nfile);
772
		return (NULL);
773
	} else if (secret &&
774
	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
775
		fclose(nfile->stream);
776
		free(nfile->name);
777
		free(nfile);
778
		return (NULL);
779
	}
780
	nfile->lineno = 1;
781
	TAILQ_INSERT_TAIL(&files, nfile, entry);
782
	return (nfile);
783
}
784
785
int
786
popfile(void)
787
{
788
	struct file	*prev;
789
790
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
791
		prev->errors += file->errors;
792
793
	TAILQ_REMOVE(&files, file, entry);
794
	fclose(file->stream);
795
	free(file->name);
796
	free(file);
797
	file = prev;
798
	return (file ? 0 : EOF);
799
}
800
801
struct snmpd *
802
parse_config(const char *filename, u_int flags)
803
{
804
	struct sym	*sym, *next;
805
806
	if ((conf = calloc(1, sizeof(*conf))) == NULL) {
807
		log_warn("cannot allocate memory");
808
		return (NULL);
809
	}
810
811
	conf->sc_flags = flags;
812
	conf->sc_confpath = filename;
813
	TAILQ_INIT(&conf->sc_addresses);
814
	TAILQ_INIT(&conf->sc_sockets);
815
	conf->sc_ps.ps_csock.cs_name = SNMPD_SOCKET;
816
	TAILQ_INIT(&conf->sc_ps.ps_rcsocks);
817
	strlcpy(conf->sc_rdcommunity, "public", SNMPD_MAXCOMMUNITYLEN);
818
	strlcpy(conf->sc_rwcommunity, "private", SNMPD_MAXCOMMUNITYLEN);
819
	strlcpy(conf->sc_trcommunity, "public", SNMPD_MAXCOMMUNITYLEN);
820
	TAILQ_INIT(&conf->sc_trapreceivers);
821
822
	if ((file = pushfile(filename, 0)) == NULL) {
823
		free(conf);
824
		return (NULL);
825
	}
826
	topfile = file;
827
	setservent(1);
828
829
	yyparse();
830
	errors = file->errors;
831
	popfile();
832
833
	endservent();
834
835
	if (TAILQ_EMPTY(&conf->sc_addresses)) {
836
		struct address		*h;
837
		if ((h = calloc(1, sizeof(*h))) == NULL)
838
			fatal("snmpe: %s", __func__);
839
		h->ss.ss_family = AF_INET;
840
		h->port = SNMPD_PORT;
841
		TAILQ_INSERT_TAIL(&conf->sc_addresses, h, entry);
842
		if ((h = calloc(1, sizeof(*h))) == NULL)
843
			fatal("snmpe: %s", __func__);
844
		h->ss.ss_family = AF_INET6;
845
		h->port = SNMPD_PORT;
846
		TAILQ_INSERT_TAIL(&conf->sc_addresses, h, entry);
847
	}
848
849
	/* Free macros and check which have not been used. */
850
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
851
		if ((conf->sc_flags & SNMPD_F_VERBOSE) && !sym->used)
852
			fprintf(stderr, "warning: macro '%s' not "
853
			    "used\n", sym->nam);
854
		if (!sym->persist) {
855
			free(sym->nam);
856
			free(sym->val);
857
			TAILQ_REMOVE(&symhead, sym, entry);
858
			free(sym);
859
		}
860
	}
861
862
	if (errors) {
863
		free(conf);
864
		return (NULL);
865
	}
866
867
	return (conf);
868
}
869
870
int
871
symset(const char *nam, const char *val, int persist)
872
{
873
	struct sym	*sym;
874
875
	TAILQ_FOREACH(sym, &symhead, entry) {
876
		if (strcmp(nam, sym->nam) == 0)
877
			break;
878
	}
879
880
	if (sym != NULL) {
881
		if (sym->persist == 1)
882
			return (0);
883
		else {
884
			free(sym->nam);
885
			free(sym->val);
886
			TAILQ_REMOVE(&symhead, sym, entry);
887
			free(sym);
888
		}
889
	}
890
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
891
		return (-1);
892
893
	sym->nam = strdup(nam);
894
	if (sym->nam == NULL) {
895
		free(sym);
896
		return (-1);
897
	}
898
	sym->val = strdup(val);
899
	if (sym->val == NULL) {
900
		free(sym->nam);
901
		free(sym);
902
		return (-1);
903
	}
904
	sym->used = 0;
905
	sym->persist = persist;
906
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
907
	return (0);
908
}
909
910
int
911
cmdline_symset(char *s)
912
{
913
	char	*sym, *val;
914
	int	ret;
915
	size_t	len;
916
917
	if ((val = strrchr(s, '=')) == NULL)
918
		return (-1);
919
920
	len = strlen(s) - strlen(val) + 1;
921
	if ((sym = malloc(len)) == NULL)
922
		errx(1, "cmdline_symset: malloc");
923
924
	(void)strlcpy(sym, s, len);
925
926
	ret = symset(sym, val + 1, 1);
927
	free(sym);
928
929
	return (ret);
930
}
931
932
char *
933
symget(const char *nam)
934
{
935
	struct sym	*sym;
936
937
	TAILQ_FOREACH(sym, &symhead, entry) {
938
		if (strcmp(nam, sym->nam) == 0) {
939
			sym->used = 1;
940
			return (sym->val);
941
		}
942
	}
943
	return (NULL);
944
}
945
946
struct address *
947
host_v4(const char *s)
948
{
949
	struct in_addr		 ina;
950
	struct sockaddr_in	*sain;
951
	struct address		*h;
952
953
	bzero(&ina, sizeof(ina));
954
	if (inet_pton(AF_INET, s, &ina) != 1)
955
		return (NULL);
956
957
	if ((h = calloc(1, sizeof(*h))) == NULL)
958
		fatal(__func__);
959
	sain = (struct sockaddr_in *)&h->ss;
960
	sain->sin_len = sizeof(struct sockaddr_in);
961
	sain->sin_family = AF_INET;
962
	sain->sin_addr.s_addr = ina.s_addr;
963
964
	return (h);
965
}
966
967
struct address *
968
host_v6(const char *s)
969
{
970
	struct addrinfo		 hints, *res;
971
	struct sockaddr_in6	*sa_in6;
972
	struct address		*h = NULL;
973
974
	bzero(&hints, sizeof(hints));
975
	hints.ai_family = AF_INET6;
976
	hints.ai_socktype = SOCK_DGRAM; /* dummy */
977
	hints.ai_flags = AI_NUMERICHOST;
978
	if (getaddrinfo(s, "0", &hints, &res) == 0) {
979
		if ((h = calloc(1, sizeof(*h))) == NULL)
980
			fatal(__func__);
981
		sa_in6 = (struct sockaddr_in6 *)&h->ss;
982
		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
983
		sa_in6->sin6_family = AF_INET6;
984
		memcpy(&sa_in6->sin6_addr,
985
		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
986
		    sizeof(sa_in6->sin6_addr));
987
		sa_in6->sin6_scope_id =
988
		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
989
990
		freeaddrinfo(res);
991
	}
992
993
	return (h);
994
}
995
996
int
997
host_dns(const char *s, struct addresslist *al, int max,
998
	in_port_t port, struct ber_oid *oid, char *cmn, struct address *src)
999
{
1000
	struct addrinfo		 hints, *res0, *res;
1001
	int			 error, cnt = 0;
1002
	struct sockaddr_in	*sain;
1003
	struct sockaddr_in6	*sin6;
1004
	struct address		*h;
1005
1006
	bzero(&hints, sizeof(hints));
1007
	hints.ai_family = PF_UNSPEC;
1008
	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
1009
	hints.ai_flags = AI_ADDRCONFIG;
1010
	error = getaddrinfo(s, NULL, &hints, &res0);
1011
	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
1012
		return (0);
1013
	if (error) {
1014
		log_warnx("host_dns: could not parse \"%s\": %s", s,
1015
		    gai_strerror(error));
1016
		return (-1);
1017
	}
1018
1019
	for (res = res0; res && cnt < max; res = res->ai_next) {
1020
		if (res->ai_family != AF_INET &&
1021
		    res->ai_family != AF_INET6)
1022
			continue;
1023
		if (src != NULL && src->ss.ss_family != res->ai_family)
1024
			continue;
1025
		if ((h = calloc(1, sizeof(*h))) == NULL)
1026
			fatal(__func__);
1027
1028
		h->port = port;
1029
		if (oid != NULL) {
1030
			if ((h->sa_oid = calloc(1, sizeof(*oid))) == NULL)
1031
				fatal(__func__);
1032
			bcopy(oid, h->sa_oid, sizeof(*oid));
1033
		}
1034
		if (cmn != NULL) {
1035
			if ((h->sa_community = strdup(cmn)) == NULL)
1036
				fatal(__func__);
1037
		}
1038
1039
		h->ss.ss_family = res->ai_family;
1040
		if (res->ai_family == AF_INET) {
1041
			sain = (struct sockaddr_in *)&h->ss;
1042
			sain->sin_len = sizeof(struct sockaddr_in);
1043
			sain->sin_addr.s_addr = ((struct sockaddr_in *)
1044
			    res->ai_addr)->sin_addr.s_addr;
1045
		} else {
1046
			sin6 = (struct sockaddr_in6 *)&h->ss;
1047
			sin6->sin6_len = sizeof(struct sockaddr_in6);
1048
			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
1049
			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
1050
		}
1051
1052
		h->sa_srcaddr = src;
1053
1054
		TAILQ_INSERT_TAIL(al, h, entry);
1055
		cnt++;
1056
	}
1057
	if (cnt == max && res) {
1058
		log_warnx("host_dns: %s resolves to more than %d hosts",
1059
		    s, max);
1060
	}
1061
	freeaddrinfo(res0);
1062
	if (oid != NULL)
1063
		free(oid);
1064
	if (cmn != NULL)
1065
		free(cmn);
1066
	return (cnt);
1067
}
1068
1069
int
1070
host(const char *s, struct addresslist *al, int max,
1071
    in_port_t port, struct ber_oid *oid, char *cmn, char *srcaddr)
1072
{
1073
	struct address	*h, *src = NULL;
1074
1075
	if (srcaddr != NULL) {
1076
		src = host_v4(srcaddr);
1077
		if (src == NULL)
1078
			src = host_v6(srcaddr);
1079
		if (src == NULL) {
1080
			log_warnx("invalid source-address %s", srcaddr);
1081
			return (-1);
1082
		}
1083
	}
1084
1085
	h = host_v4(s);
1086
1087
	/* IPv6 address? */
1088
	if (h == NULL)
1089
		h = host_v6(s);
1090
1091
	if (h != NULL) {
1092
		h->port = port;
1093
		h->sa_oid = oid;
1094
		h->sa_community = cmn;
1095
		if (src != NULL && h->ss.ss_family != src->ss.ss_family) {
1096
			log_warnx("host and source-address family mismatch");
1097
			return (-1);
1098
		}
1099
		h->sa_srcaddr = src;
1100
1101
		TAILQ_INSERT_TAIL(al, h, entry);
1102
		return (1);
1103
	}
1104
1105
	return (host_dns(s, al, max, port, oid, cmn, src));
1106
}
1107
#line 1100 "parse.c"
1108
32
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
1109
16
static int yygrowstack(void)
1110
{
1111
    unsigned int newsize;
1112
    long sslen;
1113
    short *newss;
1114
16
    YYSTYPE *newvs;
1115
1116
    if ((newsize = yystacksize) == 0)
1117
        newsize = YYINITSTACKSIZE;
1118
    else if (newsize >= YYMAXDEPTH)
1119
        return -1;
1120

32
    else if ((newsize *= 2) > YYMAXDEPTH)
1121
        newsize = YYMAXDEPTH;
1122
32
    sslen = yyssp - yyss;
1123
16
#ifdef SIZE_MAX
1124
16
#define YY_SIZE_MAX SIZE_MAX
1125
#else
1126
16
#define YY_SIZE_MAX 0xffffffffU
1127
16
#endif
1128

32
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
1129
        goto bail;
1130
32
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
1131
16
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
1132
16
    if (newss == NULL)
1133
        goto bail;
1134
16
    yyss = newss;
1135
16
    yyssp = newss + sslen;
1136
16
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
1137
16
        goto bail;
1138
16
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
1139
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
1140
    if (newvs == NULL)
1141
        goto bail;
1142
    yyvs = newvs;
1143
    yyvsp = newvs + sslen;
1144
    yystacksize = newsize;
1145
    yysslim = yyss + newsize - 1;
1146
    return 0;
1147
bail:
1148
16
    if (yyss)
1149
            free(yyss);
1150
    if (yyvs)
1151
            free(yyvs);
1152
    yyss = yyssp = NULL;
1153
    yyvs = yyvsp = NULL;
1154
    yystacksize = 0;
1155
    return -1;
1156
}
1157
1158
#define YYABORT goto yyabort
1159
#define YYREJECT goto yyabort
1160
#define YYACCEPT goto yyaccept
1161
#define YYERROR goto yyerrlab
1162
int
1163
yyparse(void)
1164
{
1165
    int yym, yyn, yystate;
1166
#if YYDEBUG
1167
    const char *yys;
1168
1169
32
    if ((yys = getenv("YYDEBUG")))
1170
16
    {
1171
16
        yyn = *yys;
1172
        if (yyn >= '0' && yyn <= '9')
1173

32
            yydebug = yyn - '0';
1174
16
    }
1175
16
#endif /* YYDEBUG */
1176
16
1177
    yynerrs = 0;
1178
    yyerrflag = 0;
1179
800
    yychar = (-1);
1180
452
1181
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
1182
268
    yyssp = yyss;
1183
    yyvsp = yyvs;
1184
    *yyssp = yystate = 0;
1185
1186
yyloop:
1187
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1188
    if (yychar < 0)
1189
    {
1190
        if ((yychar = yylex()) < 0) yychar = 0;
1191
#if YYDEBUG
1192
        if (yydebug)
1193
268
        {
1194

1788
            yys = 0;
1195
884
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1196
            if (!yys) yys = "illegal-symbol";
1197
            printf("%sdebug: state %d, reading %d (%s)\n",
1198
                    YYPREFIX, yystate, yychar, yys);
1199
        }
1200
#endif
1201
    }
1202

428
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1203
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1204
    {
1205
#if YYDEBUG
1206
428
        if (yydebug)
1207
428
            printf("%sdebug: state %d, shifting to state %d\n",
1208
428
                    YYPREFIX, yystate, yytable[yyn]);
1209
428
#endif
1210
        if (yyssp >= yysslim && yygrowstack())
1211
        {
1212

96
            goto yyoverflow;
1213
48
        }
1214
        *++yyssp = yystate = yytable[yyn];
1215
24
        *++yyvsp = yylval;
1216
24
        yychar = (-1);
1217
        if (yyerrflag > 0)  --yyerrflag;
1218
        goto yyloop;
1219
    }
1220
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1221
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1222
    {
1223
        yyn = yytable[yyn];
1224
        goto yyreduce;
1225
    }
1226
    if (yyerrflag) goto yyinrecovery;
1227
#if defined(__GNUC__)
1228
    goto yynewerror;
1229
#endif
1230
yynewerror:
1231
    yyerror("syntax error");
1232
#if defined(__GNUC__)
1233
    goto yyerrlab;
1234
#endif
1235
yyerrlab:
1236
    ++yynerrs;
1237
yyinrecovery:
1238
    if (yyerrflag < 3)
1239
    {
1240
        yyerrflag = 3;
1241
        for (;;)
1242
        {
1243
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1244
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1245
            {
1246
#if YYDEBUG
1247
                if (yydebug)
1248
                    printf("%sdebug: state %d, error recovery shifting\
1249
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1250
#endif
1251
                if (yyssp >= yysslim && yygrowstack())
1252
                {
1253
                    goto yyoverflow;
1254
                }
1255
                *++yyssp = yystate = yytable[yyn];
1256
                *++yyvsp = yylval;
1257
                goto yyloop;
1258
            }
1259
            else
1260
            {
1261
#if YYDEBUG
1262
                if (yydebug)
1263
                    printf("%sdebug: error recovery discarding state %d\n",
1264
                            YYPREFIX, *yyssp);
1265
#endif
1266
                if (yyssp <= yyss) goto yyabort;
1267
                --yyssp;
1268
                --yyvsp;
1269
            }
1270
        }
1271
    }
1272
    else
1273
    {
1274
        if (yychar == 0) goto yyabort;
1275
#if YYDEBUG
1276
        if (yydebug)
1277
        {
1278
            yys = 0;
1279
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1280
            if (!yys) yys = "illegal-symbol";
1281
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1282
                    YYPREFIX, yystate, yychar, yys);
1283
        }
1284
#endif
1285
        yychar = (-1);
1286
372
        goto yyloop;
1287
372
    }
1288
320
yyreduce:
1289
#if YYDEBUG
1290
52
    if (yydebug)
1291













532
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1292
                YYPREFIX, yystate, yyn, yyrule[yyn]);
1293
#endif
1294
    yym = yylen[yyn];
1295
    if (yym)
1296
        yyval = yyvsp[1-yym];
1297
    else
1298
        memset(&yyval, 0, sizeof yyval);
1299
    switch (yyn)
1300
    {
1301
case 8:
1302
#line 151 "parse.y"
1303
{ file->errors++; }
1304
break;
1305
case 9:
1306
#line 154 "parse.y"
1307
{
1308
			struct file	*nfile;
1309
1310
			if ((nfile = pushfile(yyvsp[0].v.string, 0)) == NULL) {
1311
				yyerror("failed to include file %s", yyvsp[0].v.string);
1312
				free(yyvsp[0].v.string);
1313
				YYERROR;
1314
			}
1315
			free(yyvsp[0].v.string);
1316
1317
			file = nfile;
1318
			lungetc('\n');
1319
		}
1320
break;
1321
case 10:
1322
#line 169 "parse.y"
1323
{
1324
			char *s = yyvsp[-2].v.string;
1325
			while (*s++) {
1326
				if (isspace((unsigned char)*s)) {
1327
					yyerror("macro name cannot contain "
1328
					    "whitespace");
1329
					YYERROR;
1330
				}
1331
			}
1332
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1333
				fatal("cannot store variable");
1334
			free(yyvsp[-2].v.string);
1335
			free(yyvsp[0].v.string);
1336
		}
1337
break;
1338
case 11:
1339
#line 185 "parse.y"
1340
{
1341
			if (!strcmp(yyvsp[0].v.string, "yes"))
1342
				yyval.v.number = 1;
1343
			else if (!strcmp(yyvsp[0].v.string, "no"))
1344
				yyval.v.number = 0;
1345
			else {
1346
				yyerror("syntax error, "
1347
				    "either yes or no expected");
1348
				free(yyvsp[0].v.string);
1349
				YYERROR;
1350
			}
1351
			free(yyvsp[0].v.string);
1352
		}
1353
break;
1354
case 12:
1355
#line 200 "parse.y"
1356
{
1357
			if (host(yyvsp[0].v.string, &conf->sc_addresses, 16, SNMPD_PORT, NULL,
1358
			    NULL, NULL) <= 0) {
1359
				yyerror("invalid ip address: %s", yyvsp[0].v.string);
1360
				free(yyvsp[0].v.string);
1361
				YYERROR;
1362
			}
1363
			free(yyvsp[0].v.string);
1364
		}
1365
break;
1366
case 13:
1367
#line 209 "parse.y"
1368
{
1369
			if (strlcpy(conf->sc_rdcommunity, yyvsp[0].v.string,
1370
			    sizeof(conf->sc_rdcommunity)) >=
1371
			    sizeof(conf->sc_rdcommunity)) {
1372
				yyerror("r/o community name too long");
1373
				free(yyvsp[0].v.string);
1374
				YYERROR;
1375
			}
1376
			free(yyvsp[0].v.string);
1377
		}
1378
break;
1379
case 14:
1380
#line 219 "parse.y"
1381
{
1382
			if (strlcpy(conf->sc_rwcommunity, yyvsp[0].v.string,
1383
			    sizeof(conf->sc_rwcommunity)) >=
1384
			    sizeof(conf->sc_rwcommunity)) {
1385
				yyerror("r/w community name too long");
1386
				free(yyvsp[0].v.string);
1387
				YYERROR;
1388
			}
1389
			free(yyvsp[0].v.string);
1390
		}
1391
break;
1392
case 15:
1393
#line 229 "parse.y"
1394
{
1395
			conf->sc_readonly = 1;
1396
 		}
1397
break;
1398
case 16:
1399
#line 232 "parse.y"
1400
{
1401
			if (strlcpy(conf->sc_trcommunity, yyvsp[0].v.string,
1402
			    sizeof(conf->sc_trcommunity)) >=
1403
			    sizeof(conf->sc_trcommunity)) {
1404
				yyerror("trap community name too long");
1405
				free(yyvsp[0].v.string);
1406
				YYERROR;
1407
			}
1408
			free(yyvsp[0].v.string);
1409
		}
1410
break;
1411
case 17:
1412
#line 242 "parse.y"
1413
{
1414
			hlist = &conf->sc_trapreceivers;
1415
		}
1416
break;
1417
case 18:
1418
#line 244 "parse.y"
1419
{
1420
			hlist = NULL;
1421
		}
1422
break;
1423
case 19:
1424
#line 247 "parse.y"
1425
{
1426
			struct trapcmd *cmd = yyvsp[0].v.data.data;
1427
1428
			cmd->cmd_oid = yyvsp[-1].v.oid;
1429
1430
			if (trapcmd_add(cmd) != 0) {
1431
				free(yyvsp[-1].v.oid);
1432
				free(cmd);
1433
				yyerror("duplicate oid");
1434
				YYERROR;
1435
			}
1436
			conf->sc_traphandler = 1;
1437
		}
1438
break;
1439
case 20:
1440
#line 260 "parse.y"
1441
{
1442
			if (yyvsp[0].v.number == 1)
1443
				conf->sc_rtfilter = ROUTE_FILTER(RTM_NEWADDR) |
1444
				    ROUTE_FILTER(RTM_DELADDR) |
1445
				    ROUTE_FILTER(RTM_IFINFO) |
1446
				    ROUTE_FILTER(RTM_IFANNOUNCE);
1447
			else
1448
				conf->sc_rtfilter = 0;
1449
		}
1450
break;
1451
case 21:
1452
#line 269 "parse.y"
1453
{
1454
			conf->sc_min_seclevel = yyvsp[0].v.number;
1455
		}
1456
break;
1457
case 22:
1458
#line 272 "parse.y"
1459
{
1460
			const char *errstr;
1461
			user = usm_newuser(yyvsp[0].v.string, &errstr);
1462
			if (user == NULL) {
1463
				yyerror("%s", errstr);
1464
				free(yyvsp[0].v.string);
1465
				YYERROR;
1466
			}
1467
		}
1468
break;
1469
case 23:
1470
#line 280 "parse.y"
1471
{
1472
			const char *errstr;
1473
			if (usm_checkuser(user, &errstr) < 0) {
1474
				yyerror("%s", errstr);
1475
				YYERROR;
1476
			}
1477
			user = NULL;
1478
		}
1479
break;
1480
case 24:
1481
#line 288 "parse.y"
1482
{
1483
			if (yyvsp[0].v.number) {
1484
				struct control_sock *rcsock;
1485
1486
				rcsock = calloc(1, sizeof(*rcsock));
1487
				if (rcsock == NULL) {
1488
					yyerror("calloc");
1489
					YYERROR;
1490
				}
1491
				rcsock->cs_name = yyvsp[-1].v.string;
1492
				if (yyvsp[0].v.number == SOCK_TYPE_RESTRICTED)
1493
					rcsock->cs_restricted = 1;
1494
				else if (yyvsp[0].v.number == SOCK_TYPE_AGENTX)
1495
					rcsock->cs_agentx = 1;
1496
				TAILQ_INSERT_TAIL(&conf->sc_ps.ps_rcsocks,
1497
				    rcsock, cs_entry);
1498
			} else {
1499
				if (++nctlsocks > 1) {
1500
					yyerror("multiple control "
1501
					    "sockets specified");
1502
					YYERROR;
1503
				}
1504
				conf->sc_ps.ps_csock.cs_name = yyvsp[-1].v.string;
1505
			}
1506
		}
1507
break;
1508
case 26:
1509
#line 318 "parse.y"
1510
{
1511
			struct ber_oid	 o = OID(MIB_sysContact);
1512
			mps_set(&o, yyvsp[0].v.string, strlen(yyvsp[0].v.string));
1513
		}
1514
break;
1515
case 27:
1516
#line 322 "parse.y"
1517
{
1518
			struct ber_oid	 o = OID(MIB_sysDescr);
1519
			mps_set(&o, yyvsp[0].v.string, strlen(yyvsp[0].v.string));
1520
		}
1521
break;
1522
case 28:
1523
#line 326 "parse.y"
1524
{
1525
			struct ber_oid	 o = OID(MIB_sysLocation);
1526
			mps_set(&o, yyvsp[0].v.string, strlen(yyvsp[0].v.string));
1527
		}
1528
break;
1529
case 29:
1530
#line 330 "parse.y"
1531
{
1532
			struct ber_oid	 o = OID(MIB_sysName);
1533
			mps_set(&o, yyvsp[0].v.string, strlen(yyvsp[0].v.string));
1534
		}
1535
break;
1536
case 30:
1537
#line 334 "parse.y"
1538
{
1539
			struct ber_oid	 o = OID(MIB_sysOID);
1540
			mps_set(&o, yyvsp[0].v.oid, sizeof(struct ber_oid));
1541
		}
1542
break;
1543
case 31:
1544
#line 338 "parse.y"
1545
{
1546
			struct ber_oid	 o = OID(MIB_sysServices);
1547
			mps_set(&o, NULL, yyvsp[0].v.number);
1548
		}
1549
break;
1550
case 32:
1551
#line 344 "parse.y"
1552
{
1553
			struct oid	*oid;
1554
			if ((oid = (struct oid *)
1555
			    calloc(1, sizeof(*oid))) == NULL) {
1556
				yyerror("calloc");
1557
				free(yyvsp[-4].v.oid);
1558
				free(yyvsp[0].v.data.data);
1559
				YYERROR;
1560
			}
1561
1562
			smi_oidlen(yyvsp[-4].v.oid);
1563
			bcopy(yyvsp[-4].v.oid, &oid->o_id, sizeof(struct ber_oid));
1564
			free(yyvsp[-4].v.oid);
1565
			oid->o_name = yyvsp[-2].v.string;
1566
			oid->o_data = yyvsp[0].v.data.data;
1567
			oid->o_val = yyvsp[0].v.data.value;
1568
			switch (yyvsp[0].v.data.type) {
1569
			case 1:
1570
				oid->o_get = mps_getint;
1571
				oid->o_set = mps_setint;
1572
				break;
1573
			case 2:
1574
				oid->o_get = mps_getstr;
1575
				oid->o_set = mps_setstr;
1576
				break;
1577
			}
1578
			oid->o_flags = OID_RD|OID_DYNAMIC;
1579
			if (yyvsp[-1].v.number)
1580
				oid->o_flags |= OID_WR;
1581
1582
			if (smi_insert(oid) == -1) {
1583
				yyerror("duplicate oid");
1584
				free(oid->o_name);
1585
				free(oid->o_data);
1586
				YYERROR;
1587
			}
1588
		}
1589
break;
1590
case 33:
1591
#line 383 "parse.y"
1592
{
1593
			yyval.v.data.type = 1;
1594
			yyval.v.data.data = NULL;
1595
			yyval.v.data.value = yyvsp[0].v.number;
1596
		}
1597
break;
1598
case 34:
1599
#line 388 "parse.y"
1600
{
1601
			yyval.v.data.type = 2;
1602
			yyval.v.data.data = yyvsp[0].v.string;
1603
			yyval.v.data.value = strlen(yyvsp[0].v.string);
1604
		}
1605
break;
1606
case 35:
1607
#line 395 "parse.y"
1608
{ yyval.v.number = 0; }
1609
break;
1610
case 36:
1611
#line 396 "parse.y"
1612
{ yyval.v.number = 1; }
1613
break;
1614
case 37:
1615
#line 399 "parse.y"
1616
{
1617
			struct ber_oid	*sysoid;
1618
			if ((sysoid =
1619
			    calloc(1, sizeof(*sysoid))) == NULL) {
1620
				yyerror("calloc");
1621
				free(yyvsp[0].v.string);
1622
				YYERROR;
1623
			}
1624
			if (ber_string2oid(yyvsp[0].v.string, sysoid) == -1) {
1625
				yyerror("invalid OID: %s", yyvsp[0].v.string);
1626
				free(sysoid);
1627
				free(yyvsp[0].v.string);
1628
				YYERROR;
1629
			}
1630
			free(yyvsp[0].v.string);
1631
			yyval.v.oid = sysoid;
1632
		}
1633
break;
1634
case 38:
1635
#line 418 "parse.y"
1636
{ yyval.v.oid = yyvsp[0].v.oid; }
1637
break;
1638
case 39:
1639
#line 419 "parse.y"
1640
{
1641
			struct ber_oid	*sysoid;
1642
			if ((sysoid =
1643
			    calloc(1, sizeof(*sysoid))) == NULL) {
1644
				yyerror("calloc");
1645
				YYERROR;
1646
			}
1647
			ber_string2oid("1.3", sysoid);
1648
			yyval.v.oid = sysoid;
1649
		}
1650
break;
1651
case 40:
1652
#line 431 "parse.y"
1653
{ yyval.v.oid = NULL; }
1654
break;
1655
case 41:
1656
#line 432 "parse.y"
1657
{ yyval.v.oid = yyvsp[0].v.oid; }
1658
break;
1659
case 42:
1660
#line 435 "parse.y"
1661
{ yyval.v.string = NULL; }
1662
break;
1663
case 43:
1664
#line 436 "parse.y"
1665
{ yyval.v.string = yyvsp[0].v.string; }
1666
break;
1667
case 44:
1668
#line 439 "parse.y"
1669
{ yyval.v.string = NULL; }
1670
break;
1671
case 45:
1672
#line 440 "parse.y"
1673
{ yyval.v.string = yyvsp[0].v.string; }
1674
break;
1675
case 46:
1676
#line 443 "parse.y"
1677
{
1678
			if (host(yyvsp[-3].v.string, hlist, 1,
1679
			    SNMPD_TRAPPORT, yyvsp[-2].v.oid, yyvsp[-1].v.string, yyvsp[0].v.string) <= 0) {
1680
				yyerror("invalid host: %s", yyvsp[-3].v.string);
1681
				free(yyvsp[-3].v.string);
1682
				YYERROR;
1683
			}
1684
			free(yyvsp[-3].v.string);
1685
		}
1686
break;
1687
case 53:
1688
#line 466 "parse.y"
1689
{ yyval.v.number = 0; }
1690
break;
1691
case 54:
1692
#line 467 "parse.y"
1693
{ yyval.v.number = SNMP_MSGFLAG_AUTH; }
1694
break;
1695
case 55:
1696
#line 468 "parse.y"
1697
{ yyval.v.number = SNMP_MSGFLAG_AUTH | SNMP_MSGFLAG_PRIV; }
1698
break;
1699
case 58:
1700
#line 475 "parse.y"
1701
{
1702
			user->uu_authkey = yyvsp[0].v.string;
1703
		}
1704
break;
1705
case 59:
1706
#line 478 "parse.y"
1707
{
1708
			user->uu_auth = yyvsp[0].v.auth;
1709
		}
1710
break;
1711
case 60:
1712
#line 481 "parse.y"
1713
{
1714
			user->uu_privkey = yyvsp[0].v.string;
1715
		}
1716
break;
1717
case 61:
1718
#line 484 "parse.y"
1719
{
1720
			user->uu_priv = yyvsp[0].v.enc;
1721
		}
1722
break;
1723
case 62:
1724
#line 489 "parse.y"
1725
{
1726
			if (strcasecmp(yyvsp[0].v.string, "hmac-md5") == 0 ||
1727
			    strcasecmp(yyvsp[0].v.string, "hmac-md5-96") == 0)
1728
				yyval.v.auth = AUTH_MD5;
1729
			else if (strcasecmp(yyvsp[0].v.string, "hmac-sha1") == 0 ||
1730
			     strcasecmp(yyvsp[0].v.string, "hmac-sha1-96") == 0)
1731
				yyval.v.auth = AUTH_SHA1;
1732
			else {
1733
				yyerror("syntax error, bad auth hmac");
1734
				free(yyvsp[0].v.string);
1735
				YYERROR;
1736
			}
1737
			free(yyvsp[0].v.string);
1738
		}
1739
break;
1740
case 63:
1741
#line 505 "parse.y"
1742
{
1743
			if (strcasecmp(yyvsp[0].v.string, "des") == 0 ||
1744
			    strcasecmp(yyvsp[0].v.string, "cbc-des") == 0)
1745
				yyval.v.enc = PRIV_DES;
1746
			else if (strcasecmp(yyvsp[0].v.string, "aes") == 0 ||
1747
			    strcasecmp(yyvsp[0].v.string, "cfb128-aes-128") == 0)
1748
				yyval.v.enc = PRIV_AES;
1749
			else {
1750
				yyerror("syntax error, bad encryption cipher");
1751
				free(yyvsp[0].v.string);
1752
				YYERROR;
1753
			}
1754
			free(yyvsp[0].v.string);
1755
1756
		}
1757
break;
1758
case 64:
1759
#line 522 "parse.y"
1760
{ yyval.v.number = SOCK_TYPE_RESTRICTED; }
1761
break;
1762
case 65:
1763
#line 523 "parse.y"
1764
{ yyval.v.number = SOCK_TYPE_AGENTX; }
1765
break;
1766
case 66:
1767
#line 524 "parse.y"
1768
{ yyval.v.number = 0; }
1769
break;
1770
case 67:
1771
#line 527 "parse.y"
1772
{
1773
			struct trapcmd	*cmd;
1774
			size_t		 span, limit;
1775
			char		*pos, **args, **args2;
1776
			int		 nargs = 32;		/* XXX */
1777
1778
			if ((cmd = calloc(1, sizeof(*cmd))) == NULL ||
1779
			    (args = calloc(nargs, sizeof(char *))) == NULL) {
1780
				free(cmd);
1781
				free(yyvsp[0].v.string);
1782
				YYERROR;
1783
			}
1784
1785
			pos = yyvsp[0].v.string;
1786
			limit = strlen(yyvsp[0].v.string);
1787
1788
			while (pos < yyvsp[0].v.string + limit &&
1789
			    (span = strcspn(pos, " \t")) != 0) {
1790
				pos[span] = '\0';
1791
				args[cmd->cmd_argc] = strdup(pos);
1792
				if (args[cmd->cmd_argc] == NULL) {
1793
					trapcmd_free(cmd);
1794
					free(args);
1795
					free(yyvsp[0].v.string);
1796
					YYERROR;
1797
				}
1798
				cmd->cmd_argc++;
1799
				if (cmd->cmd_argc >= nargs - 1) {
1800
					nargs *= 2;
1801
					args2 = calloc(nargs, sizeof(char *));
1802
					if (args2 == NULL) {
1803
						trapcmd_free(cmd);
1804
						free(args);
1805
						free(yyvsp[0].v.string);
1806
						YYERROR;
1807
					}
1808
					args = args2;
1809
				}
1810
				pos += span + 1;
1811
372
			}
1812
372
			free(yyvsp[0].v.string);
1813
372
			cmd->cmd_argv = args;
1814
372
			yyval.v.data.data = cmd;
1815
372
		}
1816
break;
1817
#line 1810 "parse.c"
1818
    }
1819
    yyssp -= yym;
1820
    yystate = *yyssp;
1821
    yyvsp -= yym;
1822
    yym = yylhs[yyn];
1823
176
    if (yystate == 0 && yym == 0)
1824
176
    {
1825
176
#if YYDEBUG
1826
        if (yydebug)
1827
176
            printf("%sdebug: after reduction, shifting from state 0 to\
1828
 state %d\n", YYPREFIX, YYFINAL);
1829
#endif
1830
        yystate = YYFINAL;
1831
        *++yyssp = YYFINAL;
1832
        *++yyvsp = yyval;
1833
        if (yychar < 0)
1834
        {
1835
            if ((yychar = yylex()) < 0) yychar = 0;
1836
#if YYDEBUG
1837
            if (yydebug)
1838
176
            {
1839
176
                yys = 0;
1840
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1841
                if (!yys) yys = "illegal-symbol";
1842

260
                printf("%sdebug: state %d, reading %d (%s)\n",
1843
40
                        YYPREFIX, YYFINAL, yychar, yys);
1844
8
            }
1845
#endif
1846
188
        }
1847
        if (yychar == 0) goto yyaccept;
1848
        goto yyloop;
1849
    }
1850
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1851
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1852

196
        yystate = yytable[yyn];
1853
    else
1854
        yystate = yydgoto[yym];
1855
#if YYDEBUG
1856
196
    if (yydebug)
1857
196
        printf("%sdebug: after reduction, shifting from state %d \
1858
196
to state %d\n", YYPREFIX, *yyssp, yystate);
1859
#endif
1860
    if (yyssp >= yysslim && yygrowstack())
1861
    {
1862
        goto yyoverflow;
1863
    }
1864
    *++yyssp = yystate;
1865
    *++yyvsp = yyval;
1866
    goto yyloop;
1867
yyoverflow:
1868
    yyerror("yacc stack overflow");
1869
yyabort:
1870
    if (yyss)
1871
16
            free(yyss);
1872
16
    if (yyvs)
1873
16
            free(yyvs);
1874
16
    yyss = yyssp = NULL;
1875
16
    yyvs = yyvsp = NULL;
1876
16
    yystacksize = 0;
1877
16
    return (1);
1878
16
yyaccept:
1879
16
    if (yyss)
1880
            free(yyss);
1881
    if (yyvs)
1882
            free(yyvs);
1883
    yyss = yyssp = NULL;
1884
    yyvs = yyvsp = NULL;
1885
    yystacksize = 0;
1886
    return (0);
1887
}