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