]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/confile.c
c/r: add more logging when restore fails
[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>
67702c21 39#include <time.h>
e1daebd9 40#include <dirent.h>
c2cc9f0a 41
b2718c72 42#include "parse.h"
6ff05e18 43#include "config.h"
525f0002 44#include "confile.h"
26c39028 45#include "utils.h"
f2363e38
ÇO
46#include "log.h"
47#include "conf.h"
72d0e1cb 48#include "network.h"
58e0f57d 49#include "lxcseccomp.h"
36eb9bde 50
6ff05e18
SG
51#if HAVE_SYS_PERSONALITY_H
52#include <sys/personality.h>
53#endif
54
36eb9bde 55lxc_log_define(lxc_confile, lxc);
576f946d 56
12a50cc6
DE
57static int config_personality(const char *, const char *, struct lxc_conf *);
58static int config_pts(const char *, const char *, struct lxc_conf *);
59static int config_tty(const char *, const char *, struct lxc_conf *);
60static int config_ttydir(const char *, const char *, struct lxc_conf *);
7e0e1d94 61static int config_kmsg(const char *, const char *, struct lxc_conf *);
fe4de9a6 62static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
7aff4f43 63static int config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf *);
fe4de9a6 64static int config_lsm_se_context(const char *, const char *, struct lxc_conf *);
12a50cc6 65static int config_cgroup(const char *, const char *, struct lxc_conf *);
f6d3e3e4 66static int config_idmap(const char *, const char *, struct lxc_conf *);
4a85ce2a
SH
67static int config_loglevel(const char *, const char *, struct lxc_conf *);
68static int config_logfile(const char *, const char *, struct lxc_conf *);
12a50cc6 69static int config_mount(const char *, const char *, struct lxc_conf *);
70f55bfd
NC
70static int config_mount_auto(const char *, const char *, struct lxc_conf *);
71static int config_fstab(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
72static int config_rootfs(const char *, const char *, struct lxc_conf *);
73static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
a17b1e65 74static int config_rootfs_options(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
75static int config_pivotdir(const char *, const char *, struct lxc_conf *);
76static int config_utsname(const char *, const char *, struct lxc_conf *);
77static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
6b0d5538 78static int config_network(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
79static int config_network_type(const char *, const char *, struct lxc_conf *);
80static int config_network_flags(const char *, const char *, struct lxc_conf *);
81static int config_network_link(const char *, const char *, struct lxc_conf *);
82static int config_network_name(const char *, const char *, struct lxc_conf *);
83static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
84static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
85static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
86static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
87static int config_network_mtu(const char *, const char *, struct lxc_conf *);
88static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
89static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
8fc8295a
DE
90static int config_network_script_up(const char *, const char *, struct lxc_conf *);
91static int config_network_script_down(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
92static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
93static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
94static int config_cap_drop(const char *, const char *, struct lxc_conf *);
1fb86a7c 95static int config_cap_keep(const char *, const char *, struct lxc_conf *);
12a50cc6 96static int config_console(const char *, const char *, struct lxc_conf *);
96f15ca1 97static int config_console_logfile(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
98static int config_seccomp(const char *, const char *, struct lxc_conf *);
99static int config_includefile(const char *, const char *, struct lxc_conf *);
100static int config_network_nic(const char *, const char *, struct lxc_conf *);
101static int config_autodev(const char *, const char *, struct lxc_conf *);
f0f1d8c0 102static int config_haltsignal(const char *, const char *, struct lxc_conf *);
dd267776 103static int config_rebootsignal(const char *, const char *, struct lxc_conf *);
a84b9932 104static int config_stopsignal(const char *, const char *, struct lxc_conf *);
ee1e7aa0 105static int config_start(const char *, const char *, struct lxc_conf *);
a8dfe4e0 106static int config_monitor(const char *, const char *, struct lxc_conf *);
ee1e7aa0 107static int config_group(const char *, const char *, struct lxc_conf *);
7c661726 108static int config_environment(const char *, const char *, struct lxc_conf *);
67c660d0 109static int config_init_cmd(const char *, const char *, struct lxc_conf *);
72bb04e4
PT
110static int config_init_uid(const char *, const char *, struct lxc_conf *);
111static int config_init_gid(const char *, const char *, struct lxc_conf *);
8796becf 112static int config_ephemeral(const char *, const char *, struct lxc_conf *);
c2cc9f0a 113
72d0e1cb 114static struct lxc_config_t config[] = {
576f946d 115
cccc74b5 116 { "lxc.arch", config_personality },
e892973e
DL
117 { "lxc.pts", config_pts },
118 { "lxc.tty", config_tty },
7c6ef2a2 119 { "lxc.devttydir", config_ttydir },
7e0e1d94 120 { "lxc.kmsg", config_kmsg },
fe4de9a6 121 { "lxc.aa_profile", config_lsm_aa_profile },
7aff4f43 122 { "lxc.aa_allow_incomplete", config_lsm_aa_incomplete },
fe4de9a6 123 { "lxc.se_context", config_lsm_se_context },
e892973e 124 { "lxc.cgroup", config_cgroup },
f6d3e3e4 125 { "lxc.id_map", config_idmap },
4a85ce2a
SH
126 { "lxc.loglevel", config_loglevel },
127 { "lxc.logfile", config_logfile },
70f55bfd
NC
128 { "lxc.mount.entry", config_mount },
129 { "lxc.mount.auto", config_mount_auto },
130 { "lxc.mount", config_fstab },
23b7ea69 131 { "lxc.rootfs.mount", config_rootfs_mount },
a17b1e65 132 { "lxc.rootfs.options", config_rootfs_options },
e892973e 133 { "lxc.rootfs", config_rootfs },
bf601689 134 { "lxc.pivotdir", config_pivotdir },
e892973e 135 { "lxc.utsname", config_utsname },
26ddeedd 136 { "lxc.hook.pre-start", config_hook },
12a50cc6 137 { "lxc.hook.pre-mount", config_hook },
26ddeedd 138 { "lxc.hook.mount", config_hook },
f7bee6c6 139 { "lxc.hook.autodev", config_hook },
26ddeedd 140 { "lxc.hook.start", config_hook },
52492063 141 { "lxc.hook.stop", config_hook },
26ddeedd 142 { "lxc.hook.post-stop", config_hook },
148e91f5 143 { "lxc.hook.clone", config_hook },
37cf711b 144 { "lxc.hook.destroy", config_hook },
6b0d5538 145 { "lxc.hook", config_hook },
e892973e
DL
146 { "lxc.network.type", config_network_type },
147 { "lxc.network.flags", config_network_flags },
148 { "lxc.network.link", config_network_link },
149 { "lxc.network.name", config_network_name },
150 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
151 { "lxc.network.veth.pair", config_network_veth_pair },
8fc8295a
DE
152 { "lxc.network.script.up", config_network_script_up },
153 { "lxc.network.script.down", config_network_script_down },
e892973e
DL
154 { "lxc.network.hwaddr", config_network_hwaddr },
155 { "lxc.network.mtu", config_network_mtu },
156 { "lxc.network.vlan.id", config_network_vlan_id },
f8fee0e2 157 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
e892973e 158 { "lxc.network.ipv4", config_network_ipv4 },
f8fee0e2 159 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
e892973e 160 { "lxc.network.ipv6", config_network_ipv6 },
72d0e1cb
SG
161 /* config_network_nic must come after all other 'lxc.network.*' entries */
162 { "lxc.network.", config_network_nic },
6b0d5538 163 { "lxc.network", config_network },
81810dd1 164 { "lxc.cap.drop", config_cap_drop },
1fb86a7c 165 { "lxc.cap.keep", config_cap_keep },
96f15ca1 166 { "lxc.console.logfile", config_console_logfile },
63376d7d 167 { "lxc.console", config_console },
8f2c3a70 168 { "lxc.seccomp", config_seccomp },
09ad6246 169 { "lxc.include", config_includefile },
c6883f38 170 { "lxc.autodev", config_autodev },
f0f1d8c0 171 { "lxc.haltsignal", config_haltsignal },
dd267776 172 { "lxc.rebootsignal", config_rebootsignal },
a84b9932 173 { "lxc.stopsignal", config_stopsignal },
ee1e7aa0
SG
174 { "lxc.start.auto", config_start },
175 { "lxc.start.delay", config_start },
176 { "lxc.start.order", config_start },
a8dfe4e0 177 { "lxc.monitor.unshare", config_monitor },
ee1e7aa0 178 { "lxc.group", config_group },
7c661726 179 { "lxc.environment", config_environment },
67c660d0 180 { "lxc.init_cmd", config_init_cmd },
72bb04e4
PT
181 { "lxc.init_uid", config_init_uid },
182 { "lxc.init_gid", config_init_gid },
8796becf 183 { "lxc.ephemeral", config_ephemeral },
a84b9932
AV
184};
185
186struct signame {
187 int num;
74a3920a 188 const char *name;
a84b9932
AV
189};
190
74a3920a 191static const struct signame signames[] = {
a84b9932
AV
192 { SIGHUP, "HUP" },
193 { SIGINT, "INT" },
194 { SIGQUIT, "QUIT" },
195 { SIGILL, "ILL" },
196 { SIGABRT, "ABRT" },
197 { SIGFPE, "FPE" },
198 { SIGKILL, "KILL" },
199 { SIGSEGV, "SEGV" },
200 { SIGPIPE, "PIPE" },
201 { SIGALRM, "ALRM" },
202 { SIGTERM, "TERM" },
203 { SIGUSR1, "USR1" },
204 { SIGUSR2, "USR2" },
205 { SIGCHLD, "CHLD" },
206 { SIGCONT, "CONT" },
207 { SIGSTOP, "STOP" },
208 { SIGTSTP, "TSTP" },
209 { SIGTTIN, "TTIN" },
210 { SIGTTOU, "TTOU" },
89dfc302
SY
211#ifdef SIGTRAP
212 { SIGTRAP, "TRAP" },
213#endif
214#ifdef SIGIOT
215 { SIGIOT, "IOT" },
216#endif
217#ifdef SIGEMT
218 { SIGEMT, "EMT" },
219#endif
220#ifdef SIGBUS
221 { SIGBUS, "BUS" },
222#endif
223#ifdef SIGSTKFLT
224 { SIGSTKFLT, "STKFLT" },
225#endif
226#ifdef SIGCLD
227 { SIGCLD, "CLD" },
228#endif
229#ifdef SIGURG
230 { SIGURG, "URG" },
231#endif
232#ifdef SIGXCPU
233 { SIGXCPU, "XCPU" },
234#endif
235#ifdef SIGXFSZ
236 { SIGXFSZ, "XFSZ" },
237#endif
238#ifdef SIGVTALRM
239 { SIGVTALRM, "VTALRM" },
240#endif
241#ifdef SIGPROF
242 { SIGPROF, "PROF" },
243#endif
244#ifdef SIGWINCH
245 { SIGWINCH, "WINCH" },
246#endif
247#ifdef SIGIO
248 { SIGIO, "IO" },
249#endif
250#ifdef SIGPOLL
251 { SIGPOLL, "POLL" },
252#endif
253#ifdef SIGINFO
254 { SIGINFO, "INFO" },
255#endif
256#ifdef SIGLOST
257 { SIGLOST, "LOST" },
258#endif
259#ifdef SIGPWR
260 { SIGPWR, "PWR" },
261#endif
262#ifdef SIGUNUSED
263 { SIGUNUSED, "UNUSED" },
264#endif
265#ifdef SIGSYS
266 { SIGSYS, "SYS" },
267#endif
c2cc9f0a 268};
269
72d0e1cb 270static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
c2cc9f0a 271
72d0e1cb 272extern struct lxc_config_t *lxc_getconfig(const char *key)
c2cc9f0a 273{
274 int i;
275
276 for (i = 0; i < config_size; i++)
a871ff6b 277 if (!strncmp(config[i].name, key,
c2cc9f0a 278 strlen(config[i].name)))
279 return &config[i];
280 return NULL;
281}
282
72d0e1cb
SG
283#define strprint(str, inlen, ...) \
284 do { \
285 len = snprintf(str, inlen, ##__VA_ARGS__); \
286 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
287 fulllen += len; \
288 if (inlen > 0) { \
289 if (str) str += len; \
290 inlen -= len; \
291 if (inlen < 0) inlen = 0; \
292 } \
293 } while (0);
294
295int lxc_listconfigs(char *retv, int inlen)
296{
297 int i, fulllen = 0, len;
298
299 if (!retv)
300 inlen = 0;
301 else
302 memset(retv, 0, inlen);
303 for (i = 0; i < config_size; i++) {
304 char *s = config[i].name;
305 if (s[strlen(s)-1] == '.')
306 continue;
307 strprint(retv, inlen, "%s\n", s);
308 }
309 return fulllen;
310}
311
6d03d92a
DE
312static int config_string_item(char **conf_item, const char *value)
313{
314 char *new_value;
315
d6eca240 316 if (!value || strlen(value) == 0) {
f10fad2f 317 free(*conf_item);
d6eca240 318 *conf_item = NULL;
6d03d92a 319 return 0;
d6eca240 320 }
6d03d92a
DE
321
322 new_value = strdup(value);
323 if (!new_value) {
324 SYSERROR("failed to strdup '%s': %m", value);
325 return -1;
326 }
327
f10fad2f 328 free(*conf_item);
6d03d92a
DE
329 *conf_item = new_value;
330 return 0;
331}
332
333static int config_string_item_max(char **conf_item, const char *value,
334 size_t max)
335{
336 if (strlen(value) >= max) {
a5a82508 337 ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
6d03d92a
DE
338 return -1;
339 }
340
341 return config_string_item(conf_item, value);
342}
343
344static int config_path_item(char **conf_item, const char *value)
345{
346 return config_string_item_max(conf_item, value, PATH_MAX);
347}
348
72d0e1cb
SG
349/*
350 * config entry is something like "lxc.network.0.ipv4"
351 * the key 'lxc.network.' was found. So we make sure next
352 * comes an integer, find the right callback (by rewriting
353 * the key), and call it.
354 */
12a50cc6 355static int config_network_nic(const char *key, const char *value,
72d0e1cb
SG
356 struct lxc_conf *lxc_conf)
357{
358 char *copy = strdup(key), *p;
359 int ret = -1;
360 struct lxc_config_t *config;
361
362 if (!copy) {
363 SYSERROR("failed to allocate memory");
364 return -1;
365 }
366 /*
367 * ok we know that to get here we've got "lxc.network."
368 * and it isn't any of the other network entries. So
369 * after the second . should come an integer (# of defined
370 * nic) followed by a valid entry.
371 */
372 if (*(key+12) < '0' || *(key+12) > '9')
373 goto out;
46cd2845 374 p = strchr(key+12, '.');
72d0e1cb
SG
375 if (!p)
376 goto out;
377 strcpy(copy+12, p+1);
378 config = lxc_getconfig(copy);
379 if (!config) {
380 ERROR("unknown key %s", key);
381 goto out;
382 }
383 ret = config->cb(key, value, lxc_conf);
384
385out:
386 free(copy);
387 return ret;
388}
389
6b0d5538
SH
390static int config_network(const char *key, const char *value,
391 struct lxc_conf *lxc_conf)
392{
393 if (value && strlen(value)) {
394 ERROR("lxc.network must not have a value");
395 return -1;
396 }
397
398 return lxc_clear_config_network(lxc_conf);
399}
400
261658e8
BP
401static int macvlan_mode(int *valuep, const char *value);
402
12a50cc6 403static int config_network_type(const char *key, const char *value,
e892973e 404 struct lxc_conf *lxc_conf)
c2cc9f0a 405{
5f4535a3 406 struct lxc_list *network = &lxc_conf->network;
c2cc9f0a 407 struct lxc_netdev *netdev;
408 struct lxc_list *list;
c2cc9f0a 409
7d0eb87e
SH
410 if (!value || strlen(value) == 0)
411 return lxc_clear_config_network(lxc_conf);
412
c2cc9f0a 413 netdev = malloc(sizeof(*netdev));
414 if (!netdev) {
36eb9bde 415 SYSERROR("failed to allocate memory");
c2cc9f0a 416 return -1;
417 }
418
82d5ae15 419 memset(netdev, 0, sizeof(*netdev));
c2cc9f0a 420 lxc_list_init(&netdev->ipv4);
421 lxc_list_init(&netdev->ipv6);
c2cc9f0a 422
423 list = malloc(sizeof(*list));
424 if (!list) {
36eb9bde 425 SYSERROR("failed to allocate memory");
022de5f3 426 free(netdev);
c2cc9f0a 427 return -1;
428 }
429
430 lxc_list_init(list);
5f4535a3 431 list->elem = netdev;
c2cc9f0a 432
bac89583 433 lxc_list_add_tail(network, list);
a871ff6b 434
c2cc9f0a 435 if (!strcmp(value, "veth"))
24654103 436 netdev->type = LXC_NET_VETH;
261658e8 437 else if (!strcmp(value, "macvlan")) {
24654103 438 netdev->type = LXC_NET_MACVLAN;
261658e8
BP
439 macvlan_mode(&netdev->priv.macvlan_attr.mode, "private");
440 }
26c39028 441 else if (!strcmp(value, "vlan"))
24654103 442 netdev->type = LXC_NET_VLAN;
c2cc9f0a 443 else if (!strcmp(value, "phys"))
24654103 444 netdev->type = LXC_NET_PHYS;
5f58350a 445 else if (!strcmp(value, "empty"))
24654103 446 netdev->type = LXC_NET_EMPTY;
26b797f3
SH
447 else if (!strcmp(value, "none"))
448 netdev->type = LXC_NET_NONE;
c2cc9f0a 449 else {
36eb9bde 450 ERROR("invalid network type %s", value);
c2cc9f0a 451 return -1;
452 }
453 return 0;
454}
455
a059591e
DL
456static int config_ip_prefix(struct in_addr *addr)
457{
458 if (IN_CLASSA(addr->s_addr))
459 return 32 - IN_CLASSA_NSHIFT;
460 if (IN_CLASSB(addr->s_addr))
461 return 32 - IN_CLASSB_NSHIFT;
462 if (IN_CLASSC(addr->s_addr))
463 return 32 - IN_CLASSC_NSHIFT;
464
465 return 0;
466}
467
72d0e1cb
SG
468/*
469 * if you have p="lxc.network.0.link", pass it p+12
470 * to get back '0' (the index of the nic)
471 */
472static int get_network_netdev_idx(const char *key)
473{
474 int ret, idx;
475
476 if (*key < '0' || *key > '9')
477 return -1;
478 ret = sscanf(key, "%d", &idx);
479 if (ret != 1)
480 return -1;
481 return idx;
482}
483
484/*
485 * if you have p="lxc.network.0", pass this p+12 and it will return
486 * the netdev of the first configured nic
487 */
488static struct lxc_netdev *get_netdev_from_key(const char *key,
489 struct lxc_list *network)
490{
491 int i = 0, idx = get_network_netdev_idx(key);
492 struct lxc_netdev *netdev = NULL;
493 struct lxc_list *it;
494 if (idx == -1)
495 return NULL;
496 lxc_list_for_each(it, network) {
497 if (idx == i++) {
498 netdev = it->elem;
499 break;
500 }
501 }
502 return netdev;
503}
504
12a50cc6
DE
505extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
506 char *retv, int inlen)
72d0e1cb
SG
507{
508 struct lxc_netdev *netdev;
509 int fulllen = 0, len;
510
511 netdev = get_netdev_from_key(key+12, &c->network);
512 if (!netdev)
513 return -1;
514
515 if (!retv)
516 inlen = 0;
517 else
518 memset(retv, 0, inlen);
519
520 strprint(retv, inlen, "script.up\n");
8fc8295a 521 strprint(retv, inlen, "script.down\n");
72d0e1cb
SG
522 if (netdev->type != LXC_NET_EMPTY) {
523 strprint(retv, inlen, "flags\n");
524 strprint(retv, inlen, "link\n");
525 strprint(retv, inlen, "name\n");
526 strprint(retv, inlen, "hwaddr\n");
527 strprint(retv, inlen, "mtu\n");
528 strprint(retv, inlen, "ipv6\n");
9eaf8a59 529 strprint(retv, inlen, "ipv6.gateway\n");
72d0e1cb 530 strprint(retv, inlen, "ipv4\n");
9eaf8a59 531 strprint(retv, inlen, "ipv4.gateway\n");
72d0e1cb
SG
532 }
533 switch(netdev->type) {
534 case LXC_NET_VETH:
535 strprint(retv, inlen, "veth.pair\n");
536 break;
537 case LXC_NET_MACVLAN:
538 strprint(retv, inlen, "macvlan.mode\n");
539 break;
540 case LXC_NET_VLAN:
541 strprint(retv, inlen, "vlan.id\n");
542 break;
543 case LXC_NET_PHYS:
544 break;
545 }
546 return fulllen;
547}
548
16950ecb
DL
549static struct lxc_netdev *network_netdev(const char *key, const char *value,
550 struct lxc_list *network)
c2cc9f0a 551{
72d0e1cb 552 struct lxc_netdev *netdev = NULL;
c2cc9f0a 553
5f4535a3 554 if (lxc_list_empty(network)) {
16950ecb
DL
555 ERROR("network is not created for '%s' = '%s' option",
556 key, value);
33c945e0 557 return NULL;
c2cc9f0a 558 }
559
72d0e1cb
SG
560 if (get_network_netdev_idx(key+12) == -1)
561 netdev = lxc_list_last_elem(network);
562 else
563 netdev = get_netdev_from_key(key+12, network);
564
5f4535a3 565 if (!netdev) {
16950ecb
DL
566 ERROR("no network device defined for '%s' = '%s' option",
567 key, value);
33c945e0 568 return NULL;
c2cc9f0a 569 }
570
33c945e0 571 return netdev;
c2cc9f0a 572}
573
12a50cc6 574static int network_ifname(char **valuep, const char *value)
c2cc9f0a 575{
c9bb9a85 576 return config_string_item_max(valuep, value, IFNAMSIZ);
c2cc9f0a 577}
578
e892973e
DL
579#ifndef MACVLAN_MODE_PRIVATE
580# define MACVLAN_MODE_PRIVATE 1
581#endif
582
583#ifndef MACVLAN_MODE_VEPA
584# define MACVLAN_MODE_VEPA 2
585#endif
586
587#ifndef MACVLAN_MODE_BRIDGE
588# define MACVLAN_MODE_BRIDGE 4
589#endif
590
99854161
EL
591#ifndef MACVLAN_MODE_PASSTHRU
592# define MACVLAN_MODE_PASSTHRU 8
593#endif
594
12a50cc6 595static int macvlan_mode(int *valuep, const char *value)
e892973e
DL
596{
597 struct mc_mode {
598 char *name;
599 int mode;
600 } m[] = {
601 { "private", MACVLAN_MODE_PRIVATE },
602 { "vepa", MACVLAN_MODE_VEPA },
603 { "bridge", MACVLAN_MODE_BRIDGE },
99854161 604 { "passthru", MACVLAN_MODE_PASSTHRU },
e892973e
DL
605 };
606
607 int i;
608
609 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
610 if (strcmp(m[i].name, value))
611 continue;
612
613 *valuep = m[i].mode;
614 return 0;
615 }
616
617 return -1;
618}
619
508c263e
SH
620static int rand_complete_hwaddr(char *hwaddr)
621{
622 const char hex[] = "0123456789abcdef";
623 char *curs = hwaddr;
624
625#ifndef HAVE_RAND_R
626 randseed(true);
627#else
628 unsigned int seed=randseed(false);
629#endif
e6744e9b 630 while (*curs != '\0' && *curs != '\n')
508c263e
SH
631 {
632 if ( *curs == 'x' || *curs == 'X' ) {
633 if (curs - hwaddr == 1) {
634 //ensure address is unicast
635#ifdef HAVE_RAND_R
636 *curs = hex[rand_r(&seed) & 0x0E];
637 } else {
638 *curs = hex[rand_r(&seed) & 0x0F];
639#else
640 *curs = hex[rand() & 0x0E];
641 } else {
642 *curs = hex[rand() & 0x0F];
643#endif
644 }
645 }
646 curs++;
647 }
648 return 0;
649}
650
12a50cc6 651static int config_network_flags(const char *key, const char *value,
33c945e0 652 struct lxc_conf *lxc_conf)
c2cc9f0a 653{
c2cc9f0a 654 struct lxc_netdev *netdev;
655
16950ecb 656 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 657 if (!netdev)
c2cc9f0a 658 return -1;
c2cc9f0a 659
33c945e0 660 netdev->flags |= IFF_UP;
c2cc9f0a 661
33c945e0
MT
662 return 0;
663}
664
12a50cc6 665static int config_network_link(const char *key, const char *value,
33c945e0
MT
666 struct lxc_conf *lxc_conf)
667{
668 struct lxc_netdev *netdev;
669
16950ecb 670 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 671 if (!netdev)
c2cc9f0a 672 return -1;
c2cc9f0a 673
33c945e0 674 return network_ifname(&netdev->link, value);
c2cc9f0a 675}
676
12a50cc6 677static int config_network_name(const char *key, const char *value,
33c945e0 678 struct lxc_conf *lxc_conf)
c2cc9f0a 679{
c2cc9f0a 680 struct lxc_netdev *netdev;
681
16950ecb 682 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 683 if (!netdev)
c2cc9f0a 684 return -1;
c2cc9f0a 685
33c945e0
MT
686 return network_ifname(&netdev->name, value);
687}
688
12a50cc6 689static int config_network_veth_pair(const char *key, const char *value,
e892973e
DL
690 struct lxc_conf *lxc_conf)
691{
692 struct lxc_netdev *netdev;
693
694 netdev = network_netdev(key, value, &lxc_conf->network);
695 if (!netdev)
696 return -1;
697
c5316d60 698 if (netdev->type != LXC_NET_VETH) {
128d327a 699 ERROR("Invalid veth pair for a non-veth netdev");
c5316d60
SH
700 return -1;
701 }
e892973e
DL
702 return network_ifname(&netdev->priv.veth_attr.pair, value);
703}
704
12a50cc6 705static int config_network_macvlan_mode(const char *key, const char *value,
e892973e 706 struct lxc_conf *lxc_conf)
8634bc19
MT
707{
708 struct lxc_netdev *netdev;
709
710 netdev = network_netdev(key, value, &lxc_conf->network);
711 if (!netdev)
712 return -1;
713
c5316d60 714 if (netdev->type != LXC_NET_MACVLAN) {
128d327a 715 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
c5316d60
SH
716 return -1;
717 }
e892973e 718 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
8634bc19
MT
719}
720
12a50cc6 721static int config_network_hwaddr(const char *key, const char *value,
33c945e0
MT
722 struct lxc_conf *lxc_conf)
723{
724 struct lxc_netdev *netdev;
725
508c263e
SH
726 char *new_value = strdup(value);
727 if (!new_value) {
728 SYSERROR("failed to strdup '%s': %m", value);
c2cc9f0a 729 return -1;
508c263e
SH
730 }
731 rand_complete_hwaddr(new_value);
c2cc9f0a 732
508c263e
SH
733 netdev = network_netdev(key, new_value, &lxc_conf->network);
734 if (!netdev) {
735 free(new_value);
736 return -1;
737 };
738
739 if (!new_value || strlen(new_value) == 0) {
740 free(new_value);
741 netdev->hwaddr = NULL;
742 return 0;
743 }
744
745 netdev->hwaddr = new_value;
746 return 0;
c2cc9f0a 747}
748
12a50cc6 749static int config_network_vlan_id(const char *key, const char *value,
26c39028
JHS
750 struct lxc_conf *lxc_conf)
751{
752 struct lxc_netdev *netdev;
753
754 netdev = network_netdev(key, value, &lxc_conf->network);
755 if (!netdev)
756 return -1;
757
c5316d60 758 if (netdev->type != LXC_NET_VLAN) {
128d327a 759 ERROR("Invalid vlan.id for a non-macvlan netdev");
c5316d60
SH
760 return -1;
761 }
f6cc1de1 762 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
26c39028
JHS
763 return -1;
764
765 return 0;
766}
767
12a50cc6 768static int config_network_mtu(const char *key, const char *value,
33c945e0 769 struct lxc_conf *lxc_conf)
442cbbe6 770{
442cbbe6
TR
771 struct lxc_netdev *netdev;
772
16950ecb 773 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 774 if (!netdev)
442cbbe6 775 return -1;
442cbbe6 776
6d03d92a 777 return config_string_item(&netdev->mtu, value);
442cbbe6
TR
778}
779
12a50cc6 780static int config_network_ipv4(const char *key, const char *value,
33c945e0 781 struct lxc_conf *lxc_conf)
c2cc9f0a 782{
c2cc9f0a 783 struct lxc_netdev *netdev;
33c945e0 784 struct lxc_inetdev *inetdev;
c2cc9f0a 785 struct lxc_list *list;
786 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
787
16950ecb 788 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 789 if (!netdev)
c2cc9f0a 790 return -1;
c2cc9f0a 791
792 inetdev = malloc(sizeof(*inetdev));
793 if (!inetdev) {
36eb9bde 794 SYSERROR("failed to allocate ipv4 address");
c2cc9f0a 795 return -1;
796 }
797 memset(inetdev, 0, sizeof(*inetdev));
798
799 list = malloc(sizeof(*list));
800 if (!list) {
36eb9bde 801 SYSERROR("failed to allocate memory");
53719062 802 free(inetdev);
c2cc9f0a 803 return -1;
804 }
805
806 lxc_list_init(list);
807 list->elem = inetdev;
808
956edc54
SG
809 addr = strdup(value);
810 if (!addr) {
811 ERROR("no address specified");
53719062
SH
812 free(inetdev);
813 free(list);
956edc54
SG
814 return -1;
815 }
c2cc9f0a 816
817 cursor = strstr(addr, " ");
818 if (cursor) {
819 *cursor = '\0';
820 bcast = cursor + 1;
821 }
822
823 slash = strstr(addr, "/");
824 if (slash) {
825 *slash = '\0';
826 prefix = slash + 1;
827 }
828
c2cc9f0a 829 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
36eb9bde 830 SYSERROR("invalid ipv4 address: %s", value);
53719062 831 free(inetdev);
956edc54 832 free(addr);
53719062 833 free(list);
c2cc9f0a 834 return -1;
835 }
836
0093bb8c
DL
837 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
838 SYSERROR("invalid ipv4 broadcast address: %s", value);
53719062
SH
839 free(inetdev);
840 free(list);
956edc54 841 free(addr);
0093bb8c
DL
842 return -1;
843 }
c2cc9f0a 844
a059591e
DL
845 /* no prefix specified, determine it from the network class */
846 inetdev->prefix = prefix ? atoi(prefix) :
847 config_ip_prefix(&inetdev->addr);
848
b3df193c 849 /* if no broadcast address, let compute one from the
0093bb8c
DL
850 * prefix and address
851 */
852 if (!bcast) {
1b7d4743
DL
853 inetdev->bcast.s_addr = inetdev->addr.s_addr;
854 inetdev->bcast.s_addr |=
855 htonl(INADDR_BROADCAST >> inetdev->prefix);
0093bb8c 856 }
c2cc9f0a 857
8538f388 858 lxc_list_add_tail(&netdev->ipv4, list);
c2cc9f0a 859
956edc54 860 free(addr);
c2cc9f0a 861 return 0;
862}
863
12a50cc6 864static int config_network_ipv4_gateway(const char *key, const char *value,
f8fee0e2
MK
865 struct lxc_conf *lxc_conf)
866{
867 struct lxc_netdev *netdev;
f8fee0e2
MK
868
869 netdev = network_netdev(key, value, &lxc_conf->network);
870 if (!netdev)
871 return -1;
872
e088e926 873 free(netdev->ipv4_gateway);
f8fee0e2 874
e088e926
SG
875 if (!value || strlen(value) == 0) {
876 netdev->ipv4_gateway = NULL;
877 } else if (!strcmp(value, "auto")) {
19a26f82
MK
878 netdev->ipv4_gateway = NULL;
879 netdev->ipv4_gateway_auto = true;
880 } else {
e088e926
SG
881 struct in_addr *gw;
882
883 gw = malloc(sizeof(*gw));
884 if (!gw) {
885 SYSERROR("failed to allocate ipv4 gateway address");
886 return -1;
887 }
888
19a26f82
MK
889 if (!inet_pton(AF_INET, value, gw)) {
890 SYSERROR("invalid ipv4 gateway address: %s", value);
53719062 891 free(gw);
19a26f82
MK
892 return -1;
893 }
894
895 netdev->ipv4_gateway = gw;
896 netdev->ipv4_gateway_auto = false;
f8fee0e2
MK
897 }
898
f8fee0e2
MK
899 return 0;
900}
901
12a50cc6 902static int config_network_ipv6(const char *key, const char *value,
e892973e 903 struct lxc_conf *lxc_conf)
c2cc9f0a 904{
c2cc9f0a 905 struct lxc_netdev *netdev;
906 struct lxc_inet6dev *inet6dev;
907 struct lxc_list *list;
12a50cc6 908 char *slash,*valdup;
c2cc9f0a 909 char *netmask;
910
16950ecb 911 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 912 if (!netdev)
c2cc9f0a 913 return -1;
c2cc9f0a 914
915 inet6dev = malloc(sizeof(*inet6dev));
916 if (!inet6dev) {
36eb9bde 917 SYSERROR("failed to allocate ipv6 address");
c2cc9f0a 918 return -1;
919 }
920 memset(inet6dev, 0, sizeof(*inet6dev));
921
922 list = malloc(sizeof(*list));
923 if (!list) {
36eb9bde 924 SYSERROR("failed to allocate memory");
28027320 925 free(inet6dev);
c2cc9f0a 926 return -1;
927 }
928
929 lxc_list_init(list);
930 list->elem = inet6dev;
931
956edc54
SG
932 valdup = strdup(value);
933 if (!valdup) {
934 ERROR("no address specified");
28027320
SH
935 free(list);
936 free(inet6dev);
956edc54
SG
937 return -1;
938 }
939
a059591e 940 inet6dev->prefix = 64;
12a50cc6 941 slash = strstr(valdup, "/");
c2cc9f0a 942 if (slash) {
943 *slash = '\0';
944 netmask = slash + 1;
945 inet6dev->prefix = atoi(netmask);
946 }
947
5acccf95
SH
948 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
949 SYSERROR("invalid ipv6 address: %s", valdup);
28027320
SH
950 free(list);
951 free(inet6dev);
956edc54 952 free(valdup);
c2cc9f0a 953 return -1;
954 }
955
8538f388 956 lxc_list_add_tail(&netdev->ipv6, list);
c2cc9f0a 957
956edc54 958 free(valdup);
c2cc9f0a 959 return 0;
960}
961
12a50cc6 962static int config_network_ipv6_gateway(const char *key, const char *value,
f8fee0e2
MK
963 struct lxc_conf *lxc_conf)
964{
965 struct lxc_netdev *netdev;
f8fee0e2
MK
966
967 netdev = network_netdev(key, value, &lxc_conf->network);
968 if (!netdev)
969 return -1;
970
e088e926 971 free(netdev->ipv6_gateway);
f8fee0e2 972
e088e926
SG
973 if (!value || strlen(value) == 0) {
974 netdev->ipv4_gateway = NULL;
975 } else if (!strcmp(value, "auto")) {
19a26f82
MK
976 netdev->ipv6_gateway = NULL;
977 netdev->ipv6_gateway_auto = true;
978 } else {
8fb86a37
SH
979 struct in6_addr *gw;
980
bec695f3
DE
981 gw = malloc(sizeof(*gw));
982 if (!gw) {
983 SYSERROR("failed to allocate ipv6 gateway address");
984 return -1;
985 }
986
19a26f82
MK
987 if (!inet_pton(AF_INET6, value, gw)) {
988 SYSERROR("invalid ipv6 gateway address: %s", value);
28027320 989 free(gw);
19a26f82
MK
990 return -1;
991 }
992
993 netdev->ipv6_gateway = gw;
994 netdev->ipv6_gateway_auto = false;
f8fee0e2
MK
995 }
996
f8fee0e2
MK
997 return 0;
998}
999
8fc8295a
DE
1000static int config_network_script_up(const char *key, const char *value,
1001 struct lxc_conf *lxc_conf)
e3b4c4c4
ST
1002{
1003 struct lxc_netdev *netdev;
1004
1005 netdev = network_netdev(key, value, &lxc_conf->network);
1006 if (!netdev)
8fc8295a 1007 return -1;
e3b4c4c4 1008
8fc8295a
DE
1009 return config_string_item(&netdev->upscript, value);
1010}
1011
1012static int config_network_script_down(const char *key, const char *value,
1013 struct lxc_conf *lxc_conf)
1014{
1015 struct lxc_netdev *netdev;
1016
1017 netdev = network_netdev(key, value, &lxc_conf->network);
1018 if (!netdev)
1019 return -1;
1020
1021 return config_string_item(&netdev->downscript, value);
e3b4c4c4
ST
1022}
1023
26ddeedd
SH
1024static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
1025{
1026 struct lxc_list *hooklist;
1027
1028 hooklist = malloc(sizeof(*hooklist));
1029 if (!hooklist) {
1030 free(hook);
1031 return -1;
1032 }
1033 hooklist->elem = hook;
1034 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
1035 return 0;
1036}
1037
12a50cc6 1038static int config_seccomp(const char *key, const char *value,
8f2c3a70
SH
1039 struct lxc_conf *lxc_conf)
1040{
6d03d92a 1041 return config_path_item(&lxc_conf->seccomp, value);
8f2c3a70
SH
1042}
1043
67c660d0
SG
1044static int config_init_cmd(const char *key, const char *value,
1045 struct lxc_conf *lxc_conf)
1046{
1047 return config_path_item(&lxc_conf->init_cmd, value);
1048}
1049
72bb04e4
PT
1050static int config_init_uid(const char *key, const char *value,
1051 struct lxc_conf *lxc_conf)
1052{
1053 lxc_conf->init_uid = atoi(value);
1054 return 0;
1055}
1056
1057static int config_init_gid(const char *key, const char *value,
1058 struct lxc_conf *lxc_conf)
1059{
1060 lxc_conf->init_gid = atoi(value);
1061 return 0;
1062}
1063
12a50cc6 1064static int config_hook(const char *key, const char *value,
26ddeedd
SH
1065 struct lxc_conf *lxc_conf)
1066{
7d0eb87e 1067 char *copy;
72bb04e4 1068
7d0eb87e
SH
1069 if (!value || strlen(value) == 0)
1070 return lxc_clear_hooks(lxc_conf, key);
1071
6b0d5538
SH
1072 if (strcmp(key, "lxc.hook") == 0) {
1073 ERROR("lxc.hook cannot take a value");
1074 return -1;
1075 }
7d0eb87e 1076 copy = strdup(value);
26ddeedd
SH
1077 if (!copy) {
1078 SYSERROR("failed to dup string '%s'", value);
1079 return -1;
1080 }
1081 if (strcmp(key, "lxc.hook.pre-start") == 0)
1082 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
5ea6163a
SH
1083 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
1084 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
f7bee6c6
MW
1085 else if (strcmp(key, "lxc.hook.autodev") == 0)
1086 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
26ddeedd
SH
1087 else if (strcmp(key, "lxc.hook.mount") == 0)
1088 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
1089 else if (strcmp(key, "lxc.hook.start") == 0)
1090 return add_hook(lxc_conf, LXCHOOK_START, copy);
52492063
WB
1091 else if (strcmp(key, "lxc.hook.stop") == 0)
1092 return add_hook(lxc_conf, LXCHOOK_STOP, copy);
26ddeedd
SH
1093 else if (strcmp(key, "lxc.hook.post-stop") == 0)
1094 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
148e91f5
SH
1095 else if (strcmp(key, "lxc.hook.clone") == 0)
1096 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
37cf711b
SY
1097 else if (strcmp(key, "lxc.hook.destroy") == 0)
1098 return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
26ddeedd
SH
1099 SYSERROR("Unknown key: %s", key);
1100 free(copy);
1101 return -1;
1102}
1103
8f47bc3f 1104static int config_personality(const char *key, const char *value,
cccc74b5
DL
1105 struct lxc_conf *lxc_conf)
1106{
525f0002 1107 signed long personality = lxc_config_parse_arch(value);
cccc74b5 1108
525f0002
CS
1109 if (personality >= 0)
1110 lxc_conf->personality = personality;
1111 else
1112 WARN("unsupported personality '%s'", value);
970ab589
DL
1113
1114 return 0;
cccc74b5
DL
1115}
1116
12a50cc6
DE
1117static int config_pts(const char *key, const char *value,
1118 struct lxc_conf *lxc_conf)
10db618d 1119{
1120 int maxpts = atoi(value);
1121
1122 lxc_conf->pts = maxpts;
1123
1124 return 0;
1125}
1126
ee1e7aa0
SG
1127static int config_start(const char *key, const char *value,
1128 struct lxc_conf *lxc_conf)
1129{
1130 if(strcmp(key, "lxc.start.auto") == 0) {
1131 lxc_conf->start_auto = atoi(value);
1132 return 0;
1133 }
1134 else if (strcmp(key, "lxc.start.delay") == 0) {
1135 lxc_conf->start_delay = atoi(value);
1136 return 0;
1137 }
1138 else if (strcmp(key, "lxc.start.order") == 0) {
1139 lxc_conf->start_order = atoi(value);
1140 return 0;
1141 }
1142 SYSERROR("Unknown key: %s", key);
1143 return -1;
1144}
1145
a8dfe4e0
WB
1146static int config_monitor(const char *key, const char *value,
1147 struct lxc_conf *lxc_conf)
1148{
1149 if(strcmp(key, "lxc.monitor.unshare") == 0) {
1150 lxc_conf->monitor_unshare = atoi(value);
1151 return 0;
1152 }
1153 SYSERROR("Unknown key: %s", key);
1154 return -1;
1155}
1156
ee1e7aa0
SG
1157static int config_group(const char *key, const char *value,
1158 struct lxc_conf *lxc_conf)
1159{
1160 char *groups, *groupptr, *sptr, *token;
1161 struct lxc_list *grouplist;
1162 int ret = -1;
1163
1164 if (!strlen(value))
1165 return lxc_clear_groups(lxc_conf);
1166
1167 groups = strdup(value);
1168 if (!groups) {
1169 SYSERROR("failed to dup '%s'", value);
1170 return -1;
1171 }
1172
1173 /* in case several groups are specified in a single line
1174 * split these groups in a single element for the list */
1175 for (groupptr = groups;;groupptr = NULL) {
d028235d
SG
1176 token = strtok_r(groupptr, " \t", &sptr);
1177 if (!token) {
ee1e7aa0 1178 ret = 0;
d028235d 1179 break;
ee1e7aa0
SG
1180 }
1181
1182 grouplist = malloc(sizeof(*grouplist));
1183 if (!grouplist) {
1184 SYSERROR("failed to allocate groups list");
1185 break;
1186 }
1187
1188 grouplist->elem = strdup(token);
1189 if (!grouplist->elem) {
1190 SYSERROR("failed to dup '%s'", token);
1191 free(grouplist);
1192 break;
1193 }
1194
1195 lxc_list_add_tail(&lxc_conf->groups, grouplist);
d028235d 1196 }
ee1e7aa0
SG
1197
1198 free(groups);
1199
1200 return ret;
1201}
1202
7c661726
MP
1203static int config_environment(const char *key, const char *value,
1204 struct lxc_conf *lxc_conf)
1205{
1206 struct lxc_list *list_item = NULL;
1207
ab799c0b
SG
1208 if (!strlen(value))
1209 return lxc_clear_environment(lxc_conf);
1210
7c661726
MP
1211 list_item = malloc(sizeof(*list_item));
1212 if (!list_item)
1213 goto freak_out;
1214
1215 list_item->elem = strdup(value);
1216
1217 if (!list_item->elem)
1218 goto freak_out;
1219
1220 lxc_list_add_tail(&lxc_conf->environment, list_item);
1221
1222 return 0;
1223
1224freak_out:
f10fad2f 1225 free(list_item);
7c661726
MP
1226
1227 return -1;
1228}
1229
12a50cc6
DE
1230static int config_tty(const char *key, const char *value,
1231 struct lxc_conf *lxc_conf)
b0a33c1e 1232{
1233 int nbtty = atoi(value);
1234
1235 lxc_conf->tty = nbtty;
1236
1237 return 0;
1238}
1239
12a50cc6 1240static int config_ttydir(const char *key, const char *value,
7c6ef2a2
SH
1241 struct lxc_conf *lxc_conf)
1242{
6d03d92a 1243 return config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1);
7c6ef2a2
SH
1244}
1245
7e0e1d94
AV
1246static int config_kmsg(const char *key, const char *value,
1247 struct lxc_conf *lxc_conf)
1248{
1249 int v = atoi(value);
1250
1251 lxc_conf->kmsg = v;
1252
1253 return 0;
1254}
1255
fe4de9a6
DE
1256static int config_lsm_aa_profile(const char *key, const char *value,
1257 struct lxc_conf *lxc_conf)
e075f5d9 1258{
6d03d92a 1259 return config_string_item(&lxc_conf->lsm_aa_profile, value);
fe4de9a6
DE
1260}
1261
7aff4f43
SH
1262static int config_lsm_aa_incomplete(const char *key, const char *value,
1263 struct lxc_conf *lxc_conf)
1264{
1265 int v = atoi(value);
1266
1267 lxc_conf->lsm_aa_allow_incomplete = v == 1 ? 1 : 0;
1268
1269 return 0;
1270}
1271
fe4de9a6
DE
1272static int config_lsm_se_context(const char *key, const char *value,
1273 struct lxc_conf *lxc_conf)
1274{
6d03d92a 1275 return config_string_item(&lxc_conf->lsm_se_context, value);
e075f5d9 1276}
e075f5d9 1277
4a85ce2a 1278static int config_logfile(const char *key, const char *value,
858377e4 1279 struct lxc_conf *c)
4a85ce2a 1280{
6d03d92a
DE
1281 int ret;
1282
b40a606e
SH
1283 // store these values in the lxc_conf, and then try to set for
1284 // actual current logging.
858377e4 1285 ret = config_path_item(&c->logfile, value);
6d03d92a 1286 if (ret == 0)
858377e4 1287 ret = lxc_log_set_file(&c->logfd, c->logfile);
6d03d92a 1288 return ret;
4a85ce2a
SH
1289}
1290
1291static int config_loglevel(const char *key, const char *value,
1292 struct lxc_conf *lxc_conf)
1293{
9ea87d5d
SH
1294 int newlevel;
1295
4a85ce2a
SH
1296 if (!value || strlen(value) == 0)
1297 return 0;
1298
1299 if (value[0] >= '0' && value[0] <= '9')
9ea87d5d 1300 newlevel = atoi(value);
4a85ce2a 1301 else
9ea87d5d 1302 newlevel = lxc_log_priority_to_int(value);
b40a606e
SH
1303 // store these values in the lxc_conf, and then try to set for
1304 // actual current logging.
1305 lxc_conf->loglevel = newlevel;
858377e4 1306 return lxc_log_set_level(&lxc_conf->loglevel, newlevel);
4a85ce2a
SH
1307}
1308
12a50cc6 1309static int config_autodev(const char *key, const char *value,
c6883f38
SH
1310 struct lxc_conf *lxc_conf)
1311{
1312 int v = atoi(value);
1313
1314 lxc_conf->autodev = v;
1315
1316 return 0;
1317}
1318
a84b9932
AV
1319static int sig_num(const char *sig)
1320{
1321 int n;
1322 char *endp = NULL;
1323
1324 errno = 0;
1325 n = strtol(sig, &endp, 10);
1326 if (sig == endp || n < 0 || errno != 0)
1327 return -1;
1328 return n;
1329}
1330
1331static int rt_sig_num(const char *signame)
1332{
1333 int sig_n = 0;
1334 int rtmax = 0;
1335
1336 if (strncasecmp(signame, "max-", 4) == 0) {
1337 rtmax = 1;
1338 }
1339 signame += 4;
1340 if (!isdigit(*signame))
1341 return -1;
1342 sig_n = sig_num(signame);
1343 sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
1344 if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
1345 return -1;
1346 return sig_n;
1347}
1348
1349static int sig_parse(const char *signame) {
1350 int n;
1351
1352 if (isdigit(*signame)) {
1353 return sig_num(signame);
1354 } else if (strncasecmp(signame, "sig", 3) == 0) {
1355 signame += 3;
1356 if (strncasecmp(signame, "rt", 2) == 0)
1357 return rt_sig_num(signame + 2);
1358 for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
1359 if (strcasecmp (signames[n].name, signame) == 0)
1360 return signames[n].num;
1361 }
1362 }
1363 return -1;
1364}
1365
f0f1d8c0
DE
1366static int config_haltsignal(const char *key, const char *value,
1367 struct lxc_conf *lxc_conf)
1368{
1369 int sig_n = sig_parse(value);
1370
1371 if (sig_n < 0)
1372 return -1;
1373 lxc_conf->haltsignal = sig_n;
1374
1375 return 0;
1376}
1377
dd267776
BP
1378static int config_rebootsignal(const char *key, const char *value,
1379 struct lxc_conf *lxc_conf)
1380{
1381 int sig_n = sig_parse(value);
1382
1383 if (sig_n < 0)
1384 return -1;
1385 lxc_conf->rebootsignal = sig_n;
1386
1387 return 0;
1388}
1389
a84b9932
AV
1390static int config_stopsignal(const char *key, const char *value,
1391 struct lxc_conf *lxc_conf)
1392{
1393 int sig_n = sig_parse(value);
1394
1395 if (sig_n < 0)
1396 return -1;
1397 lxc_conf->stopsignal = sig_n;
1398
1399 return 0;
1400}
1401
12a50cc6
DE
1402static int config_cgroup(const char *key, const char *value,
1403 struct lxc_conf *lxc_conf)
576f946d 1404{
1405 char *token = "lxc.cgroup.";
1406 char *subkey;
bf83c5b9
MS
1407 struct lxc_list *cglist = NULL;
1408 struct lxc_cgroup *cgelem = NULL;
576f946d 1409
7d0eb87e
SH
1410 if (!value || strlen(value) == 0)
1411 return lxc_clear_cgroups(lxc_conf, key);
1412
576f946d 1413 subkey = strstr(key, token);
1414
1415 if (!subkey)
1416 return -1;
1417
1418 if (!strlen(subkey))
1419 return -1;
1420
1421 if (strlen(subkey) == strlen(token))
1422 return -1;
a871ff6b 1423
576f946d 1424 subkey += strlen(token);
1425
1426 cglist = malloc(sizeof(*cglist));
1427 if (!cglist)
bf83c5b9 1428 goto out;
576f946d 1429
1430 cgelem = malloc(sizeof(*cgelem));
bf83c5b9
MS
1431 if (!cgelem)
1432 goto out;
1433 memset(cgelem, 0, sizeof(*cgelem));
576f946d 1434
1435 cgelem->subsystem = strdup(subkey);
1436 cgelem->value = strdup(value);
bf83c5b9
MS
1437
1438 if (!cgelem->subsystem || !cgelem->value)
1439 goto out;
1440
576f946d 1441 cglist->elem = cgelem;
1442
94d12f0a 1443 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
576f946d 1444
1445 return 0;
bf83c5b9
MS
1446
1447out:
f10fad2f 1448 free(cglist);
bf83c5b9
MS
1449
1450 if (cgelem) {
f10fad2f 1451 free(cgelem->subsystem);
bf83c5b9 1452
f10fad2f 1453 free(cgelem->value);
bf83c5b9
MS
1454
1455 free(cgelem);
1456 }
1457
1458 return -1;
576f946d 1459}
1460
f6d3e3e4
SH
1461static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf)
1462{
1463 char *token = "lxc.id_map";
1464 char *subkey;
1465 struct lxc_list *idmaplist = NULL;
1466 struct id_map *idmap = NULL;
251d0d2a 1467 unsigned long hostid, nsid, range;
f6d3e3e4
SH
1468 char type;
1469 int ret;
1470
7d0eb87e
SH
1471 if (!value || strlen(value) == 0)
1472 return lxc_clear_idmaps(lxc_conf);
1473
f6d3e3e4
SH
1474 subkey = strstr(key, token);
1475
1476 if (!subkey)
1477 return -1;
1478
1479 if (!strlen(subkey))
1480 return -1;
1481
1482 idmaplist = malloc(sizeof(*idmaplist));
1483 if (!idmaplist)
1484 goto out;
1485
1486 idmap = malloc(sizeof(*idmap));
1487 if (!idmap)
1488 goto out;
1489 memset(idmap, 0, sizeof(*idmap));
1490
251d0d2a 1491 ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range);
f6d3e3e4
SH
1492 if (ret != 4)
1493 goto out;
7e60c3f0 1494
251d0d2a 1495 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
ac7725e7 1496 if (type == 'u')
f6d3e3e4 1497 idmap->idtype = ID_TYPE_UID;
ac7725e7 1498 else if (type == 'g')
f6d3e3e4
SH
1499 idmap->idtype = ID_TYPE_GID;
1500 else
1501 goto out;
7e60c3f0 1502
f6d3e3e4
SH
1503 idmap->hostid = hostid;
1504 idmap->nsid = nsid;
1505 idmap->range = range;
1506
7e60c3f0
SG
1507 idmaplist->elem = idmap;
1508 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
1509
f6d3e3e4
SH
1510 return 0;
1511
1512out:
f10fad2f 1513 free(idmaplist);
f6d3e3e4
SH
1514
1515 if (idmap) {
1516 free(idmap);
1517 }
1518
1519 return -1;
1520}
1521
d95db067
DE
1522static int config_fstab(const char *key, const char *value,
1523 struct lxc_conf *lxc_conf)
1524{
d9192f5d
SH
1525 if (!value || strlen(value) == 0)
1526 return -1;
6d03d92a 1527 return config_path_item(&lxc_conf->fstab, value);
d95db067
DE
1528}
1529
368bbc02
CS
1530static int config_mount_auto(const char *key, const char *value,
1531 struct lxc_conf *lxc_conf)
1532{
1533 char *autos, *autoptr, *sptr, *token;
b06b8511 1534 static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
0769b82a
CS
1535 { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1536 { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1537 { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
f24a52d5 1538 { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
0769b82a 1539 { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
f24a52d5 1540 { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
0769b82a
CS
1541 { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
1542 { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
1543 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
1544 { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
1545 { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
1546 { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
1547 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
1548 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
1549 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
70f55bfd 1550 /* NB: For adding anything that is just a single on/off, but has
b06b8511
CS
1551 * no options: keep mask and flag identical and just define the
1552 * enum value as an unused bit so far
1553 */
368bbc02
CS
1554 { NULL, 0 }
1555 };
1556 int i;
1557 int ret = -1;
1558
d9192f5d
SH
1559 if (!value || strlen(value) == 0) {
1560 lxc_conf->auto_mounts = 0;
1561 return 0;
1562 }
368bbc02
CS
1563
1564 autos = strdup(value);
1565 if (!autos) {
1566 SYSERROR("failed to dup '%s'", value);
1567 return -1;
1568 }
1569
1570 for (autoptr = autos; ; autoptr = NULL) {
d028235d
SG
1571 token = strtok_r(autoptr, " \t", &sptr);
1572 if (!token) {
368bbc02 1573 ret = 0;
d028235d 1574 break;
368bbc02
CS
1575 }
1576
1577 for (i = 0; allowed_auto_mounts[i].token; i++) {
1578 if (!strcmp(allowed_auto_mounts[i].token, token))
1579 break;
1580 }
1581
1582 if (!allowed_auto_mounts[i].token) {
1583 ERROR("Invalid filesystem to automount: %s", token);
1584 break;
1585 }
1586
b06b8511 1587 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
368bbc02 1588 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
d028235d 1589 }
368bbc02
CS
1590
1591 free(autos);
1592
1593 return ret;
1594}
1595
12a50cc6
DE
1596static int config_mount(const char *key, const char *value,
1597 struct lxc_conf *lxc_conf)
e7938e9e 1598{
e7938e9e
MN
1599 char *mntelem;
1600 struct lxc_list *mntlist;
1601
d9192f5d
SH
1602 if (!value || strlen(value) == 0)
1603 return lxc_clear_mount_entries(lxc_conf);
e7938e9e
MN
1604
1605 mntlist = malloc(sizeof(*mntlist));
1606 if (!mntlist)
1607 return -1;
1608
1609 mntelem = strdup(value);
00b6be44
SH
1610 if (!mntelem) {
1611 free(mntlist);
bf83c5b9 1612 return -1;
00b6be44 1613 }
e7938e9e
MN
1614 mntlist->elem = mntelem;
1615
1616 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1617
1618 return 0;
1619}
1620
1fb86a7c
SH
1621static int config_cap_keep(const char *key, const char *value,
1622 struct lxc_conf *lxc_conf)
1623{
1624 char *keepcaps, *keepptr, *sptr, *token;
1625 struct lxc_list *keeplist;
1626 int ret = -1;
1627
1628 if (!strlen(value))
7d0eb87e 1629 return lxc_clear_config_keepcaps(lxc_conf);
1fb86a7c
SH
1630
1631 keepcaps = strdup(value);
1632 if (!keepcaps) {
1633 SYSERROR("failed to dup '%s'", value);
1634 return -1;
1635 }
1636
1637 /* in case several capability keep is specified in a single line
1638 * split these caps in a single element for the list */
1639 for (keepptr = keepcaps;;keepptr = NULL) {
d028235d
SG
1640 token = strtok_r(keepptr, " \t", &sptr);
1641 if (!token) {
1fb86a7c 1642 ret = 0;
d028235d 1643 break;
1fb86a7c
SH
1644 }
1645
7035407c
DE
1646 if (!strcmp(token, "none"))
1647 lxc_clear_config_keepcaps(lxc_conf);
1648
1fb86a7c
SH
1649 keeplist = malloc(sizeof(*keeplist));
1650 if (!keeplist) {
1651 SYSERROR("failed to allocate keepcap list");
1652 break;
1653 }
1654
1655 keeplist->elem = strdup(token);
1656 if (!keeplist->elem) {
1657 SYSERROR("failed to dup '%s'", token);
1658 free(keeplist);
1659 break;
1660 }
1661
1662 lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
d028235d 1663 }
1fb86a7c
SH
1664
1665 free(keepcaps);
1666
1667 return ret;
1668}
1669
12a50cc6 1670static int config_cap_drop(const char *key, const char *value,
81810dd1
DL
1671 struct lxc_conf *lxc_conf)
1672{
d95db067 1673 char *dropcaps, *dropptr, *sptr, *token;
81810dd1
DL
1674 struct lxc_list *droplist;
1675 int ret = -1;
1676
1677 if (!strlen(value))
7d0eb87e 1678 return lxc_clear_config_caps(lxc_conf);
81810dd1
DL
1679
1680 dropcaps = strdup(value);
1681 if (!dropcaps) {
1682 SYSERROR("failed to dup '%s'", value);
1683 return -1;
1684 }
1685
1686 /* in case several capability drop is specified in a single line
1687 * split these caps in a single element for the list */
d95db067 1688 for (dropptr = dropcaps;;dropptr = NULL) {
d028235d
SG
1689 token = strtok_r(dropptr, " \t", &sptr);
1690 if (!token) {
81810dd1 1691 ret = 0;
d028235d 1692 break;
81810dd1 1693 }
81810dd1
DL
1694
1695 droplist = malloc(sizeof(*droplist));
1696 if (!droplist) {
1697 SYSERROR("failed to allocate drop list");
1698 break;
1699 }
1700
1701 droplist->elem = strdup(token);
1702 if (!droplist->elem) {
1703 SYSERROR("failed to dup '%s'", token);
1704 free(droplist);
1705 break;
1706 }
1707
1708 lxc_list_add_tail(&lxc_conf->caps, droplist);
d028235d 1709 }
81810dd1
DL
1710
1711 free(dropcaps);
1712
1713 return ret;
1714}
1715
12a50cc6 1716static int config_console(const char *key, const char *value,
28a4b0e5
DL
1717 struct lxc_conf *lxc_conf)
1718{
6d03d92a 1719 return config_path_item(&lxc_conf->console.path, value);
28a4b0e5
DL
1720}
1721
96f15ca1
SH
1722static int config_console_logfile(const char *key, const char *value,
1723 struct lxc_conf *lxc_conf)
1724{
1725 return config_path_item(&lxc_conf->console.log_path, value);
1726}
1727
e6744e9b
SH
1728/*
1729 * If we find a lxc.network.hwaddr in the original config file,
1730 * we expand it in the unexpanded_config, so that after a save_config
1731 * we store the hwaddr for re-use.
1732 * This is only called when reading the config file, not when executing
1733 * a lxc.include.
1734 * 'x' and 'X' are substituted in-place.
1735 */
1736static void update_hwaddr(const char *line)
1737{
1738 char *p;
1739
1740 line += lxc_char_left_gc(line, strlen(line));
1741 if (line[0] == '#')
1742 return;
1743 if (strncmp(line, "lxc.network.hwaddr", 18) != 0)
1744 return;
1745 p = strchr(line, '=');
1746 if (!p)
1747 return; // let config_network_hwaddr raise the error
1748 p++;
1749 while (isblank(*p))
1750 p++;
1751 if (!*p)
1752 return;
1753
1754 rand_complete_hwaddr(p);
1755}
1756
6b0d5538 1757int append_unexp_config_line(const char *line, struct lxc_conf *conf)
f979ac15 1758{
6b0d5538 1759 size_t len = conf->unexpanded_len, linelen = strlen(line);
f979ac15 1760
e6744e9b
SH
1761 update_hwaddr(line);
1762
6b0d5538
SH
1763 while (conf->unexpanded_alloced <= len + linelen + 2) {
1764 char *tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024);
1765 if (!tmp)
1766 return -1;
1767 if (!conf->unexpanded_config)
1768 *tmp = '\0';
1769 conf->unexpanded_config = tmp;
1770 conf->unexpanded_alloced += 1024;
1771 }
1772 strcat(conf->unexpanded_config, line);
1773 conf->unexpanded_len += linelen;
1774 if (line[linelen-1] != '\n') {
1775 strcat(conf->unexpanded_config, "\n");
1776 conf->unexpanded_len++;
f979ac15 1777 }
f979ac15
SH
1778 return 0;
1779}
1780
e1daebd9
SH
1781static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
1782{
1783 struct dirent dirent, *direntp;
1784 DIR *dir;
1785 char path[MAXPATHLEN];
1786 int ret = -1, len;
1787
1788 dir = opendir(dirp);
1789 if (!dir) {
1790 SYSERROR("failed to open '%s'", dirp);
1791 return -1;
1792 }
1793
1794 while (!readdir_r(dir, &dirent, &direntp)) {
1795 const char *fnam;
1796 if (!direntp)
1797 break;
1798
1799 fnam = direntp->d_name;
1800 if (!strcmp(fnam, "."))
1801 continue;
1802
1803 if (!strcmp(fnam, ".."))
1804 continue;
1805
1806 len = strlen(fnam);
1807 if (len < 6 || strncmp(fnam+len-5, ".conf", 5) != 0)
1808 continue;
1809 len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam);
1810 if (len < 0 || len >= MAXPATHLEN) {
1811 ERROR("lxc.include filename too long under '%s'", dirp);
1812 ret = -1;
1813 goto out;
1814 }
1815
1816 ret = lxc_config_read(path, lxc_conf, true);
1817 if (ret < 0)
1818 goto out;
1819 }
1820 ret = 0;
1821
1822out:
1823 if (closedir(dir))
1824 WARN("lxc.include dir: failed to close directory");
1825
1826 return ret;
1827}
1828
12a50cc6 1829static int config_includefile(const char *key, const char *value,
09ad6246
SH
1830 struct lxc_conf *lxc_conf)
1831{
e1daebd9
SH
1832 if (is_dir(value))
1833 return do_includedir(value, lxc_conf);
1834
6b0d5538 1835 return lxc_config_read(value, lxc_conf, true);
09ad6246
SH
1836}
1837
12a50cc6
DE
1838static int config_rootfs(const char *key, const char *value,
1839 struct lxc_conf *lxc_conf)
c2cc9f0a 1840{
6d03d92a 1841 return config_path_item(&lxc_conf->rootfs.path, value);
c2cc9f0a 1842}
1843
12a50cc6
DE
1844static int config_rootfs_mount(const char *key, const char *value,
1845 struct lxc_conf *lxc_conf)
23b7ea69 1846{
6d03d92a 1847 return config_path_item(&lxc_conf->rootfs.mount, value);
23b7ea69
DL
1848}
1849
a17b1e65
SG
1850static int config_rootfs_options(const char *key, const char *value,
1851 struct lxc_conf *lxc_conf)
1852{
1853 return config_string_item(&lxc_conf->rootfs.options, value);
1854}
1855
12a50cc6
DE
1856static int config_pivotdir(const char *key, const char *value,
1857 struct lxc_conf *lxc_conf)
bf601689 1858{
2d489f9e 1859 WARN("lxc.pivotdir is ignored. It will soon become an error.");
6d03d92a 1860 return config_path_item(&lxc_conf->rootfs.pivot, value);
bf601689
MH
1861}
1862
12a50cc6
DE
1863static int config_utsname(const char *key, const char *value,
1864 struct lxc_conf *lxc_conf)
c2cc9f0a 1865{
1866 struct utsname *utsname;
1867
1868 utsname = malloc(sizeof(*utsname));
1869 if (!utsname) {
36eb9bde 1870 SYSERROR("failed to allocate memory");
c2cc9f0a 1871 return -1;
1872 }
1873
1874 if (strlen(value) >= sizeof(utsname->nodename)) {
36eb9bde 1875 ERROR("node name '%s' is too long",
16e29c91 1876 value);
b6f24d54 1877 free(utsname);
c2cc9f0a 1878 return -1;
1879 }
1880
1881 strcpy(utsname->nodename, value);
f10fad2f 1882 free(lxc_conf->utsname);
c2cc9f0a 1883 lxc_conf->utsname = utsname;
1884
1885 return 0;
1886}
1887
6b0d5538
SH
1888struct parse_line_conf {
1889 struct lxc_conf *conf;
1890 bool from_include;
1891};
4184c3e1 1892
7a7ff0c6 1893static int parse_line(char *buffer, void *data)
c2cc9f0a 1894{
72d0e1cb 1895 struct lxc_config_t *config;
81192358 1896 char *line, *linep;
c2cc9f0a 1897 char *dot;
1898 char *key;
1899 char *value;
476d4cf1 1900 int ret = 0;
6b0d5538 1901 struct parse_line_conf *plc = data;
c2cc9f0a 1902
91480a0f 1903 if (lxc_is_line_empty(buffer))
c2cc9f0a 1904 return 0;
1905
81192358
DL
1906 /* we have to dup the buffer otherwise, at the re-exec for
1907 * reboot we modified the original string on the stack by
1908 * replacing '=' by '\0' below
91480a0f 1909 */
81192358 1910 linep = line = strdup(buffer);
91480a0f
DL
1911 if (!line) {
1912 SYSERROR("failed to allocate memory for '%s'", buffer);
81192358 1913 return -1;
91480a0f
DL
1914 }
1915
6b0d5538
SH
1916 if (!plc->from_include)
1917 if ((ret = append_unexp_config_line(line, plc->conf)))
1918 goto out;
1919
b2718c72 1920 line += lxc_char_left_gc(line, strlen(line));
476d4cf1 1921
4184c3e1
SH
1922 /* ignore comments */
1923 if (line[0] == '#')
91480a0f 1924 goto out;
476d4cf1 1925
6b0d5538
SH
1926 /* martian option - don't add it to the config itself */
1927 if (strncmp(line, "lxc.", 4))
4184c3e1 1928 goto out;
4184c3e1 1929
476d4cf1 1930 ret = -1;
c2cc9f0a 1931
b2718c72 1932 dot = strstr(line, "=");
c2cc9f0a 1933 if (!dot) {
36eb9bde 1934 ERROR("invalid configuration line: %s", line);
91480a0f 1935 goto out;
c2cc9f0a 1936 }
a871ff6b 1937
c2cc9f0a 1938 *dot = '\0';
1939 value = dot + 1;
1940
b2718c72 1941 key = line;
1942 key[lxc_char_right_gc(key, strlen(key))] = '\0';
c2cc9f0a 1943
b2718c72 1944 value += lxc_char_left_gc(value, strlen(value));
1945 value[lxc_char_right_gc(value, strlen(value))] = '\0';
c2cc9f0a 1946
72d0e1cb 1947 config = lxc_getconfig(key);
c2cc9f0a 1948 if (!config) {
6e1d9b94 1949 ERROR("unknown key %s", key);
91480a0f 1950 goto out;
c2cc9f0a 1951 }
1952
6b0d5538 1953 ret = config->cb(key, value, plc->conf);
91480a0f
DL
1954
1955out:
81192358 1956 free(linep);
91480a0f 1957 return ret;
c2cc9f0a 1958}
1959
74a3920a 1960static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
af5b0155 1961{
6b0d5538
SH
1962 struct parse_line_conf c;
1963
1964 c.conf = conf;
1965 c.from_include = false;
1966
1967 return parse_line(buffer, &c);
af5b0155
CLG
1968}
1969
6b0d5538 1970int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
c2cc9f0a 1971{
6b0d5538
SH
1972 struct parse_line_conf c;
1973
1974 c.conf = conf;
1975 c.from_include = from_include;
f979ac15 1976
f3ca99fd
SH
1977 if( access(file, R_OK) == -1 ) {
1978 return -1;
1979 }
6b0d5538 1980
f7bee6c6 1981 /* Catch only the top level config file name in the structure */
6b0d5538 1982 if( ! conf->rcfile )
f7bee6c6 1983 conf->rcfile = strdup( file );
f979ac15 1984
6b0d5538 1985 return lxc_file_for_each_line(file, parse_line, &c);
c2cc9f0a 1986}
62e46035
CLG
1987
1988int lxc_config_define_add(struct lxc_list *defines, char* arg)
1989{
1990 struct lxc_list *dent;
1991
1992 dent = malloc(sizeof(struct lxc_list));
1993 if (!dent)
1994 return -1;
1995
1996 dent->elem = arg;
1997 lxc_list_add_tail(defines, dent);
1998 return 0;
1999}
2000
226a18d6 2001int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
62e46035 2002{
9ebb03ad 2003 struct lxc_list *it,*next;
62e46035
CLG
2004 int ret = 0;
2005
2006 lxc_list_for_each(it, defines) {
2007 ret = lxc_config_readline(it->elem, conf);
2008 if (ret)
2009 break;
2010 }
2011
9ebb03ad 2012 lxc_list_for_each_safe(it, defines, next) {
62e46035
CLG
2013 lxc_list_del(it);
2014 free(it);
2015 }
2016
2017 return ret;
2018}
525f0002
CS
2019
2020signed long lxc_config_parse_arch(const char *arch)
2021{
6ff05e18 2022 #if HAVE_SYS_PERSONALITY_H
525f0002
CS
2023 struct per_name {
2024 char *name;
2025 unsigned long per;
bb8d8207 2026 } pername[] = {
525f0002 2027 { "x86", PER_LINUX32 },
bb8d8207
DE
2028 { "linux32", PER_LINUX32 },
2029 { "i386", PER_LINUX32 },
2030 { "i486", PER_LINUX32 },
2031 { "i586", PER_LINUX32 },
525f0002 2032 { "i686", PER_LINUX32 },
bb8d8207
DE
2033 { "athlon", PER_LINUX32 },
2034 { "linux64", PER_LINUX },
525f0002
CS
2035 { "x86_64", PER_LINUX },
2036 { "amd64", PER_LINUX },
2037 };
2038 size_t len = sizeof(pername) / sizeof(pername[0]);
2039
2040 int i;
2041
2042 for (i = 0; i < len; i++) {
2043 if (!strcmp(pername[i].name, arch))
2044 return pername[i].per;
2045 }
6ff05e18 2046 #endif
525f0002
CS
2047
2048 return -1;
2049}
72d0e1cb 2050
4d69b293
NK
2051int lxc_fill_elevated_privileges(char *flaglist, int *flags)
2052{
2053 char *token, *saveptr = NULL;
2054 int i, aflag;
2055 struct { const char *token; int flag; } all_privs[] = {
2056 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
2057 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
2058 { "LSM", LXC_ATTACH_LSM_EXEC },
2059 { NULL, 0 }
2060 };
2061
2062 if (!flaglist) {
2063 /* for the sake of backward compatibility, drop all privileges
2064 if none is specified */
2065 for (i = 0; all_privs[i].token; i++) {
d028235d 2066 *flags |= all_privs[i].flag;
4d69b293
NK
2067 }
2068 return 0;
2069 }
2070
2071 token = strtok_r(flaglist, "|", &saveptr);
2072 while (token) {
2073 aflag = -1;
2074 for (i = 0; all_privs[i].token; i++) {
2075 if (!strcmp(all_privs[i].token, token))
2076 aflag = all_privs[i].flag;
2077 }
2078 if (aflag < 0)
2079 return -1;
2080
2081 *flags |= aflag;
2082
2083 token = strtok_r(NULL, "|", &saveptr);
2084 }
2085 return 0;
2086}
2087
72d0e1cb
SG
2088static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
2089{
2090 if (!retv)
2091 inlen = 0;
2092 else
2093 memset(retv, 0, inlen);
2094 return snprintf(retv, inlen, "%d", v);
2095}
2096
2097static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
2098{
6ff05e18 2099 int fulllen = 0;
72d0e1cb
SG
2100
2101 if (!retv)
2102 inlen = 0;
2103 else
2104 memset(retv, 0, inlen);
2105
6ff05e18
SG
2106 #if HAVE_SYS_PERSONALITY_H
2107 int len = 0;
2108
72d0e1cb 2109 switch(c->personality) {
14622799 2110 case PER_LINUX32: strprint(retv, inlen, "i686"); break;
72d0e1cb
SG
2111 case PER_LINUX: strprint(retv, inlen, "x86_64"); break;
2112 default: break;
2113 }
6ff05e18 2114 #endif
72d0e1cb
SG
2115
2116 return fulllen;
2117}
2118
2119/*
2120 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
2121 * then just the value(s) will be printed. Since there still could be
2122 * more than one, it is newline-separated.
2123 * (Maybe that's ambigous, since some values, i.e. devices.list, will
2124 * already have newlines?)
2125 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
2126 * in 'lxc.cgroup.subsystem.key = value' format.
2127 */
12a50cc6
DE
2128static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
2129 const char *key)
72d0e1cb
SG
2130{
2131 int fulllen = 0, len;
2132 int all = 0;
2133 struct lxc_list *it;
2134
2135 if (!retv)
2136 inlen = 0;
2137 else
2138 memset(retv, 0, inlen);
2139
2140 if (strcmp(key, "all") == 0)
2141 all = 1;
2142
2143 lxc_list_for_each(it, &c->cgroup) {
2144 struct lxc_cgroup *cg = it->elem;
2145 if (all) {
2146 strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
2147 } else if (strcmp(cg->subsystem, key) == 0) {
2148 strprint(retv, inlen, "%s\n", cg->value);
2149 }
2150 }
2151 return fulllen;
2152}
2153
12a50cc6
DE
2154static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
2155 const char *key)
72d0e1cb
SG
2156{
2157 char *subkey;
2158 int len, fulllen = 0, found = -1;
2159 struct lxc_list *it;
2160 int i;
2161
2162 /* "lxc.hook.mount" */
46cd2845
PL
2163 subkey = strchr(key, '.');
2164 if (subkey) subkey = strchr(subkey+1, '.');
72d0e1cb
SG
2165 if (!subkey)
2166 return -1;
2167 subkey++;
2168 if (!*subkey)
2169 return -1;
2170 for (i=0; i<NUM_LXC_HOOKS; i++) {
2171 if (strcmp(lxchook_names[i], subkey) == 0) {
2172 found=i;
2173 break;
2174 }
2175 }
2176 if (found == -1)
2177 return -1;
2178
2179 if (!retv)
2180 inlen = 0;
2181 else
2182 memset(retv, 0, inlen);
2183
2184 lxc_list_for_each(it, &c->hooks[found]) {
2185 strprint(retv, inlen, "%s\n", (char *)it->elem);
2186 }
2187 return fulllen;
2188}
2189
ee1e7aa0
SG
2190static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen)
2191{
2192 int len, fulllen = 0;
2193 struct lxc_list *it;
2194
2195 if (!retv)
2196 inlen = 0;
2197 else
2198 memset(retv, 0, inlen);
2199
2200 lxc_list_for_each(it, &c->groups) {
2201 strprint(retv, inlen, "%s\n", (char *)it->elem);
2202 }
2203 return fulllen;
2204}
2205
ab799c0b
SG
2206static int lxc_get_item_environment(struct lxc_conf *c, char *retv, int inlen)
2207{
2208 int len, fulllen = 0;
2209 struct lxc_list *it;
2210
2211 if (!retv)
2212 inlen = 0;
2213 else
2214 memset(retv, 0, inlen);
2215
2216 lxc_list_for_each(it, &c->environment) {
2217 strprint(retv, inlen, "%s\n", (char *)it->elem);
2218 }
2219 return fulllen;
2220}
2221
72d0e1cb
SG
2222static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
2223{
2224 int len, fulllen = 0;
2225 struct lxc_list *it;
2226
2227 if (!retv)
2228 inlen = 0;
2229 else
2230 memset(retv, 0, inlen);
2231
2232 lxc_list_for_each(it, &c->caps) {
2233 strprint(retv, inlen, "%s\n", (char *)it->elem);
2234 }
2235 return fulllen;
2236}
2237
1fb86a7c
SH
2238static int lxc_get_item_cap_keep(struct lxc_conf *c, char *retv, int inlen)
2239{
2240 int len, fulllen = 0;
2241 struct lxc_list *it;
2242
2243 if (!retv)
2244 inlen = 0;
2245 else
2246 memset(retv, 0, inlen);
2247
2248 lxc_list_for_each(it, &c->keepcaps) {
2249 strprint(retv, inlen, "%s\n", (char *)it->elem);
2250 }
2251 return fulllen;
2252}
2253
72d0e1cb
SG
2254static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen)
2255{
2256 int len, fulllen = 0;
2257 struct lxc_list *it;
2258
2259 if (!retv)
2260 inlen = 0;
2261 else
2262 memset(retv, 0, inlen);
2263
2264 lxc_list_for_each(it, &c->mount_list) {
2265 strprint(retv, inlen, "%s\n", (char *)it->elem);
2266 }
2267 return fulllen;
2268}
2269
b099e9e9
SH
2270static int lxc_get_auto_mounts(struct lxc_conf *c, char *retv, int inlen)
2271{
2272 int len, fulllen = 0;
0769b82a 2273 const char *sep = "";
b099e9e9
SH
2274
2275 if (!retv)
2276 inlen = 0;
2277 else
2278 memset(retv, 0, inlen);
2279
2280 if (!(c->auto_mounts & LXC_AUTO_ALL_MASK))
2281 return 0;
2282
2283 switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
0769b82a
CS
2284 case LXC_AUTO_PROC_MIXED: strprint(retv, inlen, "%sproc:mixed", sep); sep = " "; break;
2285 case LXC_AUTO_PROC_RW: strprint(retv, inlen, "%sproc:rw", sep); sep = " "; break;
b099e9e9
SH
2286 default: break;
2287 }
2288 switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
0769b82a
CS
2289 case LXC_AUTO_SYS_RO: strprint(retv, inlen, "%ssys:ro", sep); sep = " "; break;
2290 case LXC_AUTO_SYS_RW: strprint(retv, inlen, "%ssys:rw", sep); sep = " "; break;
10f27710 2291 case LXC_AUTO_SYS_MIXED: strprint(retv, inlen, "%ssys:mixed", sep); sep = " "; break;
b099e9e9
SH
2292 default: break;
2293 }
2294 switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
0769b82a
CS
2295 case LXC_AUTO_CGROUP_NOSPEC: strprint(retv, inlen, "%scgroup", sep); sep = " "; break;
2296 case LXC_AUTO_CGROUP_MIXED: strprint(retv, inlen, "%scgroup:mixed", sep); sep = " "; break;
2297 case LXC_AUTO_CGROUP_RO: strprint(retv, inlen, "%scgroup:ro", sep); sep = " "; break;
2298 case LXC_AUTO_CGROUP_RW: strprint(retv, inlen, "%scgroup:rw", sep); sep = " "; break;
2299 case LXC_AUTO_CGROUP_FULL_NOSPEC: strprint(retv, inlen, "%scgroup-full", sep); sep = " "; break;
2300 case LXC_AUTO_CGROUP_FULL_MIXED: strprint(retv, inlen, "%scgroup-full:mixed", sep); sep = " "; break;
2301 case LXC_AUTO_CGROUP_FULL_RO: strprint(retv, inlen, "%scgroup-full:ro", sep); sep = " "; break;
2302 case LXC_AUTO_CGROUP_FULL_RW: strprint(retv, inlen, "%scgroup-full:rw", sep); sep = " "; break;
b099e9e9
SH
2303 default: break;
2304 }
0769b82a 2305
b099e9e9
SH
2306 return fulllen;
2307}
2308
72d0e1cb
SG
2309/*
2310 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
8fc8295a 2311 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
9eaf8a59 2312 * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
72d0e1cb
SG
2313 * of an address. ipv4 and ipv6 return lists (newline-separated).
2314 * things like veth.pair return '' if invalid (i.e. if called for vlan
2315 * type).
2316 */
12a50cc6
DE
2317static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
2318 const char *key)
72d0e1cb
SG
2319{
2320 char *p1;
fe88b9d2 2321 int len, fulllen = 0;
72d0e1cb
SG
2322 struct lxc_netdev *netdev;
2323
2324 if (!retv)
2325 inlen = 0;
2326 else
2327 memset(retv, 0, inlen);
2328
46cd2845 2329 p1 = strchr(key, '.');
72d0e1cb
SG
2330 if (!p1 || *(p1+1) == '\0') return -1;
2331 p1++;
2332
2333 netdev = get_netdev_from_key(key, &c->network);
2334 if (!netdev)
2335 return -1;
2336 if (strcmp(p1, "name") == 0) {
2337 if (netdev->name)
2338 strprint(retv, inlen, "%s", netdev->name);
2339 } else if (strcmp(p1, "type") == 0) {
2340 strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
2341 } else if (strcmp(p1, "link") == 0) {
2342 if (netdev->link)
2343 strprint(retv, inlen, "%s", netdev->link);
2344 } else if (strcmp(p1, "flags") == 0) {
2345 if (netdev->flags & IFF_UP)
2346 strprint(retv, inlen, "up");
8fc8295a 2347 } else if (strcmp(p1, "script.up") == 0) {
72d0e1cb
SG
2348 if (netdev->upscript)
2349 strprint(retv, inlen, "%s", netdev->upscript);
8fc8295a
DE
2350 } else if (strcmp(p1, "script.down") == 0) {
2351 if (netdev->downscript)
2352 strprint(retv, inlen, "%s", netdev->downscript);
72d0e1cb
SG
2353 } else if (strcmp(p1, "hwaddr") == 0) {
2354 if (netdev->hwaddr)
2355 strprint(retv, inlen, "%s", netdev->hwaddr);
2356 } else if (strcmp(p1, "mtu") == 0) {
2357 if (netdev->mtu)
2358 strprint(retv, inlen, "%s", netdev->mtu);
2359 } else if (strcmp(p1, "macvlan.mode") == 0) {
2360 if (netdev->type == LXC_NET_MACVLAN) {
2361 const char *mode;
2362 switch (netdev->priv.macvlan_attr.mode) {
2363 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
2364 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
2365 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
99854161 2366 case MACVLAN_MODE_PASSTHRU: mode = "passthru"; break;
72d0e1cb
SG
2367 default: mode = "(invalid)"; break;
2368 }
2369 strprint(retv, inlen, "%s", mode);
2370 }
2371 } else if (strcmp(p1, "veth.pair") == 0) {
11029c02
DE
2372 if (netdev->type == LXC_NET_VETH) {
2373 strprint(retv, inlen, "%s",
2374 netdev->priv.veth_attr.pair ?
2375 netdev->priv.veth_attr.pair :
2376 netdev->priv.veth_attr.veth1);
2377 }
72d0e1cb
SG
2378 } else if (strcmp(p1, "vlan") == 0) {
2379 if (netdev->type == LXC_NET_VLAN) {
2380 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
2381 }
9eaf8a59 2382 } else if (strcmp(p1, "ipv4.gateway") == 0) {
72d0e1cb
SG
2383 if (netdev->ipv4_gateway_auto) {
2384 strprint(retv, inlen, "auto");
2385 } else if (netdev->ipv4_gateway) {
2386 char buf[INET_ADDRSTRLEN];
2387 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
2388 strprint(retv, inlen, "%s", buf);
2389 }
2390 } else if (strcmp(p1, "ipv4") == 0) {
2391 struct lxc_list *it2;
2392 lxc_list_for_each(it2, &netdev->ipv4) {
2393 struct lxc_inetdev *i = it2->elem;
2394 char buf[INET_ADDRSTRLEN];
2395 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
28417b5a 2396 strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
72d0e1cb 2397 }
9eaf8a59 2398 } else if (strcmp(p1, "ipv6.gateway") == 0) {
72d0e1cb
SG
2399 if (netdev->ipv6_gateway_auto) {
2400 strprint(retv, inlen, "auto");
2401 } else if (netdev->ipv6_gateway) {
6afb165d
AN
2402 char buf[INET6_ADDRSTRLEN];
2403 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
72d0e1cb
SG
2404 strprint(retv, inlen, "%s", buf);
2405 }
2406 } else if (strcmp(p1, "ipv6") == 0) {
2407 struct lxc_list *it2;
2408 lxc_list_for_each(it2, &netdev->ipv6) {
6afb165d
AN
2409 struct lxc_inet6dev *i = it2->elem;
2410 char buf[INET6_ADDRSTRLEN];
72d0e1cb 2411 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
28417b5a 2412 strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
72d0e1cb
SG
2413 }
2414 }
2415 return fulllen;
2416}
2417
2418static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
2419{
2420 int len, fulllen = 0;
2421 struct lxc_list *it;
2422
2423 if (!retv)
2424 inlen = 0;
2425 else
2426 memset(retv, 0, inlen);
2427
2428 lxc_list_for_each(it, &c->network) {
2429 struct lxc_netdev *n = it->elem;
2430 const char *t = lxc_net_type_to_str(n->type);
2431 strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
2432 }
2433 return fulllen;
2434}
2435
12a50cc6
DE
2436int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
2437 int inlen)
72d0e1cb 2438{
4a85ce2a 2439 const char *v = NULL;
72d0e1cb
SG
2440
2441 if (strcmp(key, "lxc.mount.entry") == 0)
2442 return lxc_get_mount_entries(c, retv, inlen);
b099e9e9
SH
2443 else if (strcmp(key, "lxc.mount.auto") == 0)
2444 return lxc_get_auto_mounts(c, retv, inlen);
72d0e1cb
SG
2445 else if (strcmp(key, "lxc.mount") == 0)
2446 v = c->fstab;
2447 else if (strcmp(key, "lxc.tty") == 0)
2448 return lxc_get_conf_int(c, retv, inlen, c->tty);
2449 else if (strcmp(key, "lxc.pts") == 0)
2450 return lxc_get_conf_int(c, retv, inlen, c->pts);
2451 else if (strcmp(key, "lxc.devttydir") == 0)
2452 v = c->ttydir;
2453 else if (strcmp(key, "lxc.arch") == 0)
2454 return lxc_get_arch_entry(c, retv, inlen);
2455 else if (strcmp(key, "lxc.aa_profile") == 0)
fe4de9a6 2456 v = c->lsm_aa_profile;
7aff4f43
SH
2457 else if (strcmp(key, "lxc.aa_allow_incomplete") == 0)
2458 return lxc_get_conf_int(c, retv, inlen, c->lsm_aa_allow_incomplete);
fe4de9a6
DE
2459 else if (strcmp(key, "lxc.se_context") == 0)
2460 v = c->lsm_se_context;
4a85ce2a 2461 else if (strcmp(key, "lxc.logfile") == 0)
858377e4 2462 v = c->logfile;
4a85ce2a 2463 else if (strcmp(key, "lxc.loglevel") == 0)
858377e4 2464 v = lxc_log_priority_to_string(c->loglevel);
72d0e1cb
SG
2465 else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
2466 return lxc_get_cgroup_entry(c, retv, inlen, "all");
2467 else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
2468 return lxc_get_cgroup_entry(c, retv, inlen, key + 11);
2469 else if (strcmp(key, "lxc.utsname") == 0)
64fca455 2470 v = c->utsname ? c->utsname->nodename : NULL;
96f15ca1
SH
2471 else if (strcmp(key, "lxc.console.logfile") == 0)
2472 v = c->console.log_path;
72d0e1cb
SG
2473 else if (strcmp(key, "lxc.console") == 0)
2474 v = c->console.path;
2475 else if (strcmp(key, "lxc.rootfs.mount") == 0)
2476 v = c->rootfs.mount;
a17b1e65
SG
2477 else if (strcmp(key, "lxc.rootfs.options") == 0)
2478 v = c->rootfs.options;
72d0e1cb
SG
2479 else if (strcmp(key, "lxc.rootfs") == 0)
2480 v = c->rootfs.path;
2481 else if (strcmp(key, "lxc.pivotdir") == 0)
2482 v = c->rootfs.pivot;
2483 else if (strcmp(key, "lxc.cap.drop") == 0)
2484 return lxc_get_item_cap_drop(c, retv, inlen);
1fb86a7c
SH
2485 else if (strcmp(key, "lxc.cap.keep") == 0)
2486 return lxc_get_item_cap_keep(c, retv, inlen);
72d0e1cb
SG
2487 else if (strncmp(key, "lxc.hook", 8) == 0)
2488 return lxc_get_item_hooks(c, retv, inlen, key);
2489 else if (strcmp(key, "lxc.network") == 0)
2490 return lxc_get_item_network(c, retv, inlen);
2491 else if (strncmp(key, "lxc.network.", 12) == 0)
2492 return lxc_get_item_nic(c, retv, inlen, key + 12);
ee1e7aa0
SG
2493 else if (strcmp(key, "lxc.start.auto") == 0)
2494 return lxc_get_conf_int(c, retv, inlen, c->start_auto);
2495 else if (strcmp(key, "lxc.start.delay") == 0)
2496 return lxc_get_conf_int(c, retv, inlen, c->start_delay);
2497 else if (strcmp(key, "lxc.start.order") == 0)
2498 return lxc_get_conf_int(c, retv, inlen, c->start_order);
a8dfe4e0
WB
2499 else if (strcmp(key, "lxc.monitor.unshare") == 0)
2500 return lxc_get_conf_int(c, retv, inlen, c->monitor_unshare);
ee1e7aa0
SG
2501 else if (strcmp(key, "lxc.group") == 0)
2502 return lxc_get_item_groups(c, retv, inlen);
58e0f57d
SH
2503 else if (strcmp(key, "lxc.seccomp") == 0)
2504 v = c->seccomp;
ab799c0b
SG
2505 else if (strcmp(key, "lxc.environment") == 0)
2506 return lxc_get_item_environment(c, retv, inlen);
67c660d0
SG
2507 else if (strcmp(key, "lxc.init_cmd") == 0)
2508 v = c->init_cmd;
68d18db8
PT
2509 else if (strcmp(key, "lxc.init_uid") == 0)
2510 return lxc_get_conf_int(c, retv, inlen, c->init_uid);
2511 else if (strcmp(key, "lxc.init_gid") == 0)
2512 return lxc_get_conf_int(c, retv, inlen, c->init_gid);
8796becf
CB
2513 else if (strcmp(key, "lxc.ephemeral") == 0)
2514 return lxc_get_conf_int(c, retv, inlen, c->ephemeral);
72d0e1cb
SG
2515 else return -1;
2516
2517 if (!v)
2518 return 0;
2519 if (retv && inlen >= strlen(v) + 1)
2520 strncpy(retv, v, strlen(v)+1);
2521 return strlen(v);
2522}
2523
12a50cc6 2524int lxc_clear_config_item(struct lxc_conf *c, const char *key)
72d0e1cb
SG
2525{
2526 if (strcmp(key, "lxc.network") == 0)
2527 return lxc_clear_config_network(c);
2528 else if (strncmp(key, "lxc.network.", 12) == 0)
2529 return lxc_clear_nic(c, key + 12);
2530 else if (strcmp(key, "lxc.cap.drop") == 0)
2531 return lxc_clear_config_caps(c);
1fb86a7c
SH
2532 else if (strcmp(key, "lxc.cap.keep") == 0)
2533 return lxc_clear_config_keepcaps(c);
72d0e1cb
SG
2534 else if (strncmp(key, "lxc.cgroup", 10) == 0)
2535 return lxc_clear_cgroups(c, key);
2536 else if (strcmp(key, "lxc.mount.entries") == 0)
2537 return lxc_clear_mount_entries(c);
b099e9e9
SH
2538 else if (strcmp(key, "lxc.mount.auto") == 0)
2539 return lxc_clear_automounts(c);
17ed13a3
SH
2540 else if (strncmp(key, "lxc.hook", 8) == 0)
2541 return lxc_clear_hooks(c, key);
ee1e7aa0
SG
2542 else if (strncmp(key, "lxc.group", 9) == 0)
2543 return lxc_clear_groups(c);
fcdc3e50 2544 else if (strncmp(key, "lxc.environment", 15) == 0)
ab799c0b 2545 return lxc_clear_environment(c);
fcdc3e50 2546 else if (strncmp(key, "lxc.id_map", 10) == 0)
26f1b390 2547 return lxc_clear_idmaps(c);
72d0e1cb
SG
2548 return -1;
2549}
2550
2551/*
2552 * writing out a confile.
2553 */
2554void write_config(FILE *fout, struct lxc_conf *c)
2555{
6b0d5538
SH
2556 size_t len = c->unexpanded_len;
2557 int ret;
72d0e1cb 2558
6b0d5538
SH
2559 if (!len)
2560 return;
2561 ret = fwrite(c->unexpanded_config, 1, len, fout);
2562 if (ret != len)
2563 SYSERROR("Error writing configuration file");
2564}
f979ac15 2565
6b0d5538
SH
2566bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const char *v)
2567{
2568 int ret;
2569 size_t len = strlen(key) + strlen(v) + 4;
2570 char *tmp = alloca(len);
4184c3e1 2571
6b0d5538
SH
2572 ret = snprintf(tmp, len, "%s = %s", key, v);
2573 if (ret < 0 || ret >= len)
2574 return false;
2575
2576 /* Save the line verbatim into unexpanded_conf */
2577 if (append_unexp_config_line(tmp, conf))
2578 return false;
2579
2580 return true;
2581}
2582
2583void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_subkeys)
2584{
2585 char *lstart = conf->unexpanded_config, *lend;
2586
2587 if (!conf->unexpanded_config)
2588 return;
2589 while (*lstart) {
2590 lend = strchr(lstart, '\n');
2591 char v;
2592 if (!lend)
2593 lend = lstart + strlen(lstart);
2594 else
2595 lend++;
2596 if (strncmp(lstart, key, strlen(key)) != 0) {
2597 lstart = lend;
2598 continue;
5f62730e 2599 }
6b0d5538
SH
2600 if (!rm_subkeys) {
2601 v = lstart[strlen(key)];
2602 if (!isspace(v) && v != '=') {
2603 lstart = lend;
2604 continue;
2605 }
5f62730e 2606 }
6b0d5538
SH
2607 conf->unexpanded_len -= (lend - lstart);
2608 if (*lend == '\0') {
2609 *lstart = '\0';
2610 return;
fd986e08 2611 }
6b0d5538 2612 memmove(lstart, lend, strlen(lend)+1);
fd986e08 2613 }
6b0d5538
SH
2614}
2615
329b3625
CB
2616bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
2617 const char *newpath, const char *oldname,
2618 const char *newname, const char *ovldir)
2619{
2620 const char *key = "lxc.mount.entry";
2621 int ret;
2622 char *lstart = conf->unexpanded_config;
2623 char *lend;
2624 char *p;
2625 char *q;
2626 size_t newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2;
2627 size_t olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2;
2628 char *olddir = alloca(olddirlen + 1);
2629 char *newdir = alloca(newdirlen + 1);
2630
2631 ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath, oldname);
2632 if (ret < 0 || ret >= olddirlen + 1) {
2633 ERROR("Bug in %s", __func__);
2634 return false;
2635 }
2636 ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath, newname);
2637 if (ret < 0 || ret >= newdirlen + 1) {
2638 ERROR("Bug in %s", __func__);
2639 return false;
2640 }
2641 if (!conf->unexpanded_config)
2642 return true;
2643 while (*lstart) {
2644 lend = strchr(lstart, '\n');
2645 if (!lend)
2646 lend = lstart + strlen(lstart);
2647 else
2648 lend++;
2649 if (strncmp(lstart, key, strlen(key)) != 0)
2650 goto next;
2651 p = strchr(lstart + strlen(key), '=');
2652 if (!p)
2653 goto next;
2654 p++;
2655 while (isblank(*p))
2656 p++;
2657 if (p >= lend)
2658 goto next;
2659 /* Whenever an lxc.mount.entry entry is found in a line we check
2660 * if the substring " overlay" or the substring " aufs" is
2661 * present before doing any further work. We check for "
2662 * overlay" and " aufs" since both substrings need to have at
2663 * least one space before them in a valid overlay
2664 * lxc.mount.entry (/A B overlay). When the space before is
2665 * missing it is very likely that these substrings are part of a
2666 * path or something else. (Checking q >= lend ensures that we
2667 * only count matches in the current line.) */
2668 if ((!(q = strstr(p, " overlay")) || q >= lend) && (!(q = strstr(p, " aufs")) || q >= lend))
2669 goto next;
2670 if (!(q = strstr(p, olddir)) || (q >= lend))
2671 goto next;
2672
2673 /* replace the olddir with newdir */
2674 if (olddirlen >= newdirlen) {
2675 size_t diff = olddirlen - newdirlen;
2676 memcpy(q, newdir, newdirlen);
2677 if (olddirlen != newdirlen) {
2678 memmove(q + newdirlen, q + newdirlen + diff,
2679 strlen(q) - newdirlen - diff + 1);
2680 lend -= diff;
2681 conf->unexpanded_len -= diff;
2682 }
2683 } else {
2684 char *new;
2685 size_t diff = newdirlen - olddirlen;
2686 size_t oldlen = conf->unexpanded_len;
2687 size_t newlen = oldlen + diff;
2688 size_t poffset = q - conf->unexpanded_config;
2689 new = realloc(conf->unexpanded_config, newlen + 1);
2690 if (!new) {
2691 ERROR("Out of memory");
2692 return false;
2693 }
2694 conf->unexpanded_len = newlen;
2695 conf->unexpanded_alloced = newlen + 1;
2696 new[newlen - 1] = '\0';
2697 lend = new + (lend - conf->unexpanded_config);
2698 /* move over the remainder to make room for the newdir */
2699 memmove(new + poffset + newdirlen,
2700 new + poffset + olddirlen,
2701 oldlen - poffset - olddirlen + 1);
2702 conf->unexpanded_config = new;
2703 memcpy(new + poffset, newdir, newdirlen);
2704 lend += diff;
2705 }
2706next:
2707 lstart = lend;
2708 }
2709 return true;
2710}
2711
67702c21 2712bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
d546aa0e
CB
2713 const char *newpath, const char *oldname,
2714 const char *newname)
6b0d5538 2715{
67702c21
SH
2716 const char *key = "lxc.hook";
2717 int ret;
2718 char *lstart = conf->unexpanded_config, *lend, *p;
2719 size_t newdirlen = strlen(newpath) + strlen(newname) + 1;
2720 size_t olddirlen = strlen(oldpath) + strlen(oldname) + 1;
2721 char *olddir = alloca(olddirlen + 1);
2722 char *newdir = alloca(newdirlen + 1);
2723
d546aa0e
CB
2724 ret = snprintf(olddir, olddirlen + 1, "%s/%s", oldpath, oldname);
2725 if (ret < 0 || ret >= olddirlen + 1) {
67702c21
SH
2726 ERROR("Bug in %s", __func__);
2727 return false;
2728 }
d546aa0e
CB
2729 ret = snprintf(newdir, newdirlen + 1, "%s/%s", newpath, newname);
2730 if (ret < 0 || ret >= newdirlen + 1) {
67702c21
SH
2731 ERROR("Bug in %s", __func__);
2732 return false;
2733 }
2734 if (!conf->unexpanded_config)
2735 return true;
2736 while (*lstart) {
2737 lend = strchr(lstart, '\n');
2738 if (!lend)
2739 lend = lstart + strlen(lstart);
2740 else
2741 lend++;
d546aa0e
CB
2742 if (strncmp(lstart, key, strlen(key)) != 0)
2743 goto next;
2744 p = strchr(lstart + strlen(key), '=');
2745 if (!p)
2746 goto next;
67702c21
SH
2747 p++;
2748 while (isblank(*p))
2749 p++;
d546aa0e
CB
2750 if (p >= lend)
2751 goto next;
2752 if (strncmp(p, olddir, strlen(olddir)) != 0)
2753 goto next;
67702c21
SH
2754 /* replace the olddir with newdir */
2755 if (olddirlen >= newdirlen) {
2756 size_t diff = olddirlen - newdirlen;
2757 memcpy(p, newdir, newdirlen);
2758 if (olddirlen != newdirlen) {
d546aa0e
CB
2759 memmove(p + newdirlen, p + newdirlen + diff,
2760 strlen(p) - newdirlen - diff + 1);
67702c21
SH
2761 lend -= diff;
2762 conf->unexpanded_len -= diff;
2763 }
67702c21
SH
2764 } else {
2765 char *new;
2766 size_t diff = newdirlen - olddirlen;
2767 size_t oldlen = conf->unexpanded_len;
2768 size_t newlen = oldlen + diff;
2769 size_t poffset = p - conf->unexpanded_config;
d546aa0e 2770 new = realloc(conf->unexpanded_config, newlen + 1);
67702c21
SH
2771 if (!new) {
2772 ERROR("Out of memory");
6b0d5538 2773 return false;
67702c21
SH
2774 }
2775 conf->unexpanded_len = newlen;
d546aa0e
CB
2776 conf->unexpanded_alloced = newlen + 1;
2777 new[newlen - 1] = '\0';
67702c21 2778 lend = new + (lend - conf->unexpanded_config);
d546aa0e
CB
2779 /* move over the remainder to make room for the newdir */
2780 memmove(new + poffset + newdirlen,
2781 new + poffset + olddirlen,
2782 oldlen - poffset - olddirlen + 1);
67702c21 2783 conf->unexpanded_config = new;
d546aa0e
CB
2784 memcpy(new + poffset, newdir, newdirlen);
2785 lend += diff;
fd986e08 2786 }
d546aa0e
CB
2787next:
2788 lstart = lend;
fd986e08 2789 }
6b0d5538
SH
2790 return true;
2791}
2792
2793#define DO(cmd) { \
2794 if (!(cmd)) { \
2795 ERROR("Error writing to new config"); \
2796 return false; \
2797 } \
2798}
2799
67702c21
SH
2800static void new_hwaddr(char *hwaddr)
2801{
2802 FILE *f;
2803 f = fopen("/dev/urandom", "r");
2804 if (f) {
2805 unsigned int seed;
2806 int ret = fread(&seed, sizeof(seed), 1, f);
2807 if (ret != 1)
2808 seed = time(NULL);
2809 fclose(f);
2810 srand(seed);
2811 } else
2812 srand(time(NULL));
2813 snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x",
2814 rand() % 255, rand() % 255, rand() % 255);
2815}
2816
2817/*
2818 * This is called only from clone.
2819 * We wish to update all hwaddrs in the unexpanded config file. We
2820 * can't/don't want to update any which come from lxc.includes (there
2821 * shouldn't be any).
2822 * We can't just walk the c->lxc-conf->network list because that includes
2823 * netifs from the include files. So we update the ones which we find in
2824 * the unexp config file, then find the original macaddr in the
2825 * conf->network, and update that to the same value.
2826 */
2827bool network_new_hwaddrs(struct lxc_conf *conf)
6b0d5538
SH
2828{
2829 struct lxc_list *it;
2830
67702c21
SH
2831 const char *key = "lxc.network.hwaddr";
2832 char *lstart = conf->unexpanded_config, *lend, *p, *p2;
6b0d5538 2833
67702c21
SH
2834 if (!conf->unexpanded_config)
2835 return true;
2836 while (*lstart) {
2837 char newhwaddr[18], oldhwaddr[17];
2838 lend = strchr(lstart, '\n');
2839 if (!lend)
2840 lend = lstart + strlen(lstart);
2841 else
2842 lend++;
2843 if (strncmp(lstart, key, strlen(key)) != 0) {
2844 lstart = lend;
2845 continue;
72d0e1cb 2846 }
67702c21
SH
2847 p = strchr(lstart+strlen(key), '=');
2848 if (!p) {
2849 lstart = lend;
2850 continue;
72d0e1cb 2851 }
67702c21
SH
2852 p++;
2853 while (isblank(*p))
2854 p++;
2855 if (!*p)
2856 return true;
2857 p2 = p;
2858 while (*p2 && !isblank(*p2) && *p2 != '\n')
2859 p2++;
2860 if (p2-p != 17) {
2861 WARN("Bad hwaddr entry");
2862 lstart = lend;
2863 continue;
72d0e1cb 2864 }
67702c21
SH
2865 memcpy(oldhwaddr, p, 17);
2866 new_hwaddr(newhwaddr);
2867 memcpy(p, newhwaddr, 17);
2868 lxc_list_for_each(it, &conf->network) {
2869 struct lxc_netdev *n = it->elem;
2870 if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0)
2871 memcpy(n->hwaddr, newhwaddr, 17);
72d0e1cb 2872 }
67702c21
SH
2873
2874 lstart = lend;
72d0e1cb 2875 }
6b0d5538 2876 return true;
72d0e1cb 2877}
8796becf
CB
2878
2879static int config_ephemeral(const char *key, const char *value,
2880 struct lxc_conf *lxc_conf)
2881{
2882 int v = atoi(value);
2883
2884 if (v != 0 && v != 1) {
2885 ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
2886 return -1;
2887 } else {
2888 lxc_conf->ephemeral = v;
2889 }
2890
2891 return 0;
2892}
2893