xref: /openbsd-src/usr.sbin/vmctl/main.c (revision d1df930ffab53da22f3324c32bed7ac5709915e6)
1 /*	$OpenBSD: main.c,v 1.44 2018/10/01 09:31:15 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/queue.h>
22 #include <sys/un.h>
23 
24 #include <machine/vmmvar.h>
25 
26 #include <err.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <limits.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <util.h>
36 #include <imsg.h>
37 
38 #include "vmd.h"
39 #include "proc.h"
40 #include "vmctl.h"
41 
42 #define RAW_FMT		"raw"
43 #define QCOW2_FMT	"qcow2"
44 
45 static const char	*socket_name = SOCKET_NAME;
46 static int		 ctl_sock = -1;
47 static int		 tty_autoconnect = 0;
48 
49 __dead void	 usage(void);
50 __dead void	 ctl_usage(struct ctl_command *);
51 
52 int		 vmm_action(struct parse_result *);
53 
54 int		 ctl_console(struct parse_result *, int, char *[]);
55 int		 ctl_create(struct parse_result *, int, char *[]);
56 int		 ctl_load(struct parse_result *, int, char *[]);
57 int		 ctl_log(struct parse_result *, int, char *[]);
58 int		 ctl_reload(struct parse_result *, int, char *[]);
59 int		 ctl_reset(struct parse_result *, int, char *[]);
60 int		 ctl_start(struct parse_result *, int, char *[]);
61 int		 ctl_status(struct parse_result *, int, char *[]);
62 int		 ctl_stop(struct parse_result *, int, char *[]);
63 int		 ctl_pause(struct parse_result *, int, char *[]);
64 int		 ctl_unpause(struct parse_result *, int, char *[]);
65 int		 ctl_send(struct parse_result *, int, char *[]);
66 int		 ctl_receive(struct parse_result *, int, char *[]);
67 
68 struct ctl_command ctl_commands[] = {
69 	{ "console",	CMD_CONSOLE,	ctl_console,	"id" },
70 	{ "create",	CMD_CREATE,	ctl_create,	"\"path\" -s size", 1 },
71 	{ "load",	CMD_LOAD,	ctl_load,	"\"path\"" },
72 	{ "log",	CMD_LOG,	ctl_log,	"[verbose|brief]" },
73 	{ "reload",	CMD_RELOAD,	ctl_reload,	"" },
74 	{ "reset",	CMD_RESET,	ctl_reset,	"[all|vms|switches]" },
75 	{ "show",	CMD_STATUS,	ctl_status,	"[id]" },
76 	{ "start",	CMD_START,	ctl_start,	"\"name\""
77 	    " [-Lc] [-b image] [-r image] [-m size]\n"
78 	    "\t\t[-n switch] [-i count] [-d disk]* [-t name]" },
79 	{ "status",	CMD_STATUS,	ctl_status,	"[id]" },
80 	{ "stop",	CMD_STOP,	ctl_stop,	"[id|-a] [-fw]" },
81 	{ "pause",	CMD_PAUSE,	ctl_pause,	"id" },
82 	{ "unpause",	CMD_UNPAUSE,	ctl_unpause,	"id" },
83 	{ "send",	CMD_SEND,	ctl_send,	"id",	1},
84 	{ "receive",	CMD_RECEIVE,	ctl_receive,	"id" ,	1},
85 	{ NULL }
86 };
87 
88 __dead void
89 usage(void)
90 {
91 	extern char	*__progname;
92 	int		 i;
93 
94 	fprintf(stderr, "usage:\t%s command [arg ...]\n",
95 	    __progname);
96 	for (i = 0; ctl_commands[i].name != NULL; i++) {
97 		fprintf(stderr, "\t%s %s %s\n", __progname,
98 		    ctl_commands[i].name, ctl_commands[i].usage);
99 	}
100 	exit(1);
101 }
102 
103 __dead void
104 ctl_usage(struct ctl_command *ctl)
105 {
106 	extern char	*__progname;
107 
108 	fprintf(stderr, "usage:\t%s %s %s\n", __progname,
109 	    ctl->name, ctl->usage);
110 	exit(1);
111 }
112 
113 int
114 main(int argc, char *argv[])
115 {
116 	int	 ch;
117 
118 	while ((ch = getopt(argc, argv, "")) != -1) {
119 		switch (ch) {
120 		default:
121 			usage();
122 			/* NOTREACHED */
123 		}
124 	}
125 	argc -= optind;
126 	argv += optind;
127 	optreset = 1;
128 
129 	if (argc < 1)
130 		usage();
131 
132 	return (parse(argc, argv));
133 }
134 
135 int
136 parse(int argc, char *argv[])
137 {
138 	struct ctl_command	*ctl = NULL;
139 	struct parse_result	 res;
140 	int			 i;
141 
142 	memset(&res, 0, sizeof(res));
143 	res.nifs = -1;
144 
145 	for (i = 0; ctl_commands[i].name != NULL; i++) {
146 		if (strncmp(ctl_commands[i].name,
147 		    argv[0], strlen(argv[0])) == 0) {
148 			if (ctl != NULL) {
149 				fprintf(stderr,
150 				    "ambiguous argument: %s\n", argv[0]);
151 				usage();
152 			}
153 			ctl = &ctl_commands[i];
154 		}
155 	}
156 
157 	if (ctl == NULL) {
158 		fprintf(stderr, "unknown argument: %s\n", argv[0]);
159 		usage();
160 	}
161 
162 	res.action = ctl->action;
163 	res.ctl = ctl;
164 
165 	if (!ctl->has_pledge) {
166 		/* pledge(2) default if command doesn't have its own pledge */
167 		if (pledge("stdio rpath exec unix getpw unveil", NULL) == -1)
168 			err(1, "pledge");
169 	}
170 	if (ctl->main(&res, argc, argv) != 0)
171 		err(1, "failed");
172 
173 	if (ctl_sock != -1) {
174 		close(ibuf->fd);
175 		free(ibuf);
176 	}
177 
178 	return (0);
179 }
180 
181 int
182 vmmaction(struct parse_result *res)
183 {
184 	struct sockaddr_un	 sun;
185 	struct imsg		 imsg;
186 	int			 done = 0;
187 	int			 n;
188 	int			 ret, action;
189 	unsigned int		 flags;
190 
191 	if (ctl_sock == -1) {
192 		if (unveil(SOCKET_NAME, "r") == -1)
193 			err(1, "unveil");
194 		if ((ctl_sock = socket(AF_UNIX,
195 		    SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1)
196 			err(1, "socket");
197 
198 		memset(&sun, 0, sizeof(sun));
199 		sun.sun_family = AF_UNIX;
200 		strlcpy(sun.sun_path, socket_name, sizeof(sun.sun_path));
201 
202 		if (connect(ctl_sock,
203 		    (struct sockaddr *)&sun, sizeof(sun)) == -1)
204 			err(1, "connect: %s", socket_name);
205 
206 		if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
207 			err(1, "malloc");
208 		imsg_init(ibuf, ctl_sock);
209 	}
210 
211 	switch (res->action) {
212 	case CMD_START:
213 		ret = vm_start(res->id, res->name, res->size, res->nifs,
214 		    res->nets, res->ndisks, res->disks, res->disktypes,
215 		    res->path, res->isopath, res->instance);
216 		if (ret) {
217 			errno = ret;
218 			err(1, "start VM operation failed");
219 		}
220 		break;
221 	case CMD_STOP:
222 		terminate_vm(res->id, res->name, res->flags);
223 		break;
224 	case CMD_STATUS:
225 	case CMD_CONSOLE:
226 	case CMD_STOPALL:
227 		get_info_vm(res->id, res->name, res->action, res->flags);
228 		break;
229 	case CMD_LOAD:
230 		imsg_compose(ibuf, IMSG_VMDOP_LOAD, 0, 0, -1,
231 		    res->path, strlen(res->path) + 1);
232 		break;
233 	case CMD_LOG:
234 		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1,
235 		    &res->verbose, sizeof(res->verbose));
236 		break;
237 	case CMD_RELOAD:
238 		imsg_compose(ibuf, IMSG_VMDOP_RELOAD, 0, 0, -1, NULL, 0);
239 		break;
240 	case CMD_RESET:
241 		imsg_compose(ibuf, IMSG_CTL_RESET, 0, 0, -1,
242 		    &res->mode, sizeof(res->mode));
243 		break;
244 	case CMD_PAUSE:
245 		pause_vm(res->id, res->name);
246 		break;
247 	case CMD_UNPAUSE:
248 		unpause_vm(res->id, res->name);
249 		break;
250 	case CMD_SEND:
251 		send_vm(res->id, res->name);
252 		done = 1;
253 		break;
254 	case CMD_RECEIVE:
255 		vm_receive(res->id, res->name);
256 		break;
257 	case CMD_CREATE:
258 	case NONE:
259 		break;
260 	}
261 
262 	action = res->action;
263 	flags = res->flags;
264 	parse_free(res);
265 
266 	while (ibuf->w.queued)
267 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
268 			err(1, "write error");
269 
270 	while (!done) {
271 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
272 			errx(1, "imsg_read error");
273 		if (n == 0)
274 			errx(1, "pipe closed");
275 
276 		while (!done) {
277 			if ((n = imsg_get(ibuf, &imsg)) == -1)
278 				errx(1, "imsg_get error");
279 			if (n == 0)
280 				break;
281 
282 			if (imsg.hdr.type == IMSG_CTL_FAIL) {
283 				if (IMSG_DATA_SIZE(&imsg) == sizeof(ret))
284 					memcpy(&ret, imsg.data, sizeof(ret));
285 				else
286 					ret = 0;
287 				if (ret != 0) {
288 					memcpy(&ret, imsg.data, sizeof(ret));
289 					errno = ret;
290 					err(1, "command failed");
291 				} else
292 					errx(1, "command failed");
293 			}
294 
295 			ret = 0;
296 			switch (action) {
297 			case CMD_START:
298 				done = vm_start_complete(&imsg, &ret,
299 				    tty_autoconnect);
300 				break;
301 			case CMD_STOP:
302 				done = terminate_vm_complete(&imsg, &ret,
303 				    flags);
304 				break;
305 			case CMD_CONSOLE:
306 			case CMD_STATUS:
307 			case CMD_STOPALL:
308 				done = add_info(&imsg, &ret);
309 				break;
310 			case CMD_PAUSE:
311 				done = pause_vm_complete(&imsg, &ret);
312 				break;
313 			case CMD_RECEIVE:
314 				done = vm_start_complete(&imsg, &ret, 0);
315 				break;
316 			case CMD_UNPAUSE:
317 				done = unpause_vm_complete(&imsg, &ret);
318 				break;
319 			default:
320 				done = 1;
321 				break;
322 			}
323 
324 			imsg_free(&imsg);
325 		}
326 	}
327 
328 	return (0);
329 }
330 
331 void
332 parse_free(struct parse_result *res)
333 {
334 	size_t	 i;
335 
336 	free(res->name);
337 	free(res->path);
338 	free(res->isopath);
339 	free(res->instance);
340 	for (i = 0; i < res->ndisks; i++)
341 		free(res->disks[i]);
342 	free(res->disks);
343 	free(res->disktypes);
344 	memset(res, 0, sizeof(*res));
345 }
346 
347 int
348 parse_ifs(struct parse_result *res, char *word, int val)
349 {
350 	const char	*error;
351 
352 	if (word != NULL) {
353 		val = strtonum(word, 0, INT_MAX, &error);
354 		if (error != NULL)  {
355 			warnx("invalid count \"%s\": %s", word, error);
356 			return (-1);
357 		}
358 	}
359 	res->nifs = val;
360 
361 	return (0);
362 }
363 
364 int
365 parse_network(struct parse_result *res, char *word)
366 {
367 	char		**nets;
368 	char		*s;
369 
370 	if ((nets = reallocarray(res->nets, res->nnets + 1,
371 	    sizeof(char *))) == NULL) {
372 		warn("reallocarray");
373 		return (-1);
374 	}
375 	if ((s = strdup(word)) == NULL) {
376 		warn("strdup");
377 		return (-1);
378 	}
379 	nets[res->nnets] = s;
380 	res->nets = nets;
381 	res->nnets++;
382 
383 	return (0);
384 }
385 
386 int
387 parse_size(struct parse_result *res, char *word, long long val)
388 {
389 	if (word != NULL) {
390 		if (scan_scaled(word, &val) != 0) {
391 			warn("invalid size: %s", word);
392 			return (-1);
393 		}
394 	}
395 
396 	if (val < (1024 * 1024)) {
397 		warnx("size must be at least one megabyte");
398 		return (-1);
399 	} else
400 		res->size = val / 1024 / 1024;
401 
402 	if ((res->size * 1024 * 1024) != val)
403 		warnx("size rounded to %lld megabytes", res->size);
404 
405 	return (0);
406 }
407 
408 int
409 parse_disktype(const char *s, const char **ret)
410 {
411 	char		 buf[BUFSIZ];
412 	const char	*ext;
413 	int		 fd;
414 	ssize_t		 len;
415 
416 	*ret = s;
417 
418 	/* Try to parse the explicit format (qcow2:disk.qc2) */
419 	if (strstr(s, RAW_FMT) == s && *(s + strlen(RAW_FMT)) == ':') {
420 		*ret = s + strlen(RAW_FMT) + 1;
421 		return (VMDF_RAW);
422 	}
423 	if (strstr(s, QCOW2_FMT) == s && *(s + strlen(QCOW2_FMT)) == ':') {
424 		*ret = s + strlen(QCOW2_FMT) + 1;
425 		return (VMDF_QCOW2);
426 	}
427 
428 	/* Or try to derive the format from the file signature */
429 	if ((fd = open(s, O_RDONLY)) != -1) {
430 		len = read(fd, buf, sizeof(buf));
431 		close(fd);
432 
433 		if (len >= (ssize_t)strlen(VM_MAGIC_QCOW) &&
434 		    strncmp(buf, VM_MAGIC_QCOW,
435 		    strlen(VM_MAGIC_QCOW)) == 0) {
436 			/* Return qcow2, the version will be checked later */
437 			return (VMDF_QCOW2);
438 		}
439 	}
440 
441 	/*
442 	 * Use the extension as a last option.  This is needed for
443 	 * 'vmctl create' as the file, and the signature, doesn't
444 	 * exist yet.
445 	 */
446 	if ((ext = strrchr(s, '.')) != NULL && *(++ext) != '\0') {
447 		if (strcasecmp(ext, RAW_FMT) == 0)
448 			return (VMDF_RAW);
449 		else if (strcasecmp(ext, QCOW2_FMT) == 0)
450 			return (VMDF_QCOW2);
451 	}
452 
453 	/* Fallback to raw */
454 	return (VMDF_RAW);
455 }
456 
457 int
458 parse_disk(struct parse_result *res, char *word, int type)
459 {
460 	char		**disks;
461 	int		*disktypes;
462 	char		*s;
463 
464 	if ((disks = reallocarray(res->disks, res->ndisks + 1,
465 	    sizeof(char *))) == NULL) {
466 		warn("reallocarray");
467 		return (-1);
468 	}
469 	if ((disktypes = reallocarray(res->disktypes, res->ndisks + 1,
470 	    sizeof(int))) == NULL) {
471 		warn("reallocarray");
472 		return -1;
473 	}
474 	if ((s = strdup(word)) == NULL) {
475 		warn("strdup");
476 		return (-1);
477 	}
478 	disks[res->ndisks] = s;
479 	disktypes[res->ndisks] = type;
480 	res->disks = disks;
481 	res->disktypes = disktypes;
482 	res->ndisks++;
483 
484 	return (0);
485 }
486 
487 int
488 parse_vmid(struct parse_result *res, char *word, int needname)
489 {
490 	const char	*error;
491 	uint32_t	 id;
492 
493 	if (word == NULL) {
494 		warnx("missing vmid argument");
495 		return (-1);
496 	}
497 	if (*word == '-') {
498 		/* don't print a warning to allow command line options */
499 		return (-1);
500 	}
501 	id = strtonum(word, 0, UINT32_MAX, &error);
502 	if (error == NULL) {
503 		if (needname) {
504 			warnx("invalid vm name");
505 			return (-1);
506 		} else {
507 			res->id = id;
508 			res->name = NULL;
509 		}
510 	} else {
511 		if (strlen(word) >= VMM_MAX_NAME_LEN) {
512 			warnx("name too long");
513 			return (-1);
514 		}
515 		res->id = 0;
516 		if ((res->name = strdup(word)) == NULL)
517 			errx(1, "strdup");
518 	}
519 
520 	return (0);
521 }
522 
523 int
524 parse_instance(struct parse_result *res, char *word)
525 {
526 	if (strlen(word) >= VMM_MAX_NAME_LEN) {
527 		warnx("instance vm name too long");
528 		return (-1);
529 	}
530 	res->id = 0;
531 	if ((res->instance = strdup(word)) == NULL)
532 		errx(1, "strdup");
533 
534 	return (0);
535 }
536 
537 int
538 ctl_create(struct parse_result *res, int argc, char *argv[])
539 {
540 	int		 ch, ret, type;
541 	const char	*paths[2], *disk, *format;
542 
543 	if (argc < 2)
544 		ctl_usage(res->ctl);
545 
546 	type = parse_disktype(argv[1], &disk);
547 
548 	paths[0] = disk;
549 	paths[1] = NULL;
550 
551 	if (unveil(paths[0], "rwc") == -1)
552 		err(1, "unveil");
553 
554 	if (pledge("stdio rpath wpath cpath", NULL) == -1)
555 		err(1, "pledge");
556 	argc--;
557 	argv++;
558 
559 	while ((ch = getopt(argc, argv, "s:")) != -1) {
560 		switch (ch) {
561 		case 's':
562 			if (parse_size(res, optarg, 0) != 0)
563 				errx(1, "invalid size: %s", optarg);
564 			break;
565 		default:
566 			ctl_usage(res->ctl);
567 			/* NOTREACHED */
568 		}
569 	}
570 
571 	if (res->size == 0) {
572 		fprintf(stderr, "missing size argument\n");
573 		ctl_usage(res->ctl);
574 	}
575 
576 	if (type == VMDF_QCOW2) {
577 		format = "qcow2";
578 		ret = create_qc2_imagefile(paths[0], res->size);
579 	} else {
580 		format = "raw";
581 		ret = create_raw_imagefile(paths[0], res->size);
582 	}
583 
584 	if (ret != 0) {
585 		errno = ret;
586 		err(1, "create imagefile operation failed");
587 	} else
588 		warnx("%s imagefile created", format);
589 
590 	return (0);
591 }
592 
593 int
594 ctl_status(struct parse_result *res, int argc, char *argv[])
595 {
596 	if (argc == 2) {
597 		if (parse_vmid(res, argv[1], 0) == -1)
598 			errx(1, "invalid id: %s", argv[1]);
599 	} else if (argc > 2)
600 		ctl_usage(res->ctl);
601 
602 	return (vmmaction(res));
603 }
604 
605 int
606 ctl_load(struct parse_result *res, int argc, char *argv[])
607 {
608 	if (argc != 2)
609 		ctl_usage(res->ctl);
610 
611 	if ((res->path = strdup(argv[1])) == NULL)
612 		err(1, "strdup");
613 
614 	return (vmmaction(res));
615 }
616 
617 int
618 ctl_log(struct parse_result *res, int argc, char *argv[])
619 {
620 	if (argc != 2)
621 		ctl_usage(res->ctl);
622 
623 	if (strncasecmp("brief", argv[1], strlen(argv[1])) == 0)
624 		res->verbose = 0;
625 	else if (strncasecmp("verbose", argv[1], strlen(argv[1])) == 0)
626 		res->verbose = 2;
627 	else
628 		ctl_usage(res->ctl);
629 
630 	return (vmmaction(res));
631 }
632 
633 int
634 ctl_reload(struct parse_result *res, int argc, char *argv[])
635 {
636 	if (argc != 1)
637 		ctl_usage(res->ctl);
638 
639 	return (vmmaction(res));
640 }
641 
642 int
643 ctl_reset(struct parse_result *res, int argc, char *argv[])
644 {
645 	if (argc == 2) {
646 		if (strcasecmp("all", argv[1]) == 0)
647 			res->mode = CONFIG_ALL;
648 		else if (strcasecmp("vms", argv[1]) == 0)
649 			res->mode = CONFIG_VMS;
650 		else if (strcasecmp("switches", argv[1]) == 0)
651 			res->mode = CONFIG_SWITCHES;
652 		else
653 			ctl_usage(res->ctl);
654 	} else if (argc > 2)
655 		ctl_usage(res->ctl);
656 
657 	if (res->mode == 0)
658 		res->mode = CONFIG_ALL;
659 
660 	return (vmmaction(res));
661 }
662 
663 int
664 ctl_start(struct parse_result *res, int argc, char *argv[])
665 {
666 	int		 ch, i, type;
667 	char		 path[PATH_MAX];
668 	const char	*s;
669 
670 	if (argc < 2)
671 		ctl_usage(res->ctl);
672 
673 	if (parse_vmid(res, argv[1], 0) == -1)
674 		errx(1, "invalid id: %s", argv[1]);
675 
676 	argc--;
677 	argv++;
678 
679 	while ((ch = getopt(argc, argv, "b:r:cLm:n:d:i:t:")) != -1) {
680 		switch (ch) {
681 		case 'b':
682 			if (res->path)
683 				errx(1, "boot image specified multiple times");
684 			if (realpath(optarg, path) == NULL)
685 				err(1, "invalid boot image path");
686 			if ((res->path = strdup(path)) == NULL)
687 				errx(1, "strdup");
688 			break;
689 		case 'r':
690 			if (res->isopath)
691 				errx(1, "iso image specified multiple times");
692 			if (realpath(optarg, path) == NULL)
693 				err(1, "invalid iso image path");
694 			if ((res->isopath = strdup(path)) == NULL)
695 				errx(1, "strdup");
696 			break;
697 		case 'c':
698 			tty_autoconnect = 1;
699 			break;
700 		case 'L':
701 			if (parse_network(res, ".") != 0)
702 				errx(1, "invalid network: %s", optarg);
703 			break;
704 		case 'm':
705 			if (res->size)
706 				errx(1, "memory specified multiple times");
707 			if (parse_size(res, optarg, 0) != 0)
708 				errx(1, "invalid memory size: %s", optarg);
709 			break;
710 		case 'n':
711 			if (parse_network(res, optarg) != 0)
712 				errx(1, "invalid network: %s", optarg);
713 			break;
714 		case 'd':
715 			type = parse_disktype(optarg, &s);
716 			if (realpath(s, path) == NULL)
717 				err(1, "invalid disk path");
718 			if (parse_disk(res, path, type) != 0)
719 				errx(1, "invalid disk: %s", optarg);
720 			break;
721 		case 'i':
722 			if (res->nifs != -1)
723 				errx(1, "interfaces specified multiple times");
724 			if (parse_ifs(res, optarg, 0) != 0)
725 				errx(1, "invalid interface count: %s", optarg);
726 			break;
727 		case 't':
728 			if (parse_instance(res, optarg) == -1)
729 				errx(1, "invalid name: %s", optarg);
730 			break;
731 		default:
732 			ctl_usage(res->ctl);
733 			/* NOTREACHED */
734 		}
735 	}
736 
737 	for (i = res->nnets; i < res->nifs; i++) {
738 		/* Add interface that is not attached to a switch */
739 		if (parse_network(res, "") == -1)
740 			return (-1);
741 	}
742 	if (res->nnets > res->nifs)
743 		res->nifs = res->nnets;
744 
745 	return (vmmaction(res));
746 }
747 
748 int
749 ctl_stop(struct parse_result *res, int argc, char *argv[])
750 {
751 	int		 ch, ret;
752 
753 	if (argc < 2)
754 		ctl_usage(res->ctl);
755 
756 	if ((ret = parse_vmid(res, argv[1], 0)) == 0) {
757 		argc--;
758 		argv++;
759 	}
760 
761 	while ((ch = getopt(argc, argv, "afw")) != -1) {
762 		switch (ch) {
763 		case 'f':
764 			res->flags |= VMOP_FORCE;
765 			break;
766 		case 'w':
767 			res->flags |= VMOP_WAIT;
768 			break;
769 		case 'a':
770 			res->action = CMD_STOPALL;
771 			break;
772 		default:
773 			ctl_usage(res->ctl);
774 			/* NOTREACHED */
775 		}
776 	}
777 
778 	/* VM id is only expected without the -a flag */
779 	if ((res->action != CMD_STOPALL && ret == -1) ||
780 	    (res->action == CMD_STOPALL && ret != -1))
781 		errx(1, "invalid id: %s", argv[1]);
782 
783 	return (vmmaction(res));
784 }
785 
786 int
787 ctl_console(struct parse_result *res, int argc, char *argv[])
788 {
789 	if (argc == 2) {
790 		if (parse_vmid(res, argv[1], 0) == -1)
791 			errx(1, "invalid id: %s", argv[1]);
792 	} else if (argc != 2)
793 		ctl_usage(res->ctl);
794 
795 	return (vmmaction(res));
796 }
797 
798 int
799 ctl_pause(struct parse_result *res, int argc, char *argv[])
800 {
801 	if (argc == 2) {
802 		if (parse_vmid(res, argv[1], 0) == -1)
803 			errx(1, "invalid id: %s", argv[1]);
804 	} else if (argc != 2)
805 		ctl_usage(res->ctl);
806 
807 	return (vmmaction(res));
808 }
809 
810 int
811 ctl_unpause(struct parse_result *res, int argc, char *argv[])
812 {
813 	if (argc == 2) {
814 		if (parse_vmid(res, argv[1], 0) == -1)
815 			errx(1, "invalid id: %s", argv[1]);
816 	} else if (argc != 2)
817 		ctl_usage(res->ctl);
818 
819 	return (vmmaction(res));
820 }
821 
822 int
823 ctl_send(struct parse_result *res, int argc, char *argv[])
824 {
825 	if (pledge("stdio unix sendfd unveil", NULL) == -1)
826 		err(1, "pledge");
827 	if (argc == 2) {
828 		if (parse_vmid(res, argv[1], 0) == -1)
829 			errx(1, "invalid id: %s", argv[1]);
830 	} else if (argc != 2)
831 		ctl_usage(res->ctl);
832 
833 	return (vmmaction(res));
834 }
835 
836 int
837 ctl_receive(struct parse_result *res, int argc, char *argv[])
838 {
839 	if (pledge("stdio unix sendfd unveil", NULL) == -1)
840 		err(1, "pledge");
841 	if (argc == 2) {
842 		if (parse_vmid(res, argv[1], 1) == -1)
843 			errx(1, "invalid id: %s", argv[1]);
844 	} else if (argc != 2)
845 		ctl_usage(res->ctl);
846 
847 	return (vmmaction(res));
848 }
849 
850 __dead void
851 ctl_openconsole(const char *name)
852 {
853 	closefrom(STDERR_FILENO + 1);
854 	if (unveil(VMCTL_CU, "x") == -1)
855 		err(1, "unveil");
856 	execl(VMCTL_CU, VMCTL_CU, "-l", name, "-s", "115200", (char *)NULL);
857 	err(1, "failed to open the console");
858 }
859