GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/vmd/parse.c Lines: 0 348 0.0 %
Date: 2017-11-07 Branches: 0 282 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 26 "parse.y"
13
#include <sys/types.h>
14
#include <sys/queue.h>
15
#include <sys/socket.h>
16
#include <sys/uio.h>
17
18
#include <machine/vmmvar.h>
19
20
#include <net/if.h>
21
#include <netinet/in.h>
22
#include <netinet/if_ether.h>
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <limits.h>
27
#include <stdarg.h>
28
#include <string.h>
29
#include <ctype.h>
30
#include <netdb.h>
31
#include <util.h>
32
#include <errno.h>
33
#include <err.h>
34
#include <pwd.h>
35
#include <grp.h>
36
37
#include "proc.h"
38
#include "vmd.h"
39
40
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
41
static struct file {
42
	TAILQ_ENTRY(file)	 entry;
43
	FILE			*stream;
44
	char			*name;
45
	int			 lineno;
46
	int			 errors;
47
} *file, *topfile;
48
struct file	*pushfile(const char *, int);
49
int		 popfile(void);
50
int		 yyparse(void);
51
int		 yylex(void);
52
int		 yyerror(const char *, ...)
53
    __attribute__((__format__ (printf, 1, 2)))
54
    __attribute__((__nonnull__ (1)));
55
int		 kw_cmp(const void *, const void *);
56
int		 lookup(char *);
57
int		 lgetc(int);
58
int		 lungetc(int);
59
int		 findeol(void);
60
61
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
62
struct sym {
63
	TAILQ_ENTRY(sym)	 entry;
64
	int			 used;
65
	int			 persist;
66
	char			*nam;
67
	char			*val;
68
};
69
int		 symset(const char *, const char *, int);
70
char		*symget(const char *);
71
72
ssize_t		 parse_size(char *, int64_t);
73
int		 parse_disk(char *);
74
75
static struct vmop_create_params vmc;
76
static struct vm_create_params	*vcp;
77
static struct vmd_switch	*vsw;
78
static struct vmd_if		*vif;
79
static struct vmd_vm		*vm;
80
static unsigned int		 vsw_unit;
81
static char			 vsw_type[IF_NAMESIZE];
82
static int			 vcp_disable;
83
static size_t			 vcp_nnics;
84
static int			 errors;
85
extern struct vmd		*env;
86
extern const char		*vmd_descsw[];
87
88
typedef struct {
89
	union {
90
		uint8_t		 lladdr[ETHER_ADDR_LEN];
91
		int64_t		 number;
92
		char		*string;
93
		struct {
94
			uid_t	 uid;
95
			int64_t	 gid;
96
		}		 owner;
97
	} v;
98
	int lineno;
99
} YYSTYPE;
100
101
#line 102 "parse.c"
102
#define INCLUDE 257
103
#define ERROR 258
104
#define ADD 259
105
#define BOOT 260
106
#define DISABLE 261
107
#define DISK 262
108
#define DOWN 263
109
#define ENABLE 264
110
#define GROUP 265
111
#define INTERFACE 266
112
#define LLADDR 267
113
#define LOCAL 268
114
#define LOCKED 269
115
#define MEMORY 270
116
#define NIFS 271
117
#define OWNER 272
118
#define PATH 273
119
#define PREFIX 274
120
#define RDOMAIN 275
121
#define SIZE 276
122
#define SWITCH 277
123
#define UP 278
124
#define VM 279
125
#define VMID 280
126
#define NUMBER 281
127
#define STRING 282
128
#define YYERRCODE 256
129
const short yylhs[] =
130
	{                                        -1,
131
    0,    0,    0,    0,    0,    0,    0,    0,    9,   10,
132
   11,   14,   12,   16,   16,   17,   17,   17,   17,   17,
133
   17,   17,   19,   13,   20,   20,   21,   21,   21,   21,
134
   21,   21,   21,   21,    6,    6,    6,   22,   22,   22,
135
   23,   23,   24,   24,   25,   25,   25,   25,   25,    7,
136
    7,    8,    8,    1,    3,    3,    4,    4,    5,    5,
137
    2,    2,   26,   26,   15,   15,   18,
138
};
139
const short yylen[] =
140
	{                                         2,
141
    0,    3,    2,    3,    3,    3,    3,    3,    2,    3,
142
    3,    0,    7,    3,    2,    1,    2,    2,    2,    2,
143
    2,    1,    0,    7,    3,    2,    1,    2,    4,    2,
144
    2,    2,    2,    2,    0,    1,    1,    4,    1,    0,
145
    3,    2,    3,    1,    2,    2,    3,    2,    1,    1,
146
    0,    2,    1,    1,    0,    1,    0,    1,    1,    1,
147
    1,    1,    1,    0,    2,    0,    2,
148
};
149
const short yydefred[] =
150
	{                                      1,
151
    0,    0,    0,    0,    0,    0,    0,    3,    0,    0,
152
    0,    0,    0,    8,    0,    9,    0,   12,   23,    0,
153
    2,    4,    5,    6,    7,   52,   11,    0,    0,   10,
154
    0,    0,    0,    0,    0,   65,    0,   62,   60,   61,
155
    0,    0,    0,    0,   59,   16,   22,    0,    0,    0,
156
    0,   56,    0,    0,    0,   27,    0,    0,    0,   17,
157
   18,   19,   20,   21,   13,    0,   15,   30,   28,   32,
158
   33,   31,   36,   37,   34,    0,   24,    0,   26,    0,
159
   14,   50,    0,   25,   67,    0,   58,    0,    0,    0,
160
    0,   49,   29,    0,   44,   46,   48,   45,    0,    0,
161
    0,    0,    0,   54,   47,   63,   43,   38,    0,   42,
162
   41,
163
};
164
const short yydgoto[] =
165
	{                                       1,
166
  105,   46,   57,   91,   92,   75,   83,   16,    9,   10,
167
   11,   12,   13,   28,   34,   48,   49,   81,   29,   58,
168
   59,   93,  102,   94,   95,  107,
169
};
170
const short yysindex[] =
171
	{                                      0,
172
  -10,   -9, -274, -257, -274, -274,  -30,    0,   20,   23,
173
   24,   26,   27,    0, -274,    0, -235,    0,    0, -233,
174
    0,    0,    0,    0,    0,    0,    0,  -66,  -62,    0,
175
   53,   53,   53, -243,  110,    0, -274,    0,    0,    0,
176
 -274, -274, -203, -216,    0,    0,    0, -123,   53, -274,
177
 -274,    0, -275, -214, -267,    0, -198,  -33,   53,    0,
178
    0,    0,    0,    0,    0,   59,    0,    0,    0,    0,
179
    0,    0,    0,    0,    0, -211,    0,   59,    0,   53,
180
    0,    0, -118,    0,    0, -274,    0, -206, -274,   53,
181
 -183,    0,    0, -168,    0,    0,    0,    0, -168, -197,
182
   42,  -45,   53,    0,    0,    0,    0,    0,   53,    0,
183
    0,};
184
const short yyrindex[] =
185
	{                                      0,
186
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
187
    0,    0,    0,    0,   14,    0,    0,    0,    0,    0,
188
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
189
 -187, -149,  -97,    0, -179,    0,    0,    0,    0,    0,
190
    0,    0,    0,    0,    0,    0,    0,    0,  -59,    0,
191
    0,    0,    0,    0,   84,    0,    0, -179,   97,    0,
192
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
193
    0,    0,    0,    0,    0,   33,    0,    0,    0,  -77,
194
    0,    0,   -7,    0,    0,    0,    0,    0,    0, -225,
195
    0,    0,    0,   71,    0,    0,    0,    0, -171,    0,
196
   52, -171,  -52,    0,    0,    0,    0,    0,  -52,    0,
197
    0,};
198
const short yygindex[] =
199
	{                                      0,
200
    0,  -31,    0,    0,  -23,    0,    0,    4,    0,    0,
201
    0,    0,    0,    0,  -20,    0,   50,   21,    0,    0,
202
   44,    0,    0,    0,  -43,    0,
203
};
204
#define YYTABLESIZE 382
205
const short yytable[] =
206
	{                                       8,
207
   14,   65,   40,   56,   90,   70,   71,   15,   18,   19,
208
   47,   35,   36,   73,   74,   37,   17,   38,   26,   39,
209
   40,   41,   42,   53,   47,   43,   56,   66,   67,   21,
210
   20,   44,   22,   23,   45,   24,   25,   66,   79,   66,
211
   60,   66,   51,   66,   61,   62,   27,   66,   30,   66,
212
  101,   66,   66,   68,   69,  103,   31,   53,  109,   85,
213
   32,   64,   33,   63,   64,   66,   72,   76,   80,   99,
214
   82,   66,   66,   66,   97,   66,   66,   66,   66,  108,
215
   39,   66,  110,  100,  104,  106,   55,   66,  111,   96,
216
   66,   77,   98,   35,   39,   57,   86,   66,   84,    0,
217
   87,   78,    0,    0,    0,    0,   88,    0,   89,   45,
218
   66,   66,   66,    0,   66,    0,   66,   40,   66,    0,
219
   66,   66,   66,    0,    0,    0,    0,    0,    0,    0,
220
    0,    0,    0,    0,    0,   37,   53,   38,   53,   39,
221
   40,   41,   42,    0,   39,   43,   86,    0,    0,    0,
222
   87,   44,    0,    0,   45,   51,   88,   51,   89,   45,
223
    0,   66,   66,   66,   66,   66,   66,   66,   66,   66,
224
   66,   66,   66,   66,   66,    0,   64,   66,    0,   66,
225
   66,   66,   66,   66,   66,   66,   66,   66,   66,    0,
226
   66,   66,   66,   66,   66,   39,    0,   66,    0,   66,
227
   66,   66,    0,   66,   66,   66,   66,    0,   35,   66,
228
   66,    0,   66,    0,   66,   66,   66,   39,   66,   86,
229
    0,   66,   66,   87,   66,   66,   50,   38,   51,   88,
230
   40,   89,   45,    0,   52,    0,   53,   54,   55,    0,
231
    0,    0,    0,    0,    0,    2,    3,    0,    0,    0,
232
    0,    0,   40,   40,   40,    0,   40,    4,   40,   57,
233
   40,    0,   40,   40,   40,    0,    5,    0,    6,    0,
234
    0,    7,   53,   53,   53,   53,   53,   53,   53,   53,
235
   53,   53,   53,   53,   53,   53,    0,    0,   53,    0,
236
   53,   53,   51,   51,   51,   51,   51,   51,   51,   51,
237
   51,   51,   51,   51,   51,    0,    0,   51,    0,   51,
238
   51,   64,   64,   64,   64,   64,   64,   64,   64,   64,
239
   64,   64,   64,   64,    0,    0,   64,    0,   64,   64,
240
   39,   39,   39,    0,   39,    0,   39,   57,   39,    0,
241
   39,   39,   39,   35,   35,   35,    0,   35,    0,   35,
242
    0,   35,    0,   35,   35,   35,   66,   66,   66,    0,
243
   66,    0,   66,    0,   66,    0,   66,   66,   66,   50,
244
   38,   51,    0,   40,    0,    0,    0,   52,    0,   53,
245
   54,   55,
246
};
247
const short yycheck[] =
248
	{                                      10,
249
   10,  125,   10,   35,  123,  281,  282,  282,    5,    6,
250
   34,   32,   33,  281,  282,  259,  274,  261,   15,  263,
251
  264,  265,  266,   10,   48,  269,   58,  125,   49,   10,
252
   61,  275,   10,   10,  278,   10,   10,  263,   59,  265,
253
   37,  267,   10,  269,   41,   42,  282,  125,  282,  275,
254
   94,  277,  278,   50,   51,   99,  123,   44,  102,   80,
255
  123,   10,   10,  267,  281,  125,  281,  266,   10,   90,
256
  282,  259,  125,  261,  281,  263,  264,  265,  266,  125,
257
   10,  269,  103,  267,  282,   44,  266,  275,  109,   86,
258
  278,  125,   89,   10,  263,  267,  265,   48,   78,   -1,
259
  269,   58,   -1,   -1,   -1,   -1,  275,   -1,  277,  278,
260
  260,  261,  262,   -1,  264,   -1,  266,  125,  268,   -1,
261
  270,  271,  272,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
262
   -1,   -1,   -1,   -1,   -1,  259,  123,  261,  125,  263,
263
  264,  265,  266,   -1,  263,  269,  265,   -1,   -1,   -1,
264
  269,  275,   -1,   -1,  278,  123,  275,  125,  277,  278,
265
   -1,  259,  260,  261,  262,  263,  264,  265,  266,  267,
266
  268,  269,  270,  271,  272,   -1,  125,  275,   -1,  277,
267
  278,  259,  260,  261,  262,  263,  264,  265,  266,   -1,
268
  268,  269,  270,  271,  272,  125,   -1,  275,   -1,  259,
269
  278,  261,   -1,  263,  264,  265,  266,   -1,  125,  269,
270
  263,   -1,  265,   -1,  267,  275,  269,  263,  278,  265,
271
   -1,  125,  275,  269,  277,  278,  260,  261,  262,  275,
272
  264,  277,  278,   -1,  268,   -1,  270,  271,  272,   -1,
273
   -1,   -1,   -1,   -1,   -1,  256,  257,   -1,   -1,   -1,
274
   -1,   -1,  260,  261,  262,   -1,  264,  268,  266,  267,
275
  268,   -1,  270,  271,  272,   -1,  277,   -1,  279,   -1,
276
   -1,  282,  259,  260,  261,  262,  263,  264,  265,  266,
277
  267,  268,  269,  270,  271,  272,   -1,   -1,  275,   -1,
278
  277,  278,  260,  261,  262,  263,  264,  265,  266,  267,
279
  268,  269,  270,  271,  272,   -1,   -1,  275,   -1,  277,
280
  278,  260,  261,  262,  263,  264,  265,  266,  267,  268,
281
  269,  270,  271,  272,   -1,   -1,  275,   -1,  277,  278,
282
  260,  261,  262,   -1,  264,   -1,  266,  267,  268,   -1,
283
  270,  271,  272,  260,  261,  262,   -1,  264,   -1,  266,
284
   -1,  268,   -1,  270,  271,  272,  260,  261,  262,   -1,
285
  264,   -1,  266,   -1,  268,   -1,  270,  271,  272,  260,
286
  261,  262,   -1,  264,   -1,   -1,   -1,  268,   -1,  270,
287
  271,  272,
288
};
289
#define YYFINAL 1
290
#ifndef YYDEBUG
291
#define YYDEBUG 0
292
#endif
293
#define YYMAXTOKEN 282
294
#if YYDEBUG
295
const char * const yyname[] =
296
	{
297
"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,
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,
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,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,
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,0,0,0,0,0,0,
303
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",
304
"ERROR","ADD","BOOT","DISABLE","DISK","DOWN","ENABLE","GROUP","INTERFACE",
305
"LLADDR","LOCAL","LOCKED","MEMORY","NIFS","OWNER","PATH","PREFIX","RDOMAIN",
306
"SIZE","SWITCH","UP","VM","VMID","NUMBER","STRING",
307
};
308
const char * const yyrule[] =
309
	{"$accept : grammar",
310
"grammar :",
311
"grammar : grammar include '\\n'",
312
"grammar : grammar '\\n'",
313
"grammar : grammar varset '\\n'",
314
"grammar : grammar main '\\n'",
315
"grammar : grammar switch '\\n'",
316
"grammar : grammar vm '\\n'",
317
"grammar : grammar error '\\n'",
318
"include : INCLUDE string",
319
"varset : STRING '=' STRING",
320
"main : LOCAL PREFIX STRING",
321
"$$1 :",
322
"switch : SWITCH string $$1 '{' optnl switch_opts_l '}'",
323
"switch_opts_l : switch_opts_l switch_opts nl",
324
"switch_opts_l : switch_opts optnl",
325
"switch_opts : disable",
326
"switch_opts : ADD string",
327
"switch_opts : GROUP string",
328
"switch_opts : INTERFACE string",
329
"switch_opts : LOCKED LLADDR",
330
"switch_opts : RDOMAIN NUMBER",
331
"switch_opts : updown",
332
"$$2 :",
333
"vm : VM string $$2 '{' optnl vm_opts_l '}'",
334
"vm_opts_l : vm_opts_l vm_opts nl",
335
"vm_opts_l : vm_opts optnl",
336
"vm_opts : disable",
337
"vm_opts : DISK string",
338
"vm_opts : local INTERFACE optstring iface_opts_o",
339
"vm_opts : BOOT string",
340
"vm_opts : NIFS NUMBER",
341
"vm_opts : MEMORY NUMBER",
342
"vm_opts : MEMORY STRING",
343
"vm_opts : OWNER owner_id",
344
"owner_id :",
345
"owner_id : NUMBER",
346
"owner_id : STRING",
347
"iface_opts_o : '{' optnl iface_opts_l '}'",
348
"iface_opts_o : iface_opts_c",
349
"iface_opts_o :",
350
"iface_opts_l : iface_opts_l iface_opts optnl",
351
"iface_opts_l : iface_opts optnl",
352
"iface_opts_c : iface_opts_c iface_opts optcomma",
353
"iface_opts_c : iface_opts",
354
"iface_opts : SWITCH string",
355
"iface_opts : GROUP string",
356
"iface_opts : locked LLADDR lladdr",
357
"iface_opts : RDOMAIN NUMBER",
358
"iface_opts : updown",
359
"optstring : STRING",
360
"optstring :",
361
"string : STRING string",
362
"string : STRING",
363
"lladdr : STRING",
364
"local :",
365
"local : LOCAL",
366
"locked :",
367
"locked : LOCKED",
368
"updown : UP",
369
"updown : DOWN",
370
"disable : ENABLE",
371
"disable : DISABLE",
372
"optcomma : ','",
373
"optcomma :",
374
"optnl : '\\n' optnl",
375
"optnl :",
376
"nl : '\\n' optnl",
377
};
378
#endif
379
#ifdef YYSTACKSIZE
380
#undef YYMAXDEPTH
381
#define YYMAXDEPTH YYSTACKSIZE
382
#else
383
#ifdef YYMAXDEPTH
384
#define YYSTACKSIZE YYMAXDEPTH
385
#else
386
#define YYSTACKSIZE 10000
387
#define YYMAXDEPTH 10000
388
#endif
389
#endif
390
#define YYINITSTACKSIZE 200
391
/* LINTUSED */
392
int yydebug;
393
int yynerrs;
394
int yyerrflag;
395
int yychar;
396
short *yyssp;
397
YYSTYPE *yyvsp;
398
YYSTYPE yyval;
399
YYSTYPE yylval;
400
short *yyss;
401
short *yysslim;
402
YYSTYPE *yyvs;
403
unsigned int yystacksize;
404
int yyparse(void);
405
#line 614 "parse.y"
406
407
struct keywords {
408
	const char	*k_name;
409
	int		 k_val;
410
};
411
412
int
413
yyerror(const char *fmt, ...)
414
{
415
	va_list		 ap;
416
	char		*msg;
417
418
	file->errors++;
419
	va_start(ap, fmt);
420
	if (vasprintf(&msg, fmt, ap) == -1)
421
		fatal("yyerror vasprintf");
422
	va_end(ap);
423
	log_warnx("%s:%d: %s", file->name, yylval.lineno, msg);
424
	free(msg);
425
	return (0);
426
}
427
428
int
429
kw_cmp(const void *k, const void *e)
430
{
431
	return (strcmp(k, ((const struct keywords *)e)->k_name));
432
}
433
434
int
435
lookup(char *s)
436
{
437
	/* this has to be sorted always */
438
	static const struct keywords keywords[] = {
439
		{ "add",		ADD },
440
		{ "boot",		BOOT },
441
		{ "disable",		DISABLE },
442
		{ "disk",		DISK },
443
		{ "down",		DOWN },
444
		{ "enable",		ENABLE },
445
		{ "group",		GROUP },
446
		{ "id",			VMID },
447
		{ "include",		INCLUDE },
448
		{ "interface",		INTERFACE },
449
		{ "interfaces",		NIFS },
450
		{ "lladdr",		LLADDR },
451
		{ "local",		LOCAL },
452
		{ "locked",		LOCKED },
453
		{ "memory",		MEMORY },
454
		{ "owner",		OWNER },
455
		{ "prefix",		PREFIX },
456
		{ "rdomain",		RDOMAIN },
457
		{ "size",		SIZE },
458
		{ "switch",		SWITCH },
459
		{ "up",			UP },
460
		{ "vm",			VM }
461
	};
462
	const struct keywords	*p;
463
464
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
465
	    sizeof(keywords[0]), kw_cmp);
466
467
	if (p)
468
		return (p->k_val);
469
	else
470
		return (STRING);
471
}
472
473
#define MAXPUSHBACK	128
474
475
u_char	*parsebuf;
476
int	 parseindex;
477
u_char	 pushback_buffer[MAXPUSHBACK];
478
int	 pushback_index = 0;
479
480
int
481
lgetc(int quotec)
482
{
483
	int		c, next;
484
485
	if (parsebuf) {
486
		/* Read character from the parsebuffer instead of input. */
487
		if (parseindex >= 0) {
488
			c = parsebuf[parseindex++];
489
			if (c != '\0')
490
				return (c);
491
			parsebuf = NULL;
492
		} else
493
			parseindex++;
494
	}
495
496
	if (pushback_index)
497
		return (pushback_buffer[--pushback_index]);
498
499
	if (quotec) {
500
		if ((c = getc(file->stream)) == EOF) {
501
			yyerror("reached end of file while parsing "
502
			    "quoted string");
503
			if (file == topfile || popfile() == EOF)
504
				return (EOF);
505
			return (quotec);
506
		}
507
		return (c);
508
	}
509
510
	while ((c = getc(file->stream)) == '\\') {
511
		next = getc(file->stream);
512
		if (next != '\n') {
513
			c = next;
514
			break;
515
		}
516
		yylval.lineno = file->lineno;
517
		file->lineno++;
518
	}
519
	if (c == '\t' || c == ' ') {
520
		/* Compress blanks to a single space. */
521
		do {
522
			c = getc(file->stream);
523
		} while (c == '\t' || c == ' ');
524
		ungetc(c, file->stream);
525
		c = ' ';
526
	}
527
528
	while (c == EOF) {
529
		if (file == topfile || popfile() == EOF)
530
			return (EOF);
531
		c = getc(file->stream);
532
	}
533
	return (c);
534
}
535
536
int
537
lungetc(int c)
538
{
539
	if (c == EOF)
540
		return (EOF);
541
	if (parsebuf) {
542
		parseindex--;
543
		if (parseindex >= 0)
544
			return (c);
545
	}
546
	if (pushback_index < MAXPUSHBACK-1)
547
		return (pushback_buffer[pushback_index++] = c);
548
	else
549
		return (EOF);
550
}
551
552
int
553
findeol(void)
554
{
555
	int	c;
556
557
	parsebuf = NULL;
558
559
	/* skip to either EOF or the first real EOL */
560
	while (1) {
561
		if (pushback_index)
562
			c = pushback_buffer[--pushback_index];
563
		else
564
			c = lgetc(0);
565
		if (c == '\n') {
566
			file->lineno++;
567
			break;
568
		}
569
		if (c == EOF)
570
			break;
571
	}
572
	return (ERROR);
573
}
574
575
int
576
yylex(void)
577
{
578
	u_char	 buf[8096];
579
	u_char	*p, *val;
580
	int	 quotec, next, c;
581
	int	 token;
582
583
top:
584
	p = buf;
585
	while ((c = lgetc(0)) == ' ' || c == '\t')
586
		; /* nothing */
587
588
	yylval.lineno = file->lineno;
589
	if (c == '#')
590
		while ((c = lgetc(0)) != '\n' && c != EOF)
591
			; /* nothing */
592
	if (c == '$' && parsebuf == NULL) {
593
		while (1) {
594
			if ((c = lgetc(0)) == EOF)
595
				return (0);
596
597
			if (p + 1 >= buf + sizeof(buf) - 1) {
598
				yyerror("string too long");
599
				return (findeol());
600
			}
601
			if (isalnum(c) || c == '_') {
602
				*p++ = c;
603
				continue;
604
			}
605
			*p = '\0';
606
			lungetc(c);
607
			break;
608
		}
609
		val = symget(buf);
610
		if (val == NULL) {
611
			yyerror("macro '%s' not defined", buf);
612
			return (findeol());
613
		}
614
		parsebuf = val;
615
		parseindex = 0;
616
		goto top;
617
	}
618
619
	switch (c) {
620
	case '\'':
621
	case '"':
622
		quotec = c;
623
		while (1) {
624
			if ((c = lgetc(quotec)) == EOF)
625
				return (0);
626
			if (c == '\n') {
627
				file->lineno++;
628
				continue;
629
			} else if (c == '\\') {
630
				if ((next = lgetc(quotec)) == EOF)
631
					return (0);
632
				if (next == quotec || c == ' ' || c == '\t')
633
					c = next;
634
				else if (next == '\n') {
635
					file->lineno++;
636
					continue;
637
				} else
638
					lungetc(next);
639
			} else if (c == quotec) {
640
				*p = '\0';
641
				break;
642
			} else if (c == '\0') {
643
				yyerror("syntax error");
644
				return (findeol());
645
			}
646
			if (p + 1 >= buf + sizeof(buf) - 1) {
647
				yyerror("string too long");
648
				return (findeol());
649
			}
650
			*p++ = c;
651
		}
652
		yylval.v.string = strdup(buf);
653
		if (yylval.v.string == NULL)
654
			fatal("yylex: strdup");
655
		return (STRING);
656
	}
657
658
#define allowed_to_end_number(x) \
659
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
660
661
	if (c == '-' || isdigit(c)) {
662
		do {
663
			*p++ = c;
664
			if ((unsigned)(p-buf) >= sizeof(buf)) {
665
				yyerror("string too long");
666
				return (findeol());
667
			}
668
		} while ((c = lgetc(0)) != EOF && isdigit(c));
669
		lungetc(c);
670
		if (p == buf + 1 && buf[0] == '-')
671
			goto nodigits;
672
		if (c == EOF || allowed_to_end_number(c)) {
673
			const char *errstr = NULL;
674
675
			*p = '\0';
676
			yylval.v.number = strtonum(buf, LLONG_MIN,
677
			    LLONG_MAX, &errstr);
678
			if (errstr) {
679
				yyerror("\"%s\" invalid number: %s",
680
				    buf, errstr);
681
				return (findeol());
682
			}
683
			return (NUMBER);
684
		} else {
685
nodigits:
686
			while (p > buf + 1)
687
				lungetc(*--p);
688
			c = *--p;
689
			if (c == '-')
690
				return (c);
691
		}
692
	}
693
694
#define allowed_in_string(x) \
695
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
696
	x != '{' && x != '}' && \
697
	x != '!' && x != '=' && x != '#' && \
698
	x != ','))
699
700
	if (isalnum(c) || c == ':' || c == '_' || c == '/') {
701
		do {
702
			*p++ = c;
703
			if ((unsigned)(p-buf) >= sizeof(buf)) {
704
				yyerror("string too long");
705
				return (findeol());
706
			}
707
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
708
		lungetc(c);
709
		*p = '\0';
710
		if ((token = lookup(buf)) == STRING)
711
			if ((yylval.v.string = strdup(buf)) == NULL)
712
				fatal("yylex: strdup");
713
		return (token);
714
	}
715
	if (c == '\n') {
716
		yylval.lineno = file->lineno;
717
		file->lineno++;
718
	}
719
	if (c == EOF)
720
		return (0);
721
	return (c);
722
}
723
724
struct file *
725
pushfile(const char *name, int secret)
726
{
727
	struct file	*nfile;
728
729
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
730
		log_warn("malloc");
731
		return (NULL);
732
	}
733
	if ((nfile->name = strdup(name)) == NULL) {
734
		log_warn("malloc");
735
		free(nfile);
736
		return (NULL);
737
	}
738
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
739
		free(nfile->name);
740
		free(nfile);
741
		return (NULL);
742
	}
743
	nfile->lineno = 1;
744
	TAILQ_INSERT_TAIL(&files, nfile, entry);
745
	return (nfile);
746
}
747
748
int
749
popfile(void)
750
{
751
	struct file	*prev;
752
753
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
754
		prev->errors += file->errors;
755
756
	TAILQ_REMOVE(&files, file, entry);
757
	fclose(file->stream);
758
	free(file->name);
759
	free(file);
760
	file = prev;
761
	return (file ? 0 : EOF);
762
}
763
764
int
765
parse_config(const char *filename)
766
{
767
	struct sym	*sym, *next;
768
769
	if ((file = pushfile(filename, 0)) == NULL) {
770
		log_warn("failed to open %s", filename);
771
		if (errno == ENOENT)
772
			return (0);
773
		return (-1);
774
	}
775
	topfile = file;
776
	setservent(1);
777
778
	/* Set the default switch type */
779
	(void)strlcpy(vsw_type, VMD_SWITCH_TYPE, sizeof(vsw_type));
780
781
	yyparse();
782
	errors = file->errors;
783
	popfile();
784
785
	endservent();
786
787
	/* Free macros and check which have not been used. */
788
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
789
		if (!sym->used)
790
			fprintf(stderr, "warning: macro '%s' not "
791
			    "used\n", sym->nam);
792
		if (!sym->persist) {
793
			free(sym->nam);
794
			free(sym->val);
795
			TAILQ_REMOVE(&symhead, sym, entry);
796
			free(sym);
797
		}
798
	}
799
800
	if (errors)
801
		return (-1);
802
803
	return (0);
804
}
805
806
int
807
symset(const char *nam, const char *val, int persist)
808
{
809
	struct sym	*sym;
810
811
	TAILQ_FOREACH(sym, &symhead, entry) {
812
		if (strcmp(nam, sym->nam) == 0)
813
			break;
814
	}
815
816
	if (sym != NULL) {
817
		if (sym->persist == 1)
818
			return (0);
819
		else {
820
			free(sym->nam);
821
			free(sym->val);
822
			TAILQ_REMOVE(&symhead, sym, entry);
823
			free(sym);
824
		}
825
	}
826
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
827
		return (-1);
828
829
	sym->nam = strdup(nam);
830
	if (sym->nam == NULL) {
831
		free(sym);
832
		return (-1);
833
	}
834
	sym->val = strdup(val);
835
	if (sym->val == NULL) {
836
		free(sym->nam);
837
		free(sym);
838
		return (-1);
839
	}
840
	sym->used = 0;
841
	sym->persist = persist;
842
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
843
	return (0);
844
}
845
846
int
847
cmdline_symset(char *s)
848
{
849
	char	*sym, *val;
850
	int	ret;
851
	size_t	len;
852
853
	if ((val = strrchr(s, '=')) == NULL)
854
		return (-1);
855
856
	len = (val - s) + 1;
857
	if ((sym = malloc(len)) == NULL)
858
		fatal("cmdline_symset: malloc");
859
860
	(void)strlcpy(sym, s, len);
861
862
	ret = symset(sym, val + 1, 1);
863
	free(sym);
864
865
	return (ret);
866
}
867
868
char *
869
symget(const char *nam)
870
{
871
	struct sym	*sym;
872
873
	TAILQ_FOREACH(sym, &symhead, entry) {
874
		if (strcmp(nam, sym->nam) == 0) {
875
			sym->used = 1;
876
			return (sym->val);
877
		}
878
	}
879
	return (NULL);
880
}
881
882
ssize_t
883
parse_size(char *word, int64_t val)
884
{
885
	ssize_t		 size;
886
	long long	 res;
887
888
	if (word != NULL) {
889
		if (scan_scaled(word, &res) != 0) {
890
			log_warn("invalid size: %s", word);
891
			return (-1);
892
		}
893
		val = (int64_t)res;
894
	}
895
896
	if (val < (1024 * 1024)) {
897
		log_warnx("size must be at least one megabyte");
898
		return (-1);
899
	} else
900
		size = val / 1024 / 1024;
901
902
	if ((size * 1024 * 1024) != val)
903
		log_warnx("size rounded to %zd megabytes", size);
904
905
	return ((ssize_t)size);
906
}
907
908
int
909
parse_disk(char *word)
910
{
911
	if (vcp->vcp_ndisks >= VMM_MAX_DISKS_PER_VM) {
912
		log_warnx("too many disks");
913
		return (-1);
914
	}
915
916
	if (strlcpy(vcp->vcp_disks[vcp->vcp_ndisks], word,
917
	    VMM_MAX_PATH_DISK) >= VMM_MAX_PATH_DISK) {
918
		log_warnx("disk path too long");
919
		return (-1);
920
	}
921
922
	vcp->vcp_ndisks++;
923
924
	return (0);
925
}
926
927
int
928
host(const char *str, struct address *h)
929
{
930
	struct addrinfo		 hints, *res;
931
	int			 prefixlen;
932
	char			*s, *p;
933
	const char		*errstr;
934
935
	if ((s = strdup(str)) == NULL) {
936
		log_warn("strdup");
937
		goto fail;
938
	}
939
940
	if ((p = strrchr(s, '/')) != NULL) {
941
		*p++ = '\0';
942
		prefixlen = strtonum(p, 0, 128, &errstr);
943
		if (errstr) {
944
			log_warnx("prefixlen is %s: %s", errstr, p);
945
			goto fail;
946
		}
947
	} else
948
		prefixlen = 128;
949
950
	memset(&hints, 0, sizeof(hints));
951
	hints.ai_family = AF_UNSPEC;
952
	hints.ai_flags = AI_NUMERICHOST;
953
	if (getaddrinfo(s, NULL, &hints, &res) == 0) {
954
		memset(h, 0, sizeof(*h));
955
		memcpy(&h->ss, res->ai_addr, res->ai_addrlen);
956
		h->prefixlen = prefixlen;
957
		freeaddrinfo(res);
958
		free(s);
959
		return (0);
960
	}
961
962
 fail:
963
	free(s);
964
	return (-1);
965
}
966
#line 959 "parse.c"
967
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
968
static int yygrowstack(void)
969
{
970
    unsigned int newsize;
971
    long sslen;
972
    short *newss;
973
    YYSTYPE *newvs;
974
975
    if ((newsize = yystacksize) == 0)
976
        newsize = YYINITSTACKSIZE;
977
    else if (newsize >= YYMAXDEPTH)
978
        return -1;
979
    else if ((newsize *= 2) > YYMAXDEPTH)
980
        newsize = YYMAXDEPTH;
981
    sslen = yyssp - yyss;
982
#ifdef SIZE_MAX
983
#define YY_SIZE_MAX SIZE_MAX
984
#else
985
#define YY_SIZE_MAX 0xffffffffU
986
#endif
987
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
988
        goto bail;
989
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
990
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
991
    if (newss == NULL)
992
        goto bail;
993
    yyss = newss;
994
    yyssp = newss + sslen;
995
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
996
        goto bail;
997
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
998
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
999
    if (newvs == NULL)
1000
        goto bail;
1001
    yyvs = newvs;
1002
    yyvsp = newvs + sslen;
1003
    yystacksize = newsize;
1004
    yysslim = yyss + newsize - 1;
1005
    return 0;
1006
bail:
1007
    if (yyss)
1008
            free(yyss);
1009
    if (yyvs)
1010
            free(yyvs);
1011
    yyss = yyssp = NULL;
1012
    yyvs = yyvsp = NULL;
1013
    yystacksize = 0;
1014
    return -1;
1015
}
1016
1017
#define YYABORT goto yyabort
1018
#define YYREJECT goto yyabort
1019
#define YYACCEPT goto yyaccept
1020
#define YYERROR goto yyerrlab
1021
int
1022
yyparse(void)
1023
{
1024
    int yym, yyn, yystate;
1025
#if YYDEBUG
1026
    const char *yys;
1027
1028
    if ((yys = getenv("YYDEBUG")))
1029
    {
1030
        yyn = *yys;
1031
        if (yyn >= '0' && yyn <= '9')
1032
            yydebug = yyn - '0';
1033
    }
1034
#endif /* YYDEBUG */
1035
1036
    yynerrs = 0;
1037
    yyerrflag = 0;
1038
    yychar = (-1);
1039
1040
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
1041
    yyssp = yyss;
1042
    yyvsp = yyvs;
1043
    *yyssp = yystate = 0;
1044
1045
yyloop:
1046
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1047
    if (yychar < 0)
1048
    {
1049
        if ((yychar = yylex()) < 0) yychar = 0;
1050
#if YYDEBUG
1051
        if (yydebug)
1052
        {
1053
            yys = 0;
1054
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1055
            if (!yys) yys = "illegal-symbol";
1056
            printf("%sdebug: state %d, reading %d (%s)\n",
1057
                    YYPREFIX, yystate, yychar, yys);
1058
        }
1059
#endif
1060
    }
1061
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1062
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1063
    {
1064
#if YYDEBUG
1065
        if (yydebug)
1066
            printf("%sdebug: state %d, shifting to state %d\n",
1067
                    YYPREFIX, yystate, yytable[yyn]);
1068
#endif
1069
        if (yyssp >= yysslim && yygrowstack())
1070
        {
1071
            goto yyoverflow;
1072
        }
1073
        *++yyssp = yystate = yytable[yyn];
1074
        *++yyvsp = yylval;
1075
        yychar = (-1);
1076
        if (yyerrflag > 0)  --yyerrflag;
1077
        goto yyloop;
1078
    }
1079
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1080
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1081
    {
1082
        yyn = yytable[yyn];
1083
        goto yyreduce;
1084
    }
1085
    if (yyerrflag) goto yyinrecovery;
1086
#if defined(__GNUC__)
1087
    goto yynewerror;
1088
#endif
1089
yynewerror:
1090
    yyerror("syntax error");
1091
#if defined(__GNUC__)
1092
    goto yyerrlab;
1093
#endif
1094
yyerrlab:
1095
    ++yynerrs;
1096
yyinrecovery:
1097
    if (yyerrflag < 3)
1098
    {
1099
        yyerrflag = 3;
1100
        for (;;)
1101
        {
1102
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1103
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1104
            {
1105
#if YYDEBUG
1106
                if (yydebug)
1107
                    printf("%sdebug: state %d, error recovery shifting\
1108
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1109
#endif
1110
                if (yyssp >= yysslim && yygrowstack())
1111
                {
1112
                    goto yyoverflow;
1113
                }
1114
                *++yyssp = yystate = yytable[yyn];
1115
                *++yyvsp = yylval;
1116
                goto yyloop;
1117
            }
1118
            else
1119
            {
1120
#if YYDEBUG
1121
                if (yydebug)
1122
                    printf("%sdebug: error recovery discarding state %d\n",
1123
                            YYPREFIX, *yyssp);
1124
#endif
1125
                if (yyssp <= yyss) goto yyabort;
1126
                --yyssp;
1127
                --yyvsp;
1128
            }
1129
        }
1130
    }
1131
    else
1132
    {
1133
        if (yychar == 0) goto yyabort;
1134
#if YYDEBUG
1135
        if (yydebug)
1136
        {
1137
            yys = 0;
1138
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1139
            if (!yys) yys = "illegal-symbol";
1140
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1141
                    YYPREFIX, yystate, yychar, yys);
1142
        }
1143
#endif
1144
        yychar = (-1);
1145
        goto yyloop;
1146
    }
1147
yyreduce:
1148
#if YYDEBUG
1149
    if (yydebug)
1150
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1151
                YYPREFIX, yystate, yyn, yyrule[yyn]);
1152
#endif
1153
    yym = yylen[yyn];
1154
    if (yym)
1155
        yyval = yyvsp[1-yym];
1156
    else
1157
        memset(&yyval, 0, sizeof yyval);
1158
    switch (yyn)
1159
    {
1160
case 8:
1161
#line 140 "parse.y"
1162
{ file->errors++; }
1163
break;
1164
case 9:
1165
#line 143 "parse.y"
1166
{
1167
			struct file	*nfile;
1168
1169
			if ((nfile = pushfile(yyvsp[0].v.string, 0)) == NULL) {
1170
				yyerror("failed to include file %s", yyvsp[0].v.string);
1171
				free(yyvsp[0].v.string);
1172
				YYERROR;
1173
			}
1174
			free(yyvsp[0].v.string);
1175
1176
			file = nfile;
1177
			lungetc('\n');
1178
		}
1179
break;
1180
case 10:
1181
#line 158 "parse.y"
1182
{
1183
			char *s = yyvsp[-2].v.string;
1184
			while (*s++) {
1185
				if (isspace((unsigned char)*s)) {
1186
					yyerror("macro name cannot contain "
1187
					    "whitespace");
1188
					YYERROR;
1189
				}
1190
			}
1191
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1192
				fatalx("cannot store variable");
1193
			free(yyvsp[-2].v.string);
1194
			free(yyvsp[0].v.string);
1195
		}
1196
break;
1197
case 11:
1198
#line 174 "parse.y"
1199
{
1200
			struct address	 h;
1201
1202
			/* The local prefix is IPv4-only */
1203
			if (host(yyvsp[0].v.string, &h) == -1 ||
1204
			    h.ss.ss_family != AF_INET ||
1205
			    h.prefixlen > 32 || h.prefixlen < 0) {
1206
				yyerror("invalid local prefix: %s", yyvsp[0].v.string);
1207
				free(yyvsp[0].v.string);
1208
				YYERROR;
1209
			}
1210
1211
			memcpy(&env->vmd_cfg.cfg_localprefix, &h, sizeof(h));
1212
		}
1213
break;
1214
case 12:
1215
#line 190 "parse.y"
1216
{
1217
			if ((vsw = calloc(1, sizeof(*vsw))) == NULL)
1218
				fatal("could not allocate switch");
1219
1220
			vsw->sw_id = env->vmd_nswitches + 1;
1221
			vsw->sw_name = yyvsp[0].v.string;
1222
			vsw->sw_flags = VMIFF_UP;
1223
			snprintf(vsw->sw_ifname, sizeof(vsw->sw_ifname),
1224
			    "%s%u", vsw_type, vsw_unit++);
1225
			TAILQ_INIT(&vsw->sw_ifs);
1226
1227
			vcp_disable = 0;
1228
		}
1229
break;
1230
case 13:
1231
#line 202 "parse.y"
1232
{
1233
			if (vcp_disable) {
1234
				log_debug("%s:%d: switch \"%s\""
1235
				    " skipped (disabled)",
1236
				    file->name, yylval.lineno, vsw->sw_name);
1237
			} else if (!env->vmd_noaction) {
1238
				TAILQ_INSERT_TAIL(env->vmd_switches, vsw, sw_entry);
1239
				env->vmd_nswitches++;
1240
				log_debug("%s:%d: switch \"%s\" registered",
1241
				    file->name, yylval.lineno, vsw->sw_name);
1242
			}
1243
		}
1244
break;
1245
case 16:
1246
#line 220 "parse.y"
1247
{
1248
			vcp_disable = yyvsp[0].v.number;
1249
		}
1250
break;
1251
case 17:
1252
#line 223 "parse.y"
1253
{
1254
			char		type[IF_NAMESIZE];
1255
1256
			if ((vif = calloc(1, sizeof(*vif))) == NULL)
1257
				fatal("could not allocate interface");
1258
1259
			if (priv_getiftype(yyvsp[0].v.string, type, NULL) == -1) {
1260
				yyerror("invalid interface: %s", yyvsp[0].v.string);
1261
				free(yyvsp[0].v.string);
1262
				YYERROR;
1263
			}
1264
			vif->vif_name = yyvsp[0].v.string;
1265
1266
			TAILQ_INSERT_TAIL(&vsw->sw_ifs, vif, vif_entry);
1267
		}
1268
break;
1269
case 18:
1270
#line 238 "parse.y"
1271
{
1272
			if (priv_validgroup(yyvsp[0].v.string) == -1) {
1273
				yyerror("invalid group name: %s", yyvsp[0].v.string);
1274
				free(yyvsp[0].v.string);
1275
				YYERROR;
1276
			}
1277
			vsw->sw_group = yyvsp[0].v.string;
1278
		}
1279
break;
1280
case 19:
1281
#line 246 "parse.y"
1282
{
1283
			if (priv_getiftype(yyvsp[0].v.string, vsw_type, &vsw_unit) == -1 ||
1284
			    priv_findname(vsw_type, vmd_descsw) == -1) {
1285
				yyerror("invalid switch interface: %s", yyvsp[0].v.string);
1286
				free(yyvsp[0].v.string);
1287
				YYERROR;
1288
			}
1289
			vsw_unit++;
1290
1291
			if (strlcpy(vsw->sw_ifname, yyvsp[0].v.string,
1292
			    sizeof(vsw->sw_ifname)) >= sizeof(vsw->sw_ifname)) {
1293
				yyerror("switch interface too long: %s", yyvsp[0].v.string);
1294
				free(yyvsp[0].v.string);
1295
				YYERROR;
1296
			}
1297
			free(yyvsp[0].v.string);
1298
		}
1299
break;
1300
case 20:
1301
#line 263 "parse.y"
1302
{
1303
			vsw->sw_flags |= VMIFF_LOCKED;
1304
		}
1305
break;
1306
case 21:
1307
#line 266 "parse.y"
1308
{
1309
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > RT_TABLEID_MAX) {
1310
				yyerror("invalid rdomain: %lld", yyvsp[0].v.number);
1311
				YYERROR;
1312
			}
1313
			vsw->sw_flags |= VMIFF_RDOMAIN;
1314
			vsw->sw_rdomain = yyvsp[0].v.number;
1315
		}
1316
break;
1317
case 22:
1318
#line 274 "parse.y"
1319
{
1320
			if (yyvsp[0].v.number)
1321
				vsw->sw_flags |= VMIFF_UP;
1322
			else
1323
				vsw->sw_flags &= ~VMIFF_UP;
1324
		}
1325
break;
1326
case 23:
1327
#line 282 "parse.y"
1328
{
1329
			unsigned int	 i;
1330
1331
			memset(&vmc, 0, sizeof(vmc));
1332
			vcp = &vmc.vmc_params;
1333
			vcp_disable = 0;
1334
			vcp_nnics = 0;
1335
1336
			for (i = 0; i < VMM_MAX_NICS_PER_VM; i++) {
1337
				/* Set the interface to UP by default */
1338
				vmc.vmc_ifflags[i] |= IFF_UP;
1339
			}
1340
1341
			if (strlcpy(vcp->vcp_name, yyvsp[0].v.string, sizeof(vcp->vcp_name)) >=
1342
			    sizeof(vcp->vcp_name)) {
1343
				yyerror("vm name too long");
1344
				YYERROR;
1345
			}
1346
1347
			/* set default user/group permissions */
1348
			vmc.vmc_uid = 0;
1349
			vmc.vmc_gid = -1;
1350
		}
1351
break;
1352
case 24:
1353
#line 304 "parse.y"
1354
{
1355
			int ret;
1356
1357
			/* configured interfaces vs. number of interfaces */
1358
			if (vcp_nnics > vcp->vcp_nnics)
1359
				vcp->vcp_nnics = vcp_nnics;
1360
1361
			if (!env->vmd_noaction) {
1362
				ret = vm_register(&env->vmd_ps, &vmc,
1363
				    &vm, 0, 0);
1364
				if (ret == -1 && errno == EALREADY) {
1365
					log_debug("%s:%d: vm \"%s\""
1366
					    " skipped (%s)",
1367
					    file->name, yylval.lineno,
1368
					    vcp->vcp_name, vm->vm_running ?
1369
					    "running" : "already exists");
1370
				} else if (ret == -1) {
1371
					log_warn("%s:%d: vm \"%s\" failed",
1372
					    file->name, yylval.lineno,
1373
					    vcp->vcp_name);
1374
					YYERROR;
1375
				} else {
1376
					if (vcp_disable)
1377
						vm->vm_disabled = 1;
1378
					log_debug("%s:%d: vm \"%s\" registered (%s)",
1379
					    file->name, yylval.lineno,
1380
					    vcp->vcp_name,
1381
					    vcp_disable ? "disabled" : "enabled");
1382
				}
1383
				vm->vm_from_config = 1;
1384
			}
1385
		}
1386
break;
1387
case 27:
1388
#line 342 "parse.y"
1389
{
1390
			vcp_disable = yyvsp[0].v.number;
1391
		}
1392
break;
1393
case 28:
1394
#line 345 "parse.y"
1395
{
1396
			if (parse_disk(yyvsp[0].v.string) != 0) {
1397
				yyerror("failed to parse disks: %s", yyvsp[0].v.string);
1398
				free(yyvsp[0].v.string);
1399
				YYERROR;
1400
			}
1401
			free(yyvsp[0].v.string);
1402
			vmc.vmc_flags |= VMOP_CREATE_DISK;
1403
		}
1404
break;
1405
case 29:
1406
#line 354 "parse.y"
1407
{
1408
			unsigned int	i;
1409
			char		type[IF_NAMESIZE];
1410
1411
			i = vcp_nnics;
1412
			if (++vcp_nnics > VMM_MAX_NICS_PER_VM) {
1413
				yyerror("too many interfaces: %zu", vcp_nnics);
1414
				free(yyvsp[-1].v.string);
1415
				YYERROR;
1416
			}
1417
1418
			if (yyvsp[-3].v.number)
1419
				vmc.vmc_ifflags[i] |= VMIFF_LOCAL;
1420
			if (yyvsp[-1].v.string != NULL) {
1421
				if (strcmp(yyvsp[-1].v.string, "tap") != 0 &&
1422
				    (priv_getiftype(yyvsp[-1].v.string, type, NULL) == -1 ||
1423
				    strcmp(type, "tap") != 0)) {
1424
					yyerror("invalid interface: %s", yyvsp[-1].v.string);
1425
					free(yyvsp[-1].v.string);
1426
					YYERROR;
1427
				}
1428
1429
				if (strlcpy(vmc.vmc_ifnames[i], yyvsp[-1].v.string,
1430
				    sizeof(vmc.vmc_ifnames[i])) >=
1431
				    sizeof(vmc.vmc_ifnames[i])) {
1432
					yyerror("interface name too long: %s",
1433
					    yyvsp[-1].v.string);
1434
					free(yyvsp[-1].v.string);
1435
					YYERROR;
1436
				}
1437
			}
1438
			free(yyvsp[-1].v.string);
1439
			vmc.vmc_flags |= VMOP_CREATE_NETWORK;
1440
		}
1441
break;
1442
case 30:
1443
#line 388 "parse.y"
1444
{
1445
			if (vcp->vcp_kernel[0] != '\0') {
1446
				yyerror("kernel specified more than once");
1447
				free(yyvsp[0].v.string);
1448
				YYERROR;
1449
1450
			}
1451
			if (strlcpy(vcp->vcp_kernel, yyvsp[0].v.string,
1452
			    sizeof(vcp->vcp_kernel)) >=
1453
			    sizeof(vcp->vcp_kernel)) {
1454
				yyerror("kernel name too long");
1455
				free(yyvsp[0].v.string);
1456
				YYERROR;
1457
			}
1458
			free(yyvsp[0].v.string);
1459
			vmc.vmc_flags |= VMOP_CREATE_KERNEL;
1460
		}
1461
break;
1462
case 31:
1463
#line 405 "parse.y"
1464
{
1465
			if (vcp->vcp_nnics != 0) {
1466
				yyerror("interfaces specified more than once");
1467
				YYERROR;
1468
			}
1469
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > VMM_MAX_NICS_PER_VM) {
1470
				yyerror("too many interfaces: %lld", yyvsp[0].v.number);
1471
				YYERROR;
1472
			}
1473
			vcp->vcp_nnics = (size_t)yyvsp[0].v.number;
1474
			vmc.vmc_flags |= VMOP_CREATE_NETWORK;
1475
		}
1476
break;
1477
case 32:
1478
#line 417 "parse.y"
1479
{
1480
			ssize_t	 res;
1481
			if (vcp->vcp_memranges[0].vmr_size != 0) {
1482
				yyerror("memory specified more than once");
1483
				YYERROR;
1484
			}
1485
			if ((res = parse_size(NULL, yyvsp[0].v.number)) == -1) {
1486
				yyerror("failed to parse size: %lld", yyvsp[0].v.number);
1487
				YYERROR;
1488
			}
1489
			vcp->vcp_memranges[0].vmr_size = (size_t)res;
1490
			vmc.vmc_flags |= VMOP_CREATE_MEMORY;
1491
		}
1492
break;
1493
case 33:
1494
#line 430 "parse.y"
1495
{
1496
			ssize_t	 res;
1497
			if (vcp->vcp_memranges[0].vmr_size != 0) {
1498
				yyerror("argument specified more than once");
1499
				free(yyvsp[0].v.string);
1500
				YYERROR;
1501
			}
1502
			if ((res = parse_size(yyvsp[0].v.string, 0)) == -1) {
1503
				yyerror("failed to parse size: %s", yyvsp[0].v.string);
1504
				free(yyvsp[0].v.string);
1505
				YYERROR;
1506
			}
1507
			vcp->vcp_memranges[0].vmr_size = (size_t)res;
1508
			vmc.vmc_flags |= VMOP_CREATE_MEMORY;
1509
		}
1510
break;
1511
case 34:
1512
#line 445 "parse.y"
1513
{
1514
			vmc.vmc_uid = yyvsp[0].v.owner.uid;
1515
			vmc.vmc_gid = yyvsp[0].v.owner.gid;
1516
		}
1517
break;
1518
case 35:
1519
#line 451 "parse.y"
1520
{
1521
			yyval.v.owner.uid = 0;
1522
			yyval.v.owner.gid = -1;
1523
		}
1524
break;
1525
case 36:
1526
#line 455 "parse.y"
1527
{
1528
			yyval.v.owner.uid = yyvsp[0].v.number;
1529
			yyval.v.owner.gid = -1;
1530
		}
1531
break;
1532
case 37:
1533
#line 459 "parse.y"
1534
{
1535
			char		*user, *group;
1536
			struct passwd	*pw;
1537
			struct group	*gr;
1538
1539
			yyval.v.owner.uid = 0;
1540
			yyval.v.owner.gid = -1;
1541
1542
			user = yyvsp[0].v.string;
1543
			if ((group = strchr(user, ':')) != NULL) {
1544
				if (group == user)
1545
					user = NULL;
1546
				*group++ = '\0';
1547
			}
1548
1549
			if (user != NULL && *user) {
1550
				if ((pw = getpwnam(user)) == NULL) {
1551
					yyerror("failed to get user: %s",
1552
					    user);
1553
					free(yyvsp[0].v.string);
1554
					YYERROR;
1555
				}
1556
				yyval.v.owner.uid = pw->pw_uid;
1557
			}
1558
1559
			if (group != NULL && *group) {
1560
				if ((gr = getgrnam(group)) == NULL) {
1561
					yyerror("failed to get group: %s",
1562
					    group);
1563
					free(yyvsp[0].v.string);
1564
					YYERROR;
1565
				}
1566
				yyval.v.owner.gid = gr->gr_gid;
1567
			}
1568
1569
			free(yyvsp[0].v.string);
1570
		}
1571
break;
1572
case 45:
1573
#line 511 "parse.y"
1574
{
1575
			unsigned int	i = vcp_nnics;
1576
1577
			/* No need to check if the switch exists */
1578
			if (strlcpy(vmc.vmc_ifswitch[i], yyvsp[0].v.string,
1579
			    sizeof(vmc.vmc_ifswitch[i])) >=
1580
			    sizeof(vmc.vmc_ifswitch[i])) {
1581
				yyerror("switch name too long: %s", yyvsp[0].v.string);
1582
				free(yyvsp[0].v.string);
1583
				YYERROR;
1584
			}
1585
			free(yyvsp[0].v.string);
1586
		}
1587
break;
1588
case 46:
1589
#line 524 "parse.y"
1590
{
1591
			unsigned int	i = vcp_nnics;
1592
1593
			if (priv_validgroup(yyvsp[0].v.string) == -1) {
1594
				yyerror("invalid group name: %s", yyvsp[0].v.string);
1595
				free(yyvsp[0].v.string);
1596
				YYERROR;
1597
			}
1598
1599
			/* No need to check if the group exists */
1600
			(void)strlcpy(vmc.vmc_ifgroup[i], yyvsp[0].v.string,
1601
			    sizeof(vmc.vmc_ifgroup[i]));
1602
			free(yyvsp[0].v.string);
1603
		}
1604
break;
1605
case 47:
1606
#line 538 "parse.y"
1607
{
1608
			if (yyvsp[-2].v.number)
1609
				vmc.vmc_ifflags[vcp_nnics] |= VMIFF_LOCKED;
1610
			memcpy(vcp->vcp_macs[vcp_nnics], yyvsp[0].v.lladdr, ETHER_ADDR_LEN);
1611
		}
1612
break;
1613
case 48:
1614
#line 543 "parse.y"
1615
{
1616
			if (yyvsp[0].v.number < 0 || yyvsp[0].v.number > RT_TABLEID_MAX) {
1617
				yyerror("invalid rdomain: %lld", yyvsp[0].v.number);
1618
				YYERROR;
1619
			}
1620
			vmc.vmc_ifflags[vcp_nnics] |= VMIFF_RDOMAIN;
1621
			vmc.vmc_ifrdomain[vcp_nnics] = yyvsp[0].v.number;
1622
		}
1623
break;
1624
case 49:
1625
#line 551 "parse.y"
1626
{
1627
			if (yyvsp[0].v.number)
1628
				vmc.vmc_ifflags[vcp_nnics] |= VMIFF_UP;
1629
			else
1630
				vmc.vmc_ifflags[vcp_nnics] &= ~VMIFF_UP;
1631
		}
1632
break;
1633
case 50:
1634
#line 559 "parse.y"
1635
{ yyval.v.string = yyvsp[0].v.string; }
1636
break;
1637
case 51:
1638
#line 560 "parse.y"
1639
{ yyval.v.string = NULL; }
1640
break;
1641
case 52:
1642
#line 563 "parse.y"
1643
{
1644
			if (asprintf(&yyval.v.string, "%s%s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1)
1645
				fatal("asprintf string");
1646
			free(yyvsp[-1].v.string);
1647
			free(yyvsp[0].v.string);
1648
		}
1649
break;
1650
case 54:
1651
#line 572 "parse.y"
1652
{
1653
			struct ether_addr *ea;
1654
1655
			if ((ea = ether_aton(yyvsp[0].v.string)) == NULL) {
1656
				yyerror("invalid address: %s\n", yyvsp[0].v.string);
1657
				free(yyvsp[0].v.string);
1658
				YYERROR;
1659
			}
1660
			free(yyvsp[0].v.string);
1661
1662
			memcpy(yyval.v.lladdr, ea, ETHER_ADDR_LEN);
1663
		}
1664
break;
1665
case 55:
1666
#line 586 "parse.y"
1667
{ yyval.v.number = 0; }
1668
break;
1669
case 56:
1670
#line 587 "parse.y"
1671
{ yyval.v.number = 1; }
1672
break;
1673
case 57:
1674
#line 590 "parse.y"
1675
{ yyval.v.number = 0; }
1676
break;
1677
case 58:
1678
#line 591 "parse.y"
1679
{ yyval.v.number = 1; }
1680
break;
1681
case 59:
1682
#line 594 "parse.y"
1683
{ yyval.v.number = 1; }
1684
break;
1685
case 60:
1686
#line 595 "parse.y"
1687
{ yyval.v.number = 0; }
1688
break;
1689
case 61:
1690
#line 598 "parse.y"
1691
{ yyval.v.number = 0; }
1692
break;
1693
case 62:
1694
#line 599 "parse.y"
1695
{ yyval.v.number = 1; }
1696
break;
1697
#line 1690 "parse.c"
1698
    }
1699
    yyssp -= yym;
1700
    yystate = *yyssp;
1701
    yyvsp -= yym;
1702
    yym = yylhs[yyn];
1703
    if (yystate == 0 && yym == 0)
1704
    {
1705
#if YYDEBUG
1706
        if (yydebug)
1707
            printf("%sdebug: after reduction, shifting from state 0 to\
1708
 state %d\n", YYPREFIX, YYFINAL);
1709
#endif
1710
        yystate = YYFINAL;
1711
        *++yyssp = YYFINAL;
1712
        *++yyvsp = yyval;
1713
        if (yychar < 0)
1714
        {
1715
            if ((yychar = yylex()) < 0) yychar = 0;
1716
#if YYDEBUG
1717
            if (yydebug)
1718
            {
1719
                yys = 0;
1720
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1721
                if (!yys) yys = "illegal-symbol";
1722
                printf("%sdebug: state %d, reading %d (%s)\n",
1723
                        YYPREFIX, YYFINAL, yychar, yys);
1724
            }
1725
#endif
1726
        }
1727
        if (yychar == 0) goto yyaccept;
1728
        goto yyloop;
1729
    }
1730
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1731
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1732
        yystate = yytable[yyn];
1733
    else
1734
        yystate = yydgoto[yym];
1735
#if YYDEBUG
1736
    if (yydebug)
1737
        printf("%sdebug: after reduction, shifting from state %d \
1738
to state %d\n", YYPREFIX, *yyssp, yystate);
1739
#endif
1740
    if (yyssp >= yysslim && yygrowstack())
1741
    {
1742
        goto yyoverflow;
1743
    }
1744
    *++yyssp = yystate;
1745
    *++yyvsp = yyval;
1746
    goto yyloop;
1747
yyoverflow:
1748
    yyerror("yacc stack overflow");
1749
yyabort:
1750
    if (yyss)
1751
            free(yyss);
1752
    if (yyvs)
1753
            free(yyvs);
1754
    yyss = yyssp = NULL;
1755
    yyvs = yyvsp = NULL;
1756
    yystacksize = 0;
1757
    return (1);
1758
yyaccept:
1759
    if (yyss)
1760
            free(yyss);
1761
    if (yyvs)
1762
            free(yyvs);
1763
    yyss = yyssp = NULL;
1764
    yyvs = yyvsp = NULL;
1765
    yystacksize = 0;
1766
    return (0);
1767
}