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