1 /*
2  * Copyright 2009-2017 Citrix Ltd and other contributors
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; version 2.1 only. with the special
7  * exception on linking described in file LICENSE.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14 
15 #include <ctype.h>
16 #include <inttypes.h>
17 #include <limits.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <xen/hvm/e820.h>
21 #include <xen/hvm/params.h>
22 #include <xen/io/sndif.h>
23 #include <xen/io/kbdif.h>
24 
25 #include <libxl.h>
26 #include <libxl_utils.h>
27 #include <libxlutil.h>
28 
29 #include "xl.h"
30 #include "xl_utils.h"
31 #include "xl_parse.h"
32 
33 extern void set_default_nic_values(libxl_device_nic *nic);
34 
35 #define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
36     ({                                                                  \
37         typeof((count)) array_extend_old_count = (count);               \
38         (count)++;                                                      \
39         (array) = xrealloc((array), sizeof(*array) * (count));          \
40         (initfn)(&(array)[array_extend_old_count]);                     \
41         more;                                                           \
42         &(array)[array_extend_old_count];                               \
43     })
44 
45 #define ARRAY_EXTEND_INIT(array,count,initfn)                           \
46     ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
47         (array)[array_extend_old_count].devid = array_extend_old_count; \
48         }))
49 
50 #define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
51     ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
52 
53 static const char *action_on_shutdown_names[] = {
54     [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
55 
56     [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
57     [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
58 
59     [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
60 
61     [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
62     [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
63 
64     [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
65 };
66 
get_action_on_shutdown_name(libxl_action_on_shutdown a)67 const char *get_action_on_shutdown_name(libxl_action_on_shutdown a)
68 {
69     return action_on_shutdown_names[a];
70 }
71 
parse_action_on_shutdown(const char * buf,libxl_action_on_shutdown * a)72 static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
73 {
74     int i;
75     const char *n;
76 
77     for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
78         n = action_on_shutdown_names[i];
79 
80         if (!n) continue;
81 
82         if (strcmp(buf, n) == 0) {
83             *a = i;
84             return 1;
85         }
86     }
87     return 0;
88 }
89 
90 #define DSTATE_INITIAL   0
91 #define DSTATE_TAP       1
92 #define DSTATE_PHYSPATH  2
93 #define DSTATE_VIRTPATH  3
94 #define DSTATE_VIRTTYPE  4
95 #define DSTATE_RW        5
96 #define DSTATE_TERMINAL  6
97 
parse_disk_config_multistring(XLU_Config ** config,int nspecs,const char * const * specs,libxl_device_disk * disk)98 void parse_disk_config_multistring(XLU_Config **config,
99                                    int nspecs, const char *const *specs,
100                                    libxl_device_disk *disk)
101 {
102     int e;
103 
104     libxl_device_disk_init(disk);
105 
106     if (!*config) {
107         *config = xlu_cfg_init(stderr, "command line");
108         if (!*config) { perror("xlu_cfg_init"); exit(-1); }
109     }
110 
111     e = xlu_disk_parse(*config, nspecs, specs, disk);
112     if (e == EINVAL) exit(EXIT_FAILURE);
113     if (e) {
114         fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
115         exit(EXIT_FAILURE);
116     }
117 }
118 
parse_disk_config(XLU_Config ** config,const char * spec,libxl_device_disk * disk)119 void parse_disk_config(XLU_Config **config, const char *spec,
120                        libxl_device_disk *disk)
121 {
122     parse_disk_config_multistring(config, 1, &spec, disk);
123 }
124 
parse_vif_rate(XLU_Config ** config,const char * rate,libxl_device_nic * nic)125 static void parse_vif_rate(XLU_Config **config, const char *rate,
126                            libxl_device_nic *nic)
127 {
128     int e;
129 
130     e = xlu_vif_parse_rate(*config, rate, nic);
131     if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
132     if (e) {
133         fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
134         exit(EXIT_FAILURE);
135     }
136 }
137 
parse_range(const char * str,unsigned long * a,unsigned long * b)138 int parse_range(const char *str, unsigned long *a, unsigned long *b)
139 {
140     const char *nstr;
141     char *endptr;
142 
143     *a = *b = strtoul(str, &endptr, 10);
144     if (endptr == str || *a == ULONG_MAX)
145         return 1;
146 
147     if (*endptr == '-') {
148         nstr = endptr + 1;
149 
150         *b = strtoul(nstr, &endptr, 10);
151         if (endptr == nstr || *b == ULONG_MAX || *b < *a)
152             return 1;
153     }
154 
155     /* Valid value or range so far, but we also don't want junk after that */
156     if (*endptr != '\0')
157         return 1;
158 
159     return 0;
160 }
161 
162 /*
163  * Add or removes a specific set of cpus (specified in str, either as
164  * single cpus or as entire NUMA nodes) to/from cpumap.
165  */
update_cpumap_range(const char * str,libxl_bitmap * cpumap)166 static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
167 {
168     unsigned long ida, idb;
169     libxl_bitmap node_cpumap;
170     bool is_not = false, is_nodes = false;
171     int rc = 0;
172 
173     libxl_bitmap_init(&node_cpumap);
174 
175     rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
176     if (rc) {
177         fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
178         goto out;
179     }
180 
181     /* Are we adding or removing cpus/nodes? */
182     if (STR_SKIP_PREFIX(str, "^")) {
183         is_not = true;
184     }
185 
186     /* Are we dealing with cpus or full nodes? */
187     if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
188         is_nodes = true;
189     }
190 
191     if (strcmp(str, "all") == 0) {
192         /* We do not accept "^all" or "^nodes:all" */
193         if (is_not) {
194             fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
195             rc = ERROR_INVAL;
196         } else
197             libxl_bitmap_set_any(cpumap);
198         goto out;
199     }
200 
201     rc = parse_range(str, &ida, &idb);
202     if (rc) {
203         fprintf(stderr, "Invalid pcpu range: %s.\n", str);
204         goto out;
205     }
206 
207     /* Add or remove the specified cpus in the range */
208     while (ida <= idb) {
209         if (is_nodes) {
210             /* Add/Remove all the cpus of a NUMA node */
211             int i;
212 
213             rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
214             if (rc) {
215                 fprintf(stderr, "libxl_node_to_cpumap failed.\n");
216                 goto out;
217             }
218 
219             /* Add/Remove all the cpus in the node cpumap */
220             libxl_for_each_set_bit(i, node_cpumap) {
221                 is_not ? libxl_bitmap_reset(cpumap, i) :
222                          libxl_bitmap_set(cpumap, i);
223             }
224         } else {
225             /* Add/Remove this cpu */
226             is_not ? libxl_bitmap_reset(cpumap, ida) :
227                      libxl_bitmap_set(cpumap, ida);
228         }
229         ida++;
230     }
231 
232  out:
233     libxl_bitmap_dispose(&node_cpumap);
234     return rc;
235 }
236 
237 /*
238  * Takes a string representing a set of cpus (specified either as
239  * single cpus or as eintire NUMA nodes) and turns it into the
240  * corresponding libxl_bitmap (in cpumap).
241  */
parse_cpurange(const char * cpu,libxl_bitmap * cpumap)242 int parse_cpurange(const char *cpu, libxl_bitmap *cpumap)
243 {
244     char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
245     int rc = 0;
246 
247     for (ptr = strtok_r(buf, ",", &saveptr); ptr;
248          ptr = strtok_r(NULL, ",", &saveptr)) {
249         rc = update_cpumap_range(ptr, cpumap);
250         if (rc)
251             break;
252     }
253     free(buf);
254 
255     return rc;
256 }
257 
parse_top_level_vnc_options(XLU_Config * config,libxl_vnc_info * vnc)258 static void parse_top_level_vnc_options(XLU_Config *config,
259                                         libxl_vnc_info *vnc)
260 {
261     long l;
262 
263     xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
264     xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
265     xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
266     if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
267         vnc->display = l;
268     xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
269 }
270 
parse_top_level_sdl_options(XLU_Config * config,libxl_sdl_info * sdl)271 static void parse_top_level_sdl_options(XLU_Config *config,
272                                         libxl_sdl_info *sdl)
273 {
274     xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
275     xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
276     xlu_cfg_replace_string (config, "display", &sdl->display, 0);
277     xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
278 }
279 
parse_cmdline(XLU_Config * config)280 static char *parse_cmdline(XLU_Config *config)
281 {
282     char *cmdline = NULL;
283     const char *root = NULL, *extra = NULL, *buf = NULL;
284 
285     xlu_cfg_get_string (config, "cmdline", &buf, 0);
286     xlu_cfg_get_string (config, "root", &root, 0);
287     xlu_cfg_get_string (config, "extra", &extra, 0);
288 
289     if (buf) {
290         cmdline = strdup(buf);
291         if (root || extra)
292             fprintf(stderr, "Warning: ignoring root= and extra= "
293                     "in favour of cmdline=\n");
294     } else {
295         if (root && extra) {
296             xasprintf(&cmdline, "root=%s %s", root, extra);
297         } else if (root) {
298             xasprintf(&cmdline, "root=%s", root);
299         } else if (extra) {
300             cmdline = strdup(extra);
301         }
302     }
303 
304     if ((buf || root || extra) && !cmdline) {
305         fprintf(stderr, "Failed to allocate memory for cmdline\n");
306         exit(EXIT_FAILURE);
307     }
308 
309     return cmdline;
310 }
311 
parse_vcpu_affinity(libxl_domain_build_info * b_info,XLU_ConfigList * cpus,const char * buf,int num_cpus,bool is_hard)312 static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
313                                 XLU_ConfigList *cpus, const char *buf,
314                                 int num_cpus, bool is_hard)
315 {
316     libxl_bitmap *vcpu_affinity_array;
317 
318     /*
319      * If we are here, and buf is !NULL, we're dealing with a string. What
320      * we do in this case is parse it, and copy the result in _all_ (up to
321      * b_info->max_vcpus) the elements of the vcpu affinity array.
322      *
323      * If buf is NULL, we have a list, and what we do is putting in the
324      * i-eth element of the vcpu affinity array the result of the parsing
325      * of the i-eth entry of the list. If there are more vcpus than
326      * entries, it is fine to just not touch the last array elements.
327      */
328 
329     /* Silently ignore values corresponding to non existing vcpus */
330     if (buf || num_cpus > b_info->max_vcpus)
331         num_cpus = b_info->max_vcpus;
332 
333     if (is_hard) {
334         b_info->num_vcpu_hard_affinity = num_cpus;
335         b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
336         vcpu_affinity_array = b_info->vcpu_hard_affinity;
337     } else {
338         b_info->num_vcpu_soft_affinity = num_cpus;
339         b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
340         vcpu_affinity_array = b_info->vcpu_soft_affinity;
341     }
342 
343     if (!buf) {
344         int j = 0;
345 
346         while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
347             libxl_bitmap_init(&vcpu_affinity_array[j]);
348             if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
349                 fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
350                 exit(EXIT_FAILURE);
351             }
352 
353             if (parse_cpurange(buf, &vcpu_affinity_array[j]))
354                 exit(EXIT_FAILURE);
355 
356             j++;
357         }
358 
359         /* When we have a list of cpumaps, always disable automatic placement */
360         libxl_defbool_set(&b_info->numa_placement, false);
361     } else {
362         int i;
363 
364         libxl_bitmap_init(&vcpu_affinity_array[0]);
365         if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
366             fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
367             exit(EXIT_FAILURE);
368         }
369 
370         if (parse_cpurange(buf, &vcpu_affinity_array[0]))
371             exit(EXIT_FAILURE);
372 
373         for (i = 1; i < b_info->max_vcpus; i++) {
374             libxl_bitmap_init(&vcpu_affinity_array[i]);
375             if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
376                 fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
377                 exit(EXIT_FAILURE);
378             }
379             libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
380                               &vcpu_affinity_array[0]);
381         }
382 
383         /* We have soft affinity already, disable automatic placement */
384         if (!is_hard)
385             libxl_defbool_set(&b_info->numa_placement, false);
386     }
387 }
388 
parse_ulong(const char * str)389 static unsigned long parse_ulong(const char *str)
390 {
391     char *endptr;
392     unsigned long val;
393 
394     val = strtoul(str, &endptr, 10);
395     if (endptr == str || val == ULONG_MAX) {
396         fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
397         exit(EXIT_FAILURE);
398     }
399     return val;
400 }
401 
replace_string(char ** str,const char * val)402 void replace_string(char **str, const char *val)
403 {
404     free(*str);
405     *str = xstrdup(val);
406 }
407 
match_option_size(const char * prefix,size_t len,char * arg,char ** argopt)408 int match_option_size(const char *prefix, size_t len,
409                       char *arg, char **argopt)
410 {
411     int rc = strncmp(prefix, arg, len);
412     if (!rc) *argopt = arg+len;
413     return !rc;
414 }
415 
416 /* Parses network data and adds info into nic
417  * Returns 1 if the input token does not match one of the keys
418  * or parsed values are not correct. Successful parse returns 0 */
parse_nic_config(libxl_device_nic * nic,XLU_Config ** config,char * token)419 int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
420 {
421     char *endptr, *oparg;
422     int i;
423     unsigned int val;
424 
425     if (MATCH_OPTION("type", token, oparg)) {
426         if (!strcmp("vif", oparg)) {
427             nic->nictype = LIBXL_NIC_TYPE_VIF;
428         } else if (!strcmp("ioemu", oparg)) {
429             nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
430         } else {
431             fprintf(stderr, "Invalid parameter `type'.\n");
432             return 1;
433         }
434     } else if (MATCH_OPTION("mac", token, oparg)) {
435         for (i = 0; i < 6; i++) {
436             val = strtoul(oparg, &endptr, 16);
437             if ((oparg == endptr) || (val > 255)) {
438                 fprintf(stderr, "Invalid parameter `mac'.\n");
439                 return 1;
440             }
441             nic->mac[i] = val;
442             oparg = endptr + 1;
443         }
444     } else if (MATCH_OPTION("bridge", token, oparg)) {
445         replace_string(&nic->bridge, oparg);
446     } else if (MATCH_OPTION("netdev", token, oparg)) {
447         fprintf(stderr, "the netdev parameter is deprecated, "
448                         "please use gatewaydev instead\n");
449         replace_string(&nic->gatewaydev, oparg);
450     } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
451         replace_string(&nic->gatewaydev, oparg);
452     } else if (MATCH_OPTION("ip", token, oparg)) {
453         replace_string(&nic->ip, oparg);
454     } else if (MATCH_OPTION("script", token, oparg)) {
455         replace_string(&nic->script, oparg);
456     } else if (MATCH_OPTION("backend", token, oparg)) {
457         replace_string(&nic->backend_domname, oparg);
458     } else if (MATCH_OPTION("vifname", token, oparg)) {
459         replace_string(&nic->ifname, oparg);
460     } else if (MATCH_OPTION("model", token, oparg)) {
461         replace_string(&nic->model, oparg);
462     } else if (MATCH_OPTION("rate", token, oparg)) {
463         parse_vif_rate(config, oparg, nic);
464     } else if (MATCH_OPTION("forwarddev", token, oparg)) {
465         replace_string(&nic->coloft_forwarddev, oparg);
466     } else if (MATCH_OPTION("colo_sock_mirror_id", token, oparg)) {
467         replace_string(&nic->colo_sock_mirror_id, oparg);
468     } else if (MATCH_OPTION("colo_sock_mirror_ip", token, oparg)) {
469         replace_string(&nic->colo_sock_mirror_ip, oparg);
470     } else if (MATCH_OPTION("colo_sock_mirror_port", token, oparg)) {
471         replace_string(&nic->colo_sock_mirror_port, oparg);
472     } else if (MATCH_OPTION("colo_sock_compare_sec_in_id", token, oparg)) {
473         replace_string(&nic->colo_sock_compare_sec_in_id, oparg);
474     } else if (MATCH_OPTION("colo_sock_compare_sec_in_ip", token, oparg)) {
475         replace_string(&nic->colo_sock_compare_sec_in_ip, oparg);
476     } else if (MATCH_OPTION("colo_sock_compare_sec_in_port", token, oparg)) {
477         replace_string(&nic->colo_sock_compare_sec_in_port, oparg);
478     } else if (MATCH_OPTION("colo_sock_redirector0_id", token, oparg)) {
479         replace_string(&nic->colo_sock_redirector0_id, oparg);
480     } else if (MATCH_OPTION("colo_sock_redirector0_ip", token, oparg)) {
481         replace_string(&nic->colo_sock_redirector0_ip, oparg);
482     } else if (MATCH_OPTION("colo_sock_redirector0_port", token, oparg)) {
483         replace_string(&nic->colo_sock_redirector0_port, oparg);
484     } else if (MATCH_OPTION("colo_sock_redirector1_id", token, oparg)) {
485         replace_string(&nic->colo_sock_redirector1_id, oparg);
486     } else if (MATCH_OPTION("colo_sock_redirector1_ip", token, oparg)) {
487         replace_string(&nic->colo_sock_redirector1_ip, oparg);
488     } else if (MATCH_OPTION("colo_sock_redirector1_port", token, oparg)) {
489         replace_string(&nic->colo_sock_redirector1_port, oparg);
490     } else if (MATCH_OPTION("colo_sock_redirector2_id", token, oparg)) {
491         replace_string(&nic->colo_sock_redirector2_id, oparg);
492     } else if (MATCH_OPTION("colo_sock_redirector2_ip", token, oparg)) {
493         replace_string(&nic->colo_sock_redirector2_ip, oparg);
494     } else if (MATCH_OPTION("colo_sock_redirector2_port", token, oparg)) {
495         replace_string(&nic->colo_sock_redirector2_port, oparg);
496     } else if (MATCH_OPTION("colo_sock_compare_pri_in_id", token, oparg)) {
497         replace_string(&nic->colo_sock_compare_pri_in_id, oparg);
498     } else if (MATCH_OPTION("colo_sock_compare_pri_in_ip", token, oparg)) {
499         replace_string(&nic->colo_sock_compare_pri_in_ip, oparg);
500     } else if (MATCH_OPTION("colo_sock_compare_pri_in_port", token, oparg)) {
501         replace_string(&nic->colo_sock_compare_pri_in_port, oparg);
502     } else if (MATCH_OPTION("colo_sock_compare_notify_id", token, oparg)) {
503         replace_string(&nic->colo_sock_compare_notify_id, oparg);
504     } else if (MATCH_OPTION("colo_sock_compare_notify_ip", token, oparg)) {
505         replace_string(&nic->colo_sock_compare_notify_ip, oparg);
506     } else if (MATCH_OPTION("colo_sock_compare_notify_port", token, oparg)) {
507         replace_string(&nic->colo_sock_compare_notify_port, oparg);
508     } else if (MATCH_OPTION("colo_filter_mirror_queue", token, oparg)) {
509         replace_string(&nic->colo_filter_mirror_queue, oparg);
510     } else if (MATCH_OPTION("colo_filter_mirror_outdev", token, oparg)) {
511         replace_string(&nic->colo_filter_mirror_outdev, oparg);
512     } else if (MATCH_OPTION("colo_filter_redirector0_queue", token, oparg)) {
513         replace_string(&nic->colo_filter_redirector0_queue, oparg);
514     } else if (MATCH_OPTION("colo_filter_redirector0_indev", token, oparg)) {
515         replace_string(&nic->colo_filter_redirector0_indev, oparg);
516     } else if (MATCH_OPTION("colo_filter_redirector0_outdev", token, oparg)) {
517         replace_string(&nic->colo_filter_redirector0_outdev, oparg);
518     } else if (MATCH_OPTION("colo_filter_redirector1_queue", token, oparg)) {
519         replace_string(&nic->colo_filter_redirector1_queue, oparg);
520     } else if (MATCH_OPTION("colo_filter_redirector1_indev", token, oparg)) {
521         replace_string(&nic->colo_filter_redirector1_indev, oparg);
522     } else if (MATCH_OPTION("colo_filter_redirector1_outdev", token, oparg)) {
523         replace_string(&nic->colo_filter_redirector1_outdev, oparg);
524     } else if (MATCH_OPTION("colo_compare_pri_in", token, oparg)) {
525         replace_string(&nic->colo_compare_pri_in, oparg);
526     } else if (MATCH_OPTION("colo_compare_sec_in", token, oparg)) {
527         replace_string(&nic->colo_compare_sec_in, oparg);
528     } else if (MATCH_OPTION("colo_compare_out", token, oparg)) {
529         replace_string(&nic->colo_compare_out, oparg);
530     } else if (MATCH_OPTION("colo_compare_notify_dev", token, oparg)) {
531         replace_string(&nic->colo_compare_notify_dev, oparg);
532     } else if (MATCH_OPTION("colo_sock_sec_redirector0_id", token, oparg)) {
533         replace_string(&nic->colo_sock_sec_redirector0_id, oparg);
534     } else if (MATCH_OPTION("colo_sock_sec_redirector0_ip", token, oparg)) {
535         replace_string(&nic->colo_sock_sec_redirector0_ip, oparg);
536     } else if (MATCH_OPTION("colo_sock_sec_redirector0_port", token, oparg)) {
537         replace_string(&nic->colo_sock_sec_redirector0_port, oparg);
538     } else if (MATCH_OPTION("colo_sock_sec_redirector1_id", token, oparg)) {
539         replace_string(&nic->colo_sock_sec_redirector1_id, oparg);
540     } else if (MATCH_OPTION("colo_sock_sec_redirector1_ip", token, oparg)) {
541         replace_string(&nic->colo_sock_sec_redirector1_ip, oparg);
542     } else if (MATCH_OPTION("colo_sock_sec_redirector1_port", token, oparg)) {
543         replace_string(&nic->colo_sock_sec_redirector1_port, oparg);
544     } else if (MATCH_OPTION("colo_filter_sec_redirector0_queue", token, oparg)) {
545         replace_string(&nic->colo_filter_sec_redirector0_queue, oparg);
546     } else if (MATCH_OPTION("colo_filter_sec_redirector0_indev", token, oparg)) {
547         replace_string(&nic->colo_filter_sec_redirector0_indev, oparg);
548     } else if (MATCH_OPTION("colo_filter_sec_redirector0_outdev", token, oparg)) {
549         replace_string(&nic->colo_filter_sec_redirector0_outdev, oparg);
550     } else if (MATCH_OPTION("colo_filter_sec_redirector1_queue", token, oparg)) {
551         replace_string(&nic->colo_filter_sec_redirector1_queue, oparg);
552     } else if (MATCH_OPTION("colo_filter_sec_redirector1_indev", token, oparg)) {
553         replace_string(&nic->colo_filter_sec_redirector1_indev, oparg);
554     } else if (MATCH_OPTION("colo_filter_sec_redirector1_outdev", token, oparg)) {
555         replace_string(&nic->colo_filter_sec_redirector1_outdev, oparg);
556     } else if (MATCH_OPTION("colo_filter_sec_rewriter0_queue", token, oparg)) {
557         replace_string(&nic->colo_filter_sec_rewriter0_queue, oparg);
558     } else if (MATCH_OPTION("colo_checkpoint_host", token, oparg)) {
559         replace_string(&nic->colo_checkpoint_host, oparg);
560     } else if (MATCH_OPTION("colo_checkpoint_port", token, oparg)) {
561         replace_string(&nic->colo_checkpoint_port, oparg);
562     } else if (MATCH_OPTION("accel", token, oparg)) {
563         fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
564     } else if (MATCH_OPTION("devid", token, oparg)) {
565         nic->devid = parse_ulong(oparg);
566     } else {
567         fprintf(stderr, "unrecognized argument `%s'\n", token);
568         return 1;
569     }
570     return 0;
571 }
572 
parse_vnuma_config(const XLU_Config * config,libxl_domain_build_info * b_info)573 static void parse_vnuma_config(const XLU_Config *config,
574                                libxl_domain_build_info *b_info)
575 {
576     libxl_physinfo physinfo;
577     uint32_t nr_nodes;
578     XLU_ConfigList *vnuma;
579     int i, j, len, num_vnuma;
580     unsigned long max_vcpus = 0, max_memkb = 0;
581     /* Temporary storage for parsed vcpus information to avoid
582      * parsing config twice. This array has num_vnuma elements.
583      */
584     libxl_bitmap *vcpu_parsed;
585 
586     libxl_physinfo_init(&physinfo);
587     if (libxl_get_physinfo(ctx, &physinfo) != 0) {
588         libxl_physinfo_dispose(&physinfo);
589         fprintf(stderr, "libxl_get_physinfo failed\n");
590         exit(EXIT_FAILURE);
591     }
592 
593     nr_nodes = physinfo.nr_nodes;
594     libxl_physinfo_dispose(&physinfo);
595 
596     if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
597         return;
598 
599     if (!num_vnuma)
600         return;
601 
602     b_info->num_vnuma_nodes = num_vnuma;
603     b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
604     vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
605     for (i = 0; i < num_vnuma; i++) {
606         libxl_bitmap_init(&vcpu_parsed[i]);
607         if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
608             fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
609             exit(EXIT_FAILURE);
610         }
611     }
612 
613     for (i = 0; i < b_info->num_vnuma_nodes; i++) {
614         libxl_vnode_info *p = &b_info->vnuma_nodes[i];
615 
616         libxl_vnode_info_init(p);
617         p->distances = xcalloc(b_info->num_vnuma_nodes,
618                                sizeof(*p->distances));
619         p->num_distances = b_info->num_vnuma_nodes;
620     }
621 
622     for (i = 0; i < num_vnuma; i++) {
623         XLU_ConfigValue *vnode_spec, *conf_option;
624         XLU_ConfigList *vnode_config_list;
625         int conf_count;
626         libxl_vnode_info *p = &b_info->vnuma_nodes[i];
627 
628         vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
629         assert(vnode_spec);
630 
631         xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
632         if (!vnode_config_list) {
633             fprintf(stderr, "xl: cannot get vnode config option list\n");
634             exit(EXIT_FAILURE);
635         }
636 
637         for (conf_count = 0;
638              (conf_option =
639               xlu_cfg_get_listitem2(vnode_config_list, conf_count));
640              conf_count++) {
641 
642             if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
643                 char *buf, *option_untrimmed, *value_untrimmed;
644                 char *option, *value;
645                 unsigned long val;
646 
647                 xlu_cfg_value_get_string(config, conf_option, &buf, 0);
648 
649                 if (!buf) continue;
650 
651                 if (split_string_into_pair(buf, "=",
652                                            &option_untrimmed,
653                                            &value_untrimmed)) {
654                     fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
655                             buf);
656                     exit(EXIT_FAILURE);
657                 }
658                 trim(isspace, option_untrimmed, &option);
659                 trim(isspace, value_untrimmed, &value);
660 
661                 if (!strcmp("pnode", option)) {
662                     val = parse_ulong(value);
663                     if (val >= nr_nodes) {
664                         fprintf(stderr,
665                                 "xl: invalid pnode number: %lu\n", val);
666                         exit(EXIT_FAILURE);
667                     }
668                     p->pnode = val;
669                     libxl_defbool_set(&b_info->numa_placement, false);
670                 } else if (!strcmp("size", option)) {
671                     val = parse_ulong(value);
672                     p->memkb = val << 10;
673                     max_memkb += p->memkb;
674                 } else if (!strcmp("vcpus", option)) {
675                     libxl_string_list cpu_spec_list;
676                     unsigned long s, e;
677 
678                     split_string_into_string_list(value, ",", &cpu_spec_list);
679                     len = libxl_string_list_length(&cpu_spec_list);
680 
681                     for (j = 0; j < len; j++) {
682                         parse_range(cpu_spec_list[j], &s, &e);
683                         for (; s <= e; s++) {
684                             /*
685                              * Note that if we try to set a bit beyond
686                              * the size of bitmap, libxl_bitmap_set
687                              * has no effect. The resulted bitmap
688                              * doesn't reflect what user wants. The
689                              * fallout is dealt with later after
690                              * parsing.
691                              */
692                             libxl_bitmap_set(&vcpu_parsed[i], s);
693                             max_vcpus++;
694                         }
695                     }
696 
697                     libxl_string_list_dispose(&cpu_spec_list);
698                 } else if (!strcmp("vdistances", option)) {
699                     libxl_string_list vdist;
700 
701                     split_string_into_string_list(value, ",", &vdist);
702                     len = libxl_string_list_length(&vdist);
703 
704                     for (j = 0; j < len; j++) {
705                         val = parse_ulong(vdist[j]);
706                         p->distances[j] = val;
707                     }
708                     libxl_string_list_dispose(&vdist);
709                 }
710                 free(option);
711                 free(value);
712                 free(option_untrimmed);
713                 free(value_untrimmed);
714             }
715         }
716     }
717 
718     /* User has specified maxvcpus= */
719     if (b_info->max_vcpus != 0) {
720         if (b_info->max_vcpus != max_vcpus) {
721             fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
722             exit(EXIT_FAILURE);
723         }
724     } else {
725         int host_cpus = libxl_get_online_cpus(ctx);
726 
727         if (host_cpus < 0) {
728             fprintf(stderr, "Failed to get online cpus\n");
729             exit(EXIT_FAILURE);
730         }
731 
732         if (host_cpus < max_vcpus) {
733             fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
734                     "use maxvcpus= to override this check.\n");
735             exit(EXIT_FAILURE);
736         }
737 
738         b_info->max_vcpus = max_vcpus;
739     }
740 
741     /* User has specified maxmem= */
742     if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
743         b_info->max_memkb != max_memkb) {
744         fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
745         exit(EXIT_FAILURE);
746     } else
747         b_info->max_memkb = max_memkb;
748 
749     for (i = 0; i < b_info->num_vnuma_nodes; i++) {
750         libxl_vnode_info *p = &b_info->vnuma_nodes[i];
751 
752         libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
753         libxl_bitmap_dispose(&vcpu_parsed[i]);
754     }
755 
756     free(vcpu_parsed);
757 }
758 
759 /* Parses usbctrl data and adds info into usbctrl
760  * Returns 1 if the input token does not match one of the keys
761  * or parsed values are not correct. Successful parse returns 0 */
parse_usbctrl_config(libxl_device_usbctrl * usbctrl,char * token)762 int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
763 {
764     char *oparg;
765 
766     if (MATCH_OPTION("type", token, oparg)) {
767         if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
768             fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
769             return 1;
770         }
771     } else if (MATCH_OPTION("version", token, oparg)) {
772         usbctrl->version = atoi(oparg);
773     } else if (MATCH_OPTION("ports", token, oparg)) {
774         usbctrl->ports = atoi(oparg);
775     } else {
776         fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
777         return 1;
778     }
779 
780     return 0;
781 }
782 
783 /* Parses usbdev data and adds info into usbdev
784  * Returns 1 if the input token does not match one of the keys
785  * or parsed values are not correct. Successful parse returns 0 */
parse_usbdev_config(libxl_device_usbdev * usbdev,char * token)786 int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
787 {
788     char *oparg;
789 
790     if (MATCH_OPTION("type", token, oparg)) {
791         if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
792             fprintf(stderr, "Invalid usb device type: %s\n", optarg);
793             return 1;
794         }
795     } else if (MATCH_OPTION("hostbus", token, oparg)) {
796         usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
797     } else if (MATCH_OPTION("hostaddr", token, oparg)) {
798         usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
799     } else if (MATCH_OPTION("controller", token, oparg)) {
800         usbdev->ctrl = atoi(oparg);
801     } else if (MATCH_OPTION("port", token, oparg)) {
802         usbdev->port = atoi(oparg);
803     } else {
804         fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
805         return 1;
806     }
807 
808     return 0;
809 }
810 
parse_vdispl_config(libxl_device_vdispl * vdispl,char * token)811 int parse_vdispl_config(libxl_device_vdispl *vdispl, char *token)
812 {
813     char *oparg;
814     libxl_string_list connectors = NULL;
815     int i;
816     int rc;
817 
818     if (MATCH_OPTION("backend", token, oparg)) {
819         vdispl->backend_domname = strdup(oparg);
820     } else if (MATCH_OPTION("be-alloc", token, oparg)) {
821         vdispl->be_alloc = strtoul(oparg, NULL, 0);
822     } else if (MATCH_OPTION("connectors", token, oparg)) {
823         split_string_into_string_list(oparg, ";", &connectors);
824 
825         vdispl->num_connectors = libxl_string_list_length(&connectors);
826         vdispl->connectors = xcalloc(vdispl->num_connectors,
827                                      sizeof(*vdispl->connectors));
828 
829         for(i = 0; i < vdispl->num_connectors; i++)
830         {
831             char *resolution;
832 
833             rc = split_string_into_pair(connectors[i], ":",
834                                         &vdispl->connectors[i].unique_id,
835                                         &resolution);
836 
837             rc= sscanf(resolution, "%ux%u", &vdispl->connectors[i].width,
838                        &vdispl->connectors[i].height);
839             free(resolution);
840 
841             if (rc != 2) {
842                 fprintf(stderr, "Can't parse connector resolution\n");
843                 goto out;
844             }
845         }
846     } else {
847         fprintf(stderr, "Unknown string \"%s\" in vdispl spec\n", token);
848         rc = 1; goto out;
849     }
850 
851     rc = 0;
852 
853 out:
854     libxl_string_list_dispose(&connectors);
855     return rc;
856 }
857 
parse_vsnd_params(libxl_vsnd_params * params,char * token)858 static int parse_vsnd_params(libxl_vsnd_params *params, char *token)
859 {
860     char *oparg;
861     int i;
862 
863     if (MATCH_OPTION(XENSND_FIELD_SAMPLE_RATES, token, oparg)) {
864         libxl_string_list rates = NULL;
865 
866         split_string_into_string_list(oparg, ";", &rates);
867 
868         params->num_sample_rates = libxl_string_list_length(&rates);
869         params->sample_rates = xcalloc(params->num_sample_rates,
870                                        sizeof(*params->sample_rates));
871 
872         for (i = 0; i < params->num_sample_rates; i++) {
873             params->sample_rates[i] = strtoul(rates[i], NULL, 0);
874         }
875 
876         libxl_string_list_dispose(&rates);
877     } else if (MATCH_OPTION(XENSND_FIELD_SAMPLE_FORMATS, token, oparg)) {
878         libxl_string_list formats = NULL;
879 
880         split_string_into_string_list(oparg, ";", &formats);
881 
882         params->num_sample_formats = libxl_string_list_length(&formats);
883         params->sample_formats = xcalloc(params->num_sample_formats,
884                                          sizeof(*params->sample_formats));
885 
886         for (i = 0; i < params->num_sample_formats; i++) {
887             libxl_vsnd_pcm_format format;
888 
889             if (libxl_vsnd_pcm_format_from_string(formats[i], &format)) {
890                 fprintf(stderr, "Invalid pcm format: %s\n", formats[i]);
891                 exit(EXIT_FAILURE);
892             }
893 
894             params->sample_formats[i] = format;
895         }
896 
897         libxl_string_list_dispose(&formats);
898     } else if (MATCH_OPTION(XENSND_FIELD_CHANNELS_MIN, token, oparg)) {
899         params->channels_min = strtoul(oparg, NULL, 0);
900     } else if (MATCH_OPTION(XENSND_FIELD_CHANNELS_MAX, token, oparg)) {
901         params->channels_max = strtoul(oparg, NULL, 0);
902     } else if (MATCH_OPTION(XENSND_FIELD_BUFFER_SIZE, token, oparg)) {
903         params->buffer_size = strtoul(oparg, NULL, 0);
904     } else {
905         return 1;
906     }
907 
908     return 0;
909 }
910 
parse_vsnd_pcm_stream(libxl_device_vsnd * vsnd,char * param)911 static int parse_vsnd_pcm_stream(libxl_device_vsnd *vsnd, char *param)
912 {
913     if (vsnd->num_vsnd_pcms == 0) {
914         fprintf(stderr, "No vsnd pcm device\n");
915         return -1;
916     }
917 
918     libxl_vsnd_pcm *pcm = &vsnd->pcms[vsnd->num_vsnd_pcms - 1];
919 
920     if (pcm->num_vsnd_streams == 0) {
921         fprintf(stderr, "No vsnd stream\n");
922         return -1;
923     }
924 
925     libxl_vsnd_stream *stream = &pcm->streams[pcm->num_vsnd_streams - 1];
926 
927     if (parse_vsnd_params(&stream->params, param)) {
928         char *oparg;
929 
930         if (MATCH_OPTION(XENSND_FIELD_STREAM_UNIQUE_ID, param, oparg)) {
931             stream->unique_id = strdup(oparg);
932         } else if (MATCH_OPTION(XENSND_FIELD_TYPE, param, oparg)) {
933             if (libxl_vsnd_stream_type_from_string(oparg, &stream->type)) {
934                 fprintf(stderr, "Invalid stream type: %s\n", oparg);
935                 return -1;
936             }
937         } else {
938             fprintf(stderr, "Invalid parameter: %s\n", param);
939             return -1;
940         }
941     }
942 
943     return 0;
944 }
945 
parse_vsnd_pcm_param(libxl_device_vsnd * vsnd,char * param)946 static int parse_vsnd_pcm_param(libxl_device_vsnd *vsnd, char *param)
947 {
948     if (vsnd->num_vsnd_pcms == 0) {
949         fprintf(stderr, "No pcm device\n");
950         return -1;
951     }
952 
953     libxl_vsnd_pcm *pcm = &vsnd->pcms[vsnd->num_vsnd_pcms - 1];
954 
955     if (parse_vsnd_params(&pcm->params, param)) {
956         char *oparg;
957 
958         if (MATCH_OPTION(XENSND_FIELD_DEVICE_NAME, param, oparg)) {
959             pcm->name = strdup(oparg);
960         } else {
961             fprintf(stderr, "Invalid parameter: %s\n", param);
962             return -1;
963         }
964     }
965 
966     return 0;
967 }
968 
parse_vsnd_card_param(libxl_device_vsnd * vsnd,char * param)969 static int parse_vsnd_card_param(libxl_device_vsnd *vsnd, char *param)
970 {
971     if (parse_vsnd_params(&vsnd->params, param)) {
972         char *oparg;
973 
974         if (MATCH_OPTION("backend", param, oparg)) {
975             vsnd->backend_domname = strdup(oparg);
976         } else if (MATCH_OPTION(XENSND_FIELD_VCARD_SHORT_NAME, param, oparg)) {
977             vsnd->short_name = strdup(oparg);
978         } else if (MATCH_OPTION(XENSND_FIELD_VCARD_LONG_NAME, param, oparg)) {
979             vsnd->long_name = strdup(oparg);
980         } else {
981             fprintf(stderr, "Invalid parameter: %s\n", param);
982             return -1;
983         }
984     }
985 
986     return 0;
987 }
988 
parse_vsnd_create_item(libxl_device_vsnd * vsnd,const char * key)989 static int parse_vsnd_create_item(libxl_device_vsnd *vsnd, const char *key)
990 {
991     if (strcasecmp(key, "card") == 0) {
992 
993     } else if (strcasecmp(key, "pcm") == 0) {
994         ARRAY_EXTEND_INIT_NODEVID(vsnd->pcms, vsnd->num_vsnd_pcms,
995                                   libxl_vsnd_pcm_init);
996     } else if (strcasecmp(key, "stream") == 0) {
997         if (vsnd->num_vsnd_pcms == 0) {
998             ARRAY_EXTEND_INIT_NODEVID(vsnd->pcms, vsnd->num_vsnd_pcms,
999                                       libxl_vsnd_pcm_init);
1000         }
1001 
1002         libxl_vsnd_pcm *pcm =  &vsnd->pcms[vsnd->num_vsnd_pcms - 1];
1003 
1004         ARRAY_EXTEND_INIT_NODEVID(pcm->streams, pcm->num_vsnd_streams,
1005                                   libxl_vsnd_stream_init);
1006     } else {
1007         fprintf(stderr, "Invalid key: %s\n", key);
1008         return -1;
1009     }
1010 
1011     return 0;
1012 }
1013 
parse_vsnd_item(libxl_device_vsnd * vsnd,const char * spec)1014 int parse_vsnd_item(libxl_device_vsnd *vsnd, const char *spec)
1015 {
1016     char *buf = strdup(spec);
1017     char *token = strtok(buf, ",");
1018     char *key = NULL;
1019     int ret;
1020 
1021     while (token) {
1022         while (*token == ' ') token++;
1023 
1024         if (!key) {
1025             key = token;
1026             ret = parse_vsnd_create_item(vsnd, key);
1027             if (ret) goto out;
1028         } else {
1029             if (strcasecmp(key, "card") == 0) {
1030                 ret = parse_vsnd_card_param(vsnd, token);
1031                 if (ret) goto out;
1032             } else if (strcasecmp(key, "pcm") == 0) {
1033                 ret = parse_vsnd_pcm_param(vsnd, token);
1034                 if (ret) goto out;
1035             } else if (strcasecmp(key, "stream") == 0) {
1036                 ret = parse_vsnd_pcm_stream(vsnd, token);
1037                 if (ret) goto out;
1038             }
1039         }
1040         token = strtok (NULL, ",");
1041     }
1042 
1043     ret = 0;
1044 
1045 out:
1046     free(buf);
1047     return ret;
1048 }
1049 
parse_vsnd_card_config(const XLU_Config * config,XLU_ConfigValue * card_value,libxl_domain_config * d_config)1050 static void parse_vsnd_card_config(const XLU_Config *config,
1051                                    XLU_ConfigValue *card_value,
1052                                    libxl_domain_config *d_config)
1053 {
1054     int ret;
1055     XLU_ConfigList *card_list;
1056     libxl_device_vsnd *vsnd;
1057     const char *card_item;
1058     int item = 0;
1059 
1060     ret = xlu_cfg_value_get_list(config, card_value,  &card_list, 0);
1061 
1062     if (ret) {
1063         fprintf(stderr, "Failed to get vsnd card list: %s\n", strerror(ret));
1064         goto out;
1065     }
1066 
1067     vsnd = ARRAY_EXTEND_INIT(d_config->vsnds,
1068                              d_config->num_vsnds,
1069                              libxl_device_vsnd_init);
1070 
1071     while ((card_item = xlu_cfg_get_listitem(card_list, item++)) != NULL) {
1072         ret = parse_vsnd_item(vsnd, card_item);
1073         if (ret) goto out;
1074     }
1075 
1076     ret = 0;
1077 
1078 out:
1079 
1080     if (ret) exit(EXIT_FAILURE);
1081 }
1082 
parse_vsnd_config(const XLU_Config * config,libxl_domain_config * d_config)1083 static void parse_vsnd_config(const XLU_Config *config,
1084                               libxl_domain_config *d_config)
1085 {
1086     XLU_ConfigList *vsnds;
1087 
1088     if (!xlu_cfg_get_list(config, "vsnd", &vsnds, 0, 0)) {
1089         XLU_ConfigValue *card_value;
1090 
1091         d_config->num_vsnds = 0;
1092         d_config->vsnds = NULL;
1093 
1094         while ((card_value = xlu_cfg_get_listitem2(vsnds, d_config->num_vsnds))
1095                != NULL) {
1096             parse_vsnd_card_config(config, card_value, d_config);
1097         }
1098     }
1099 }
1100 
parse_vkb_config(libxl_device_vkb * vkb,char * token)1101 int parse_vkb_config(libxl_device_vkb *vkb, char *token)
1102 {
1103     char *oparg;
1104 
1105     if (MATCH_OPTION("backend", token, oparg)) {
1106         vkb->backend_domname = strdup(oparg);
1107     } else if (MATCH_OPTION("backend-type", token, oparg)) {
1108         libxl_vkb_backend backend_type;
1109         if (libxl_vkb_backend_from_string(oparg, &backend_type)) {
1110             fprintf(stderr, "Unknown backend_type \"%s\" in vkb spec\n",
1111                             oparg);
1112             return -1;
1113         }
1114         vkb->backend_type = backend_type;
1115     } else if (MATCH_OPTION(XENKBD_FIELD_UNIQUE_ID, token, oparg)) {
1116         vkb->unique_id = strdup(oparg);
1117     } else if (MATCH_OPTION(XENKBD_FIELD_FEAT_DSBL_KEYBRD, token, oparg)) {
1118         vkb->feature_disable_keyboard = strtoul(oparg, NULL, 0);
1119     } else if (MATCH_OPTION(XENKBD_FIELD_FEAT_DSBL_POINTER, token, oparg)) {
1120         vkb->feature_disable_pointer = strtoul(oparg, NULL, 0);
1121     } else if (MATCH_OPTION(XENKBD_FIELD_FEAT_ABS_POINTER, token, oparg)) {
1122         vkb->feature_abs_pointer = strtoul(oparg, NULL, 0);
1123     } else if (MATCH_OPTION(XENKBD_FIELD_FEAT_RAW_POINTER, token, oparg)) {
1124         vkb->feature_raw_pointer = strtoul(oparg, NULL, 0);
1125     } else if (MATCH_OPTION(XENKBD_FIELD_FEAT_MTOUCH, token, oparg)) {
1126         vkb->feature_multi_touch = strtoul(oparg, NULL, 0);
1127     } else if (MATCH_OPTION(XENKBD_FIELD_MT_WIDTH, token, oparg)) {
1128         vkb->multi_touch_width = strtoul(oparg, NULL, 0);
1129     } else if (MATCH_OPTION(XENKBD_FIELD_MT_HEIGHT, token, oparg)) {
1130         vkb->multi_touch_height = strtoul(oparg, NULL, 0);
1131     } else if (MATCH_OPTION(XENKBD_FIELD_MT_NUM_CONTACTS, token, oparg)) {
1132         vkb->multi_touch_num_contacts = strtoul(oparg, NULL, 0);
1133     } else if (MATCH_OPTION(XENKBD_FIELD_WIDTH, token, oparg)) {
1134         vkb->width = strtoul(oparg, NULL, 0);
1135     } else if (MATCH_OPTION(XENKBD_FIELD_HEIGHT, token, oparg)) {
1136         vkb->height = strtoul(oparg, NULL, 0);
1137     } else {
1138         fprintf(stderr, "Unknown string \"%s\" in vkb spec\n", token);
1139         return -1;
1140     }
1141 
1142     return 0;
1143 }
1144 
parse_vkb_list(const XLU_Config * config,libxl_domain_config * d_config)1145 static void parse_vkb_list(const XLU_Config *config,
1146                            libxl_domain_config *d_config)
1147 {
1148     XLU_ConfigList *vkbs;
1149     const char *item;
1150     char *buf = NULL;
1151     int rc;
1152 
1153     if (!xlu_cfg_get_list (config, "vkb", &vkbs, 0, 0)) {
1154         int entry = 0;
1155         while ((item = xlu_cfg_get_listitem(vkbs, entry)) != NULL) {
1156             libxl_device_vkb *vkb;
1157             char *p;
1158 
1159             vkb = ARRAY_EXTEND_INIT(d_config->vkbs,
1160                                     d_config->num_vkbs,
1161                                     libxl_device_vkb_init);
1162 
1163             buf = strdup(item);
1164 
1165             p = strtok (buf, ",");
1166             while (p != NULL)
1167             {
1168                 while (*p == ' ') p++;
1169 
1170                 rc = parse_vkb_config(vkb, p);
1171                 if (rc) goto out;
1172 
1173                 p = strtok (NULL, ",");
1174             }
1175 
1176             if (vkb->backend_type == LIBXL_VKB_BACKEND_UNKNOWN) {
1177                 fprintf(stderr, "backend-type should be set in vkb spec\n");
1178                 rc = ERROR_FAIL; goto out;
1179             }
1180 
1181             if (vkb->multi_touch_height || vkb->multi_touch_width ||
1182                 vkb->multi_touch_num_contacts) {
1183                 vkb->feature_multi_touch = true;
1184             }
1185 
1186             if (vkb->feature_multi_touch && !(vkb->multi_touch_height ||
1187                 vkb->multi_touch_width || vkb->multi_touch_num_contacts)) {
1188                 fprintf(stderr, XENKBD_FIELD_MT_WIDTH", "XENKBD_FIELD_MT_HEIGHT", "
1189                                 XENKBD_FIELD_MT_NUM_CONTACTS" should be set for "
1190                                 "multi touch in vkb spec\n");
1191                 rc = ERROR_FAIL; goto out;
1192             }
1193 
1194             entry++;
1195         }
1196     }
1197 
1198     rc = 0;
1199 
1200 out:
1201     free(buf);
1202     if (rc) exit(EXIT_FAILURE);
1203 }
1204 
parse_config_data(const char * config_source,const char * config_data,int config_len,libxl_domain_config * d_config)1205 void parse_config_data(const char *config_source,
1206                        const char *config_data,
1207                        int config_len,
1208                        libxl_domain_config *d_config)
1209 {
1210     libxl_physinfo physinfo;
1211     const char *buf;
1212     long l, vcpus = 0;
1213     XLU_Config *config;
1214     XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
1215                    *usbctrls, *usbdevs, *p9devs, *vdispls, *pvcallsifs_devs;
1216     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs,
1217                    *mca_caps;
1218     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps;
1219     int pci_power_mgmt = 0;
1220     int pci_msitranslate = 0;
1221     int pci_permissive = 0;
1222     int pci_seize = 0;
1223     int i, e;
1224     char *kernel_basename;
1225 
1226     libxl_domain_create_info *c_info = &d_config->c_info;
1227     libxl_domain_build_info *b_info = &d_config->b_info;
1228 
1229     libxl_physinfo_init(&physinfo);
1230     if (libxl_get_physinfo(ctx, &physinfo) != 0) {
1231         libxl_physinfo_dispose(&physinfo);
1232         fprintf(stderr, "libxl_get_physinfo failed\n");
1233         exit(EXIT_FAILURE);
1234     }
1235 
1236     libxl_physinfo_dispose(&physinfo);
1237 
1238     config= xlu_cfg_init(stderr, config_source);
1239     if (!config) {
1240         fprintf(stderr, "Failed to allocate for configuration\n");
1241         exit(1);
1242     }
1243 
1244     e= xlu_cfg_readdata(config, config_data, config_len);
1245     if (e) {
1246         fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
1247         exit(1);
1248     }
1249 
1250     if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
1251         xlu_cfg_replace_string(config, "init_seclabel",
1252                                &c_info->ssid_label, 0);
1253 
1254     if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
1255         if (c_info->ssid_label)
1256             xlu_cfg_replace_string(config, "seclabel",
1257                                    &b_info->exec_ssid_label, 0);
1258         else
1259             xlu_cfg_replace_string(config, "seclabel",
1260                                    &c_info->ssid_label, 0);
1261     }
1262 
1263     libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
1264 
1265     if (!xlu_cfg_get_string(config, "type", &buf, 0)) {
1266         if (!strncmp(buf, "hvm", strlen(buf)))
1267             c_info->type = LIBXL_DOMAIN_TYPE_HVM;
1268         else if (!strncmp(buf, "pv", strlen(buf)))
1269             c_info->type = LIBXL_DOMAIN_TYPE_PV;
1270         else if (!strncmp(buf, "pvh", strlen(buf)))
1271             c_info->type = LIBXL_DOMAIN_TYPE_PVH;
1272         else {
1273             fprintf(stderr, "Invalid domain type %s.\n", buf);
1274             exit(1);
1275         }
1276     }
1277 
1278     /* Deprecated since Xen 4.10. */
1279     if (!xlu_cfg_get_string(config, "builder", &buf, 0)) {
1280         libxl_domain_type builder_type;
1281 
1282         if (!strncmp(buf, "hvm", strlen(buf)))
1283             builder_type = LIBXL_DOMAIN_TYPE_HVM;
1284         else if (!strncmp(buf, "generic", strlen(buf)))
1285             builder_type = LIBXL_DOMAIN_TYPE_PV;
1286         else {
1287             fprintf(stderr, "Invalid domain type %s.\n", buf);
1288             exit(1);
1289         }
1290 
1291         if (c_info->type != LIBXL_DOMAIN_TYPE_INVALID &&
1292             c_info->type != builder_type) {
1293             fprintf(stderr,
1294             "Contradicting \"builder\" and \"type\" options specified.\n");
1295             exit(1);
1296         }
1297         c_info->type = builder_type;
1298     }
1299 
1300     if (c_info->type == LIBXL_DOMAIN_TYPE_INVALID)
1301 #if defined(__arm__) || defined(__aarch64__)
1302         c_info->type = LIBXL_DOMAIN_TYPE_PVH;
1303 #else
1304         c_info->type = LIBXL_DOMAIN_TYPE_PV;
1305 #endif
1306 
1307     xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
1308 
1309     if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
1310         fprintf(stderr, "Domain name must be specified.\n");
1311         exit(1);
1312     }
1313 
1314     if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
1315         if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
1316             fprintf(stderr, "Failed to parse UUID: %s\n", buf);
1317             exit(1);
1318         }
1319     }else{
1320         libxl_uuid_generate(&c_info->uuid);
1321     }
1322 
1323     xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
1324 
1325     if (!xlu_cfg_get_string (config, "pool", &buf, 0))
1326         xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
1327 
1328     libxl_domain_build_info_init_type(b_info, c_info->type);
1329 
1330     if (b_info->type == LIBXL_DOMAIN_TYPE_PVH) {
1331         xlu_cfg_get_defbool(config, "pvshim", &b_info->u.pvh.pvshim, 0);
1332         if (!xlu_cfg_get_string(config, "pvshim_path", &buf, 0))
1333             xlu_cfg_replace_string(config, "pvshim_path",
1334                                    &b_info->u.pvh.pvshim_path, 0);
1335         if (!xlu_cfg_get_string(config, "pvshim_cmdline", &buf, 0))
1336             xlu_cfg_replace_string(config, "pvshim_cmdline",
1337                                    &b_info->u.pvh.pvshim_cmdline, 0);
1338         if (!xlu_cfg_get_string(config, "pvshim_extra", &buf, 0))
1339             xlu_cfg_replace_string(config, "pvshim_extra",
1340                                    &b_info->u.pvh.pvshim_extra, 0);
1341     }
1342 
1343     if (blkdev_start)
1344         b_info->blkdev_start = strdup(blkdev_start);
1345 
1346     /* the following is the actual config parsing with overriding
1347      * values in the structures */
1348     if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
1349         b_info->sched_params.weight = l;
1350     if (!xlu_cfg_get_long (config, "cap", &l, 0))
1351         b_info->sched_params.cap = l;
1352     if (!xlu_cfg_get_long (config, "period", &l, 0))
1353         b_info->sched_params.period = l;
1354     if (!xlu_cfg_get_long (config, "slice", &l, 0))
1355         b_info->sched_params.slice = l;
1356     if (!xlu_cfg_get_long (config, "latency", &l, 0))
1357         b_info->sched_params.latency = l;
1358     if (!xlu_cfg_get_long (config, "extratime", &l, 0))
1359         b_info->sched_params.extratime = l;
1360 
1361     if (!xlu_cfg_get_long (config, "memory", &l, 0))
1362         b_info->target_memkb = l * 1024;
1363 
1364     if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
1365         b_info->max_memkb = l * 1024;
1366 
1367     if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
1368         vcpus = l;
1369         if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
1370             fprintf(stderr, "Unable to allocate cpumap\n");
1371             exit(1);
1372         }
1373         libxl_bitmap_set_none(&b_info->avail_vcpus);
1374         while (l-- > 0)
1375             libxl_bitmap_set((&b_info->avail_vcpus), l);
1376     }
1377 
1378     if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
1379         b_info->max_vcpus = l;
1380 
1381     if (!xlu_cfg_get_string(config, "vuart", &buf, 0)) {
1382         if (libxl_vuart_type_from_string(buf, &b_info->arch_arm.vuart)) {
1383             fprintf(stderr, "ERROR: invalid value \"%s\" for \"vuart\"\n",
1384                     buf);
1385             exit(1);
1386         }
1387     }
1388 
1389     parse_vnuma_config(config, b_info);
1390 
1391     /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
1392      * they are not set by user specified config option or vnuma.
1393      */
1394     if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
1395         b_info->max_memkb = b_info->target_memkb;
1396     if (b_info->max_vcpus == 0)
1397         b_info->max_vcpus = vcpus;
1398 
1399     if (b_info->max_vcpus < vcpus) {
1400         fprintf(stderr, "xl: maxvcpus < vcpus\n");
1401         exit(1);
1402     }
1403 
1404     buf = NULL;
1405     if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
1406         !xlu_cfg_get_string (config, "cpus", &buf, 0))
1407         parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
1408 
1409     buf = NULL;
1410     if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
1411         !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
1412         parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
1413 
1414     e = xlu_cfg_get_bounded_long (config, "max_grant_frames", 0, INT_MAX,
1415                                   &l, 1);
1416     if (e == ESRCH) /* not specified */
1417         b_info->max_grant_frames = max_grant_frames;
1418     else if (!e)
1419         b_info->max_grant_frames = l;
1420     else
1421         exit(1);
1422 
1423     e = xlu_cfg_get_bounded_long (config, "max_maptrack_frames", 0,
1424                                   INT_MAX, &l, 1);
1425     if (e == ESRCH) /* not specified */
1426         b_info->max_maptrack_frames = max_maptrack_frames;
1427     else if (!e)
1428         b_info->max_maptrack_frames = l;
1429     else
1430         exit(1);
1431 
1432     libxl_defbool_set(&b_info->claim_mode, claim_mode);
1433 
1434     if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
1435         buf = "destroy";
1436     if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
1437         fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
1438         exit(1);
1439     }
1440 
1441     if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
1442         buf = "restart";
1443     if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
1444         fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
1445         exit(1);
1446     }
1447 
1448     if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
1449         buf = "destroy";
1450     if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
1451         fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
1452         exit(1);
1453     }
1454 
1455 
1456     if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
1457         buf = "destroy";
1458     if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
1459         fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
1460         exit(1);
1461     }
1462 
1463     if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
1464         buf = "soft-reset";
1465     if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
1466         fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
1467         exit(1);
1468     }
1469 
1470     if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
1471         d_config->num_pcidevs = 0;
1472         d_config->pcidevs = NULL;
1473         for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
1474             libxl_device_pci *pcidev;
1475 
1476             pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
1477                                                d_config->num_pcidevs,
1478                                                libxl_device_pci_init);
1479             pcidev->msitranslate = pci_msitranslate;
1480             pcidev->power_mgmt = pci_power_mgmt;
1481             pcidev->permissive = pci_permissive;
1482             pcidev->seize = pci_seize;
1483             /*
1484              * Like other pci option, the per-device policy always follows
1485              * the global policy by default.
1486              */
1487             pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
1488             e = xlu_pci_parse_bdf(config, pcidev, buf);
1489             if (e) {
1490                 fprintf(stderr,
1491                         "unable to parse PCI BDF `%s' for passthrough\n",
1492                         buf);
1493                 exit(-e);
1494             }
1495         }
1496         if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
1497             libxl_defbool_set(&b_info->u.pv.e820_host, true);
1498     }
1499 
1500     if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
1501         d_config->num_dtdevs = 0;
1502         d_config->dtdevs = NULL;
1503         for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
1504             libxl_device_dtdev *dtdev;
1505 
1506             dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
1507                                               d_config->num_dtdevs,
1508                                               libxl_device_dtdev_init);
1509 
1510             dtdev->path = strdup(buf);
1511             if (dtdev->path == NULL) {
1512                 fprintf(stderr, "unable to duplicate string for dtdevs\n");
1513                 exit(-1);
1514             }
1515         }
1516     }
1517 
1518     if (!xlu_cfg_get_string(config, "passthrough", &buf, 0)) {
1519         if (libxl_passthrough_from_string(buf, &c_info->passthrough)) {
1520             fprintf(stderr,
1521                     "ERROR: unknown passthrough option '%s'\n",
1522                     buf);
1523             exit(1);
1524         }
1525     }
1526 
1527     if (!xlu_cfg_get_long(config, "shadow_memory", &l, 0))
1528         b_info->shadow_memkb = l * 1024;
1529 
1530     xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
1531 
1532     if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
1533         const char *s = libxl_tsc_mode_to_string(l);
1534         fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
1535                 "Please use the named parameter variant. %s%s%s\n",
1536                 s ? "e.g. tsc_mode=\"" : "",
1537                 s ? s : "",
1538                 s ? "\"" : "");
1539 
1540         if (l < LIBXL_TSC_MODE_DEFAULT ||
1541             l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
1542             fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
1543             exit (1);
1544         }
1545         b_info->tsc_mode = l;
1546     } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
1547         fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
1548         if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
1549             fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
1550                     buf);
1551             exit (1);
1552         }
1553     }
1554 
1555     if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
1556         b_info->rtc_timeoffset = l;
1557 
1558     if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
1559         fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
1560                 "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
1561 
1562     xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
1563 
1564     if (!xlu_cfg_get_long (config, "videoram", &l, 0))
1565         b_info->video_memkb = l * 1024;
1566 
1567     if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
1568         b_info->event_channels = l;
1569 
1570     xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
1571     xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
1572     xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
1573     b_info->cmdline = parse_cmdline(config);
1574 
1575     xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
1576     xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
1577 
1578     xlu_cfg_replace_string (config, "bootloader", &b_info->bootloader, 0);
1579     switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
1580                                             &b_info->bootloader_args, 1)) {
1581     case 0:
1582         break; /* Success */
1583     case ESRCH: break; /* Option not present */
1584     case EINVAL:
1585         if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
1586 
1587             fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
1588                     " as a string is deprecated. "
1589                     "Please use a list of arguments.\n");
1590             split_string_into_string_list(buf, " \t\n",
1591                                           &b_info->bootloader_args);
1592         }
1593         break;
1594     default:
1595         fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
1596         exit(-ERROR_FAIL);
1597     }
1598 
1599     if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
1600         const char *s = libxl_timer_mode_to_string(l);
1601 
1602         if (b_info->type == LIBXL_DOMAIN_TYPE_PV) {
1603             fprintf(stderr,
1604             "ERROR: \"timer_mode\" option is not supported for PV guests.\n");
1605             exit(-ERROR_FAIL);
1606         }
1607 
1608         fprintf(stderr,
1609         "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
1610         "Please use the named parameter variant. %s%s%s\n",
1611                 s ? "e.g. timer_mode=\"" : "",
1612                 s ? s : "",
1613                 s ? "\"" : "");
1614 
1615         if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
1616             l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
1617             fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n",
1618                     l);
1619             exit (1);
1620         }
1621         b_info->timer_mode = l;
1622     } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
1623         if (b_info->type == LIBXL_DOMAIN_TYPE_PV) {
1624             fprintf(stderr,
1625             "ERROR: \"timer_mode\" option is not supported for PV guests.\n");
1626             exit(-ERROR_FAIL);
1627         }
1628 
1629         if (libxl_timer_mode_from_string(buf, &b_info->timer_mode)) {
1630             fprintf(stderr,
1631                     "ERROR: invalid value \"%s\" for \"timer_mode\"\n", buf);
1632             exit (1);
1633         }
1634     }
1635 
1636     xlu_cfg_get_defbool(config, "nestedhvm", &b_info->nested_hvm, 0);
1637 
1638     switch(b_info->type) {
1639     case LIBXL_DOMAIN_TYPE_HVM:
1640         kernel_basename = libxl_basename(b_info->kernel);
1641         if (!strcmp(kernel_basename, "hvmloader")) {
1642             fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
1643                     "directive to override HVM guest firmware. Ignore "
1644                     "that. Use \"firmware_override\" instead if you "
1645                     "really want a non-default firmware\n");
1646             b_info->kernel = NULL;
1647         }
1648         free(kernel_basename);
1649 
1650         xlu_cfg_replace_string (config, "firmware_override",
1651                                 &b_info->u.hvm.firmware, 0);
1652         xlu_cfg_replace_string (config, "bios_path_override",
1653                                 &b_info->u.hvm.system_firmware, 0);
1654         if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
1655             if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
1656                 fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
1657                     buf);
1658                 exit (1);
1659             }
1660         } else if (b_info->u.hvm.system_firmware)
1661             fprintf(stderr, "WARNING: "
1662                     "bios_path_override given without specific bios name\n");
1663 
1664         xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
1665         xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
1666         xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
1667         xlu_cfg_get_defbool(config, "acpi_laptop_slate", &b_info->u.hvm.acpi_laptop_slate, 0);
1668         xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
1669         xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
1670         xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
1671         xlu_cfg_get_defbool(config, "apic", &b_info->apic, 0);
1672 
1673         switch (xlu_cfg_get_list(config, "viridian",
1674                                  &viridian, &num_viridian, 1))
1675         {
1676         case 0: /* Success */
1677             if (num_viridian) {
1678                 libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
1679                                    LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
1680                 libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
1681                                    LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
1682             }
1683             for (i = 0; i < num_viridian; i++) {
1684                 libxl_viridian_enlightenment v;
1685 
1686                 buf = xlu_cfg_get_listitem(viridian, i);
1687                 if (strcmp(buf, "all") == 0)
1688                     libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
1689                 else if (strcmp(buf, "defaults") == 0)
1690                     libxl_defbool_set(&b_info->u.hvm.viridian, true);
1691                 else {
1692                     libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
1693                     libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
1694 
1695                     if (*buf == '!') {
1696                         s = &b_info->u.hvm.viridian_disable;
1697                         r = &b_info->u.hvm.viridian_enable;
1698                         buf++;
1699                     }
1700 
1701                     e = libxl_viridian_enlightenment_from_string(buf, &v);
1702                     if (e) {
1703                         fprintf(stderr,
1704                                 "xl: unknown viridian enlightenment '%s'\n",
1705                                 buf);
1706                         exit(-ERROR_FAIL);
1707                     }
1708 
1709                     libxl_bitmap_set(s, v);
1710                     libxl_bitmap_reset(r, v);
1711                 }
1712             }
1713             break;
1714         case ESRCH: break; /* Option not present */
1715         case EINVAL:
1716             xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
1717             break;
1718         default:
1719             fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
1720             exit(-ERROR_FAIL);
1721         }
1722 
1723         if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
1724             uint64_t mmio_hole_size;
1725 
1726             b_info->u.hvm.mmio_hole_memkb = l * 1024;
1727             mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
1728             if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
1729                 mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
1730                 fprintf(stderr,
1731                         "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
1732                 exit (1);
1733             }
1734         }
1735 
1736         if (!xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0))
1737             fprintf(stderr, "WARNING: Specifying \"altp2mhvm\" is deprecated. "
1738                     "Please use \"altp2m\" instead.\n");
1739 
1740         xlu_cfg_replace_string(config, "smbios_firmware",
1741                                &b_info->u.hvm.smbios_firmware, 0);
1742         xlu_cfg_replace_string(config, "acpi_firmware",
1743                                &b_info->u.hvm.acpi_firmware, 0);
1744 
1745         if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
1746             if (!strcmp(buf, "generate")) {
1747                 e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
1748                 if (e) {
1749                     fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
1750                     exit(1);
1751                 }
1752             } else if (!strcmp(buf, "none")) {
1753                 ;
1754             } else {
1755                     fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
1756                     exit(1);
1757             }
1758         }
1759 
1760         if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
1761             b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
1762 
1763         switch (xlu_cfg_get_list(config, "mca_caps",
1764                                  &mca_caps, &num_mca_caps, 1))
1765         {
1766         case 0: /* Success */
1767             for (i = 0; i < num_mca_caps; i++) {
1768                 buf = xlu_cfg_get_listitem(mca_caps, i);
1769                 if (!strcmp(buf, "lmce"))
1770                     b_info->u.hvm.mca_caps |= XEN_HVM_MCA_CAP_LMCE;
1771                 else {
1772                     fprintf(stderr, "ERROR: unrecognized MCA capability '%s'.\n",
1773                             buf);
1774                     exit(-ERROR_FAIL);
1775                 }
1776             }
1777             break;
1778 
1779         case ESRCH: /* Option not present */
1780             break;
1781 
1782         default:
1783             fprintf(stderr, "ERROR: unable to parse mca_caps.\n");
1784             exit(-ERROR_FAIL);
1785         }
1786 
1787         /*
1788          * The firmware config option can be used as a simplification
1789          * instead of setting bios or firmware_override. It has the
1790          * following meanings for HVM guests:
1791          *
1792          *  - ovmf | seabios | rombios: maps directly into the "bios"
1793          *    option.
1794          *  - uefi | bios: maps into one of the above options and is set
1795          *    in the bios field.
1796          *  - Anything else is treated as a path that is copied into
1797          *    firmware.
1798          */
1799         if (!xlu_cfg_get_string (config, "firmware", &buf, 0) &&
1800             libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
1801             if (!strncmp(buf, "uefi", strlen(buf)))
1802                 b_info->u.hvm.bios = LIBXL_BIOS_TYPE_OVMF;
1803             else if (strncmp(buf, "bios", strlen(buf)))
1804                 /* Assume it's a path to a custom firmware. */
1805                 xlu_cfg_replace_string(config, "firmware",
1806                                        &b_info->u.hvm.firmware, 0);
1807             /*
1808              * BIOS is the default, and will be chosen by libxl based on
1809              * the device model specified.
1810              */
1811         }
1812 
1813         break;
1814     case LIBXL_DOMAIN_TYPE_PVH:
1815     case LIBXL_DOMAIN_TYPE_PV:
1816     {
1817         /*
1818          * The firmware config option can be used as a simplification
1819          * instead of directly setting kernel. It will be translated to
1820          * XENFIRMWAREDIR/<string>.bin
1821          */
1822         if (!xlu_cfg_get_string (config, "firmware", &buf, 0)) {
1823             if (b_info->kernel) {
1824                 fprintf(stderr,
1825                         "ERROR: both kernel and firmware specified\n");
1826                 exit(1);
1827             }
1828             if (strncmp(buf, "pvgrub32", strlen(buf)) &&
1829                 strncmp(buf, "pvgrub64", strlen(buf))) {
1830                 fprintf(stderr,
1831             "ERROR: only pvgrub{32|64} supported as firmware options\n");
1832                 exit(1);
1833             }
1834 
1835             xasprintf(&b_info->kernel, XENFIRMWAREDIR "/%s.bin", buf);
1836         }
1837         if (!b_info->bootloader && !b_info->kernel) {
1838             fprintf(stderr, "Neither kernel nor bootloader specified\n");
1839             exit(1);
1840         }
1841 
1842         break;
1843     }
1844     default:
1845         abort();
1846     }
1847 
1848     if (!xlu_cfg_get_long(config, "altp2m", &l, 1)) {
1849         if (l < LIBXL_ALTP2M_MODE_DISABLED ||
1850             l > LIBXL_ALTP2M_MODE_LIMITED) {
1851             fprintf(stderr, "ERROR: invalid value %ld for \"altp2m\"\n", l);
1852             exit (1);
1853         }
1854 
1855         b_info->altp2m = l;
1856     } else if (!xlu_cfg_get_string(config, "altp2m", &buf, 0)) {
1857         if (libxl_altp2m_mode_from_string(buf, &b_info->altp2m)) {
1858             fprintf(stderr, "ERROR: invalid value \"%s\" for \"altp2m\"\n",
1859                     buf);
1860             exit (1);
1861         }
1862     }
1863 
1864     if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
1865         b_info->num_ioports = num_ioports;
1866         b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
1867         if (b_info->ioports == NULL) {
1868             fprintf(stderr, "unable to allocate memory for ioports\n");
1869             exit(-1);
1870         }
1871 
1872         for (i = 0; i < num_ioports; i++) {
1873             const char *buf2;
1874             char *ep;
1875             uint32_t start, end;
1876             unsigned long ul;
1877 
1878             buf = xlu_cfg_get_listitem (ioports, i);
1879             if (!buf) {
1880                 fprintf(stderr,
1881                         "xl: Unable to get element #%d in ioport list\n", i);
1882                 exit(1);
1883             }
1884             ul = strtoul(buf, &ep, 16);
1885             if (ep == buf) {
1886                 fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
1887                         buf);
1888                 exit(1);
1889             }
1890             if (ul >= UINT32_MAX) {
1891                 fprintf(stderr, "xl: ioport %lx too big\n", ul);
1892                 exit(1);
1893             }
1894             start = end = ul;
1895 
1896             if (*ep == '-') {
1897                 buf2 = ep + 1;
1898                 ul = strtoul(buf2, &ep, 16);
1899                 if (ep == buf2 || *ep != '\0' || start > end) {
1900                     fprintf(stderr,
1901                             "xl: Invalid argument parsing ioport: %s\n", buf);
1902                     exit(1);
1903                 }
1904                 if (ul >= UINT32_MAX) {
1905                     fprintf(stderr, "xl: ioport %lx too big\n", ul);
1906                     exit(1);
1907                 }
1908                 end = ul;
1909             } else if ( *ep != '\0' )
1910                 fprintf(stderr,
1911                         "xl: Invalid argument parsing ioport: %s\n", buf);
1912             b_info->ioports[i].first = start;
1913             b_info->ioports[i].number = end - start + 1;
1914         }
1915     }
1916 
1917     if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
1918         b_info->num_irqs = num_irqs;
1919         b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
1920         if (b_info->irqs == NULL) {
1921             fprintf(stderr, "unable to allocate memory for ioports\n");
1922             exit(-1);
1923         }
1924         for (i = 0; i < num_irqs; i++) {
1925             char *ep;
1926             unsigned long ul;
1927             buf = xlu_cfg_get_listitem (irqs, i);
1928             if (!buf) {
1929                 fprintf(stderr,
1930                         "xl: Unable to get element %d in irq list\n", i);
1931                 exit(1);
1932             }
1933             ul = strtoul(buf, &ep, 10);
1934             if (ep == buf || *ep != '\0') {
1935                 fprintf(stderr,
1936                         "xl: Invalid argument parsing irq: %s\n", buf);
1937                 exit(1);
1938             }
1939             if (ul >= UINT32_MAX) {
1940                 fprintf(stderr, "xl: irq %lx too big\n", ul);
1941                 exit(1);
1942             }
1943             b_info->irqs[i] = ul;
1944         }
1945     }
1946 
1947     if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
1948         int ret;
1949         b_info->num_iomem = num_iomem;
1950         b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
1951         if (b_info->iomem == NULL) {
1952             fprintf(stderr, "unable to allocate memory for iomem\n");
1953             exit(-1);
1954         }
1955         for (i = 0; i < num_iomem; i++) {
1956             int used;
1957 
1958             buf = xlu_cfg_get_listitem (iomem, i);
1959             if (!buf) {
1960                 fprintf(stderr,
1961                         "xl: Unable to get element %d in iomem list\n", i);
1962                 exit(1);
1963             }
1964             libxl_iomem_range_init(&b_info->iomem[i]);
1965             ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
1966                          &b_info->iomem[i].start,
1967                          &b_info->iomem[i].number, &used,
1968                          &b_info->iomem[i].gfn, &used);
1969             if (ret < 2 || buf[used] != '\0') {
1970                 fprintf(stderr,
1971                         "xl: Invalid argument parsing iomem: %s\n", buf);
1972                 exit(1);
1973             }
1974         }
1975     }
1976 
1977 
1978 
1979     if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
1980         d_config->num_disks = 0;
1981         d_config->disks = NULL;
1982         while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
1983             libxl_device_disk *disk;
1984             char *buf2 = strdup(buf);
1985 
1986             disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
1987                                              d_config->num_disks,
1988                                              libxl_device_disk_init);
1989             parse_disk_config(&config, buf2, disk);
1990 
1991             free(buf2);
1992         }
1993     }
1994 
1995     if (!xlu_cfg_get_list(config, "p9", &p9devs, 0, 0)) {
1996         libxl_device_p9 *p9;
1997         char *security_model = NULL;
1998         char *path = NULL;
1999         char *tag = NULL;
2000         char *backend = NULL;
2001         char *p, *p2, *buf2;
2002 
2003         d_config->num_p9s = 0;
2004         d_config->p9s = NULL;
2005         while ((buf = xlu_cfg_get_listitem (p9devs, d_config->num_p9s)) != NULL) {
2006             p9 = ARRAY_EXTEND_INIT(d_config->p9s,
2007                                    d_config->num_p9s,
2008                                    libxl_device_p9_init);
2009             libxl_device_p9_init(p9);
2010 
2011             buf2 = strdup(buf);
2012             p = strtok(buf2, ",");
2013             if(p) {
2014                do {
2015                   while(*p == ' ')
2016                      ++p;
2017                   if ((p2 = strchr(p, '=')) == NULL)
2018                      break;
2019                   *p2 = '\0';
2020                   if (!strcmp(p, "security_model")) {
2021                      security_model = strdup(p2 + 1);
2022                   } else if(!strcmp(p, "path")) {
2023                      path = strdup(p2 + 1);
2024                   } else if(!strcmp(p, "tag")) {
2025                      tag = strdup(p2 + 1);
2026                   } else if(!strcmp(p, "backend")) {
2027                      backend = strdup(p2 + 1);
2028                   } else {
2029                      fprintf(stderr, "Unknown string `%s' in 9pfs spec\n", p);
2030                      exit(1);
2031                   }
2032                } while ((p = strtok(NULL, ",")) != NULL);
2033             }
2034             if (!path || !security_model || !tag) {
2035                fprintf(stderr, "9pfs spec missing required field!\n");
2036                exit(1);
2037             }
2038             free(buf2);
2039 
2040             replace_string(&p9->tag, tag);
2041             replace_string(&p9->security_model, security_model);
2042             replace_string(&p9->path, path);
2043             if (backend)
2044                     replace_string(&p9->backend_domname, backend);
2045         }
2046     }
2047 
2048     if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
2049         d_config->num_vtpms = 0;
2050         d_config->vtpms = NULL;
2051         while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
2052             libxl_device_vtpm *vtpm;
2053             char * buf2 = strdup(buf);
2054             char *p, *p2;
2055             bool got_backend = false;
2056 
2057             vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
2058                                      d_config->num_vtpms,
2059                                      libxl_device_vtpm_init);
2060 
2061             p = strtok(buf2, ",");
2062             if(p) {
2063                do {
2064                   while(*p == ' ')
2065                      ++p;
2066                   if ((p2 = strchr(p, '=')) == NULL)
2067                      break;
2068                   *p2 = '\0';
2069                   if (!strcmp(p, "backend")) {
2070                      vtpm->backend_domname = strdup(p2 + 1);
2071                      got_backend = true;
2072                   } else if(!strcmp(p, "uuid")) {
2073                      if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
2074                         fprintf(stderr,
2075                               "Failed to parse vtpm UUID: %s\n", p2 + 1);
2076                         exit(1);
2077                     }
2078                   } else {
2079                      fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
2080                      exit(1);
2081                   }
2082                } while ((p = strtok(NULL, ",")) != NULL);
2083             }
2084             if(!got_backend) {
2085                fprintf(stderr, "vtpm spec missing required backend field!\n");
2086                exit(1);
2087             }
2088             free(buf2);
2089         }
2090     }
2091 
2092     if (!xlu_cfg_get_list(config, "vdispl", &vdispls, 0, 0)) {
2093         d_config->num_vdispls = 0;
2094         d_config->vdispls = NULL;
2095         while ((buf = xlu_cfg_get_listitem(vdispls, d_config->num_vdispls)) != NULL) {
2096             libxl_device_vdispl *vdispl;
2097             char * buf2 = strdup(buf);
2098             char *p;
2099             vdispl = ARRAY_EXTEND_INIT(d_config->vdispls,
2100                                        d_config->num_vdispls,
2101                                        libxl_device_vdispl_init);
2102             p = strtok (buf2, ",");
2103             while (p != NULL)
2104             {
2105                 while (*p == ' ') p++;
2106                 if (parse_vdispl_config(vdispl, p)) {
2107                     free(buf2);
2108                     exit(1);
2109                 }
2110                 p = strtok (NULL, ",");
2111             }
2112             free(buf2);
2113             if (vdispl->num_connectors == 0) {
2114                 fprintf(stderr, "At least one connector should be specified.\n");
2115                 exit(1);
2116             }
2117         }
2118     }
2119 
2120     if (!xlu_cfg_get_list(config, "pvcalls", &pvcallsifs_devs, 0, 0)) {
2121         d_config->num_pvcallsifs = 0;
2122         d_config->pvcallsifs = NULL;
2123         while ((buf = xlu_cfg_get_listitem (pvcallsifs_devs, d_config->num_pvcallsifs)) != NULL) {
2124             libxl_device_pvcallsif *pvcallsif;
2125             char *backend = NULL;
2126             char *p, *p2, *buf2;
2127             pvcallsif = ARRAY_EXTEND_INIT(d_config->pvcallsifs,
2128                                           d_config->num_pvcallsifs,
2129                                           libxl_device_pvcallsif_init);
2130 
2131             buf2 = strdup(buf);
2132             p = strtok(buf2, ",");
2133             if (p) {
2134                do {
2135                   while (*p == ' ')
2136                      ++p;
2137                   if ((p2 = strchr(p, '=')) == NULL)
2138                      break;
2139                   *p2 = '\0';
2140                   if(!strcmp(p, "backend")) {
2141                      backend = strdup(p2 + 1);
2142                   } else {
2143                      fprintf(stderr, "Unknown string `%s' in pvcalls spec\n", p);
2144                      exit(1);
2145                   }
2146                } while ((p = strtok(NULL, ",")) != NULL);
2147             }
2148             free(buf2);
2149 
2150             if (backend)
2151                     replace_string(&pvcallsif->backend_domname, backend);
2152         }
2153     }
2154 
2155     parse_vsnd_config(config, d_config);
2156 
2157     if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
2158         d_config->num_channels = 0;
2159         d_config->channels = NULL;
2160         while ((buf = xlu_cfg_get_listitem (channels,
2161                 d_config->num_channels)) != NULL) {
2162             libxl_device_channel *chn;
2163             libxl_string_list pairs;
2164             char *path = NULL;
2165             int len;
2166 
2167             chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
2168                                    libxl_device_channel_init);
2169 
2170             split_string_into_string_list(buf, ",", &pairs);
2171             len = libxl_string_list_length(&pairs);
2172             for (i = 0; i < len; i++) {
2173                 char *key, *key_untrimmed, *value, *value_untrimmed;
2174                 int rc;
2175                 rc = split_string_into_pair(pairs[i], "=",
2176                                             &key_untrimmed,
2177                                             &value_untrimmed);
2178                 if (rc != 0) {
2179                     fprintf(stderr, "failed to parse channel configuration: %s",
2180                             pairs[i]);
2181                     exit(1);
2182                 }
2183                 trim(isspace, key_untrimmed, &key);
2184                 trim(isspace, value_untrimmed, &value);
2185 
2186                 if (!strcmp(key, "backend")) {
2187                     replace_string(&chn->backend_domname, value);
2188                 } else if (!strcmp(key, "name")) {
2189                     replace_string(&chn->name, value);
2190                 } else if (!strcmp(key, "path")) {
2191                     replace_string(&path, value);
2192                 } else if (!strcmp(key, "connection")) {
2193                     if (!strcmp(value, "pty")) {
2194                         chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
2195                     } else if (!strcmp(value, "socket")) {
2196                         chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
2197                     } else {
2198                         fprintf(stderr, "unknown channel connection '%s'\n",
2199                                 value);
2200                         exit(1);
2201                     }
2202                 } else {
2203                     fprintf(stderr, "unknown channel parameter '%s',"
2204                                   " ignoring\n", key);
2205                 }
2206                 free(key);
2207                 free(key_untrimmed);
2208                 free(value);
2209                 free(value_untrimmed);
2210             }
2211             switch (chn->connection) {
2212             case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
2213                 fprintf(stderr, "channel has unknown 'connection'\n");
2214                 exit(1);
2215             case LIBXL_CHANNEL_CONNECTION_SOCKET:
2216                 if (!path) {
2217                     fprintf(stderr, "channel connection 'socket' requires path=..\n");
2218                     exit(1);
2219                 }
2220                 chn->u.socket.path = xstrdup(path);
2221                 break;
2222             case LIBXL_CHANNEL_CONNECTION_PTY:
2223                 /* Nothing to do since PTY has no arguments */
2224                 break;
2225             default:
2226                 fprintf(stderr, "unknown channel connection: %d",
2227                         chn->connection);
2228                 exit(1);
2229             }
2230             libxl_string_list_dispose(&pairs);
2231             free(path);
2232         }
2233     }
2234 
2235     if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
2236         d_config->num_nics = 0;
2237         d_config->nics = NULL;
2238         while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
2239             libxl_device_nic *nic;
2240             char *buf2 = strdup(buf);
2241             char *p;
2242 
2243             nic = ARRAY_EXTEND_INIT(d_config->nics,
2244                                     d_config->num_nics,
2245                                     libxl_device_nic_init);
2246             set_default_nic_values(nic);
2247 
2248             p = strtok(buf2, ",");
2249             if (!p)
2250                 goto skip_nic;
2251             do {
2252                 while (*p == ' ')
2253                     p++;
2254                 parse_nic_config(nic, &config, p);
2255             } while ((p = strtok(NULL, ",")) != NULL);
2256 skip_nic:
2257             free(buf2);
2258         }
2259     }
2260 
2261     if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
2262         fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
2263     }
2264 
2265     d_config->num_vfbs = 0;
2266     d_config->num_vkbs = 0;
2267     d_config->vfbs = NULL;
2268     d_config->vkbs = NULL;
2269 
2270     if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
2271         while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
2272             libxl_device_vfb *vfb;
2273             libxl_device_vkb *vkb;
2274 
2275             char *buf2 = strdup(buf);
2276             char *p, *p2;
2277 
2278             vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
2279                                     libxl_device_vfb_init);
2280 
2281             vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
2282                                     libxl_device_vkb_init);
2283 
2284             p = strtok(buf2, ",");
2285             if (!p)
2286                 goto skip_vfb;
2287             do {
2288                 while (*p == ' ')
2289                     p++;
2290                 if ((p2 = strchr(p, '=')) == NULL)
2291                     break;
2292                 *p2 = '\0';
2293                 if (!strcmp(p, "vnc")) {
2294                     libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
2295                 } else if (!strcmp(p, "vnclisten")) {
2296                     free(vfb->vnc.listen);
2297                     vfb->vnc.listen = strdup(p2 + 1);
2298                 } else if (!strcmp(p, "vncpasswd")) {
2299                     free(vfb->vnc.passwd);
2300                     vfb->vnc.passwd = strdup(p2 + 1);
2301                 } else if (!strcmp(p, "vncdisplay")) {
2302                     vfb->vnc.display = atoi(p2 + 1);
2303                 } else if (!strcmp(p, "vncunused")) {
2304                     libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
2305                 } else if (!strcmp(p, "keymap")) {
2306                     free(vfb->keymap);
2307                     vfb->keymap = strdup(p2 + 1);
2308                 } else if (!strcmp(p, "sdl")) {
2309                     libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
2310                 } else if (!strcmp(p, "opengl")) {
2311                     libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
2312                 } else if (!strcmp(p, "display")) {
2313                     free(vfb->sdl.display);
2314                     vfb->sdl.display = strdup(p2 + 1);
2315                 } else if (!strcmp(p, "xauthority")) {
2316                     free(vfb->sdl.xauthority);
2317                     vfb->sdl.xauthority = strdup(p2 + 1);
2318                 }
2319             } while ((p = strtok(NULL, ",")) != NULL);
2320 
2321 skip_vfb:
2322             free(buf2);
2323         }
2324     }
2325 
2326     if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
2327         pci_msitranslate = l;
2328 
2329     if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
2330         pci_power_mgmt = l;
2331 
2332     if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
2333         pci_permissive = l;
2334 
2335     if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
2336         pci_seize = l;
2337 
2338     /* To be reworked (automatically enabled) once the auto ballooning
2339      * after guest starts is done (with PCI devices passed in). */
2340     if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
2341         xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
2342     }
2343 
2344     if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
2345         libxl_rdm_reserve rdm;
2346         if (!xlu_rdm_parse(config, &rdm, buf)) {
2347             b_info->u.hvm.rdm.strategy = rdm.strategy;
2348             b_info->u.hvm.rdm.policy = rdm.policy;
2349         }
2350     }
2351 
2352     if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
2353         d_config->num_usbctrls = 0;
2354         d_config->usbctrls = NULL;
2355         while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
2356                != NULL) {
2357             libxl_device_usbctrl *usbctrl;
2358             char *buf2 = strdup(buf);
2359             char *p;
2360 
2361             usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
2362                                         d_config->num_usbctrls,
2363                                         libxl_device_usbctrl_init);
2364             p = strtok(buf2, ",");
2365             if (!p)
2366                 goto skip_usbctrl;
2367             do {
2368                 while (*p == ' ')
2369                     p++;
2370                 if (parse_usbctrl_config(usbctrl, p))
2371                     exit(1);
2372             } while ((p = strtok(NULL, ",")) != NULL);
2373 skip_usbctrl:
2374             free(buf2);
2375         }
2376     }
2377 
2378     if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
2379         d_config->num_usbdevs = 0;
2380         d_config->usbdevs = NULL;
2381         while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
2382                != NULL) {
2383             libxl_device_usbdev *usbdev;
2384             char *buf2 = strdup(buf);
2385             char *p;
2386 
2387             usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
2388                                                d_config->num_usbdevs,
2389                                                libxl_device_usbdev_init);
2390             p = strtok(buf2, ",");
2391             if (!p)
2392                 goto skip_usbdev;
2393             do {
2394                 while (*p == ' ')
2395                     p++;
2396                 if (parse_usbdev_config(usbdev, p))
2397                     exit(1);
2398             } while ((p = strtok(NULL, ",")) != NULL);
2399 skip_usbdev:
2400             free(buf2);
2401         }
2402     }
2403 
2404     switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
2405     case 0:
2406         {
2407             const char *errstr;
2408 
2409             for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
2410                 e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
2411                 switch (e) {
2412                 case 0: continue;
2413                 case 1:
2414                     errstr = "illegal leaf number";
2415                     break;
2416                 case 2:
2417                     errstr = "illegal subleaf number";
2418                     break;
2419                 case 3:
2420                     errstr = "missing colon";
2421                     break;
2422                 case 4:
2423                     errstr = "invalid register name (must be e[abcd]x)";
2424                     break;
2425                 case 5:
2426                     errstr = "policy string must be exactly 32 characters long";
2427                     break;
2428                 default:
2429                     errstr = "unknown error";
2430                     break;
2431                 }
2432                 fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
2433                 fprintf(stderr, "  error #%i: %s\n", e, errstr);
2434             }
2435         }
2436         break;
2437     case EINVAL:    /* config option is not a list, parse as a string */
2438         if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
2439             char *buf2, *p, *strtok_ptr = NULL;
2440             const char *errstr;
2441 
2442             buf2 = strdup(buf);
2443             p = strtok_r(buf2, ",", &strtok_ptr);
2444             if (p == NULL) {
2445                 free(buf2);
2446                 break;
2447             }
2448             if (strcmp(p, "host")) {
2449                 fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
2450                 fprintf(stderr, "  error: first word must be \"host\"\n");
2451                 free(buf2);
2452                 break;
2453             }
2454             for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
2455                  p = strtok_r(NULL, ",", &strtok_ptr)) {
2456                 e = libxl_cpuid_parse_config(&b_info->cpuid, p);
2457                 switch (e) {
2458                 case 0: continue;
2459                 case 1:
2460                     errstr = "missing \"=\" in key=value";
2461                     break;
2462                 case 2:
2463                     errstr = "unknown CPUID flag name";
2464                     break;
2465                 case 3:
2466                     errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
2467                     break;
2468                 default:
2469                     errstr = "unknown error";
2470                     break;
2471                 }
2472                 fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
2473                 fprintf(stderr, "  error #%i: %s\n", e, errstr);
2474             }
2475             free(buf2);
2476         }
2477         break;
2478     default:
2479         break;
2480     }
2481 
2482     /* parse device model arguments, this works for pv, hvm and stubdom */
2483     if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
2484         fprintf(stderr,
2485                 "WARNING: ignoring device_model directive.\n"
2486                 "WARNING: Use \"device_model_override\" instead if you"
2487                 " really want a non-default device_model\n");
2488         if (strstr(buf, "stubdom-dm")) {
2489             if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
2490                 fprintf(stderr, "WARNING: Or use"
2491                         " \"device_model_stubdomain_override\" if you "
2492                         " want to enable stubdomains\n");
2493             else
2494                 fprintf(stderr, "WARNING: ignoring"
2495                         " \"device_model_stubdomain_override\" directive"
2496                         " for pv guest\n");
2497         }
2498     }
2499 
2500 
2501     xlu_cfg_replace_string (config, "device_model_override",
2502                             &b_info->device_model, 0);
2503     if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
2504         if (!strcmp(buf, "qemu-xen-traditional")) {
2505             b_info->device_model_version
2506                 = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
2507         } else if (!strcmp(buf, "qemu-xen")) {
2508             b_info->device_model_version
2509                 = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
2510         } else {
2511             fprintf(stderr,
2512                     "Unknown device_model_version \"%s\" specified\n", buf);
2513             exit(1);
2514         }
2515     } else if (b_info->device_model)
2516         fprintf(stderr, "WARNING: device model override given without specific DM version\n");
2517     xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
2518                          &b_info->device_model_stubdomain, 0);
2519 
2520     if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
2521                              &buf, 0))
2522         xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
2523                                &b_info->device_model_ssid_label, 0);
2524 
2525     xlu_cfg_replace_string(config, "device_model_user",
2526                            &b_info->device_model_user, 0);
2527 
2528     xlu_cfg_replace_string (config, "stubdomain_kernel",
2529                             &b_info->stubdomain_kernel, 0);
2530     xlu_cfg_replace_string (config, "stubdomain_ramdisk",
2531                             &b_info->stubdomain_ramdisk, 0);
2532     if (!xlu_cfg_get_long (config, "stubdomain_memory", &l, 0))
2533         b_info->stubdomain_memkb = l * 1024;
2534 
2535 #define parse_extra_args(type)                                            \
2536     e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
2537                                     &b_info->extra##type, 0);            \
2538     if (e && e != ESRCH) {                                                \
2539         fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
2540         exit(-ERROR_FAIL);                                                \
2541     }
2542 
2543     /* parse extra args for qemu, common to both pv, hvm */
2544     parse_extra_args();
2545 
2546     /* parse extra args dedicated to pv */
2547     parse_extra_args(_pv);
2548 
2549     /* parse extra args dedicated to hvm */
2550     parse_extra_args(_hvm);
2551 
2552 #undef parse_extra_args
2553 
2554     /* If we've already got vfb=[] for PV guest then ignore top level
2555      * VNC config. */
2556     if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
2557         long vnc_enabled = 0;
2558 
2559         if (!xlu_cfg_get_long (config, "vnc", &l, 0))
2560             vnc_enabled = l;
2561 
2562         if (vnc_enabled) {
2563             libxl_device_vfb *vfb;
2564             libxl_device_vkb *vkb;
2565 
2566             vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
2567                                     libxl_device_vfb_init);
2568 
2569             vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
2570                                     libxl_device_vkb_init);
2571 
2572             parse_top_level_vnc_options(config, &vfb->vnc);
2573             parse_top_level_sdl_options(config, &vfb->sdl);
2574             xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
2575         }
2576     } else {
2577         parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
2578         parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
2579     }
2580 
2581     xlu_cfg_get_defbool(config, "dm_restrict", &b_info->dm_restrict, 0);
2582 
2583     if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
2584         if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
2585             if (!strcmp(buf, "stdvga")) {
2586                 b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
2587             } else if (!strcmp(buf, "cirrus")) {
2588                 b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
2589             } else if (!strcmp(buf, "none")) {
2590                 b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
2591             } else if (!strcmp(buf, "qxl")) {
2592                 b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
2593             } else {
2594                 fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
2595                 exit(1);
2596             }
2597         } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
2598             b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
2599                                          LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
2600 
2601         if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
2602             libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
2603                 fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
2604                     buf);
2605                 exit (1);
2606         }
2607 
2608         xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
2609         xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
2610         if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
2611             b_info->u.hvm.spice.port = l;
2612         if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
2613             b_info->u.hvm.spice.tls_port = l;
2614         xlu_cfg_replace_string (config, "spicehost",
2615                                 &b_info->u.hvm.spice.host, 0);
2616         xlu_cfg_get_defbool(config, "spicedisable_ticketing",
2617                             &b_info->u.hvm.spice.disable_ticketing, 0);
2618         xlu_cfg_replace_string (config, "spicepasswd",
2619                                 &b_info->u.hvm.spice.passwd, 0);
2620         xlu_cfg_get_defbool(config, "spiceagent_mouse",
2621                             &b_info->u.hvm.spice.agent_mouse, 0);
2622         xlu_cfg_get_defbool(config, "spicevdagent",
2623                             &b_info->u.hvm.spice.vdagent, 0);
2624         xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
2625                             &b_info->u.hvm.spice.clipboard_sharing, 0);
2626         if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
2627             b_info->u.hvm.spice.usbredirection = l;
2628         xlu_cfg_replace_string (config, "spice_image_compression",
2629                                 &b_info->u.hvm.spice.image_compression, 0);
2630         xlu_cfg_replace_string (config, "spice_streaming_video",
2631                                 &b_info->u.hvm.spice.streaming_video, 0);
2632         xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
2633         if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
2634             libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
2635         } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
2636             if (libxl_gfx_passthru_kind_from_string(buf,
2637                                         &b_info->u.hvm.gfx_passthru_kind)) {
2638                 fprintf(stderr,
2639                         "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
2640                         buf);
2641                 exit (1);
2642             }
2643             libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
2644         }
2645         switch (xlu_cfg_get_list_as_string_list(config, "serial",
2646                                                 &b_info->u.hvm.serial_list,
2647                                                 1))
2648         {
2649 
2650         case 0: break; /* Success */
2651         case ESRCH: break; /* Option not present */
2652         case EINVAL:
2653             /* If it's not a valid list, try reading it as an atom,
2654              * falling through to an error if it fails */
2655             if (!xlu_cfg_replace_string(config, "serial",
2656                                         &b_info->u.hvm.serial, 0))
2657                 break;
2658             /* FALLTHRU */
2659         default:
2660             fprintf(stderr,"xl: Unable to parse serial.\n");
2661             exit(-ERROR_FAIL);
2662         }
2663         xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
2664         xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
2665         if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
2666             b_info->u.hvm.usbversion = l;
2667         switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
2668                                                 &b_info->u.hvm.usbdevice_list,
2669                                                 1))
2670         {
2671 
2672         case 0: break; /* Success */
2673         case ESRCH: break; /* Option not present */
2674         case EINVAL:
2675             /* If it's not a valid list, try reading it as an atom,
2676              * falling through to an error if it fails */
2677             if (!xlu_cfg_replace_string(config, "usbdevice",
2678                                         &b_info->u.hvm.usbdevice, 0))
2679                 break;
2680             /* FALLTHRU */
2681         default:
2682             fprintf(stderr,"xl: Unable to parse usbdevice.\n");
2683             exit(-ERROR_FAIL);
2684         }
2685         xlu_cfg_get_defbool(config, "vkb_device", &b_info->u.hvm.vkb_device, 0);
2686         xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
2687         xlu_cfg_get_defbool(config, "xen_platform_pci",
2688                             &b_info->u.hvm.xen_platform_pci, 0);
2689 
2690         if(b_info->u.hvm.vnc.listen
2691            && b_info->u.hvm.vnc.display
2692            && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
2693             fprintf(stderr,
2694                     "ERROR: Display specified both in vnclisten"
2695                     " and vncdisplay!\n");
2696             exit (1);
2697 
2698         }
2699 
2700         if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
2701             libxl_vendor_device d;
2702 
2703             e = libxl_vendor_device_from_string(buf, &d);
2704             if (e) {
2705                 fprintf(stderr,
2706                         "xl: unknown vendor_device '%s'\n",
2707                         buf);
2708                 exit(-ERROR_FAIL);
2709             }
2710 
2711             b_info->u.hvm.vendor_device = d;
2712         }
2713     }
2714 
2715     if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
2716         e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
2717         if (e) {
2718             fprintf(stderr,
2719                     "Unknown gic_version \"%s\" specified\n", buf);
2720             exit(-ERROR_FAIL);
2721         }
2722     }
2723 
2724     if (!xlu_cfg_get_string (config, "tee", &buf, 1)) {
2725         e = libxl_tee_type_from_string(buf, &b_info->tee);
2726         if (e) {
2727             fprintf(stderr,
2728                     "Unknown tee \"%s\" specified\n", buf);
2729             exit(-ERROR_FAIL);
2730         }
2731     }
2732 
2733     parse_vkb_list(config, d_config);
2734 
2735     xlu_cfg_get_defbool(config, "xend_suspend_evtchn_compat",
2736                         &c_info->xend_suspend_evtchn_compat, 0);
2737 
2738     xlu_cfg_destroy(config);
2739 }
2740 
2741 /* Returns -1 on failure; the amount of memory on success. */
parse_mem_size_kb(const char * mem)2742 int64_t parse_mem_size_kb(const char *mem)
2743 {
2744     char *endptr;
2745     int64_t kbytes;
2746 
2747     kbytes = strtoll(mem, &endptr, 10);
2748 
2749     if (strlen(endptr) > 1)
2750         return -1;
2751 
2752     switch (tolower((uint8_t)*endptr)) {
2753     case 't':
2754         kbytes <<= 10;
2755         /* fallthrough */
2756     case 'g':
2757         kbytes <<= 10;
2758         /* fallthrough */
2759     case '\0':
2760     case 'm':
2761         kbytes <<= 10;
2762         /* fallthrough */
2763     case 'k':
2764         break;
2765     case 'b':
2766         kbytes >>= 10;
2767         break;
2768     default:
2769         return -1;
2770     }
2771 
2772     return kbytes;
2773 }
2774 
2775 
split_string_into_string_list(const char * str,const char * delim,libxl_string_list * psl)2776 void split_string_into_string_list(const char *str,
2777                                    const char *delim,
2778                                    libxl_string_list *psl)
2779 {
2780     char *s, *saveptr;
2781     const char *p;
2782     libxl_string_list sl;
2783 
2784     int i = 0, nr = 0;
2785 
2786     s = strdup(str);
2787     if (s == NULL) {
2788         fprintf(stderr, "unable to allocate memory to split string\n");
2789         exit(-1);
2790     }
2791 
2792     /* Count number of entries */
2793     p = strtok_r(s, delim, &saveptr);
2794     do {
2795         nr++;
2796     } while ((p = strtok_r(NULL, delim, &saveptr)));
2797 
2798     free(s);
2799 
2800     s = strdup(str);
2801 
2802     sl = malloc((nr+1) * sizeof (char *));
2803     if (sl == NULL) {
2804         fprintf(stderr, "unable to allocate memory to split string\n");
2805         exit(-1);
2806     }
2807 
2808     p = strtok_r(s, delim, &saveptr);
2809     do {
2810         assert(i < nr);
2811         sl[i] = strdup(p);
2812         i++;
2813     } while ((p = strtok_r(NULL, delim, &saveptr)));
2814     sl[i] = NULL;
2815 
2816     *psl = sl;
2817 
2818     free(s);
2819 }
2820 
trim(char_predicate_t predicate,const char * input,char ** output)2821 void trim(char_predicate_t predicate, const char *input, char **output)
2822 {
2823     const char *first, *after;
2824 
2825     for (first = input;
2826          *first && predicate((unsigned char)first[0]);
2827          first++)
2828         ;
2829 
2830     for (after = first + strlen(first);
2831          after > first && predicate((unsigned char)after[-1]);
2832          after--)
2833         ;
2834 
2835     size_t len_nonnull = after - first;
2836     char *result = xmalloc(len_nonnull + 1);
2837 
2838     memcpy(result, first, len_nonnull);
2839     result[len_nonnull] = 0;
2840 
2841     *output = result;
2842 }
2843 
split_string_into_pair(const char * str,const char * delim,char ** a,char ** b)2844 int split_string_into_pair(const char *str,
2845                            const char *delim,
2846                            char **a,
2847                            char **b)
2848 {
2849     char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
2850     int rc = 0;
2851 
2852     s = xstrdup(str);
2853 
2854     p = strtok_r(s, delim, &saveptr);
2855     if (p == NULL) {
2856         rc = ERROR_INVAL;
2857         goto out;
2858     }
2859     aa = xstrdup(p);
2860     p = strtok_r(NULL, delim, &saveptr);
2861     if (p == NULL) {
2862         rc = ERROR_INVAL;
2863         goto out;
2864     }
2865     bb = xstrdup(p);
2866 
2867     *a = aa;
2868     aa = NULL;
2869     *b = bb;
2870     bb = NULL;
2871 out:
2872     free(s);
2873     free(aa);
2874     free(bb);
2875     return rc;
2876 }
2877 
2878 
2879 /*
2880  * Local variables:
2881  * mode: C
2882  * c-basic-offset: 4
2883  * indent-tabs-mode: nil
2884  * End:
2885  */
2886