1 |
|
|
/* $OpenBSD: vmd.h,v 1.66 2017/11/11 02:50:08 mlarkin Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2015 Mike Larkin <mlarkin@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/queue.h> |
21 |
|
|
#include <sys/socket.h> |
22 |
|
|
|
23 |
|
|
#include <machine/vmmvar.h> |
24 |
|
|
|
25 |
|
|
#include <net/if.h> |
26 |
|
|
#include <netinet/in.h> |
27 |
|
|
#include <netinet/if_ether.h> |
28 |
|
|
|
29 |
|
|
#include <limits.h> |
30 |
|
|
#include <stdio.h> |
31 |
|
|
#include <pthread.h> |
32 |
|
|
|
33 |
|
|
#include "proc.h" |
34 |
|
|
|
35 |
|
|
#ifndef VMD_H |
36 |
|
|
#define VMD_H |
37 |
|
|
|
38 |
|
|
#define SET(_v, _m) ((_v) |= (_m)) |
39 |
|
|
#define CLR(_v, _m) ((_v) &= ~(_m)) |
40 |
|
|
#define ISSET(_v, _m) ((_v) & (_m)) |
41 |
|
|
|
42 |
|
|
#define VMD_USER "_vmd" |
43 |
|
|
#define VMD_CONF "/etc/vm.conf" |
44 |
|
|
#define SOCKET_NAME "/var/run/vmd.sock" |
45 |
|
|
#define VMM_NODE "/dev/vmm" |
46 |
|
|
#define VM_DEFAULT_BIOS "/etc/firmware/vmm-bios" |
47 |
|
|
#define VM_DEFAULT_KERNEL "/bsd" |
48 |
|
|
#define VM_DEFAULT_DEVICE "hd0a" |
49 |
|
|
#define VM_BOOT_CONF "/etc/boot.conf" |
50 |
|
|
#define VM_NAME_MAX 64 |
51 |
|
|
#define VM_TTYNAME_MAX 16 |
52 |
|
|
#define MAX_TAP 256 |
53 |
|
|
#define NR_BACKLOG 5 |
54 |
|
|
#define VMD_SWITCH_TYPE "bridge" |
55 |
|
|
#define VM_DEFAULT_MEMORY 512 |
56 |
|
|
|
57 |
|
|
/* vmd -> vmctl error codes */ |
58 |
|
|
#define VMD_BIOS_MISSING 1001 |
59 |
|
|
#define VMD_DISK_MISSING 1002 |
60 |
|
|
#define VMD_DISK_INVALID 1003 |
61 |
|
|
#define VMD_VM_STOP_INVALID 1004 |
62 |
|
|
|
63 |
|
|
/* 100.64.0.0/10 from rfc6598 (IPv4 Prefix for Shared Address Space) */ |
64 |
|
|
#define VMD_DHCP_PREFIX "100.64.0.0/10" |
65 |
|
|
|
66 |
|
|
#ifdef VMD_DEBUG |
67 |
|
|
#define dprintf(x...) do { log_debug(x); } while(0) |
68 |
|
|
#else |
69 |
|
|
#define dprintf(x...) |
70 |
|
|
#endif /* VMD_DEBUG */ |
71 |
|
|
|
72 |
|
|
enum imsg_type { |
73 |
|
|
IMSG_VMDOP_START_VM_REQUEST = IMSG_PROC_MAX, |
74 |
|
|
IMSG_VMDOP_START_VM_DISK, |
75 |
|
|
IMSG_VMDOP_START_VM_IF, |
76 |
|
|
IMSG_VMDOP_START_VM_END, |
77 |
|
|
IMSG_VMDOP_START_VM_RESPONSE, |
78 |
|
|
IMSG_VMDOP_PAUSE_VM, |
79 |
|
|
IMSG_VMDOP_PAUSE_VM_RESPONSE, |
80 |
|
|
IMSG_VMDOP_UNPAUSE_VM, |
81 |
|
|
IMSG_VMDOP_UNPAUSE_VM_RESPONSE, |
82 |
|
|
IMSG_VMDOP_SEND_VM_REQUEST, |
83 |
|
|
IMSG_VMDOP_SEND_VM_RESPONSE, |
84 |
|
|
IMSG_VMDOP_RECEIVE_VM_REQUEST, |
85 |
|
|
IMSG_VMDOP_RECEIVE_VM_RESPONSE, |
86 |
|
|
IMSG_VMDOP_RECEIVE_VM_END, |
87 |
|
|
IMSG_VMDOP_TERMINATE_VM_REQUEST, |
88 |
|
|
IMSG_VMDOP_TERMINATE_VM_RESPONSE, |
89 |
|
|
IMSG_VMDOP_TERMINATE_VM_EVENT, |
90 |
|
|
IMSG_VMDOP_GET_INFO_VM_REQUEST, |
91 |
|
|
IMSG_VMDOP_GET_INFO_VM_DATA, |
92 |
|
|
IMSG_VMDOP_GET_INFO_VM_END_DATA, |
93 |
|
|
IMSG_VMDOP_LOAD, |
94 |
|
|
IMSG_VMDOP_RELOAD, |
95 |
|
|
IMSG_VMDOP_PRIV_IFDESCR, |
96 |
|
|
IMSG_VMDOP_PRIV_IFADD, |
97 |
|
|
IMSG_VMDOP_PRIV_IFEXISTS, |
98 |
|
|
IMSG_VMDOP_PRIV_IFUP, |
99 |
|
|
IMSG_VMDOP_PRIV_IFDOWN, |
100 |
|
|
IMSG_VMDOP_PRIV_IFGROUP, |
101 |
|
|
IMSG_VMDOP_PRIV_IFADDR, |
102 |
|
|
IMSG_VMDOP_PRIV_IFRDOMAIN, |
103 |
|
|
IMSG_VMDOP_VM_SHUTDOWN, |
104 |
|
|
IMSG_VMDOP_VM_REBOOT, |
105 |
|
|
IMSG_VMDOP_CONFIG |
106 |
|
|
}; |
107 |
|
|
|
108 |
|
|
struct vmop_result { |
109 |
|
|
int vmr_result; |
110 |
|
|
uint32_t vmr_id; |
111 |
|
|
pid_t vmr_pid; |
112 |
|
|
char vmr_ttyname[VM_TTYNAME_MAX]; |
113 |
|
|
}; |
114 |
|
|
|
115 |
|
|
struct vmop_info_result { |
116 |
|
|
struct vm_info_result vir_info; |
117 |
|
|
char vir_ttyname[VM_TTYNAME_MAX]; |
118 |
|
|
uid_t vir_uid; |
119 |
|
|
int64_t vir_gid; |
120 |
|
|
}; |
121 |
|
|
|
122 |
|
|
struct vmop_id { |
123 |
|
|
uint32_t vid_id; |
124 |
|
|
char vid_name[VMM_MAX_NAME_LEN]; |
125 |
|
|
uid_t vid_uid; |
126 |
|
|
}; |
127 |
|
|
|
128 |
|
|
struct vmop_ifreq { |
129 |
|
|
uint32_t vfr_id; |
130 |
|
|
char vfr_name[IF_NAMESIZE]; |
131 |
|
|
char vfr_value[VM_NAME_MAX]; |
132 |
|
|
struct ifaliasreq vfr_ifra; |
133 |
|
|
}; |
134 |
|
|
|
135 |
|
|
struct vmop_create_params { |
136 |
|
|
struct vm_create_params vmc_params; |
137 |
|
|
unsigned int vmc_flags; |
138 |
|
|
#define VMOP_CREATE_KERNEL 0x01 |
139 |
|
|
#define VMOP_CREATE_MEMORY 0x02 |
140 |
|
|
#define VMOP_CREATE_NETWORK 0x04 |
141 |
|
|
#define VMOP_CREATE_DISK 0x08 |
142 |
|
|
|
143 |
|
|
/* userland-only part of the create params */ |
144 |
|
|
unsigned int vmc_ifflags[VMM_MAX_NICS_PER_VM]; |
145 |
|
|
#define VMIFF_UP 0x01 |
146 |
|
|
#define VMIFF_LOCKED 0x02 |
147 |
|
|
#define VMIFF_LOCAL 0x04 |
148 |
|
|
#define VMIFF_RDOMAIN 0x08 |
149 |
|
|
#define VMIFF_OPTMASK (VMIFF_LOCKED|VMIFF_LOCAL|VMIFF_RDOMAIN) |
150 |
|
|
char vmc_ifnames[VMM_MAX_NICS_PER_VM][IF_NAMESIZE]; |
151 |
|
|
char vmc_ifswitch[VMM_MAX_NICS_PER_VM][VM_NAME_MAX]; |
152 |
|
|
char vmc_ifgroup[VMM_MAX_NICS_PER_VM][IF_NAMESIZE]; |
153 |
|
|
unsigned int vmc_ifrdomain[VMM_MAX_NICS_PER_VM]; |
154 |
|
|
uid_t vmc_uid; |
155 |
|
|
int64_t vmc_gid; |
156 |
|
|
}; |
157 |
|
|
|
158 |
|
|
struct vm_dump_header_cpuid { |
159 |
|
|
unsigned long code, leaf; |
160 |
|
|
unsigned int a, b, c, d; |
161 |
|
|
}; |
162 |
|
|
|
163 |
|
|
#define VM_DUMP_HEADER_CPUID_COUNT 5 |
164 |
|
|
|
165 |
|
|
struct vm_dump_header { |
166 |
|
|
uint8_t vmh_signature[12]; |
167 |
|
|
#define VM_DUMP_SIGNATURE VMM_HV_SIGNATURE |
168 |
|
|
uint8_t vmh_pad[3]; |
169 |
|
|
uint8_t vmh_version; |
170 |
|
|
#define VM_DUMP_VERSION 2 |
171 |
|
|
struct vm_dump_header_cpuid |
172 |
|
|
vmh_cpuids[VM_DUMP_HEADER_CPUID_COUNT]; |
173 |
|
|
} __packed; |
174 |
|
|
|
175 |
|
|
struct vmboot_params { |
176 |
|
|
int vbp_fd; |
177 |
|
|
off_t vbp_partoff; |
178 |
|
|
char vbp_device[PATH_MAX]; |
179 |
|
|
char vbp_image[PATH_MAX]; |
180 |
|
|
uint32_t vbp_bootdev; |
181 |
|
|
uint32_t vbp_howto; |
182 |
|
|
char *vbp_arg; |
183 |
|
|
}; |
184 |
|
|
|
185 |
|
|
struct vmd_if { |
186 |
|
|
char *vif_name; |
187 |
|
|
char *vif_switch; |
188 |
|
|
char *vif_group; |
189 |
|
|
int vif_fd; |
190 |
|
|
unsigned int vif_rdomain; |
191 |
|
|
unsigned int vif_flags; |
192 |
|
|
TAILQ_ENTRY(vmd_if) vif_entry; |
193 |
|
|
}; |
194 |
|
|
|
195 |
|
|
struct vmd_switch { |
196 |
|
|
uint32_t sw_id; |
197 |
|
|
char *sw_name; |
198 |
|
|
char sw_ifname[IF_NAMESIZE]; |
199 |
|
|
char *sw_group; |
200 |
|
|
unsigned int sw_rdomain; |
201 |
|
|
unsigned int sw_flags; |
202 |
|
|
int sw_running; |
203 |
|
|
TAILQ_ENTRY(vmd_switch) sw_entry; |
204 |
|
|
}; |
205 |
|
|
TAILQ_HEAD(switchlist, vmd_switch); |
206 |
|
|
|
207 |
|
|
struct vmd_vm { |
208 |
|
|
struct vmop_create_params vm_params; |
209 |
|
|
pid_t vm_pid; |
210 |
|
|
uint32_t vm_vmid; |
211 |
|
|
int vm_kernel; |
212 |
|
|
int vm_disks[VMM_MAX_DISKS_PER_VM]; |
213 |
|
|
struct vmd_if vm_ifs[VMM_MAX_NICS_PER_VM]; |
214 |
|
|
char *vm_ttyname; |
215 |
|
|
int vm_tty; |
216 |
|
|
uint32_t vm_peerid; |
217 |
|
|
/* When set, VM is running now (PROC_PARENT only) */ |
218 |
|
|
int vm_running; |
219 |
|
|
/* When set, VM is not started by default (PROC_PARENT only) */ |
220 |
|
|
int vm_disabled; |
221 |
|
|
/* When set, VM was defined in a config file */ |
222 |
|
|
int vm_from_config; |
223 |
|
|
struct imsgev vm_iev; |
224 |
|
|
int vm_shutdown; |
225 |
|
|
uid_t vm_uid; |
226 |
|
|
int vm_received; |
227 |
|
|
int vm_paused; |
228 |
|
|
int vm_receive_fd; |
229 |
|
|
|
230 |
|
|
TAILQ_ENTRY(vmd_vm) vm_entry; |
231 |
|
|
}; |
232 |
|
|
TAILQ_HEAD(vmlist, vmd_vm); |
233 |
|
|
|
234 |
|
|
struct address { |
235 |
|
|
struct sockaddr_storage ss; |
236 |
|
|
int prefixlen; |
237 |
|
|
TAILQ_ENTRY(address) entry; |
238 |
|
|
}; |
239 |
|
|
TAILQ_HEAD(addresslist, address); |
240 |
|
|
|
241 |
|
|
struct vmd_config { |
242 |
|
|
struct address cfg_localprefix; |
243 |
|
|
}; |
244 |
|
|
|
245 |
|
|
struct vmd { |
246 |
|
|
struct privsep vmd_ps; |
247 |
|
|
const char *vmd_conffile; |
248 |
|
|
|
249 |
|
|
/* global configuration that is sent to the children */ |
250 |
|
|
struct vmd_config vmd_cfg; |
251 |
|
|
|
252 |
|
|
int vmd_debug; |
253 |
|
|
int vmd_verbose; |
254 |
|
|
int vmd_noaction; |
255 |
|
|
|
256 |
|
|
uint32_t vmd_nvm; |
257 |
|
|
struct vmlist *vmd_vms; |
258 |
|
|
uint32_t vmd_nswitches; |
259 |
|
|
struct switchlist *vmd_switches; |
260 |
|
|
|
261 |
|
|
int vmd_fd; |
262 |
|
|
int vmd_ptmfd; |
263 |
|
|
}; |
264 |
|
|
|
265 |
|
|
static inline struct sockaddr_in * |
266 |
|
|
ss2sin(struct sockaddr_storage *ss) |
267 |
|
|
{ |
268 |
|
|
return ((struct sockaddr_in *)ss); |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
static inline struct sockaddr_in6 * |
272 |
|
|
ss2sin6(struct sockaddr_storage *ss) |
273 |
|
|
{ |
274 |
|
|
return ((struct sockaddr_in6 *)ss); |
275 |
|
|
} |
276 |
|
|
|
277 |
|
|
struct packet_ctx { |
278 |
|
|
uint8_t pc_htype; |
279 |
|
|
uint8_t pc_hlen; |
280 |
|
|
uint8_t pc_smac[ETHER_ADDR_LEN]; |
281 |
|
|
uint8_t pc_dmac[ETHER_ADDR_LEN]; |
282 |
|
|
|
283 |
|
|
struct sockaddr_storage pc_src; |
284 |
|
|
struct sockaddr_storage pc_dst; |
285 |
|
|
}; |
286 |
|
|
|
287 |
|
|
/* packet.c */ |
288 |
|
|
ssize_t assemble_hw_header(unsigned char *, size_t, size_t, |
289 |
|
|
struct packet_ctx *, unsigned int); |
290 |
|
|
ssize_t assemble_udp_ip_header(unsigned char *, size_t, size_t, |
291 |
|
|
struct packet_ctx *pc, unsigned char *, size_t); |
292 |
|
|
ssize_t decode_hw_header(unsigned char *, size_t, size_t, struct packet_ctx *, |
293 |
|
|
unsigned int); |
294 |
|
|
ssize_t decode_udp_ip_header(unsigned char *, size_t, size_t, |
295 |
|
|
struct packet_ctx *); |
296 |
|
|
|
297 |
|
|
/* vmd.c */ |
298 |
|
|
int vmd_reload(unsigned int, const char *); |
299 |
|
|
struct vmd_vm *vm_getbyid(uint32_t); |
300 |
|
|
struct vmd_vm *vm_getbyvmid(uint32_t); |
301 |
|
|
uint32_t vm_id2vmid(uint32_t, struct vmd_vm *); |
302 |
|
|
uint32_t vm_vmid2id(uint32_t, struct vmd_vm *); |
303 |
|
|
struct vmd_vm *vm_getbyname(const char *); |
304 |
|
|
struct vmd_vm *vm_getbypid(pid_t); |
305 |
|
|
void vm_stop(struct vmd_vm *, int); |
306 |
|
|
void vm_remove(struct vmd_vm *); |
307 |
|
|
int vm_register(struct privsep *, struct vmop_create_params *, |
308 |
|
|
struct vmd_vm **, uint32_t, uid_t); |
309 |
|
|
int vm_checkperm(struct vmd_vm *, uid_t); |
310 |
|
|
int vm_opentty(struct vmd_vm *); |
311 |
|
|
void vm_closetty(struct vmd_vm *); |
312 |
|
|
void switch_remove(struct vmd_switch *); |
313 |
|
|
struct vmd_switch *switch_getbyname(const char *); |
314 |
|
|
char *get_string(uint8_t *, size_t); |
315 |
|
|
uint32_t prefixlen2mask(uint8_t); |
316 |
|
|
|
317 |
|
|
/* priv.c */ |
318 |
|
|
void priv(struct privsep *, struct privsep_proc *); |
319 |
|
|
int priv_getiftype(char *, char *, unsigned int *); |
320 |
|
|
int priv_findname(const char *, const char **); |
321 |
|
|
int priv_validgroup(const char *); |
322 |
|
|
int vm_priv_ifconfig(struct privsep *, struct vmd_vm *); |
323 |
|
|
int vm_priv_brconfig(struct privsep *, struct vmd_switch *); |
324 |
|
|
uint32_t vm_priv_addr(struct address *, uint32_t, int, int); |
325 |
|
|
|
326 |
|
|
/* vmm.c */ |
327 |
|
|
struct iovec; |
328 |
|
|
|
329 |
|
|
void vmm(struct privsep *, struct privsep_proc *); |
330 |
|
|
void vmm_shutdown(void); |
331 |
|
|
void *vaddr_mem(paddr_t, size_t); |
332 |
|
|
int write_mem(paddr_t, const void *buf, size_t); |
333 |
|
|
int read_mem(paddr_t, void *buf, size_t); |
334 |
|
|
int iovec_mem(paddr_t, size_t, struct iovec *, int); |
335 |
|
|
int opentap(char *); |
336 |
|
|
int fd_hasdata(int); |
337 |
|
|
void mutex_lock(pthread_mutex_t *); |
338 |
|
|
void mutex_unlock(pthread_mutex_t *); |
339 |
|
|
int vmm_pipe(struct vmd_vm *, int, void (*)(int, short, void *)); |
340 |
|
|
|
341 |
|
|
/* vm.c */ |
342 |
|
|
int start_vm(struct vmd_vm *, int); |
343 |
|
|
int receive_vm(struct vmd_vm *, int, int); |
344 |
|
|
__dead void vm_shutdown(unsigned int); |
345 |
|
|
|
346 |
|
|
/* control.c */ |
347 |
|
|
int config_init(struct vmd *); |
348 |
|
|
void config_purge(struct vmd *, unsigned int); |
349 |
|
|
int config_setconfig(struct vmd *); |
350 |
|
|
int config_getconfig(struct vmd *, struct imsg *); |
351 |
|
|
int config_setreset(struct vmd *, unsigned int); |
352 |
|
|
int config_getreset(struct vmd *, struct imsg *); |
353 |
|
|
int config_setvm(struct privsep *, struct vmd_vm *, uint32_t, uid_t); |
354 |
|
|
int config_getvm(struct privsep *, struct imsg *); |
355 |
|
|
int config_getdisk(struct privsep *, struct imsg *); |
356 |
|
|
int config_getif(struct privsep *, struct imsg *); |
357 |
|
|
|
358 |
|
|
/* vmboot.c */ |
359 |
|
|
FILE *vmboot_open(int, int, struct vmboot_params *); |
360 |
|
|
void vmboot_close(FILE *, struct vmboot_params *); |
361 |
|
|
|
362 |
|
|
/* parse.y */ |
363 |
|
|
int parse_config(const char *); |
364 |
|
|
int cmdline_symset(char *); |
365 |
|
|
int host(const char *, struct address *); |
366 |
|
|
|
367 |
|
|
#endif /* VMD_H */ |