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