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