]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/confile.c
Automatic mounting: write lxc.mount.auto in write_config
[mirror_lxc.git] / src / lxc / confile.c
CommitLineData
c2cc9f0a 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
c2cc9f0a 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
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
c2cc9f0a 22 */
12a50cc6 23#define _GNU_SOURCE
c2cc9f0a 24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#include <errno.h>
63376d7d 29#include <fcntl.h>
a84b9932
AV
30#include <ctype.h>
31#include <signal.h>
63376d7d 32#include <sys/stat.h>
c2cc9f0a 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
b2718c72 40#include "parse.h"
6ff05e18 41#include "config.h"
525f0002 42#include "confile.h"
26c39028 43#include "utils.h"
c2cc9f0a 44
36eb9bde 45#include <lxc/log.h>
00b3c2e2 46#include <lxc/conf.h>
72d0e1cb 47#include "network.h"
36eb9bde 48
6ff05e18
SG
49#if HAVE_SYS_PERSONALITY_H
50#include <sys/personality.h>
51#endif
52
36eb9bde 53lxc_log_define(lxc_confile, lxc);
576f946d 54
12a50cc6
DE
55static int config_personality(const char *, const char *, struct lxc_conf *);
56static int config_pts(const char *, const char *, struct lxc_conf *);
57static int config_tty(const char *, const char *, struct lxc_conf *);
58static int config_ttydir(const char *, const char *, struct lxc_conf *);
7e0e1d94 59static int config_kmsg(const char *, const char *, struct lxc_conf *);
fe4de9a6
DE
60static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
61static int config_lsm_se_context(const char *, const char *, struct lxc_conf *);
12a50cc6 62static int config_cgroup(const char *, const char *, struct lxc_conf *);
f6d3e3e4 63static int config_idmap(const char *, const char *, struct lxc_conf *);
4a85ce2a
SH
64static int config_loglevel(const char *, const char *, struct lxc_conf *);
65static int config_logfile(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
66static int config_mount(const char *, const char *, struct lxc_conf *);
67static int config_rootfs(const char *, const char *, struct lxc_conf *);
68static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
69static int config_pivotdir(const char *, const char *, struct lxc_conf *);
70static int config_utsname(const char *, const char *, struct lxc_conf *);
71static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
72static int config_network_type(const char *, const char *, struct lxc_conf *);
73static int config_network_flags(const char *, const char *, struct lxc_conf *);
74static int config_network_link(const char *, const char *, struct lxc_conf *);
75static int config_network_name(const char *, const char *, struct lxc_conf *);
76static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
77static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
78static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
79static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
80static int config_network_mtu(const char *, const char *, struct lxc_conf *);
81static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
82static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
83static int config_network_script(const char *, const char *, struct lxc_conf *);
84static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
85static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
86static int config_cap_drop(const char *, const char *, struct lxc_conf *);
1fb86a7c 87static int config_cap_keep(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
88static int config_console(const char *, const char *, struct lxc_conf *);
89static int config_seccomp(const char *, const char *, struct lxc_conf *);
90static int config_includefile(const char *, const char *, struct lxc_conf *);
91static int config_network_nic(const char *, const char *, struct lxc_conf *);
92static int config_autodev(const char *, const char *, struct lxc_conf *);
a84b9932 93static int config_stopsignal(const char *, const char *, struct lxc_conf *);
c2cc9f0a 94
72d0e1cb 95static struct lxc_config_t config[] = {
576f946d 96
cccc74b5 97 { "lxc.arch", config_personality },
e892973e
DL
98 { "lxc.pts", config_pts },
99 { "lxc.tty", config_tty },
7c6ef2a2 100 { "lxc.devttydir", config_ttydir },
7e0e1d94 101 { "lxc.kmsg", config_kmsg },
fe4de9a6
DE
102 { "lxc.aa_profile", config_lsm_aa_profile },
103 { "lxc.se_context", config_lsm_se_context },
e892973e 104 { "lxc.cgroup", config_cgroup },
f6d3e3e4 105 { "lxc.id_map", config_idmap },
4a85ce2a
SH
106 { "lxc.loglevel", config_loglevel },
107 { "lxc.logfile", config_logfile },
e892973e 108 { "lxc.mount", config_mount },
23b7ea69 109 { "lxc.rootfs.mount", config_rootfs_mount },
e892973e 110 { "lxc.rootfs", config_rootfs },
bf601689 111 { "lxc.pivotdir", config_pivotdir },
e892973e 112 { "lxc.utsname", config_utsname },
26ddeedd 113 { "lxc.hook.pre-start", config_hook },
12a50cc6 114 { "lxc.hook.pre-mount", config_hook },
26ddeedd 115 { "lxc.hook.mount", config_hook },
f7bee6c6 116 { "lxc.hook.autodev", config_hook },
26ddeedd
SH
117 { "lxc.hook.start", config_hook },
118 { "lxc.hook.post-stop", config_hook },
148e91f5 119 { "lxc.hook.clone", config_hook },
e892973e
DL
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 },
e3b4c4c4 126 { "lxc.network.script.up", config_network_script },
74a2b586 127 { "lxc.network.script.down", config_network_script },
e892973e
DL
128 { "lxc.network.hwaddr", config_network_hwaddr },
129 { "lxc.network.mtu", config_network_mtu },
130 { "lxc.network.vlan.id", config_network_vlan_id },
f8fee0e2 131 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
e892973e 132 { "lxc.network.ipv4", config_network_ipv4 },
f8fee0e2 133 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
e892973e 134 { "lxc.network.ipv6", config_network_ipv6 },
72d0e1cb
SG
135 /* config_network_nic must come after all other 'lxc.network.*' entries */
136 { "lxc.network.", config_network_nic },
81810dd1 137 { "lxc.cap.drop", config_cap_drop },
1fb86a7c 138 { "lxc.cap.keep", config_cap_keep },
63376d7d 139 { "lxc.console", config_console },
8f2c3a70 140 { "lxc.seccomp", config_seccomp },
09ad6246 141 { "lxc.include", config_includefile },
c6883f38 142 { "lxc.autodev", config_autodev },
a84b9932
AV
143 { "lxc.stopsignal", config_stopsignal },
144};
145
146struct signame {
147 int num;
148 char *name;
149};
150
151struct 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" },
c2cc9f0a 171};
172
72d0e1cb 173static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
c2cc9f0a 174
72d0e1cb 175extern struct lxc_config_t *lxc_getconfig(const char *key)
c2cc9f0a 176{
177 int i;
178
179 for (i = 0; i < config_size; i++)
a871ff6b 180 if (!strncmp(config[i].name, key,
c2cc9f0a 181 strlen(config[i].name)))
182 return &config[i];
183 return NULL;
184}
185
72d0e1cb
SG
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
198int 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 */
12a50cc6 221static int config_network_nic(const char *key, const char *value,
72d0e1cb
SG
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
251out:
252 free(copy);
253 return ret;
254}
255
12a50cc6 256static int config_network_type(const char *key, const char *value,
e892973e 257 struct lxc_conf *lxc_conf)
c2cc9f0a 258{
5f4535a3 259 struct lxc_list *network = &lxc_conf->network;
c2cc9f0a 260 struct lxc_netdev *netdev;
261 struct lxc_list *list;
c2cc9f0a 262
263 netdev = malloc(sizeof(*netdev));
264 if (!netdev) {
36eb9bde 265 SYSERROR("failed to allocate memory");
c2cc9f0a 266 return -1;
267 }
268
82d5ae15 269 memset(netdev, 0, sizeof(*netdev));
c2cc9f0a 270 lxc_list_init(&netdev->ipv4);
271 lxc_list_init(&netdev->ipv6);
c2cc9f0a 272
273 list = malloc(sizeof(*list));
274 if (!list) {
36eb9bde 275 SYSERROR("failed to allocate memory");
022de5f3 276 free(netdev);
c2cc9f0a 277 return -1;
278 }
279
280 lxc_list_init(list);
5f4535a3 281 list->elem = netdev;
c2cc9f0a 282
bac89583 283 lxc_list_add_tail(network, list);
a871ff6b 284
c2cc9f0a 285 if (!strcmp(value, "veth"))
24654103 286 netdev->type = LXC_NET_VETH;
c2cc9f0a 287 else if (!strcmp(value, "macvlan"))
24654103 288 netdev->type = LXC_NET_MACVLAN;
26c39028 289 else if (!strcmp(value, "vlan"))
24654103 290 netdev->type = LXC_NET_VLAN;
c2cc9f0a 291 else if (!strcmp(value, "phys"))
24654103 292 netdev->type = LXC_NET_PHYS;
5f58350a 293 else if (!strcmp(value, "empty"))
24654103 294 netdev->type = LXC_NET_EMPTY;
c2cc9f0a 295 else {
36eb9bde 296 ERROR("invalid network type %s", value);
c2cc9f0a 297 return -1;
298 }
299 return 0;
300}
301
a059591e
DL
302static 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
72d0e1cb
SG
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 */
318static 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 */
334static 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
12a50cc6
DE
351extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
352 char *retv, int inlen)
72d0e1cb
SG
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
16950ecb
DL
394static struct lxc_netdev *network_netdev(const char *key, const char *value,
395 struct lxc_list *network)
c2cc9f0a 396{
72d0e1cb 397 struct lxc_netdev *netdev = NULL;
c2cc9f0a 398
5f4535a3 399 if (lxc_list_empty(network)) {
16950ecb
DL
400 ERROR("network is not created for '%s' = '%s' option",
401 key, value);
33c945e0 402 return NULL;
c2cc9f0a 403 }
404
72d0e1cb
SG
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
5f4535a3 410 if (!netdev) {
16950ecb
DL
411 ERROR("no network device defined for '%s' = '%s' option",
412 key, value);
33c945e0 413 return NULL;
c2cc9f0a 414 }
415
33c945e0 416 return netdev;
c2cc9f0a 417}
418
12a50cc6 419static int network_ifname(char **valuep, const char *value)
c2cc9f0a 420{
bf83c5b9 421 if (strlen(value) >= IFNAMSIZ) {
5480b13b
DL
422 ERROR("interface name '%s' too long (>%d)\n",
423 value, IFNAMSIZ - 1);
c2cc9f0a 424 return -1;
425 }
426
33c945e0 427 *valuep = strdup(value);
16950ecb
DL
428 if (!*valuep) {
429 ERROR("failed to dup string '%s'", value);
430 return -1;
431 }
33c945e0 432
c2cc9f0a 433 return 0;
434}
435
e892973e
DL
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
12a50cc6 448static int macvlan_mode(int *valuep, const char *value)
e892973e
DL
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
12a50cc6 472static int config_network_flags(const char *key, const char *value,
33c945e0 473 struct lxc_conf *lxc_conf)
c2cc9f0a 474{
c2cc9f0a 475 struct lxc_netdev *netdev;
476
16950ecb 477 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 478 if (!netdev)
c2cc9f0a 479 return -1;
c2cc9f0a 480
33c945e0 481 netdev->flags |= IFF_UP;
c2cc9f0a 482
33c945e0
MT
483 return 0;
484}
485
12a50cc6 486static int config_network_link(const char *key, const char *value,
33c945e0
MT
487 struct lxc_conf *lxc_conf)
488{
489 struct lxc_netdev *netdev;
490
16950ecb 491 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 492 if (!netdev)
c2cc9f0a 493 return -1;
c2cc9f0a 494
33c945e0 495 return network_ifname(&netdev->link, value);
c2cc9f0a 496}
497
12a50cc6 498static int config_network_name(const char *key, const char *value,
33c945e0 499 struct lxc_conf *lxc_conf)
c2cc9f0a 500{
c2cc9f0a 501 struct lxc_netdev *netdev;
502
16950ecb 503 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 504 if (!netdev)
c2cc9f0a 505 return -1;
c2cc9f0a 506
33c945e0
MT
507 return network_ifname(&netdev->name, value);
508}
509
12a50cc6 510static int config_network_veth_pair(const char *key, const char *value,
e892973e
DL
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
12a50cc6 522static int config_network_macvlan_mode(const char *key, const char *value,
e892973e 523 struct lxc_conf *lxc_conf)
8634bc19
MT
524{
525 struct lxc_netdev *netdev;
526
527 netdev = network_netdev(key, value, &lxc_conf->network);
528 if (!netdev)
529 return -1;
530
e892973e 531 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
8634bc19
MT
532}
533
12a50cc6 534static int config_network_hwaddr(const char *key, const char *value,
33c945e0
MT
535 struct lxc_conf *lxc_conf)
536{
537 struct lxc_netdev *netdev;
d95db067 538 char *hwaddr;
33c945e0 539
16950ecb 540 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 541 if (!netdev)
c2cc9f0a 542 return -1;
c2cc9f0a 543
d95db067
DE
544 hwaddr = strdup(value);
545 if (!hwaddr) {
16950ecb
DL
546 SYSERROR("failed to dup string '%s'", value);
547 return -1;
548 }
33c945e0 549
d95db067
DE
550 if (netdev->hwaddr)
551 free(netdev->hwaddr);
552 netdev->hwaddr = hwaddr;
c2cc9f0a 553 return 0;
554}
555
12a50cc6 556static int config_network_vlan_id(const char *key, const char *value,
26c39028
JHS
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
f6cc1de1 565 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
26c39028
JHS
566 return -1;
567
568 return 0;
569}
570
12a50cc6 571static int config_network_mtu(const char *key, const char *value,
33c945e0 572 struct lxc_conf *lxc_conf)
442cbbe6 573{
442cbbe6 574 struct lxc_netdev *netdev;
d95db067 575 char *mtu;
442cbbe6 576
16950ecb 577 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 578 if (!netdev)
442cbbe6 579 return -1;
442cbbe6 580
d95db067
DE
581 mtu = strdup(value);
582 if (!mtu) {
16950ecb
DL
583 SYSERROR("failed to dup string '%s'", value);
584 return -1;
585 }
33c945e0 586
d95db067
DE
587 if (netdev->mtu)
588 free(netdev->mtu);
589 netdev->mtu = mtu;
442cbbe6
TR
590 return 0;
591}
592
12a50cc6 593static int config_network_ipv4(const char *key, const char *value,
33c945e0 594 struct lxc_conf *lxc_conf)
c2cc9f0a 595{
c2cc9f0a 596 struct lxc_netdev *netdev;
33c945e0 597 struct lxc_inetdev *inetdev;
c2cc9f0a 598 struct lxc_list *list;
599 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
600
16950ecb 601 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 602 if (!netdev)
c2cc9f0a 603 return -1;
c2cc9f0a 604
605 inetdev = malloc(sizeof(*inetdev));
606 if (!inetdev) {
36eb9bde 607 SYSERROR("failed to allocate ipv4 address");
c2cc9f0a 608 return -1;
609 }
610 memset(inetdev, 0, sizeof(*inetdev));
611
612 list = malloc(sizeof(*list));
613 if (!list) {
36eb9bde 614 SYSERROR("failed to allocate memory");
53719062 615 free(inetdev);
c2cc9f0a 616 return -1;
617 }
618
619 lxc_list_init(list);
620 list->elem = inetdev;
621
956edc54
SG
622 addr = strdup(value);
623 if (!addr) {
624 ERROR("no address specified");
53719062
SH
625 free(inetdev);
626 free(list);
956edc54
SG
627 return -1;
628 }
c2cc9f0a 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
c2cc9f0a 642 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
36eb9bde 643 SYSERROR("invalid ipv4 address: %s", value);
53719062 644 free(inetdev);
956edc54 645 free(addr);
53719062 646 free(list);
c2cc9f0a 647 return -1;
648 }
649
0093bb8c
DL
650 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
651 SYSERROR("invalid ipv4 broadcast address: %s", value);
53719062
SH
652 free(inetdev);
653 free(list);
956edc54 654 free(addr);
0093bb8c
DL
655 return -1;
656 }
c2cc9f0a 657
a059591e
DL
658 /* no prefix specified, determine it from the network class */
659 inetdev->prefix = prefix ? atoi(prefix) :
660 config_ip_prefix(&inetdev->addr);
661
b3df193c 662 /* if no broadcast address, let compute one from the
0093bb8c
DL
663 * prefix and address
664 */
665 if (!bcast) {
1b7d4743
DL
666 inetdev->bcast.s_addr = inetdev->addr.s_addr;
667 inetdev->bcast.s_addr |=
668 htonl(INADDR_BROADCAST >> inetdev->prefix);
0093bb8c 669 }
c2cc9f0a 670
8538f388 671 lxc_list_add_tail(&netdev->ipv4, list);
c2cc9f0a 672
956edc54 673 free(addr);
c2cc9f0a 674 return 0;
675}
676
12a50cc6 677static int config_network_ipv4_gateway(const char *key, const char *value,
f8fee0e2
MK
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");
53719062 695 free(gw);
f8fee0e2
MK
696 return -1;
697 }
698
19a26f82
MK
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);
53719062 705 free(gw);
19a26f82
MK
706 return -1;
707 }
708
709 netdev->ipv4_gateway = gw;
710 netdev->ipv4_gateway_auto = false;
f8fee0e2
MK
711 }
712
f8fee0e2
MK
713 return 0;
714}
715
12a50cc6 716static int config_network_ipv6(const char *key, const char *value,
e892973e 717 struct lxc_conf *lxc_conf)
c2cc9f0a 718{
c2cc9f0a 719 struct lxc_netdev *netdev;
720 struct lxc_inet6dev *inet6dev;
721 struct lxc_list *list;
12a50cc6 722 char *slash,*valdup;
c2cc9f0a 723 char *netmask;
724
16950ecb 725 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 726 if (!netdev)
c2cc9f0a 727 return -1;
c2cc9f0a 728
729 inet6dev = malloc(sizeof(*inet6dev));
730 if (!inet6dev) {
36eb9bde 731 SYSERROR("failed to allocate ipv6 address");
c2cc9f0a 732 return -1;
733 }
734 memset(inet6dev, 0, sizeof(*inet6dev));
735
736 list = malloc(sizeof(*list));
737 if (!list) {
36eb9bde 738 SYSERROR("failed to allocate memory");
28027320 739 free(inet6dev);
c2cc9f0a 740 return -1;
741 }
742
743 lxc_list_init(list);
744 list->elem = inet6dev;
745
956edc54
SG
746 valdup = strdup(value);
747 if (!valdup) {
748 ERROR("no address specified");
28027320
SH
749 free(list);
750 free(inet6dev);
956edc54
SG
751 return -1;
752 }
753
a059591e 754 inet6dev->prefix = 64;
12a50cc6 755 slash = strstr(valdup, "/");
c2cc9f0a 756 if (slash) {
757 *slash = '\0';
758 netmask = slash + 1;
759 inet6dev->prefix = atoi(netmask);
760 }
761
5acccf95
SH
762 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
763 SYSERROR("invalid ipv6 address: %s", valdup);
28027320
SH
764 free(list);
765 free(inet6dev);
956edc54 766 free(valdup);
c2cc9f0a 767 return -1;
768 }
769
8538f388 770 lxc_list_add_tail(&netdev->ipv6, list);
c2cc9f0a 771
956edc54 772 free(valdup);
c2cc9f0a 773 return 0;
774}
775
12a50cc6 776static int config_network_ipv6_gateway(const char *key, const char *value,
f8fee0e2
MK
777 struct lxc_conf *lxc_conf)
778{
779 struct lxc_netdev *netdev;
f8fee0e2
MK
780
781 netdev = network_netdev(key, value, &lxc_conf->network);
782 if (!netdev)
783 return -1;
784
f8fee0e2
MK
785 if (!value) {
786 ERROR("no ipv6 gateway address specified");
787 return -1;
788 }
789
19a26f82
MK
790 if (!strcmp(value, "auto")) {
791 netdev->ipv6_gateway = NULL;
792 netdev->ipv6_gateway_auto = true;
793 } else {
8fb86a37
SH
794 struct in6_addr *gw;
795
bec695f3
DE
796 gw = malloc(sizeof(*gw));
797 if (!gw) {
798 SYSERROR("failed to allocate ipv6 gateway address");
799 return -1;
800 }
801
19a26f82
MK
802 if (!inet_pton(AF_INET6, value, gw)) {
803 SYSERROR("invalid ipv6 gateway address: %s", value);
28027320 804 free(gw);
19a26f82
MK
805 return -1;
806 }
807
808 netdev->ipv6_gateway = gw;
809 netdev->ipv6_gateway_auto = false;
f8fee0e2
MK
810 }
811
f8fee0e2
MK
812 return 0;
813}
814
12a50cc6 815static int config_network_script(const char *key, const char *value,
e3b4c4c4
ST
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 }
72d0e1cb 829 if (strstr(key, "script.up") != NULL) {
e3b4c4c4
ST
830 netdev->upscript = copy;
831 return 0;
832 }
74a2b586
JK
833 if (strcmp(key, "lxc.network.script.down") == 0) {
834 netdev->downscript = copy;
835 return 0;
836 }
e3b4c4c4
ST
837 SYSERROR("Unknown key: %s", key);
838 free(copy);
839 return -1;
840}
841
26ddeedd
SH
842static 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
12a50cc6 856static int config_seccomp(const char *key, const char *value,
8f2c3a70
SH
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
d95db067
DE
871 if (lxc_conf->seccomp)
872 free(lxc_conf->seccomp);
8f2c3a70
SH
873 lxc_conf->seccomp = path;
874
875 return 0;
876}
877
12a50cc6 878static int config_hook(const char *key, const char *value,
26ddeedd
SH
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);
5ea6163a
SH
888 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
889 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
f7bee6c6
MW
890 else if (strcmp(key, "lxc.hook.autodev") == 0)
891 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
26ddeedd
SH
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);
148e91f5
SH
898 else if (strcmp(key, "lxc.hook.clone") == 0)
899 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
26ddeedd
SH
900 SYSERROR("Unknown key: %s", key);
901 free(copy);
902 return -1;
903}
904
12a50cc6 905static int config_personality(const char *key, const const char *value,
cccc74b5
DL
906 struct lxc_conf *lxc_conf)
907{
525f0002 908 signed long personality = lxc_config_parse_arch(value);
cccc74b5 909
525f0002
CS
910 if (personality >= 0)
911 lxc_conf->personality = personality;
912 else
913 WARN("unsupported personality '%s'", value);
970ab589
DL
914
915 return 0;
cccc74b5
DL
916}
917
12a50cc6
DE
918static int config_pts(const char *key, const char *value,
919 struct lxc_conf *lxc_conf)
10db618d 920{
921 int maxpts = atoi(value);
922
923 lxc_conf->pts = maxpts;
924
925 return 0;
926}
927
12a50cc6
DE
928static int config_tty(const char *key, const char *value,
929 struct lxc_conf *lxc_conf)
b0a33c1e 930{
931 int nbtty = atoi(value);
932
933 lxc_conf->tty = nbtty;
934
935 return 0;
936}
937
12a50cc6 938static int config_ttydir(const char *key, const char *value,
7c6ef2a2
SH
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
d95db067
DE
951 if (lxc_conf->ttydir)
952 free(lxc_conf->ttydir);
7c6ef2a2
SH
953 lxc_conf->ttydir = path;
954
955 return 0;
956}
957
7e0e1d94
AV
958static 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
fe4de9a6
DE
968static int config_lsm_aa_profile(const char *key, const char *value,
969 struct lxc_conf *lxc_conf)
e075f5d9
SH
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
fe4de9a6
DE
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
988static 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;
e075f5d9
SH
1004
1005 return 0;
1006}
e075f5d9 1007
4a85ce2a
SH
1008static int config_logfile(const char *key, const char *value,
1009 struct lxc_conf *lxc_conf)
1010{
b40a606e
SH
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);
9ea87d5d 1016 return lxc_log_set_file(value);
4a85ce2a
SH
1017}
1018
1019static int config_loglevel(const char *key, const char *value,
1020 struct lxc_conf *lxc_conf)
1021{
9ea87d5d
SH
1022 int newlevel;
1023
4a85ce2a
SH
1024 if (!value || strlen(value) == 0)
1025 return 0;
1026
9ea87d5d
SH
1027 if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET) {
1028 DEBUG("Log level already set - ignoring new value");
1029 return 0;
1030 }
4a85ce2a 1031 if (value[0] >= '0' && value[0] <= '9')
9ea87d5d 1032 newlevel = atoi(value);
4a85ce2a 1033 else
9ea87d5d 1034 newlevel = lxc_log_priority_to_int(value);
b40a606e
SH
1035 // store these values in the lxc_conf, and then try to set for
1036 // actual current logging.
1037 lxc_conf->loglevel = newlevel;
9ea87d5d 1038 return lxc_log_set_level(newlevel);
4a85ce2a
SH
1039}
1040
12a50cc6 1041static int config_autodev(const char *key, const char *value,
c6883f38
SH
1042 struct lxc_conf *lxc_conf)
1043{
1044 int v = atoi(value);
1045
1046 lxc_conf->autodev = v;
1047
1048 return 0;
1049}
1050
a84b9932
AV
1051static 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
1063static 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
1081static 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
1098static 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
12a50cc6
DE
1110static int config_cgroup(const char *key, const char *value,
1111 struct lxc_conf *lxc_conf)
576f946d 1112{
1113 char *token = "lxc.cgroup.";
1114 char *subkey;
bf83c5b9
MS
1115 struct lxc_list *cglist = NULL;
1116 struct lxc_cgroup *cgelem = NULL;
576f946d 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;
a871ff6b 1128
576f946d 1129 subkey += strlen(token);
1130
1131 cglist = malloc(sizeof(*cglist));
1132 if (!cglist)
bf83c5b9 1133 goto out;
576f946d 1134
1135 cgelem = malloc(sizeof(*cgelem));
bf83c5b9
MS
1136 if (!cgelem)
1137 goto out;
1138 memset(cgelem, 0, sizeof(*cgelem));
576f946d 1139
1140 cgelem->subsystem = strdup(subkey);
1141 cgelem->value = strdup(value);
bf83c5b9
MS
1142
1143 if (!cgelem->subsystem || !cgelem->value)
1144 goto out;
1145
576f946d 1146 cglist->elem = cgelem;
1147
94d12f0a 1148 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
576f946d 1149
1150 return 0;
bf83c5b9
MS
1151
1152out:
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;
576f946d 1167}
1168
f6d3e3e4
SH
1169static 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;
251d0d2a 1175 unsigned long hostid, nsid, range;
f6d3e3e4
SH
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
251d0d2a 1200 ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range);
f6d3e3e4
SH
1201 if (ret != 4)
1202 goto out;
251d0d2a 1203 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
ac7725e7 1204 if (type == 'u')
f6d3e3e4 1205 idmap->idtype = ID_TYPE_UID;
ac7725e7 1206 else if (type == 'g')
f6d3e3e4
SH
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
1216out:
1217 if (idmaplist)
1218 free(idmaplist);
1219
1220 if (idmap) {
1221 free(idmap);
1222 }
1223
1224 return -1;
1225}
1226
d95db067
DE
1227static int config_path_item(const char *key, const char *value,
1228 struct lxc_conf *lxc_conf, char **conf_item)
c2cc9f0a 1229{
d95db067 1230 char *valdup;
c2cc9f0a 1231 if (strlen(value) >= MAXPATHLEN) {
36eb9bde 1232 ERROR("%s path is too long", value);
c2cc9f0a 1233 return -1;
1234 }
1235
d95db067
DE
1236 valdup = strdup(value);
1237 if (!valdup) {
36eb9bde 1238 SYSERROR("failed to duplicate string %s", value);
c2cc9f0a 1239 return -1;
1240 }
d95db067
DE
1241 if (*conf_item)
1242 free(*conf_item);
1243 *conf_item = valdup;
c2cc9f0a 1244
1245 return 0;
1246}
1247
d95db067
DE
1248static 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
368bbc02
CS
1254static int config_mount_auto(const char *key, const char *value,
1255 struct lxc_conf *lxc_conf)
1256{
1257 char *autos, *autoptr, *sptr, *token;
b06b8511
CS
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 */
368bbc02
CS
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
b06b8511 1308 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
368bbc02
CS
1309 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
1310 }
1311
1312 free(autos);
1313
1314 return ret;
1315}
1316
12a50cc6
DE
1317static int config_mount(const char *key, const char *value,
1318 struct lxc_conf *lxc_conf)
e7938e9e
MN
1319{
1320 char *fstab_token = "lxc.mount";
1321 char *token = "lxc.mount.entry";
368bbc02 1322 char *auto_token = "lxc.mount.auto";
e7938e9e
MN
1323 char *subkey;
1324 char *mntelem;
1325 struct lxc_list *mntlist;
1326
1327 subkey = strstr(key, token);
1328
1329 if (!subkey) {
368bbc02 1330 subkey = strstr(key, auto_token);
e7938e9e 1331
368bbc02
CS
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 }
e7938e9e 1340
368bbc02 1341 return config_mount_auto(key, value, lxc_conf);
e7938e9e
MN
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);
00b6be44
SH
1352 if (!mntelem) {
1353 free(mntlist);
bf83c5b9 1354 return -1;
00b6be44 1355 }
e7938e9e
MN
1356 mntlist->elem = mntelem;
1357
1358 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1359
1360 return 0;
1361}
1362
1fb86a7c
SH
1363static 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
12a50cc6 1409static int config_cap_drop(const char *key, const char *value,
81810dd1
DL
1410 struct lxc_conf *lxc_conf)
1411{
d95db067 1412 char *dropcaps, *dropptr, *sptr, *token;
81810dd1
DL
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 */
d95db067
DE
1427 for (dropptr = dropcaps;;dropptr = NULL) {
1428 token = strtok_r(dropptr, " \t", &sptr);
81810dd1
DL
1429 if (!token) {
1430 ret = 0;
1431 break;
1432 }
81810dd1
DL
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
12a50cc6 1455static int config_console(const char *key, const char *value,
28a4b0e5
DL
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
d95db067
DE
1466 if (lxc_conf->console.path)
1467 free(lxc_conf->console.path);
28a4b0e5
DL
1468 lxc_conf->console.path = path;
1469
1470 return 0;
1471}
1472
12a50cc6 1473static int config_includefile(const char *key, const char *value,
09ad6246
SH
1474 struct lxc_conf *lxc_conf)
1475{
1476 return lxc_config_read(value, lxc_conf);
1477}
1478
12a50cc6
DE
1479static int config_rootfs(const char *key, const char *value,
1480 struct lxc_conf *lxc_conf)
c2cc9f0a 1481{
d95db067 1482 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.path);
c2cc9f0a 1483}
1484
12a50cc6
DE
1485static int config_rootfs_mount(const char *key, const char *value,
1486 struct lxc_conf *lxc_conf)
23b7ea69 1487{
d95db067 1488 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.mount);
23b7ea69
DL
1489}
1490
12a50cc6
DE
1491static int config_pivotdir(const char *key, const char *value,
1492 struct lxc_conf *lxc_conf)
bf601689 1493{
d95db067 1494 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.pivot);
bf601689
MH
1495}
1496
12a50cc6
DE
1497static int config_utsname(const char *key, const char *value,
1498 struct lxc_conf *lxc_conf)
c2cc9f0a 1499{
1500 struct utsname *utsname;
1501
1502 utsname = malloc(sizeof(*utsname));
1503 if (!utsname) {
36eb9bde 1504 SYSERROR("failed to allocate memory");
c2cc9f0a 1505 return -1;
1506 }
1507
1508 if (strlen(value) >= sizeof(utsname->nodename)) {
36eb9bde 1509 ERROR("node name '%s' is too long",
c2cc9f0a 1510 utsname->nodename);
b6f24d54 1511 free(utsname);
c2cc9f0a 1512 return -1;
1513 }
1514
1515 strcpy(utsname->nodename, value);
d95db067
DE
1516 if (lxc_conf->utsname)
1517 free(lxc_conf->utsname);
c2cc9f0a 1518 lxc_conf->utsname = utsname;
1519
1520 return 0;
1521}
1522
7a7ff0c6 1523static int parse_line(char *buffer, void *data)
c2cc9f0a 1524{
72d0e1cb 1525 struct lxc_config_t *config;
81192358 1526 char *line, *linep;
c2cc9f0a 1527 char *dot;
1528 char *key;
1529 char *value;
476d4cf1 1530 int ret = 0;
c2cc9f0a 1531
91480a0f 1532 if (lxc_is_line_empty(buffer))
c2cc9f0a 1533 return 0;
1534
81192358
DL
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
91480a0f 1538 */
81192358 1539 linep = line = strdup(buffer);
91480a0f
DL
1540 if (!line) {
1541 SYSERROR("failed to allocate memory for '%s'", buffer);
81192358 1542 return -1;
91480a0f
DL
1543 }
1544
b2718c72 1545 line += lxc_char_left_gc(line, strlen(line));
476d4cf1
DL
1546
1547 /* martian option - ignoring it, the commented lines beginning by '#'
1548 * fall in this case
1549 */
1550 if (strncmp(line, "lxc.", 4))
91480a0f 1551 goto out;
476d4cf1
DL
1552
1553 ret = -1;
c2cc9f0a 1554
b2718c72 1555 dot = strstr(line, "=");
c2cc9f0a 1556 if (!dot) {
36eb9bde 1557 ERROR("invalid configuration line: %s", line);
91480a0f 1558 goto out;
c2cc9f0a 1559 }
a871ff6b 1560
c2cc9f0a 1561 *dot = '\0';
1562 value = dot + 1;
1563
b2718c72 1564 key = line;
1565 key[lxc_char_right_gc(key, strlen(key))] = '\0';
c2cc9f0a 1566
b2718c72 1567 value += lxc_char_left_gc(value, strlen(value));
1568 value[lxc_char_right_gc(value, strlen(value))] = '\0';
c2cc9f0a 1569
72d0e1cb 1570 config = lxc_getconfig(key);
c2cc9f0a 1571 if (!config) {
6e1d9b94 1572 ERROR("unknown key %s", key);
91480a0f 1573 goto out;
c2cc9f0a 1574 }
1575
91480a0f
DL
1576 ret = config->cb(key, value, data);
1577
1578out:
81192358 1579 free(linep);
91480a0f 1580 return ret;
c2cc9f0a 1581}
1582
af5b0155
CLG
1583int lxc_config_readline(char *buffer, struct lxc_conf *conf)
1584{
1585 return parse_line(buffer, conf);
1586}
1587
b2718c72 1588int lxc_config_read(const char *file, struct lxc_conf *conf)
c2cc9f0a 1589{
f3ca99fd
SH
1590 if( access(file, R_OK) == -1 ) {
1591 return -1;
1592 }
f7bee6c6
MW
1593 /* Catch only the top level config file name in the structure */
1594 if( ! conf->rcfile ) {
1595 conf->rcfile = strdup( file );
1596 }
2382ecff 1597 return lxc_file_for_each_line(file, parse_line, conf);
c2cc9f0a 1598}
62e46035
CLG
1599
1600int 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
226a18d6 1613int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
62e46035 1614{
9ebb03ad 1615 struct lxc_list *it,*next;
62e46035
CLG
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
9ebb03ad 1624 lxc_list_for_each_safe(it, defines, next) {
62e46035
CLG
1625 lxc_list_del(it);
1626 free(it);
1627 }
1628
1629 return ret;
1630}
525f0002
CS
1631
1632signed long lxc_config_parse_arch(const char *arch)
1633{
6ff05e18 1634 #if HAVE_SYS_PERSONALITY_H
525f0002
CS
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 }
6ff05e18 1652 #endif
525f0002
CS
1653
1654 return -1;
1655}
72d0e1cb
SG
1656
1657static 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
1666static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
1667{
6ff05e18 1668 int fulllen = 0;
72d0e1cb
SG
1669
1670 if (!retv)
1671 inlen = 0;
1672 else
1673 memset(retv, 0, inlen);
1674
6ff05e18
SG
1675 #if HAVE_SYS_PERSONALITY_H
1676 int len = 0;
1677
72d0e1cb
SG
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 }
6ff05e18 1683 #endif
72d0e1cb
SG
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 */
12a50cc6
DE
1697static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
1698 const char *key)
72d0e1cb
SG
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
12a50cc6
DE
1723static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
1724 const char *key)
72d0e1cb
SG
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
1759static 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
1fb86a7c
SH
1775static 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
72d0e1cb
SG
1791static 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 */
12a50cc6
DE
1815static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
1816 const char *key)
72d0e1cb
SG
1817{
1818 char *p1;
fe88b9d2 1819 int len, fulllen = 0;
72d0e1cb
SG
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) {
11029c02
DE
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 }
72d0e1cb
SG
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
1912static 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
12a50cc6
DE
1930int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
1931 int inlen)
72d0e1cb 1932{
4a85ce2a 1933 const char *v = NULL;
72d0e1cb
SG
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)
fe4de9a6
DE
1948 v = c->lsm_aa_profile;
1949 else if (strcmp(key, "lxc.se_context") == 0)
1950 v = c->lsm_se_context;
4a85ce2a 1951 else if (strcmp(key, "lxc.logfile") == 0)
9ea87d5d 1952 v = lxc_log_get_file();
4a85ce2a 1953 else if (strcmp(key, "lxc.loglevel") == 0)
9ea87d5d 1954 v = lxc_log_priority_to_string(lxc_log_get_level());
72d0e1cb
SG
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)
64fca455 1960 v = c->utsname ? c->utsname->nodename : NULL;
72d0e1cb
SG
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);
1fb86a7c
SH
1971 else if (strcmp(key, "lxc.cap.keep") == 0)
1972 return lxc_get_item_cap_keep(c, retv, inlen);
72d0e1cb
SG
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
12a50cc6 1988int lxc_clear_config_item(struct lxc_conf *c, const char *key)
72d0e1cb
SG
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);
1fb86a7c
SH
1996 else if (strcmp(key, "lxc.cap.keep") == 0)
1997 return lxc_clear_config_keepcaps(c);
72d0e1cb
SG
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);
17ed13a3
SH
2002 else if (strncmp(key, "lxc.hook", 8) == 0)
2003 return lxc_clear_hooks(c, key);
72d0e1cb
SG
2004
2005 return -1;
2006}
2007
2008/*
2009 * writing out a confile.
2010 */
2011void 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 }
5f62730e
CS
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 }
72d0e1cb
SG
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);
6ff05e18 2050 #if HAVE_SYS_PERSONALITY_H
72d0e1cb
SG
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 }
6ff05e18 2056 #endif
fe4de9a6
DE
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);
b40a606e
SH
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);
72d0e1cb
SG
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);
1fb86a7c
SH
2133 lxc_list_for_each(it, &c->keepcaps)
2134 fprintf(fout, "lxc.cap.keep = %s\n", (char *)it->elem);
27c27d73
SH
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 }
72d0e1cb
SG
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}