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