]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
69d1bb667632b4abcd0f5c4733fea409127b58c6
[mirror_lxc.git] / src / lxc / confile.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <signal.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/utsname.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <net/if.h>
39
40 #include "parse.h"
41 #include "config.h"
42 #include "confile.h"
43 #include "utils.h"
44 #include "log.h"
45 #include "conf.h"
46 #include "network.h"
47 #include "lxcseccomp.h"
48
49 #if HAVE_SYS_PERSONALITY_H
50 #include <sys/personality.h>
51 #endif
52
53 lxc_log_define(lxc_confile, lxc);
54
55 static int config_personality(const char *, const char *, struct lxc_conf *);
56 static int config_pts(const char *, const char *, struct lxc_conf *);
57 static int config_tty(const char *, const char *, struct lxc_conf *);
58 static int config_ttydir(const char *, const char *, struct lxc_conf *);
59 static int config_kmsg(const char *, const char *, struct lxc_conf *);
60 static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
61 static int config_lsm_se_context(const char *, const char *, struct lxc_conf *);
62 static int config_cgroup(const char *, const char *, struct lxc_conf *);
63 static int config_idmap(const char *, const char *, struct lxc_conf *);
64 static int config_loglevel(const char *, const char *, struct lxc_conf *);
65 static int config_logfile(const char *, const char *, struct lxc_conf *);
66 static int config_mount(const char *, const char *, struct lxc_conf *);
67 static int config_rootfs(const char *, const char *, struct lxc_conf *);
68 static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
69 static int config_rootfs_options(const char *, const char *, struct lxc_conf *);
70 static int config_pivotdir(const char *, const char *, struct lxc_conf *);
71 static int config_utsname(const char *, const char *, struct lxc_conf *);
72 static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
73 static int config_network_type(const char *, const char *, struct lxc_conf *);
74 static int config_network_flags(const char *, const char *, struct lxc_conf *);
75 static int config_network_link(const char *, const char *, struct lxc_conf *);
76 static int config_network_name(const char *, const char *, struct lxc_conf *);
77 static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
78 static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
79 static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
80 static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
81 static int config_network_mtu(const char *, const char *, struct lxc_conf *);
82 static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
83 static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
84 static int config_network_script_up(const char *, const char *, struct lxc_conf *);
85 static int config_network_script_down(const char *, const char *, struct lxc_conf *);
86 static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
87 static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
88 static int config_cap_drop(const char *, const char *, struct lxc_conf *);
89 static int config_cap_keep(const char *, const char *, struct lxc_conf *);
90 static int config_console(const char *, const char *, struct lxc_conf *);
91 static int config_seccomp(const char *, const char *, struct lxc_conf *);
92 static int config_includefile(const char *, const char *, struct lxc_conf *);
93 static int config_network_nic(const char *, const char *, struct lxc_conf *);
94 static int config_autodev(const char *, const char *, struct lxc_conf *);
95 static int config_haltsignal(const char *, const char *, struct lxc_conf *);
96 static int config_stopsignal(const char *, const char *, struct lxc_conf *);
97 static int config_start(const char *, const char *, struct lxc_conf *);
98 static int config_group(const char *, const char *, struct lxc_conf *);
99
100 static struct lxc_config_t config[] = {
101
102 { "lxc.arch", config_personality },
103 { "lxc.pts", config_pts },
104 { "lxc.tty", config_tty },
105 { "lxc.devttydir", config_ttydir },
106 { "lxc.kmsg", config_kmsg },
107 { "lxc.aa_profile", config_lsm_aa_profile },
108 { "lxc.se_context", config_lsm_se_context },
109 { "lxc.cgroup", config_cgroup },
110 { "lxc.id_map", config_idmap },
111 { "lxc.loglevel", config_loglevel },
112 { "lxc.logfile", config_logfile },
113 { "lxc.mount", config_mount },
114 { "lxc.rootfs.mount", config_rootfs_mount },
115 { "lxc.rootfs.options", config_rootfs_options },
116 { "lxc.rootfs", config_rootfs },
117 { "lxc.pivotdir", config_pivotdir },
118 { "lxc.utsname", config_utsname },
119 { "lxc.hook.pre-start", config_hook },
120 { "lxc.hook.pre-mount", config_hook },
121 { "lxc.hook.mount", config_hook },
122 { "lxc.hook.autodev", config_hook },
123 { "lxc.hook.start", config_hook },
124 { "lxc.hook.post-stop", config_hook },
125 { "lxc.hook.clone", config_hook },
126 { "lxc.network.type", config_network_type },
127 { "lxc.network.flags", config_network_flags },
128 { "lxc.network.link", config_network_link },
129 { "lxc.network.name", config_network_name },
130 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
131 { "lxc.network.veth.pair", config_network_veth_pair },
132 { "lxc.network.script.up", config_network_script_up },
133 { "lxc.network.script.down", config_network_script_down },
134 { "lxc.network.hwaddr", config_network_hwaddr },
135 { "lxc.network.mtu", config_network_mtu },
136 { "lxc.network.vlan.id", config_network_vlan_id },
137 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
138 { "lxc.network.ipv4", config_network_ipv4 },
139 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
140 { "lxc.network.ipv6", config_network_ipv6 },
141 /* config_network_nic must come after all other 'lxc.network.*' entries */
142 { "lxc.network.", config_network_nic },
143 { "lxc.cap.drop", config_cap_drop },
144 { "lxc.cap.keep", config_cap_keep },
145 { "lxc.console", config_console },
146 { "lxc.seccomp", config_seccomp },
147 { "lxc.include", config_includefile },
148 { "lxc.autodev", config_autodev },
149 { "lxc.haltsignal", config_haltsignal },
150 { "lxc.stopsignal", config_stopsignal },
151 { "lxc.start.auto", config_start },
152 { "lxc.start.delay", config_start },
153 { "lxc.start.order", config_start },
154 { "lxc.group", config_group },
155 };
156
157 struct signame {
158 int num;
159 const char *name;
160 };
161
162 static const struct signame signames[] = {
163 { SIGHUP, "HUP" },
164 { SIGINT, "INT" },
165 { SIGQUIT, "QUIT" },
166 { SIGILL, "ILL" },
167 { SIGABRT, "ABRT" },
168 { SIGFPE, "FPE" },
169 { SIGKILL, "KILL" },
170 { SIGSEGV, "SEGV" },
171 { SIGPIPE, "PIPE" },
172 { SIGALRM, "ALRM" },
173 { SIGTERM, "TERM" },
174 { SIGUSR1, "USR1" },
175 { SIGUSR2, "USR2" },
176 { SIGCHLD, "CHLD" },
177 { SIGCONT, "CONT" },
178 { SIGSTOP, "STOP" },
179 { SIGTSTP, "TSTP" },
180 { SIGTTIN, "TTIN" },
181 { SIGTTOU, "TTOU" },
182 };
183
184 static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
185
186 extern struct lxc_config_t *lxc_getconfig(const char *key)
187 {
188 int i;
189
190 for (i = 0; i < config_size; i++)
191 if (!strncmp(config[i].name, key,
192 strlen(config[i].name)))
193 return &config[i];
194 return NULL;
195 }
196
197 #define strprint(str, inlen, ...) \
198 do { \
199 len = snprintf(str, inlen, ##__VA_ARGS__); \
200 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
201 fulllen += len; \
202 if (inlen > 0) { \
203 if (str) str += len; \
204 inlen -= len; \
205 if (inlen < 0) inlen = 0; \
206 } \
207 } while (0);
208
209 int lxc_listconfigs(char *retv, int inlen)
210 {
211 int i, fulllen = 0, len;
212
213 if (!retv)
214 inlen = 0;
215 else
216 memset(retv, 0, inlen);
217 for (i = 0; i < config_size; i++) {
218 char *s = config[i].name;
219 if (s[strlen(s)-1] == '.')
220 continue;
221 strprint(retv, inlen, "%s\n", s);
222 }
223 return fulllen;
224 }
225
226 static int config_string_item(char **conf_item, const char *value)
227 {
228 char *new_value;
229
230 if (!value || strlen(value) == 0) {
231 if (*conf_item)
232 free(*conf_item);
233 *conf_item = NULL;
234 return 0;
235 }
236
237 new_value = strdup(value);
238 if (!new_value) {
239 SYSERROR("failed to strdup '%s': %m", value);
240 return -1;
241 }
242
243 if (*conf_item)
244 free(*conf_item);
245 *conf_item = new_value;
246 return 0;
247 }
248
249 static int config_string_item_max(char **conf_item, const char *value,
250 size_t max)
251 {
252 if (strlen(value) >= max) {
253 ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
254 return -1;
255 }
256
257 return config_string_item(conf_item, value);
258 }
259
260 static int config_path_item(char **conf_item, const char *value)
261 {
262 return config_string_item_max(conf_item, value, PATH_MAX);
263 }
264
265 /*
266 * config entry is something like "lxc.network.0.ipv4"
267 * the key 'lxc.network.' was found. So we make sure next
268 * comes an integer, find the right callback (by rewriting
269 * the key), and call it.
270 */
271 static int config_network_nic(const char *key, const char *value,
272 struct lxc_conf *lxc_conf)
273 {
274 char *copy = strdup(key), *p;
275 int ret = -1;
276 struct lxc_config_t *config;
277
278 if (!copy) {
279 SYSERROR("failed to allocate memory");
280 return -1;
281 }
282 /*
283 * ok we know that to get here we've got "lxc.network."
284 * and it isn't any of the other network entries. So
285 * after the second . should come an integer (# of defined
286 * nic) followed by a valid entry.
287 */
288 if (*(key+12) < '0' || *(key+12) > '9')
289 goto out;
290 p = index(key+12, '.');
291 if (!p)
292 goto out;
293 strcpy(copy+12, p+1);
294 config = lxc_getconfig(copy);
295 if (!config) {
296 ERROR("unknown key %s", key);
297 goto out;
298 }
299 ret = config->cb(key, value, lxc_conf);
300
301 out:
302 free(copy);
303 return ret;
304 }
305
306 static int macvlan_mode(int *valuep, const char *value);
307
308 static int config_network_type(const char *key, const char *value,
309 struct lxc_conf *lxc_conf)
310 {
311 struct lxc_list *network = &lxc_conf->network;
312 struct lxc_netdev *netdev;
313 struct lxc_list *list;
314
315 if (!value || strlen(value) == 0)
316 return lxc_clear_config_network(lxc_conf);
317
318 netdev = malloc(sizeof(*netdev));
319 if (!netdev) {
320 SYSERROR("failed to allocate memory");
321 return -1;
322 }
323
324 memset(netdev, 0, sizeof(*netdev));
325 lxc_list_init(&netdev->ipv4);
326 lxc_list_init(&netdev->ipv6);
327
328 list = malloc(sizeof(*list));
329 if (!list) {
330 SYSERROR("failed to allocate memory");
331 free(netdev);
332 return -1;
333 }
334
335 lxc_list_init(list);
336 list->elem = netdev;
337
338 lxc_list_add_tail(network, list);
339
340 if (!strcmp(value, "veth"))
341 netdev->type = LXC_NET_VETH;
342 else if (!strcmp(value, "macvlan")) {
343 netdev->type = LXC_NET_MACVLAN;
344 macvlan_mode(&netdev->priv.macvlan_attr.mode, "private");
345 }
346 else if (!strcmp(value, "vlan"))
347 netdev->type = LXC_NET_VLAN;
348 else if (!strcmp(value, "phys"))
349 netdev->type = LXC_NET_PHYS;
350 else if (!strcmp(value, "empty"))
351 netdev->type = LXC_NET_EMPTY;
352 else if (!strcmp(value, "none"))
353 netdev->type = LXC_NET_NONE;
354 else {
355 ERROR("invalid network type %s", value);
356 return -1;
357 }
358 return 0;
359 }
360
361 static int config_ip_prefix(struct in_addr *addr)
362 {
363 if (IN_CLASSA(addr->s_addr))
364 return 32 - IN_CLASSA_NSHIFT;
365 if (IN_CLASSB(addr->s_addr))
366 return 32 - IN_CLASSB_NSHIFT;
367 if (IN_CLASSC(addr->s_addr))
368 return 32 - IN_CLASSC_NSHIFT;
369
370 return 0;
371 }
372
373 /*
374 * if you have p="lxc.network.0.link", pass it p+12
375 * to get back '0' (the index of the nic)
376 */
377 static int get_network_netdev_idx(const char *key)
378 {
379 int ret, idx;
380
381 if (*key < '0' || *key > '9')
382 return -1;
383 ret = sscanf(key, "%d", &idx);
384 if (ret != 1)
385 return -1;
386 return idx;
387 }
388
389 /*
390 * if you have p="lxc.network.0", pass this p+12 and it will return
391 * the netdev of the first configured nic
392 */
393 static struct lxc_netdev *get_netdev_from_key(const char *key,
394 struct lxc_list *network)
395 {
396 int i = 0, idx = get_network_netdev_idx(key);
397 struct lxc_netdev *netdev = NULL;
398 struct lxc_list *it;
399 if (idx == -1)
400 return NULL;
401 lxc_list_for_each(it, network) {
402 if (idx == i++) {
403 netdev = it->elem;
404 break;
405 }
406 }
407 return netdev;
408 }
409
410 extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
411 char *retv, int inlen)
412 {
413 struct lxc_netdev *netdev;
414 int fulllen = 0, len;
415
416 netdev = get_netdev_from_key(key+12, &c->network);
417 if (!netdev)
418 return -1;
419
420 if (!retv)
421 inlen = 0;
422 else
423 memset(retv, 0, inlen);
424
425 strprint(retv, inlen, "script.up\n");
426 strprint(retv, inlen, "script.down\n");
427 if (netdev->type != LXC_NET_EMPTY) {
428 strprint(retv, inlen, "flags\n");
429 strprint(retv, inlen, "link\n");
430 strprint(retv, inlen, "name\n");
431 strprint(retv, inlen, "hwaddr\n");
432 strprint(retv, inlen, "mtu\n");
433 strprint(retv, inlen, "ipv6\n");
434 strprint(retv, inlen, "ipv6_gateway\n");
435 strprint(retv, inlen, "ipv4\n");
436 strprint(retv, inlen, "ipv4_gateway\n");
437 }
438 switch(netdev->type) {
439 case LXC_NET_VETH:
440 strprint(retv, inlen, "veth.pair\n");
441 break;
442 case LXC_NET_MACVLAN:
443 strprint(retv, inlen, "macvlan.mode\n");
444 break;
445 case LXC_NET_VLAN:
446 strprint(retv, inlen, "vlan.id\n");
447 break;
448 case LXC_NET_PHYS:
449 break;
450 }
451 return fulllen;
452 }
453
454 static struct lxc_netdev *network_netdev(const char *key, const char *value,
455 struct lxc_list *network)
456 {
457 struct lxc_netdev *netdev = NULL;
458
459 if (lxc_list_empty(network)) {
460 ERROR("network is not created for '%s' = '%s' option",
461 key, value);
462 return NULL;
463 }
464
465 if (get_network_netdev_idx(key+12) == -1)
466 netdev = lxc_list_last_elem(network);
467 else
468 netdev = get_netdev_from_key(key+12, network);
469
470 if (!netdev) {
471 ERROR("no network device defined for '%s' = '%s' option",
472 key, value);
473 return NULL;
474 }
475
476 return netdev;
477 }
478
479 static int network_ifname(char **valuep, const char *value)
480 {
481 return config_string_item_max(valuep, value, IFNAMSIZ);
482 }
483
484 #ifndef MACVLAN_MODE_PRIVATE
485 # define MACVLAN_MODE_PRIVATE 1
486 #endif
487
488 #ifndef MACVLAN_MODE_VEPA
489 # define MACVLAN_MODE_VEPA 2
490 #endif
491
492 #ifndef MACVLAN_MODE_BRIDGE
493 # define MACVLAN_MODE_BRIDGE 4
494 #endif
495
496 static int macvlan_mode(int *valuep, const char *value)
497 {
498 struct mc_mode {
499 char *name;
500 int mode;
501 } m[] = {
502 { "private", MACVLAN_MODE_PRIVATE },
503 { "vepa", MACVLAN_MODE_VEPA },
504 { "bridge", MACVLAN_MODE_BRIDGE },
505 };
506
507 int i;
508
509 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
510 if (strcmp(m[i].name, value))
511 continue;
512
513 *valuep = m[i].mode;
514 return 0;
515 }
516
517 return -1;
518 }
519
520 static int rand_complete_hwaddr(char *hwaddr)
521 {
522 const char hex[] = "0123456789abcdef";
523 char *curs = hwaddr;
524
525 #ifndef HAVE_RAND_R
526 randseed(true);
527 #else
528 unsigned int seed=randseed(false);
529 #endif
530 while (*curs != '\0')
531 {
532 if ( *curs == 'x' || *curs == 'X' ) {
533 if (curs - hwaddr == 1) {
534 //ensure address is unicast
535 #ifdef HAVE_RAND_R
536 *curs = hex[rand_r(&seed) & 0x0E];
537 } else {
538 *curs = hex[rand_r(&seed) & 0x0F];
539 #else
540 *curs = hex[rand() & 0x0E];
541 } else {
542 *curs = hex[rand() & 0x0F];
543 #endif
544 }
545 }
546 curs++;
547 }
548 return 0;
549 }
550
551 static int config_network_flags(const char *key, const char *value,
552 struct lxc_conf *lxc_conf)
553 {
554 struct lxc_netdev *netdev;
555
556 netdev = network_netdev(key, value, &lxc_conf->network);
557 if (!netdev)
558 return -1;
559
560 netdev->flags |= IFF_UP;
561
562 return 0;
563 }
564
565 static int config_network_link(const char *key, const char *value,
566 struct lxc_conf *lxc_conf)
567 {
568 struct lxc_netdev *netdev;
569
570 netdev = network_netdev(key, value, &lxc_conf->network);
571 if (!netdev)
572 return -1;
573
574 return network_ifname(&netdev->link, value);
575 }
576
577 static int config_network_name(const char *key, const char *value,
578 struct lxc_conf *lxc_conf)
579 {
580 struct lxc_netdev *netdev;
581
582 netdev = network_netdev(key, value, &lxc_conf->network);
583 if (!netdev)
584 return -1;
585
586 return network_ifname(&netdev->name, value);
587 }
588
589 static int config_network_veth_pair(const char *key, const char *value,
590 struct lxc_conf *lxc_conf)
591 {
592 struct lxc_netdev *netdev;
593
594 netdev = network_netdev(key, value, &lxc_conf->network);
595 if (!netdev)
596 return -1;
597
598 return network_ifname(&netdev->priv.veth_attr.pair, value);
599 }
600
601 static int config_network_macvlan_mode(const char *key, const char *value,
602 struct lxc_conf *lxc_conf)
603 {
604 struct lxc_netdev *netdev;
605
606 netdev = network_netdev(key, value, &lxc_conf->network);
607 if (!netdev)
608 return -1;
609
610 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
611 }
612
613 static int config_network_hwaddr(const char *key, const char *value,
614 struct lxc_conf *lxc_conf)
615 {
616 struct lxc_netdev *netdev;
617
618 char *new_value = strdup(value);
619 if (!new_value) {
620 SYSERROR("failed to strdup '%s': %m", value);
621 return -1;
622 }
623 rand_complete_hwaddr(new_value);
624
625 netdev = network_netdev(key, new_value, &lxc_conf->network);
626 if (!netdev) {
627 free(new_value);
628 return -1;
629 };
630
631 if (!new_value || strlen(new_value) == 0) {
632 free(new_value);
633 netdev->hwaddr = NULL;
634 return 0;
635 }
636
637 netdev->hwaddr = new_value;
638 return 0;
639 }
640
641 static int config_network_vlan_id(const char *key, const char *value,
642 struct lxc_conf *lxc_conf)
643 {
644 struct lxc_netdev *netdev;
645
646 netdev = network_netdev(key, value, &lxc_conf->network);
647 if (!netdev)
648 return -1;
649
650 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
651 return -1;
652
653 return 0;
654 }
655
656 static int config_network_mtu(const char *key, const char *value,
657 struct lxc_conf *lxc_conf)
658 {
659 struct lxc_netdev *netdev;
660
661 netdev = network_netdev(key, value, &lxc_conf->network);
662 if (!netdev)
663 return -1;
664
665 return config_string_item(&netdev->mtu, value);
666 }
667
668 static int config_network_ipv4(const char *key, const char *value,
669 struct lxc_conf *lxc_conf)
670 {
671 struct lxc_netdev *netdev;
672 struct lxc_inetdev *inetdev;
673 struct lxc_list *list;
674 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
675
676 netdev = network_netdev(key, value, &lxc_conf->network);
677 if (!netdev)
678 return -1;
679
680 inetdev = malloc(sizeof(*inetdev));
681 if (!inetdev) {
682 SYSERROR("failed to allocate ipv4 address");
683 return -1;
684 }
685 memset(inetdev, 0, sizeof(*inetdev));
686
687 list = malloc(sizeof(*list));
688 if (!list) {
689 SYSERROR("failed to allocate memory");
690 free(inetdev);
691 return -1;
692 }
693
694 lxc_list_init(list);
695 list->elem = inetdev;
696
697 addr = strdup(value);
698 if (!addr) {
699 ERROR("no address specified");
700 free(inetdev);
701 free(list);
702 return -1;
703 }
704
705 cursor = strstr(addr, " ");
706 if (cursor) {
707 *cursor = '\0';
708 bcast = cursor + 1;
709 }
710
711 slash = strstr(addr, "/");
712 if (slash) {
713 *slash = '\0';
714 prefix = slash + 1;
715 }
716
717 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
718 SYSERROR("invalid ipv4 address: %s", value);
719 free(inetdev);
720 free(addr);
721 free(list);
722 return -1;
723 }
724
725 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
726 SYSERROR("invalid ipv4 broadcast address: %s", value);
727 free(inetdev);
728 free(list);
729 free(addr);
730 return -1;
731 }
732
733 /* no prefix specified, determine it from the network class */
734 inetdev->prefix = prefix ? atoi(prefix) :
735 config_ip_prefix(&inetdev->addr);
736
737 /* if no broadcast address, let compute one from the
738 * prefix and address
739 */
740 if (!bcast) {
741 inetdev->bcast.s_addr = inetdev->addr.s_addr;
742 inetdev->bcast.s_addr |=
743 htonl(INADDR_BROADCAST >> inetdev->prefix);
744 }
745
746 lxc_list_add_tail(&netdev->ipv4, list);
747
748 free(addr);
749 return 0;
750 }
751
752 static int config_network_ipv4_gateway(const char *key, const char *value,
753 struct lxc_conf *lxc_conf)
754 {
755 struct lxc_netdev *netdev;
756 struct in_addr *gw;
757
758 netdev = network_netdev(key, value, &lxc_conf->network);
759 if (!netdev)
760 return -1;
761
762 gw = malloc(sizeof(*gw));
763 if (!gw) {
764 SYSERROR("failed to allocate ipv4 gateway address");
765 return -1;
766 }
767
768 if (!value) {
769 ERROR("no ipv4 gateway address specified");
770 free(gw);
771 return -1;
772 }
773
774 if (!strcmp(value, "auto")) {
775 free(gw);
776 netdev->ipv4_gateway = NULL;
777 netdev->ipv4_gateway_auto = true;
778 } else {
779 if (!inet_pton(AF_INET, value, gw)) {
780 SYSERROR("invalid ipv4 gateway address: %s", value);
781 free(gw);
782 return -1;
783 }
784
785 netdev->ipv4_gateway = gw;
786 netdev->ipv4_gateway_auto = false;
787 }
788
789 return 0;
790 }
791
792 static int config_network_ipv6(const char *key, const char *value,
793 struct lxc_conf *lxc_conf)
794 {
795 struct lxc_netdev *netdev;
796 struct lxc_inet6dev *inet6dev;
797 struct lxc_list *list;
798 char *slash,*valdup;
799 char *netmask;
800
801 netdev = network_netdev(key, value, &lxc_conf->network);
802 if (!netdev)
803 return -1;
804
805 inet6dev = malloc(sizeof(*inet6dev));
806 if (!inet6dev) {
807 SYSERROR("failed to allocate ipv6 address");
808 return -1;
809 }
810 memset(inet6dev, 0, sizeof(*inet6dev));
811
812 list = malloc(sizeof(*list));
813 if (!list) {
814 SYSERROR("failed to allocate memory");
815 free(inet6dev);
816 return -1;
817 }
818
819 lxc_list_init(list);
820 list->elem = inet6dev;
821
822 valdup = strdup(value);
823 if (!valdup) {
824 ERROR("no address specified");
825 free(list);
826 free(inet6dev);
827 return -1;
828 }
829
830 inet6dev->prefix = 64;
831 slash = strstr(valdup, "/");
832 if (slash) {
833 *slash = '\0';
834 netmask = slash + 1;
835 inet6dev->prefix = atoi(netmask);
836 }
837
838 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
839 SYSERROR("invalid ipv6 address: %s", valdup);
840 free(list);
841 free(inet6dev);
842 free(valdup);
843 return -1;
844 }
845
846 lxc_list_add_tail(&netdev->ipv6, list);
847
848 free(valdup);
849 return 0;
850 }
851
852 static int config_network_ipv6_gateway(const char *key, const char *value,
853 struct lxc_conf *lxc_conf)
854 {
855 struct lxc_netdev *netdev;
856
857 netdev = network_netdev(key, value, &lxc_conf->network);
858 if (!netdev)
859 return -1;
860
861 if (!value) {
862 ERROR("no ipv6 gateway address specified");
863 return -1;
864 }
865
866 if (!strcmp(value, "auto")) {
867 netdev->ipv6_gateway = NULL;
868 netdev->ipv6_gateway_auto = true;
869 } else {
870 struct in6_addr *gw;
871
872 gw = malloc(sizeof(*gw));
873 if (!gw) {
874 SYSERROR("failed to allocate ipv6 gateway address");
875 return -1;
876 }
877
878 if (!inet_pton(AF_INET6, value, gw)) {
879 SYSERROR("invalid ipv6 gateway address: %s", value);
880 free(gw);
881 return -1;
882 }
883
884 netdev->ipv6_gateway = gw;
885 netdev->ipv6_gateway_auto = false;
886 }
887
888 return 0;
889 }
890
891 static int config_network_script_up(const char *key, const char *value,
892 struct lxc_conf *lxc_conf)
893 {
894 struct lxc_netdev *netdev;
895
896 netdev = network_netdev(key, value, &lxc_conf->network);
897 if (!netdev)
898 return -1;
899
900 return config_string_item(&netdev->upscript, value);
901 }
902
903 static int config_network_script_down(const char *key, const char *value,
904 struct lxc_conf *lxc_conf)
905 {
906 struct lxc_netdev *netdev;
907
908 netdev = network_netdev(key, value, &lxc_conf->network);
909 if (!netdev)
910 return -1;
911
912 return config_string_item(&netdev->downscript, value);
913 }
914
915 static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
916 {
917 struct lxc_list *hooklist;
918
919 hooklist = malloc(sizeof(*hooklist));
920 if (!hooklist) {
921 free(hook);
922 return -1;
923 }
924 hooklist->elem = hook;
925 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
926 return 0;
927 }
928
929 static int config_seccomp(const char *key, const char *value,
930 struct lxc_conf *lxc_conf)
931 {
932 return config_path_item(&lxc_conf->seccomp, value);
933 }
934
935 static int config_hook(const char *key, const char *value,
936 struct lxc_conf *lxc_conf)
937 {
938 char *copy;
939
940 if (!value || strlen(value) == 0)
941 return lxc_clear_hooks(lxc_conf, key);
942
943 copy = strdup(value);
944 if (!copy) {
945 SYSERROR("failed to dup string '%s'", value);
946 return -1;
947 }
948 if (strcmp(key, "lxc.hook.pre-start") == 0)
949 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
950 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
951 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
952 else if (strcmp(key, "lxc.hook.autodev") == 0)
953 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
954 else if (strcmp(key, "lxc.hook.mount") == 0)
955 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
956 else if (strcmp(key, "lxc.hook.start") == 0)
957 return add_hook(lxc_conf, LXCHOOK_START, copy);
958 else if (strcmp(key, "lxc.hook.post-stop") == 0)
959 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
960 else if (strcmp(key, "lxc.hook.clone") == 0)
961 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
962 SYSERROR("Unknown key: %s", key);
963 free(copy);
964 return -1;
965 }
966
967 static int config_personality(const char *key, const char *value,
968 struct lxc_conf *lxc_conf)
969 {
970 signed long personality = lxc_config_parse_arch(value);
971
972 if (personality >= 0)
973 lxc_conf->personality = personality;
974 else
975 WARN("unsupported personality '%s'", value);
976
977 return 0;
978 }
979
980 static int config_pts(const char *key, const char *value,
981 struct lxc_conf *lxc_conf)
982 {
983 int maxpts = atoi(value);
984
985 lxc_conf->pts = maxpts;
986
987 return 0;
988 }
989
990 static int config_start(const char *key, const char *value,
991 struct lxc_conf *lxc_conf)
992 {
993 if(strcmp(key, "lxc.start.auto") == 0) {
994 lxc_conf->start_auto = atoi(value);
995 return 0;
996 }
997 else if (strcmp(key, "lxc.start.delay") == 0) {
998 lxc_conf->start_delay = atoi(value);
999 return 0;
1000 }
1001 else if (strcmp(key, "lxc.start.order") == 0) {
1002 lxc_conf->start_order = atoi(value);
1003 return 0;
1004 }
1005 SYSERROR("Unknown key: %s", key);
1006 return -1;
1007 }
1008
1009 static int config_group(const char *key, const char *value,
1010 struct lxc_conf *lxc_conf)
1011 {
1012 char *groups, *groupptr, *sptr, *token;
1013 struct lxc_list *grouplist;
1014 int ret = -1;
1015
1016 if (!strlen(value))
1017 return lxc_clear_groups(lxc_conf);
1018
1019 groups = strdup(value);
1020 if (!groups) {
1021 SYSERROR("failed to dup '%s'", value);
1022 return -1;
1023 }
1024
1025 /* in case several groups are specified in a single line
1026 * split these groups in a single element for the list */
1027 for (groupptr = groups;;groupptr = NULL) {
1028 token = strtok_r(groupptr, " \t", &sptr);
1029 if (!token) {
1030 ret = 0;
1031 break;
1032 }
1033
1034 grouplist = malloc(sizeof(*grouplist));
1035 if (!grouplist) {
1036 SYSERROR("failed to allocate groups list");
1037 break;
1038 }
1039
1040 grouplist->elem = strdup(token);
1041 if (!grouplist->elem) {
1042 SYSERROR("failed to dup '%s'", token);
1043 free(grouplist);
1044 break;
1045 }
1046
1047 lxc_list_add_tail(&lxc_conf->groups, grouplist);
1048 }
1049
1050 free(groups);
1051
1052 return ret;
1053 }
1054
1055 static int config_tty(const char *key, const char *value,
1056 struct lxc_conf *lxc_conf)
1057 {
1058 int nbtty = atoi(value);
1059
1060 lxc_conf->tty = nbtty;
1061
1062 return 0;
1063 }
1064
1065 static int config_ttydir(const char *key, const char *value,
1066 struct lxc_conf *lxc_conf)
1067 {
1068 return config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1);
1069 }
1070
1071 static int config_kmsg(const char *key, const char *value,
1072 struct lxc_conf *lxc_conf)
1073 {
1074 int v = atoi(value);
1075
1076 lxc_conf->kmsg = v;
1077
1078 return 0;
1079 }
1080
1081 static int config_lsm_aa_profile(const char *key, const char *value,
1082 struct lxc_conf *lxc_conf)
1083 {
1084 return config_string_item(&lxc_conf->lsm_aa_profile, value);
1085 }
1086
1087 static int config_lsm_se_context(const char *key, const char *value,
1088 struct lxc_conf *lxc_conf)
1089 {
1090 return config_string_item(&lxc_conf->lsm_se_context, value);
1091 }
1092
1093 static int config_logfile(const char *key, const char *value,
1094 struct lxc_conf *lxc_conf)
1095 {
1096 int ret;
1097
1098 // store these values in the lxc_conf, and then try to set for
1099 // actual current logging.
1100 ret = config_path_item(&lxc_conf->logfile, value);
1101 if (ret == 0)
1102 ret = lxc_log_set_file(lxc_conf->logfile);
1103 return ret;
1104 }
1105
1106 static int config_loglevel(const char *key, const char *value,
1107 struct lxc_conf *lxc_conf)
1108 {
1109 int newlevel;
1110
1111 if (!value || strlen(value) == 0)
1112 return 0;
1113
1114 if (value[0] >= '0' && value[0] <= '9')
1115 newlevel = atoi(value);
1116 else
1117 newlevel = lxc_log_priority_to_int(value);
1118 // store these values in the lxc_conf, and then try to set for
1119 // actual current logging.
1120 lxc_conf->loglevel = newlevel;
1121 return lxc_log_set_level(newlevel);
1122 }
1123
1124 static int config_autodev(const char *key, const char *value,
1125 struct lxc_conf *lxc_conf)
1126 {
1127 int v = atoi(value);
1128
1129 lxc_conf->autodev = v;
1130
1131 return 0;
1132 }
1133
1134 static int sig_num(const char *sig)
1135 {
1136 int n;
1137 char *endp = NULL;
1138
1139 errno = 0;
1140 n = strtol(sig, &endp, 10);
1141 if (sig == endp || n < 0 || errno != 0)
1142 return -1;
1143 return n;
1144 }
1145
1146 static int rt_sig_num(const char *signame)
1147 {
1148 int sig_n = 0;
1149 int rtmax = 0;
1150
1151 if (strncasecmp(signame, "max-", 4) == 0) {
1152 rtmax = 1;
1153 }
1154 signame += 4;
1155 if (!isdigit(*signame))
1156 return -1;
1157 sig_n = sig_num(signame);
1158 sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
1159 if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
1160 return -1;
1161 return sig_n;
1162 }
1163
1164 static const char *sig_name(int signum) {
1165 int n;
1166
1167 for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
1168 if (signum == signames[n].num)
1169 return signames[n].name;
1170 }
1171 return NULL;
1172 }
1173
1174 static int sig_parse(const char *signame) {
1175 int n;
1176
1177 if (isdigit(*signame)) {
1178 return sig_num(signame);
1179 } else if (strncasecmp(signame, "sig", 3) == 0) {
1180 signame += 3;
1181 if (strncasecmp(signame, "rt", 2) == 0)
1182 return rt_sig_num(signame + 2);
1183 for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
1184 if (strcasecmp (signames[n].name, signame) == 0)
1185 return signames[n].num;
1186 }
1187 }
1188 return -1;
1189 }
1190
1191 static int config_haltsignal(const char *key, const char *value,
1192 struct lxc_conf *lxc_conf)
1193 {
1194 int sig_n = sig_parse(value);
1195
1196 if (sig_n < 0)
1197 return -1;
1198 lxc_conf->haltsignal = sig_n;
1199
1200 return 0;
1201 }
1202
1203 static int config_stopsignal(const char *key, const char *value,
1204 struct lxc_conf *lxc_conf)
1205 {
1206 int sig_n = sig_parse(value);
1207
1208 if (sig_n < 0)
1209 return -1;
1210 lxc_conf->stopsignal = sig_n;
1211
1212 return 0;
1213 }
1214
1215 static int config_cgroup(const char *key, const char *value,
1216 struct lxc_conf *lxc_conf)
1217 {
1218 char *token = "lxc.cgroup.";
1219 char *subkey;
1220 struct lxc_list *cglist = NULL;
1221 struct lxc_cgroup *cgelem = NULL;
1222
1223 if (!value || strlen(value) == 0)
1224 return lxc_clear_cgroups(lxc_conf, key);
1225
1226 subkey = strstr(key, token);
1227
1228 if (!subkey)
1229 return -1;
1230
1231 if (!strlen(subkey))
1232 return -1;
1233
1234 if (strlen(subkey) == strlen(token))
1235 return -1;
1236
1237 subkey += strlen(token);
1238
1239 cglist = malloc(sizeof(*cglist));
1240 if (!cglist)
1241 goto out;
1242
1243 cgelem = malloc(sizeof(*cgelem));
1244 if (!cgelem)
1245 goto out;
1246 memset(cgelem, 0, sizeof(*cgelem));
1247
1248 cgelem->subsystem = strdup(subkey);
1249 cgelem->value = strdup(value);
1250
1251 if (!cgelem->subsystem || !cgelem->value)
1252 goto out;
1253
1254 cglist->elem = cgelem;
1255
1256 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
1257
1258 return 0;
1259
1260 out:
1261 if (cglist)
1262 free(cglist);
1263
1264 if (cgelem) {
1265 if (cgelem->subsystem)
1266 free(cgelem->subsystem);
1267
1268 if (cgelem->value)
1269 free(cgelem->value);
1270
1271 free(cgelem);
1272 }
1273
1274 return -1;
1275 }
1276
1277 static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf)
1278 {
1279 char *token = "lxc.id_map";
1280 char *subkey;
1281 struct lxc_list *idmaplist = NULL;
1282 struct id_map *idmap = NULL;
1283 unsigned long hostid, nsid, range;
1284 char type;
1285 int ret;
1286
1287 if (!value || strlen(value) == 0)
1288 return lxc_clear_idmaps(lxc_conf);
1289
1290 subkey = strstr(key, token);
1291
1292 if (!subkey)
1293 return -1;
1294
1295 if (!strlen(subkey))
1296 return -1;
1297
1298 idmaplist = malloc(sizeof(*idmaplist));
1299 if (!idmaplist)
1300 goto out;
1301
1302 idmap = malloc(sizeof(*idmap));
1303 if (!idmap)
1304 goto out;
1305 memset(idmap, 0, sizeof(*idmap));
1306
1307 ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range);
1308 if (ret != 4)
1309 goto out;
1310
1311 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
1312 if (type == 'u')
1313 idmap->idtype = ID_TYPE_UID;
1314 else if (type == 'g')
1315 idmap->idtype = ID_TYPE_GID;
1316 else
1317 goto out;
1318
1319 idmap->hostid = hostid;
1320 idmap->nsid = nsid;
1321 idmap->range = range;
1322
1323 idmaplist->elem = idmap;
1324 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
1325
1326 return 0;
1327
1328 out:
1329 if (idmaplist)
1330 free(idmaplist);
1331
1332 if (idmap) {
1333 free(idmap);
1334 }
1335
1336 return -1;
1337 }
1338
1339 static int config_fstab(const char *key, const char *value,
1340 struct lxc_conf *lxc_conf)
1341 {
1342 return config_path_item(&lxc_conf->fstab, value);
1343 }
1344
1345 static int config_mount_auto(const char *key, const char *value,
1346 struct lxc_conf *lxc_conf)
1347 {
1348 char *autos, *autoptr, *sptr, *token;
1349 static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
1350 { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1351 { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1352 { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
1353 { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
1354 { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
1355 { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
1356 { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
1357 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
1358 { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
1359 { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
1360 { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
1361 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
1362 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
1363 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
1364 /* NB: For adding anything that ist just a single on/off, but has
1365 * no options: keep mask and flag identical and just define the
1366 * enum value as an unused bit so far
1367 */
1368 { NULL, 0 }
1369 };
1370 int i;
1371 int ret = -1;
1372
1373 if (!strlen(value))
1374 return -1;
1375
1376 autos = strdup(value);
1377 if (!autos) {
1378 SYSERROR("failed to dup '%s'", value);
1379 return -1;
1380 }
1381
1382 for (autoptr = autos; ; autoptr = NULL) {
1383 token = strtok_r(autoptr, " \t", &sptr);
1384 if (!token) {
1385 ret = 0;
1386 break;
1387 }
1388
1389 for (i = 0; allowed_auto_mounts[i].token; i++) {
1390 if (!strcmp(allowed_auto_mounts[i].token, token))
1391 break;
1392 }
1393
1394 if (!allowed_auto_mounts[i].token) {
1395 ERROR("Invalid filesystem to automount: %s", token);
1396 break;
1397 }
1398
1399 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
1400 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
1401 }
1402
1403 free(autos);
1404
1405 return ret;
1406 }
1407
1408 static int config_mount(const char *key, const char *value,
1409 struct lxc_conf *lxc_conf)
1410 {
1411 char *fstab_token = "lxc.mount";
1412 char *token = "lxc.mount.entry";
1413 char *auto_token = "lxc.mount.auto";
1414 char *subkey;
1415 char *mntelem;
1416 struct lxc_list *mntlist;
1417
1418 if (!value || strlen(value) == 0)
1419 return lxc_clear_mount_entries(lxc_conf);
1420
1421 subkey = strstr(key, token);
1422
1423 if (!subkey) {
1424 subkey = strstr(key, auto_token);
1425
1426 if (!subkey) {
1427 subkey = strstr(key, fstab_token);
1428
1429 if (!subkey)
1430 return -1;
1431
1432 return config_fstab(key, value, lxc_conf);
1433 }
1434
1435 return config_mount_auto(key, value, lxc_conf);
1436 }
1437
1438 if (!strlen(subkey))
1439 return -1;
1440
1441 mntlist = malloc(sizeof(*mntlist));
1442 if (!mntlist)
1443 return -1;
1444
1445 mntelem = strdup(value);
1446 if (!mntelem) {
1447 free(mntlist);
1448 return -1;
1449 }
1450 mntlist->elem = mntelem;
1451
1452 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1453
1454 return 0;
1455 }
1456
1457 static int config_cap_keep(const char *key, const char *value,
1458 struct lxc_conf *lxc_conf)
1459 {
1460 char *keepcaps, *keepptr, *sptr, *token;
1461 struct lxc_list *keeplist;
1462 int ret = -1;
1463
1464 if (!strlen(value))
1465 return lxc_clear_config_keepcaps(lxc_conf);
1466
1467 keepcaps = strdup(value);
1468 if (!keepcaps) {
1469 SYSERROR("failed to dup '%s'", value);
1470 return -1;
1471 }
1472
1473 /* in case several capability keep is specified in a single line
1474 * split these caps in a single element for the list */
1475 for (keepptr = keepcaps;;keepptr = NULL) {
1476 token = strtok_r(keepptr, " \t", &sptr);
1477 if (!token) {
1478 ret = 0;
1479 break;
1480 }
1481
1482 if (!strcmp(token, "none"))
1483 lxc_clear_config_keepcaps(lxc_conf);
1484
1485 keeplist = malloc(sizeof(*keeplist));
1486 if (!keeplist) {
1487 SYSERROR("failed to allocate keepcap list");
1488 break;
1489 }
1490
1491 keeplist->elem = strdup(token);
1492 if (!keeplist->elem) {
1493 SYSERROR("failed to dup '%s'", token);
1494 free(keeplist);
1495 break;
1496 }
1497
1498 lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
1499 }
1500
1501 free(keepcaps);
1502
1503 return ret;
1504 }
1505
1506 static int config_cap_drop(const char *key, const char *value,
1507 struct lxc_conf *lxc_conf)
1508 {
1509 char *dropcaps, *dropptr, *sptr, *token;
1510 struct lxc_list *droplist;
1511 int ret = -1;
1512
1513 if (!strlen(value))
1514 return lxc_clear_config_caps(lxc_conf);
1515
1516 dropcaps = strdup(value);
1517 if (!dropcaps) {
1518 SYSERROR("failed to dup '%s'", value);
1519 return -1;
1520 }
1521
1522 /* in case several capability drop is specified in a single line
1523 * split these caps in a single element for the list */
1524 for (dropptr = dropcaps;;dropptr = NULL) {
1525 token = strtok_r(dropptr, " \t", &sptr);
1526 if (!token) {
1527 ret = 0;
1528 break;
1529 }
1530
1531 droplist = malloc(sizeof(*droplist));
1532 if (!droplist) {
1533 SYSERROR("failed to allocate drop list");
1534 break;
1535 }
1536
1537 droplist->elem = strdup(token);
1538 if (!droplist->elem) {
1539 SYSERROR("failed to dup '%s'", token);
1540 free(droplist);
1541 break;
1542 }
1543
1544 lxc_list_add_tail(&lxc_conf->caps, droplist);
1545 }
1546
1547 free(dropcaps);
1548
1549 return ret;
1550 }
1551
1552 static int config_console(const char *key, const char *value,
1553 struct lxc_conf *lxc_conf)
1554 {
1555 return config_path_item(&lxc_conf->console.path, value);
1556 }
1557
1558 static int add_include_file(const char *fname, struct lxc_conf *lxc_conf)
1559 {
1560 struct lxc_list *list;
1561 char *v;
1562 int len = strlen(fname);
1563
1564 list = malloc(sizeof(*list));
1565 if (!list)
1566 return -1;
1567 lxc_list_init(list);
1568 v = malloc(len+1);
1569 if (!v) {
1570 free(list);
1571 return -1;
1572 }
1573 strncpy(v, fname, len);
1574 v[len] = '\0';
1575 list->elem = v;
1576 lxc_list_add_tail(&lxc_conf->includes, list);
1577 return 0;
1578 }
1579
1580 static int config_includefile(const char *key, const char *value,
1581 struct lxc_conf *lxc_conf)
1582 {
1583 if (lxc_conf->unexpanded)
1584 return add_include_file(value, lxc_conf);
1585 return lxc_config_read(value, lxc_conf, NULL);
1586 }
1587
1588 static int config_rootfs(const char *key, const char *value,
1589 struct lxc_conf *lxc_conf)
1590 {
1591 return config_path_item(&lxc_conf->rootfs.path, value);
1592 }
1593
1594 static int config_rootfs_mount(const char *key, const char *value,
1595 struct lxc_conf *lxc_conf)
1596 {
1597 return config_path_item(&lxc_conf->rootfs.mount, value);
1598 }
1599
1600 static int config_rootfs_options(const char *key, const char *value,
1601 struct lxc_conf *lxc_conf)
1602 {
1603 return config_string_item(&lxc_conf->rootfs.options, value);
1604 }
1605
1606 static int config_pivotdir(const char *key, const char *value,
1607 struct lxc_conf *lxc_conf)
1608 {
1609 return config_path_item(&lxc_conf->rootfs.pivot, value);
1610 }
1611
1612 static int config_utsname(const char *key, const char *value,
1613 struct lxc_conf *lxc_conf)
1614 {
1615 struct utsname *utsname;
1616
1617 utsname = malloc(sizeof(*utsname));
1618 if (!utsname) {
1619 SYSERROR("failed to allocate memory");
1620 return -1;
1621 }
1622
1623 if (strlen(value) >= sizeof(utsname->nodename)) {
1624 ERROR("node name '%s' is too long",
1625 value);
1626 free(utsname);
1627 return -1;
1628 }
1629
1630 strcpy(utsname->nodename, value);
1631 if (lxc_conf->utsname)
1632 free(lxc_conf->utsname);
1633 lxc_conf->utsname = utsname;
1634
1635 return 0;
1636 }
1637
1638 static int store_martian_option(char *line, void *data)
1639 {
1640 struct lxc_conf *conf = data;
1641 char *str;
1642 struct lxc_list *list;
1643 size_t len = strlen(line);
1644
1645 if (!conf->unexpanded)
1646 return 0;
1647 list = malloc(sizeof(*list));
1648 if (!list)
1649 return -1;
1650 lxc_list_init(list);
1651 str = malloc(len+1);
1652 if (!str) {
1653 free(list);
1654 return -1;
1655 }
1656 strncpy(str, line, len);
1657 str[len] = '\0';
1658 list->elem = str;
1659 lxc_list_add_tail(&conf->aliens, list);
1660 return 0;
1661 }
1662
1663 static int parse_line(char *buffer, void *data)
1664 {
1665 struct lxc_config_t *config;
1666 char *line, *linep;
1667 char *dot;
1668 char *key;
1669 char *value;
1670 int ret = 0;
1671
1672 if (lxc_is_line_empty(buffer))
1673 return 0;
1674
1675 /* we have to dup the buffer otherwise, at the re-exec for
1676 * reboot we modified the original string on the stack by
1677 * replacing '=' by '\0' below
1678 */
1679 linep = line = strdup(buffer);
1680 if (!line) {
1681 SYSERROR("failed to allocate memory for '%s'", buffer);
1682 return -1;
1683 }
1684
1685 line += lxc_char_left_gc(line, strlen(line));
1686
1687 /* ignore comments */
1688 if (line[0] == '#')
1689 goto out;
1690
1691 /* martian option - save it in the unexpanded config only */
1692 if (strncmp(line, "lxc.", 4)) {
1693 ret = store_martian_option(line, data);
1694 goto out;
1695 }
1696
1697 ret = -1;
1698
1699 dot = strstr(line, "=");
1700 if (!dot) {
1701 ERROR("invalid configuration line: %s", line);
1702 goto out;
1703 }
1704
1705 *dot = '\0';
1706 value = dot + 1;
1707
1708 key = line;
1709 key[lxc_char_right_gc(key, strlen(key))] = '\0';
1710
1711 value += lxc_char_left_gc(value, strlen(value));
1712 value[lxc_char_right_gc(value, strlen(value))] = '\0';
1713
1714 config = lxc_getconfig(key);
1715 if (!config) {
1716 ERROR("unknown key %s", key);
1717 goto out;
1718 }
1719
1720 ret = config->cb(key, value, data);
1721
1722 out:
1723 free(linep);
1724 return ret;
1725 }
1726
1727 static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
1728 {
1729 return parse_line(buffer, conf);
1730 }
1731
1732 int lxc_config_read(const char *file, struct lxc_conf *conf, struct lxc_conf *unexp_conf)
1733 {
1734 int ret;
1735
1736 if( access(file, R_OK) == -1 ) {
1737 return -1;
1738 }
1739 /* Catch only the top level config file name in the structure */
1740 if( ! conf->rcfile ) {
1741 conf->rcfile = strdup( file );
1742 }
1743 ret = lxc_file_for_each_line(file, parse_line, conf);
1744 if (ret)
1745 return ret;
1746 if (!unexp_conf)
1747 return 0;
1748 if (!unexp_conf->rcfile) {
1749 unexp_conf->rcfile = strdup( file );
1750 }
1751
1752 return lxc_file_for_each_line(file, parse_line, unexp_conf);
1753 }
1754
1755 int lxc_config_define_add(struct lxc_list *defines, char* arg)
1756 {
1757 struct lxc_list *dent;
1758
1759 dent = malloc(sizeof(struct lxc_list));
1760 if (!dent)
1761 return -1;
1762
1763 dent->elem = arg;
1764 lxc_list_add_tail(defines, dent);
1765 return 0;
1766 }
1767
1768 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
1769 {
1770 struct lxc_list *it,*next;
1771 int ret = 0;
1772
1773 lxc_list_for_each(it, defines) {
1774 ret = lxc_config_readline(it->elem, conf);
1775 if (ret)
1776 break;
1777 }
1778
1779 lxc_list_for_each_safe(it, defines, next) {
1780 lxc_list_del(it);
1781 free(it);
1782 }
1783
1784 return ret;
1785 }
1786
1787 signed long lxc_config_parse_arch(const char *arch)
1788 {
1789 #if HAVE_SYS_PERSONALITY_H
1790 struct per_name {
1791 char *name;
1792 unsigned long per;
1793 } pername[] = {
1794 { "x86", PER_LINUX32 },
1795 { "linux32", PER_LINUX32 },
1796 { "i386", PER_LINUX32 },
1797 { "i486", PER_LINUX32 },
1798 { "i586", PER_LINUX32 },
1799 { "i686", PER_LINUX32 },
1800 { "athlon", PER_LINUX32 },
1801 { "linux64", PER_LINUX },
1802 { "x86_64", PER_LINUX },
1803 { "amd64", PER_LINUX },
1804 };
1805 size_t len = sizeof(pername) / sizeof(pername[0]);
1806
1807 int i;
1808
1809 for (i = 0; i < len; i++) {
1810 if (!strcmp(pername[i].name, arch))
1811 return pername[i].per;
1812 }
1813 #endif
1814
1815 return -1;
1816 }
1817
1818 int lxc_fill_elevated_privileges(char *flaglist, int *flags)
1819 {
1820 char *token, *saveptr = NULL;
1821 int i, aflag;
1822 struct { const char *token; int flag; } all_privs[] = {
1823 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
1824 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
1825 { "LSM", LXC_ATTACH_LSM_EXEC },
1826 { NULL, 0 }
1827 };
1828
1829 if (!flaglist) {
1830 /* for the sake of backward compatibility, drop all privileges
1831 if none is specified */
1832 for (i = 0; all_privs[i].token; i++) {
1833 *flags |= all_privs[i].flag;
1834 }
1835 return 0;
1836 }
1837
1838 token = strtok_r(flaglist, "|", &saveptr);
1839 while (token) {
1840 aflag = -1;
1841 for (i = 0; all_privs[i].token; i++) {
1842 if (!strcmp(all_privs[i].token, token))
1843 aflag = all_privs[i].flag;
1844 }
1845 if (aflag < 0)
1846 return -1;
1847
1848 *flags |= aflag;
1849
1850 token = strtok_r(NULL, "|", &saveptr);
1851 }
1852 return 0;
1853 }
1854
1855 static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
1856 {
1857 if (!retv)
1858 inlen = 0;
1859 else
1860 memset(retv, 0, inlen);
1861 return snprintf(retv, inlen, "%d", v);
1862 }
1863
1864 static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
1865 {
1866 int fulllen = 0;
1867
1868 if (!retv)
1869 inlen = 0;
1870 else
1871 memset(retv, 0, inlen);
1872
1873 #if HAVE_SYS_PERSONALITY_H
1874 int len = 0;
1875
1876 switch(c->personality) {
1877 case PER_LINUX32: strprint(retv, inlen, "i686"); break;
1878 case PER_LINUX: strprint(retv, inlen, "x86_64"); break;
1879 default: break;
1880 }
1881 #endif
1882
1883 return fulllen;
1884 }
1885
1886 /*
1887 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1888 * then just the value(s) will be printed. Since there still could be
1889 * more than one, it is newline-separated.
1890 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1891 * already have newlines?)
1892 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1893 * in 'lxc.cgroup.subsystem.key = value' format.
1894 */
1895 static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
1896 const char *key)
1897 {
1898 int fulllen = 0, len;
1899 int all = 0;
1900 struct lxc_list *it;
1901
1902 if (!retv)
1903 inlen = 0;
1904 else
1905 memset(retv, 0, inlen);
1906
1907 if (strcmp(key, "all") == 0)
1908 all = 1;
1909
1910 lxc_list_for_each(it, &c->cgroup) {
1911 struct lxc_cgroup *cg = it->elem;
1912 if (all) {
1913 strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
1914 } else if (strcmp(cg->subsystem, key) == 0) {
1915 strprint(retv, inlen, "%s\n", cg->value);
1916 }
1917 }
1918 return fulllen;
1919 }
1920
1921 static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
1922 const char *key)
1923 {
1924 char *subkey;
1925 int len, fulllen = 0, found = -1;
1926 struct lxc_list *it;
1927 int i;
1928
1929 /* "lxc.hook.mount" */
1930 subkey = index(key, '.');
1931 if (subkey) subkey = index(subkey+1, '.');
1932 if (!subkey)
1933 return -1;
1934 subkey++;
1935 if (!*subkey)
1936 return -1;
1937 for (i=0; i<NUM_LXC_HOOKS; i++) {
1938 if (strcmp(lxchook_names[i], subkey) == 0) {
1939 found=i;
1940 break;
1941 }
1942 }
1943 if (found == -1)
1944 return -1;
1945
1946 if (!retv)
1947 inlen = 0;
1948 else
1949 memset(retv, 0, inlen);
1950
1951 lxc_list_for_each(it, &c->hooks[found]) {
1952 strprint(retv, inlen, "%s\n", (char *)it->elem);
1953 }
1954 return fulllen;
1955 }
1956
1957 static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen)
1958 {
1959 int len, fulllen = 0;
1960 struct lxc_list *it;
1961
1962 if (!retv)
1963 inlen = 0;
1964 else
1965 memset(retv, 0, inlen);
1966
1967 lxc_list_for_each(it, &c->groups) {
1968 strprint(retv, inlen, "%s\n", (char *)it->elem);
1969 }
1970 return fulllen;
1971 }
1972
1973 static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
1974 {
1975 int len, fulllen = 0;
1976 struct lxc_list *it;
1977
1978 if (!retv)
1979 inlen = 0;
1980 else
1981 memset(retv, 0, inlen);
1982
1983 lxc_list_for_each(it, &c->caps) {
1984 strprint(retv, inlen, "%s\n", (char *)it->elem);
1985 }
1986 return fulllen;
1987 }
1988
1989 static int lxc_get_item_cap_keep(struct lxc_conf *c, char *retv, int inlen)
1990 {
1991 int len, fulllen = 0;
1992 struct lxc_list *it;
1993
1994 if (!retv)
1995 inlen = 0;
1996 else
1997 memset(retv, 0, inlen);
1998
1999 lxc_list_for_each(it, &c->keepcaps) {
2000 strprint(retv, inlen, "%s\n", (char *)it->elem);
2001 }
2002 return fulllen;
2003 }
2004
2005 static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen)
2006 {
2007 int len, fulllen = 0;
2008 struct lxc_list *it;
2009
2010 if (!retv)
2011 inlen = 0;
2012 else
2013 memset(retv, 0, inlen);
2014
2015 lxc_list_for_each(it, &c->mount_list) {
2016 strprint(retv, inlen, "%s\n", (char *)it->elem);
2017 }
2018 return fulllen;
2019 }
2020
2021 static int lxc_get_auto_mounts(struct lxc_conf *c, char *retv, int inlen)
2022 {
2023 int len, fulllen = 0;
2024 const char *sep = "";
2025
2026 if (!retv)
2027 inlen = 0;
2028 else
2029 memset(retv, 0, inlen);
2030
2031 if (!(c->auto_mounts & LXC_AUTO_ALL_MASK))
2032 return 0;
2033
2034 switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
2035 case LXC_AUTO_PROC_MIXED: strprint(retv, inlen, "%sproc:mixed", sep); sep = " "; break;
2036 case LXC_AUTO_PROC_RW: strprint(retv, inlen, "%sproc:rw", sep); sep = " "; break;
2037 default: break;
2038 }
2039 switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
2040 case LXC_AUTO_SYS_RO: strprint(retv, inlen, "%ssys:ro", sep); sep = " "; break;
2041 case LXC_AUTO_SYS_RW: strprint(retv, inlen, "%ssys:rw", sep); sep = " "; break;
2042 default: break;
2043 }
2044 switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
2045 case LXC_AUTO_CGROUP_NOSPEC: strprint(retv, inlen, "%scgroup", sep); sep = " "; break;
2046 case LXC_AUTO_CGROUP_MIXED: strprint(retv, inlen, "%scgroup:mixed", sep); sep = " "; break;
2047 case LXC_AUTO_CGROUP_RO: strprint(retv, inlen, "%scgroup:ro", sep); sep = " "; break;
2048 case LXC_AUTO_CGROUP_RW: strprint(retv, inlen, "%scgroup:rw", sep); sep = " "; break;
2049 case LXC_AUTO_CGROUP_FULL_NOSPEC: strprint(retv, inlen, "%scgroup-full", sep); sep = " "; break;
2050 case LXC_AUTO_CGROUP_FULL_MIXED: strprint(retv, inlen, "%scgroup-full:mixed", sep); sep = " "; break;
2051 case LXC_AUTO_CGROUP_FULL_RO: strprint(retv, inlen, "%scgroup-full:ro", sep); sep = " "; break;
2052 case LXC_AUTO_CGROUP_FULL_RW: strprint(retv, inlen, "%scgroup-full:rw", sep); sep = " "; break;
2053 default: break;
2054 }
2055
2056 return fulllen;
2057 }
2058
2059 /*
2060 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
2061 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
2062 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
2063 * of an address. ipv4 and ipv6 return lists (newline-separated).
2064 * things like veth.pair return '' if invalid (i.e. if called for vlan
2065 * type).
2066 */
2067 static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
2068 const char *key)
2069 {
2070 char *p1;
2071 int len, fulllen = 0;
2072 struct lxc_netdev *netdev;
2073
2074 if (!retv)
2075 inlen = 0;
2076 else
2077 memset(retv, 0, inlen);
2078
2079 p1 = index(key, '.');
2080 if (!p1 || *(p1+1) == '\0') return -1;
2081 p1++;
2082
2083 netdev = get_netdev_from_key(key, &c->network);
2084 if (!netdev)
2085 return -1;
2086 if (strcmp(p1, "name") == 0) {
2087 if (netdev->name)
2088 strprint(retv, inlen, "%s", netdev->name);
2089 } else if (strcmp(p1, "type") == 0) {
2090 strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
2091 } else if (strcmp(p1, "link") == 0) {
2092 if (netdev->link)
2093 strprint(retv, inlen, "%s", netdev->link);
2094 } else if (strcmp(p1, "flags") == 0) {
2095 if (netdev->flags & IFF_UP)
2096 strprint(retv, inlen, "up");
2097 } else if (strcmp(p1, "script.up") == 0) {
2098 if (netdev->upscript)
2099 strprint(retv, inlen, "%s", netdev->upscript);
2100 } else if (strcmp(p1, "script.down") == 0) {
2101 if (netdev->downscript)
2102 strprint(retv, inlen, "%s", netdev->downscript);
2103 } else if (strcmp(p1, "hwaddr") == 0) {
2104 if (netdev->hwaddr)
2105 strprint(retv, inlen, "%s", netdev->hwaddr);
2106 } else if (strcmp(p1, "mtu") == 0) {
2107 if (netdev->mtu)
2108 strprint(retv, inlen, "%s", netdev->mtu);
2109 } else if (strcmp(p1, "macvlan.mode") == 0) {
2110 if (netdev->type == LXC_NET_MACVLAN) {
2111 const char *mode;
2112 switch (netdev->priv.macvlan_attr.mode) {
2113 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
2114 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
2115 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
2116 default: mode = "(invalid)"; break;
2117 }
2118 strprint(retv, inlen, "%s", mode);
2119 }
2120 } else if (strcmp(p1, "veth.pair") == 0) {
2121 if (netdev->type == LXC_NET_VETH) {
2122 strprint(retv, inlen, "%s",
2123 netdev->priv.veth_attr.pair ?
2124 netdev->priv.veth_attr.pair :
2125 netdev->priv.veth_attr.veth1);
2126 }
2127 } else if (strcmp(p1, "vlan") == 0) {
2128 if (netdev->type == LXC_NET_VLAN) {
2129 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
2130 }
2131 } else if (strcmp(p1, "ipv4_gateway") == 0) {
2132 if (netdev->ipv4_gateway_auto) {
2133 strprint(retv, inlen, "auto");
2134 } else if (netdev->ipv4_gateway) {
2135 char buf[INET_ADDRSTRLEN];
2136 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
2137 strprint(retv, inlen, "%s", buf);
2138 }
2139 } else if (strcmp(p1, "ipv4") == 0) {
2140 struct lxc_list *it2;
2141 lxc_list_for_each(it2, &netdev->ipv4) {
2142 struct lxc_inetdev *i = it2->elem;
2143 char buf[INET_ADDRSTRLEN];
2144 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
2145 strprint(retv, inlen, "%s\n", buf);
2146 }
2147 } else if (strcmp(p1, "ipv6_gateway") == 0) {
2148 if (netdev->ipv6_gateway_auto) {
2149 strprint(retv, inlen, "auto");
2150 } else if (netdev->ipv6_gateway) {
2151 char buf[INET_ADDRSTRLEN];
2152 inet_ntop(AF_INET, netdev->ipv6_gateway, buf, sizeof(buf));
2153 strprint(retv, inlen, "%s", buf);
2154 }
2155 } else if (strcmp(p1, "ipv6") == 0) {
2156 struct lxc_list *it2;
2157 lxc_list_for_each(it2, &netdev->ipv6) {
2158 struct lxc_inetdev *i = it2->elem;
2159 char buf[INET_ADDRSTRLEN];
2160 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
2161 strprint(retv, inlen, "%s\n", buf);
2162 }
2163 }
2164 return fulllen;
2165 }
2166
2167 static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
2168 {
2169 int len, fulllen = 0;
2170 struct lxc_list *it;
2171
2172 if (!retv)
2173 inlen = 0;
2174 else
2175 memset(retv, 0, inlen);
2176
2177 lxc_list_for_each(it, &c->network) {
2178 struct lxc_netdev *n = it->elem;
2179 const char *t = lxc_net_type_to_str(n->type);
2180 strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
2181 }
2182 return fulllen;
2183 }
2184
2185 int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
2186 int inlen)
2187 {
2188 const char *v = NULL;
2189
2190 if (strcmp(key, "lxc.mount.entry") == 0)
2191 return lxc_get_mount_entries(c, retv, inlen);
2192 else if (strcmp(key, "lxc.mount.auto") == 0)
2193 return lxc_get_auto_mounts(c, retv, inlen);
2194 else if (strcmp(key, "lxc.mount") == 0)
2195 v = c->fstab;
2196 else if (strcmp(key, "lxc.tty") == 0)
2197 return lxc_get_conf_int(c, retv, inlen, c->tty);
2198 else if (strcmp(key, "lxc.pts") == 0)
2199 return lxc_get_conf_int(c, retv, inlen, c->pts);
2200 else if (strcmp(key, "lxc.devttydir") == 0)
2201 v = c->ttydir;
2202 else if (strcmp(key, "lxc.arch") == 0)
2203 return lxc_get_arch_entry(c, retv, inlen);
2204 else if (strcmp(key, "lxc.aa_profile") == 0)
2205 v = c->lsm_aa_profile;
2206 else if (strcmp(key, "lxc.se_context") == 0)
2207 v = c->lsm_se_context;
2208 else if (strcmp(key, "lxc.logfile") == 0)
2209 v = lxc_log_get_file();
2210 else if (strcmp(key, "lxc.loglevel") == 0)
2211 v = lxc_log_priority_to_string(lxc_log_get_level());
2212 else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
2213 return lxc_get_cgroup_entry(c, retv, inlen, "all");
2214 else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
2215 return lxc_get_cgroup_entry(c, retv, inlen, key + 11);
2216 else if (strcmp(key, "lxc.utsname") == 0)
2217 v = c->utsname ? c->utsname->nodename : NULL;
2218 else if (strcmp(key, "lxc.console") == 0)
2219 v = c->console.path;
2220 else if (strcmp(key, "lxc.rootfs.mount") == 0)
2221 v = c->rootfs.mount;
2222 else if (strcmp(key, "lxc.rootfs.options") == 0)
2223 v = c->rootfs.options;
2224 else if (strcmp(key, "lxc.rootfs") == 0)
2225 v = c->rootfs.path;
2226 else if (strcmp(key, "lxc.pivotdir") == 0)
2227 v = c->rootfs.pivot;
2228 else if (strcmp(key, "lxc.cap.drop") == 0)
2229 return lxc_get_item_cap_drop(c, retv, inlen);
2230 else if (strcmp(key, "lxc.cap.keep") == 0)
2231 return lxc_get_item_cap_keep(c, retv, inlen);
2232 else if (strncmp(key, "lxc.hook", 8) == 0)
2233 return lxc_get_item_hooks(c, retv, inlen, key);
2234 else if (strcmp(key, "lxc.network") == 0)
2235 return lxc_get_item_network(c, retv, inlen);
2236 else if (strncmp(key, "lxc.network.", 12) == 0)
2237 return lxc_get_item_nic(c, retv, inlen, key + 12);
2238 else if (strcmp(key, "lxc.start.auto") == 0)
2239 return lxc_get_conf_int(c, retv, inlen, c->start_auto);
2240 else if (strcmp(key, "lxc.start.delay") == 0)
2241 return lxc_get_conf_int(c, retv, inlen, c->start_delay);
2242 else if (strcmp(key, "lxc.start.order") == 0)
2243 return lxc_get_conf_int(c, retv, inlen, c->start_order);
2244 else if (strcmp(key, "lxc.group") == 0)
2245 return lxc_get_item_groups(c, retv, inlen);
2246 else if (strcmp(key, "lxc.seccomp") == 0)
2247 v = c->seccomp;
2248 else return -1;
2249
2250 if (!v)
2251 return 0;
2252 if (retv && inlen >= strlen(v) + 1)
2253 strncpy(retv, v, strlen(v)+1);
2254 return strlen(v);
2255 }
2256
2257 int lxc_clear_config_item(struct lxc_conf *c, const char *key)
2258 {
2259 if (strcmp(key, "lxc.network") == 0)
2260 return lxc_clear_config_network(c);
2261 else if (strncmp(key, "lxc.network.", 12) == 0)
2262 return lxc_clear_nic(c, key + 12);
2263 else if (strcmp(key, "lxc.cap.drop") == 0)
2264 return lxc_clear_config_caps(c);
2265 else if (strcmp(key, "lxc.cap.keep") == 0)
2266 return lxc_clear_config_keepcaps(c);
2267 else if (strncmp(key, "lxc.cgroup", 10) == 0)
2268 return lxc_clear_cgroups(c, key);
2269 else if (strcmp(key, "lxc.mount.entries") == 0)
2270 return lxc_clear_mount_entries(c);
2271 else if (strcmp(key, "lxc.mount.auto") == 0)
2272 return lxc_clear_automounts(c);
2273 else if (strncmp(key, "lxc.hook", 8) == 0)
2274 return lxc_clear_hooks(c, key);
2275 else if (strncmp(key, "lxc.group", 9) == 0)
2276 return lxc_clear_groups(c);
2277 else if (strncmp(key, "lxc.seccomp", 11) == 0) {
2278 lxc_seccomp_free(c);
2279 return 0;
2280 }
2281
2282 return -1;
2283 }
2284
2285 /*
2286 * writing out a confile.
2287 */
2288 void write_config(FILE *fout, struct lxc_conf *c)
2289 {
2290 struct lxc_list *it;
2291 int i;
2292 const char *signame;
2293
2294 /* first write any includes */
2295 lxc_list_for_each(it, &c->includes) {
2296 fprintf(fout, "lxc.include = %s\n", (char *)it->elem);
2297 }
2298
2299 /* now write any aliens */
2300 lxc_list_for_each(it, &c->aliens) {
2301 fprintf(fout, "%s\n", (char *)it->elem);
2302 }
2303
2304 if (c->fstab)
2305 fprintf(fout, "lxc.mount = %s\n", c->fstab);
2306 lxc_list_for_each(it, &c->mount_list) {
2307 fprintf(fout, "lxc.mount.entry = %s\n", (char *)it->elem);
2308 }
2309 if (c->auto_mounts & LXC_AUTO_ALL_MASK) {
2310 fprintf(fout, "lxc.mount.auto =");
2311 switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
2312 case LXC_AUTO_PROC_MIXED: fprintf(fout, " proc:mixed"); break;
2313 case LXC_AUTO_PROC_RW: fprintf(fout, " proc:rw"); break;
2314 default: break;
2315 }
2316 switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
2317 case LXC_AUTO_SYS_RO: fprintf(fout, " sys:ro"); break;
2318 case LXC_AUTO_SYS_RW: fprintf(fout, " sys:rw"); break;
2319 default: break;
2320 }
2321 switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
2322 case LXC_AUTO_CGROUP_NOSPEC: fprintf(fout, " cgroup"); break;
2323 case LXC_AUTO_CGROUP_MIXED: fprintf(fout, " cgroup:mixed"); break;
2324 case LXC_AUTO_CGROUP_RO: fprintf(fout, " cgroup:ro"); break;
2325 case LXC_AUTO_CGROUP_RW: fprintf(fout, " cgroup:rw"); break;
2326 case LXC_AUTO_CGROUP_FULL_NOSPEC: fprintf(fout, " cgroup-full"); break;
2327 case LXC_AUTO_CGROUP_FULL_MIXED: fprintf(fout, " cgroup-full:mixed"); break;
2328 case LXC_AUTO_CGROUP_FULL_RO: fprintf(fout, " cgroup-full:ro"); break;
2329 case LXC_AUTO_CGROUP_FULL_RW: fprintf(fout, " cgroup-full:rw"); break;
2330 default: break;
2331 }
2332 fprintf(fout, "\n");
2333 }
2334 if (c->tty)
2335 fprintf(fout, "lxc.tty = %d\n", c->tty);
2336 if (c->pts)
2337 fprintf(fout, "lxc.pts = %d\n", c->pts);
2338 if (c->ttydir)
2339 fprintf(fout, "lxc.devttydir = %s\n", c->ttydir);
2340 if (c->haltsignal) {
2341 signame = sig_name(c->haltsignal);
2342 if (signame == NULL) {
2343 fprintf(fout, "lxc.haltsignal = %d\n", c->haltsignal);
2344 } else {
2345 fprintf(fout, "lxc.haltsignal = SIG%s\n", signame);
2346 }
2347 }
2348 if (c->stopsignal) {
2349 signame = sig_name(c->stopsignal);
2350 if (signame == NULL) {
2351 fprintf(fout, "lxc.stopsignal = %d\n", c->stopsignal);
2352 } else {
2353 fprintf(fout, "lxc.stopsignal = SIG%s\n", signame);
2354 }
2355 }
2356 #if HAVE_SYS_PERSONALITY_H
2357 switch(c->personality) {
2358 case PER_LINUX32: fprintf(fout, "lxc.arch = i686\n"); break;
2359 case PER_LINUX: fprintf(fout, "lxc.arch = x86_64\n"); break;
2360 default: break;
2361 }
2362 #endif
2363 if (c->lsm_aa_profile)
2364 fprintf(fout, "lxc.aa_profile = %s\n", c->lsm_aa_profile);
2365 if (c->lsm_se_context)
2366 fprintf(fout, "lxc.se_context = %s\n", c->lsm_se_context);
2367 if (c->seccomp)
2368 fprintf(fout, "lxc.seccomp = %s\n", c->seccomp);
2369 if (c->kmsg == 0)
2370 fprintf(fout, "lxc.kmsg = 0\n");
2371 if (c->autodev > 0)
2372 fprintf(fout, "lxc.autodev = 1\n");
2373 if (c->loglevel != LXC_LOG_PRIORITY_NOTSET)
2374 fprintf(fout, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c->loglevel));
2375 if (c->logfile)
2376 fprintf(fout, "lxc.logfile = %s\n", c->logfile);
2377 lxc_list_for_each(it, &c->cgroup) {
2378 struct lxc_cgroup *cg = it->elem;
2379 fprintf(fout, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
2380 }
2381 if (c->utsname)
2382 fprintf(fout, "lxc.utsname = %s\n", c->utsname->nodename);
2383 lxc_list_for_each(it, &c->network) {
2384 struct lxc_netdev *n = it->elem;
2385 const char *t = lxc_net_type_to_str(n->type);
2386 struct lxc_list *it2;
2387 fprintf(fout, "lxc.network.type = %s\n", t ? t : "(invalid)");
2388 if (n->flags & IFF_UP)
2389 fprintf(fout, "lxc.network.flags = up\n");
2390 if (n->link)
2391 fprintf(fout, "lxc.network.link = %s\n", n->link);
2392 if (n->name)
2393 fprintf(fout, "lxc.network.name = %s\n", n->name);
2394 if (n->type == LXC_NET_MACVLAN) {
2395 const char *mode;
2396 switch (n->priv.macvlan_attr.mode) {
2397 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
2398 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
2399 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
2400 default: mode = "(invalid)"; break;
2401 }
2402 fprintf(fout, "lxc.network.macvlan.mode = %s\n", mode);
2403 } else if (n->type == LXC_NET_VETH) {
2404 if (n->priv.veth_attr.pair)
2405 fprintf(fout, "lxc.network.veth.pair = %s\n",
2406 n->priv.veth_attr.pair);
2407 } else if (n->type == LXC_NET_VLAN) {
2408 fprintf(fout, "lxc.network.vlan.id = %d\n", n->priv.vlan_attr.vid);
2409 }
2410 if (n->upscript)
2411 fprintf(fout, "lxc.network.script.up = %s\n", n->upscript);
2412 if (n->downscript)
2413 fprintf(fout, "lxc.network.script.down = %s\n", n->downscript);
2414 if (n->hwaddr)
2415 fprintf(fout, "lxc.network.hwaddr = %s\n", n->hwaddr);
2416 if (n->mtu)
2417 fprintf(fout, "lxc.network.mtu = %s\n", n->mtu);
2418 if (n->ipv4_gateway_auto)
2419 fprintf(fout, "lxc.network.ipv4.gateway = auto\n");
2420 else if (n->ipv4_gateway) {
2421 char buf[INET_ADDRSTRLEN];
2422 inet_ntop(AF_INET, n->ipv4_gateway, buf, sizeof(buf));
2423 fprintf(fout, "lxc.network.ipv4.gateway = %s\n", buf);
2424 }
2425 lxc_list_for_each(it2, &n->ipv4) {
2426 struct lxc_inetdev *i = it2->elem;
2427 char buf[INET_ADDRSTRLEN];
2428 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
2429 fprintf(fout, "lxc.network.ipv4 = %s", buf);
2430
2431 if (i->prefix)
2432 fprintf(fout, "/%d", i->prefix);
2433
2434 if (i->bcast.s_addr != (i->addr.s_addr |
2435 htonl(INADDR_BROADCAST >> i->prefix))) {
2436
2437 inet_ntop(AF_INET, &i->bcast, buf, sizeof(buf));
2438 fprintf(fout, " %s\n", buf);
2439 }
2440 else
2441 fprintf(fout, "\n");
2442 }
2443 if (n->ipv6_gateway_auto)
2444 fprintf(fout, "lxc.network.ipv6.gateway = auto\n");
2445 else if (n->ipv6_gateway) {
2446 char buf[INET6_ADDRSTRLEN];
2447 inet_ntop(AF_INET6, n->ipv6_gateway, buf, sizeof(buf));
2448 fprintf(fout, "lxc.network.ipv6.gateway = %s\n", buf);
2449 }
2450 lxc_list_for_each(it2, &n->ipv6) {
2451 struct lxc_inet6dev *i = it2->elem;
2452 char buf[INET6_ADDRSTRLEN];
2453 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
2454 if (i->prefix)
2455 fprintf(fout, "lxc.network.ipv6 = %s/%d\n",
2456 buf, i->prefix);
2457 else
2458 fprintf(fout, "lxc.network.ipv6 = %s\n", buf);
2459 }
2460 }
2461 lxc_list_for_each(it, &c->caps)
2462 fprintf(fout, "lxc.cap.drop = %s\n", (char *)it->elem);
2463 lxc_list_for_each(it, &c->keepcaps)
2464 fprintf(fout, "lxc.cap.keep = %s\n", (char *)it->elem);
2465 lxc_list_for_each(it, &c->id_map) {
2466 struct id_map *idmap = it->elem;
2467 fprintf(fout, "lxc.id_map = %c %lu %lu %lu\n",
2468 idmap->idtype == ID_TYPE_UID ? 'u' : 'g', idmap->nsid,
2469 idmap->hostid, idmap->range);
2470 }
2471 for (i=0; i<NUM_LXC_HOOKS; i++) {
2472 lxc_list_for_each(it, &c->hooks[i])
2473 fprintf(fout, "lxc.hook.%s = %s\n",
2474 lxchook_names[i], (char *)it->elem);
2475 }
2476 if (c->console.path)
2477 fprintf(fout, "lxc.console = %s\n", c->console.path);
2478 if (c->rootfs.path)
2479 fprintf(fout, "lxc.rootfs = %s\n", c->rootfs.path);
2480 if (c->rootfs.mount && strcmp(c->rootfs.mount, LXCROOTFSMOUNT) != 0)
2481 fprintf(fout, "lxc.rootfs.mount = %s\n", c->rootfs.mount);
2482 if (c->rootfs.options)
2483 fprintf(fout, "lxc.rootfs.options = %s\n", c->rootfs.options);
2484 if (c->rootfs.pivot)
2485 fprintf(fout, "lxc.pivotdir = %s\n", c->rootfs.pivot);
2486 if (c->start_auto)
2487 fprintf(fout, "lxc.start.auto = %d\n", c->start_auto);
2488 if (c->start_delay)
2489 fprintf(fout, "lxc.start.delay = %d\n", c->start_delay);
2490 if (c->start_order)
2491 fprintf(fout, "lxc.start.order = %d\n", c->start_order);
2492 lxc_list_for_each(it, &c->groups)
2493 fprintf(fout, "lxc.group = %s\n", (char *)it->elem);
2494 }