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