]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/confile.c
lxcutmp.c: Fix typo causing build failure
[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:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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>
63376d7d 30#include <sys/stat.h>
c2cc9f0a 31#include <sys/types.h>
32#include <sys/param.h>
33#include <sys/utsname.h>
34#include <arpa/inet.h>
35#include <netinet/in.h>
36#include <net/if.h>
37
b2718c72 38#include "parse.h"
6ff05e18 39#include "config.h"
525f0002 40#include "confile.h"
26c39028 41#include "utils.h"
c2cc9f0a 42
36eb9bde 43#include <lxc/log.h>
00b3c2e2 44#include <lxc/conf.h>
72d0e1cb 45#include "network.h"
36eb9bde 46
6ff05e18
SG
47#if HAVE_SYS_PERSONALITY_H
48#include <sys/personality.h>
49#endif
50
36eb9bde 51lxc_log_define(lxc_confile, lxc);
576f946d 52
12a50cc6
DE
53static int config_personality(const char *, const char *, struct lxc_conf *);
54static int config_pts(const char *, const char *, struct lxc_conf *);
55static int config_tty(const char *, const char *, struct lxc_conf *);
56static int config_ttydir(const char *, const char *, struct lxc_conf *);
e075f5d9 57#if HAVE_APPARMOR
12a50cc6 58static int config_aa_profile(const char *, const char *, struct lxc_conf *);
e075f5d9 59#endif
12a50cc6 60static int config_cgroup(const char *, const char *, struct lxc_conf *);
4a85ce2a
SH
61static int config_loglevel(const char *, const char *, struct lxc_conf *);
62static int config_logfile(const char *, const char *, struct lxc_conf *);
12a50cc6
DE
63static int config_mount(const char *, const char *, struct lxc_conf *);
64static int config_rootfs(const char *, const char *, struct lxc_conf *);
65static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
66static int config_pivotdir(const char *, const char *, struct lxc_conf *);
67static int config_utsname(const char *, const char *, struct lxc_conf *);
68static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
69static int config_network_type(const char *, const char *, struct lxc_conf *);
70static int config_network_flags(const char *, const char *, struct lxc_conf *);
71static int config_network_link(const char *, const char *, struct lxc_conf *);
72static int config_network_name(const char *, const char *, struct lxc_conf *);
73static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
74static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
75static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
76static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
77static int config_network_mtu(const char *, const char *, struct lxc_conf *);
78static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
79static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
80static int config_network_script(const char *, const char *, struct lxc_conf *);
81static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
82static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
83static int config_cap_drop(const char *, const char *, struct lxc_conf *);
84static int config_console(const char *, const char *, struct lxc_conf *);
85static int config_seccomp(const char *, const char *, struct lxc_conf *);
86static int config_includefile(const char *, const char *, struct lxc_conf *);
87static int config_network_nic(const char *, const char *, struct lxc_conf *);
88static int config_autodev(const char *, const char *, struct lxc_conf *);
c2cc9f0a 89
72d0e1cb 90static struct lxc_config_t config[] = {
576f946d 91
cccc74b5 92 { "lxc.arch", config_personality },
e892973e
DL
93 { "lxc.pts", config_pts },
94 { "lxc.tty", config_tty },
7c6ef2a2 95 { "lxc.devttydir", config_ttydir },
e075f5d9
SH
96#if HAVE_APPARMOR
97 { "lxc.aa_profile", config_aa_profile },
98#endif
e892973e 99 { "lxc.cgroup", config_cgroup },
4a85ce2a
SH
100 { "lxc.loglevel", config_loglevel },
101 { "lxc.logfile", config_logfile },
e892973e 102 { "lxc.mount", config_mount },
23b7ea69 103 { "lxc.rootfs.mount", config_rootfs_mount },
e892973e 104 { "lxc.rootfs", config_rootfs },
bf601689 105 { "lxc.pivotdir", config_pivotdir },
e892973e 106 { "lxc.utsname", config_utsname },
26ddeedd 107 { "lxc.hook.pre-start", config_hook },
12a50cc6 108 { "lxc.hook.pre-mount", config_hook },
26ddeedd
SH
109 { "lxc.hook.mount", config_hook },
110 { "lxc.hook.start", config_hook },
111 { "lxc.hook.post-stop", config_hook },
e892973e
DL
112 { "lxc.network.type", config_network_type },
113 { "lxc.network.flags", config_network_flags },
114 { "lxc.network.link", config_network_link },
115 { "lxc.network.name", config_network_name },
116 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
117 { "lxc.network.veth.pair", config_network_veth_pair },
e3b4c4c4 118 { "lxc.network.script.up", config_network_script },
74a2b586 119 { "lxc.network.script.down", config_network_script },
e892973e
DL
120 { "lxc.network.hwaddr", config_network_hwaddr },
121 { "lxc.network.mtu", config_network_mtu },
122 { "lxc.network.vlan.id", config_network_vlan_id },
f8fee0e2 123 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
e892973e 124 { "lxc.network.ipv4", config_network_ipv4 },
f8fee0e2 125 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
e892973e 126 { "lxc.network.ipv6", config_network_ipv6 },
72d0e1cb
SG
127 /* config_network_nic must come after all other 'lxc.network.*' entries */
128 { "lxc.network.", config_network_nic },
81810dd1 129 { "lxc.cap.drop", config_cap_drop },
63376d7d 130 { "lxc.console", config_console },
8f2c3a70 131 { "lxc.seccomp", config_seccomp },
09ad6246 132 { "lxc.include", config_includefile },
c6883f38 133 { "lxc.autodev", config_autodev },
c2cc9f0a 134};
135
72d0e1cb 136static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
c2cc9f0a 137
72d0e1cb 138extern struct lxc_config_t *lxc_getconfig(const char *key)
c2cc9f0a 139{
140 int i;
141
142 for (i = 0; i < config_size; i++)
a871ff6b 143 if (!strncmp(config[i].name, key,
c2cc9f0a 144 strlen(config[i].name)))
145 return &config[i];
146 return NULL;
147}
148
72d0e1cb
SG
149#define strprint(str, inlen, ...) \
150 do { \
151 len = snprintf(str, inlen, ##__VA_ARGS__); \
152 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
153 fulllen += len; \
154 if (inlen > 0) { \
155 if (str) str += len; \
156 inlen -= len; \
157 if (inlen < 0) inlen = 0; \
158 } \
159 } while (0);
160
161int lxc_listconfigs(char *retv, int inlen)
162{
163 int i, fulllen = 0, len;
164
165 if (!retv)
166 inlen = 0;
167 else
168 memset(retv, 0, inlen);
169 for (i = 0; i < config_size; i++) {
170 char *s = config[i].name;
171 if (s[strlen(s)-1] == '.')
172 continue;
173 strprint(retv, inlen, "%s\n", s);
174 }
175 return fulllen;
176}
177
178/*
179 * config entry is something like "lxc.network.0.ipv4"
180 * the key 'lxc.network.' was found. So we make sure next
181 * comes an integer, find the right callback (by rewriting
182 * the key), and call it.
183 */
12a50cc6 184static int config_network_nic(const char *key, const char *value,
72d0e1cb
SG
185 struct lxc_conf *lxc_conf)
186{
187 char *copy = strdup(key), *p;
188 int ret = -1;
189 struct lxc_config_t *config;
190
191 if (!copy) {
192 SYSERROR("failed to allocate memory");
193 return -1;
194 }
195 /*
196 * ok we know that to get here we've got "lxc.network."
197 * and it isn't any of the other network entries. So
198 * after the second . should come an integer (# of defined
199 * nic) followed by a valid entry.
200 */
201 if (*(key+12) < '0' || *(key+12) > '9')
202 goto out;
203 p = index(key+12, '.');
204 if (!p)
205 goto out;
206 strcpy(copy+12, p+1);
207 config = lxc_getconfig(copy);
208 if (!config) {
209 ERROR("unknown key %s", key);
210 goto out;
211 }
212 ret = config->cb(key, value, lxc_conf);
213
214out:
215 free(copy);
216 return ret;
217}
218
12a50cc6 219static int config_network_type(const char *key, const char *value,
e892973e 220 struct lxc_conf *lxc_conf)
c2cc9f0a 221{
5f4535a3 222 struct lxc_list *network = &lxc_conf->network;
c2cc9f0a 223 struct lxc_netdev *netdev;
224 struct lxc_list *list;
c2cc9f0a 225
226 netdev = malloc(sizeof(*netdev));
227 if (!netdev) {
36eb9bde 228 SYSERROR("failed to allocate memory");
c2cc9f0a 229 return -1;
230 }
231
82d5ae15 232 memset(netdev, 0, sizeof(*netdev));
c2cc9f0a 233 lxc_list_init(&netdev->ipv4);
234 lxc_list_init(&netdev->ipv6);
c2cc9f0a 235
236 list = malloc(sizeof(*list));
237 if (!list) {
36eb9bde 238 SYSERROR("failed to allocate memory");
c2cc9f0a 239 return -1;
240 }
241
242 lxc_list_init(list);
5f4535a3 243 list->elem = netdev;
c2cc9f0a 244
bac89583 245 lxc_list_add_tail(network, list);
a871ff6b 246
c2cc9f0a 247 if (!strcmp(value, "veth"))
24654103 248 netdev->type = LXC_NET_VETH;
c2cc9f0a 249 else if (!strcmp(value, "macvlan"))
24654103 250 netdev->type = LXC_NET_MACVLAN;
26c39028 251 else if (!strcmp(value, "vlan"))
24654103 252 netdev->type = LXC_NET_VLAN;
c2cc9f0a 253 else if (!strcmp(value, "phys"))
24654103 254 netdev->type = LXC_NET_PHYS;
5f58350a 255 else if (!strcmp(value, "empty"))
24654103 256 netdev->type = LXC_NET_EMPTY;
c2cc9f0a 257 else {
36eb9bde 258 ERROR("invalid network type %s", value);
c2cc9f0a 259 return -1;
260 }
261 return 0;
262}
263
a059591e
DL
264static int config_ip_prefix(struct in_addr *addr)
265{
266 if (IN_CLASSA(addr->s_addr))
267 return 32 - IN_CLASSA_NSHIFT;
268 if (IN_CLASSB(addr->s_addr))
269 return 32 - IN_CLASSB_NSHIFT;
270 if (IN_CLASSC(addr->s_addr))
271 return 32 - IN_CLASSC_NSHIFT;
272
273 return 0;
274}
275
72d0e1cb
SG
276/*
277 * if you have p="lxc.network.0.link", pass it p+12
278 * to get back '0' (the index of the nic)
279 */
280static int get_network_netdev_idx(const char *key)
281{
282 int ret, idx;
283
284 if (*key < '0' || *key > '9')
285 return -1;
286 ret = sscanf(key, "%d", &idx);
287 if (ret != 1)
288 return -1;
289 return idx;
290}
291
292/*
293 * if you have p="lxc.network.0", pass this p+12 and it will return
294 * the netdev of the first configured nic
295 */
296static struct lxc_netdev *get_netdev_from_key(const char *key,
297 struct lxc_list *network)
298{
299 int i = 0, idx = get_network_netdev_idx(key);
300 struct lxc_netdev *netdev = NULL;
301 struct lxc_list *it;
302 if (idx == -1)
303 return NULL;
304 lxc_list_for_each(it, network) {
305 if (idx == i++) {
306 netdev = it->elem;
307 break;
308 }
309 }
310 return netdev;
311}
312
12a50cc6
DE
313extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
314 char *retv, int inlen)
72d0e1cb
SG
315{
316 struct lxc_netdev *netdev;
317 int fulllen = 0, len;
318
319 netdev = get_netdev_from_key(key+12, &c->network);
320 if (!netdev)
321 return -1;
322
323 if (!retv)
324 inlen = 0;
325 else
326 memset(retv, 0, inlen);
327
328 strprint(retv, inlen, "script.up\n");
329 if (netdev->type != LXC_NET_EMPTY) {
330 strprint(retv, inlen, "flags\n");
331 strprint(retv, inlen, "link\n");
332 strprint(retv, inlen, "name\n");
333 strprint(retv, inlen, "hwaddr\n");
334 strprint(retv, inlen, "mtu\n");
335 strprint(retv, inlen, "ipv6\n");
336 strprint(retv, inlen, "ipv6_gateway\n");
337 strprint(retv, inlen, "ipv4\n");
338 strprint(retv, inlen, "ipv4_gateway\n");
339 }
340 switch(netdev->type) {
341 case LXC_NET_VETH:
342 strprint(retv, inlen, "veth.pair\n");
343 break;
344 case LXC_NET_MACVLAN:
345 strprint(retv, inlen, "macvlan.mode\n");
346 break;
347 case LXC_NET_VLAN:
348 strprint(retv, inlen, "vlan.id\n");
349 break;
350 case LXC_NET_PHYS:
351 break;
352 }
353 return fulllen;
354}
355
16950ecb
DL
356static struct lxc_netdev *network_netdev(const char *key, const char *value,
357 struct lxc_list *network)
c2cc9f0a 358{
72d0e1cb 359 struct lxc_netdev *netdev = NULL;
c2cc9f0a 360
5f4535a3 361 if (lxc_list_empty(network)) {
16950ecb
DL
362 ERROR("network is not created for '%s' = '%s' option",
363 key, value);
33c945e0 364 return NULL;
c2cc9f0a 365 }
366
72d0e1cb
SG
367 if (get_network_netdev_idx(key+12) == -1)
368 netdev = lxc_list_last_elem(network);
369 else
370 netdev = get_netdev_from_key(key+12, network);
371
5f4535a3 372 if (!netdev) {
16950ecb
DL
373 ERROR("no network device defined for '%s' = '%s' option",
374 key, value);
33c945e0 375 return NULL;
c2cc9f0a 376 }
377
33c945e0 378 return netdev;
c2cc9f0a 379}
380
12a50cc6 381static int network_ifname(char **valuep, const char *value)
c2cc9f0a 382{
bf83c5b9 383 if (strlen(value) >= IFNAMSIZ) {
5480b13b
DL
384 ERROR("interface name '%s' too long (>%d)\n",
385 value, IFNAMSIZ - 1);
c2cc9f0a 386 return -1;
387 }
388
33c945e0 389 *valuep = strdup(value);
16950ecb
DL
390 if (!*valuep) {
391 ERROR("failed to dup string '%s'", value);
392 return -1;
393 }
33c945e0 394
c2cc9f0a 395 return 0;
396}
397
e892973e
DL
398#ifndef MACVLAN_MODE_PRIVATE
399# define MACVLAN_MODE_PRIVATE 1
400#endif
401
402#ifndef MACVLAN_MODE_VEPA
403# define MACVLAN_MODE_VEPA 2
404#endif
405
406#ifndef MACVLAN_MODE_BRIDGE
407# define MACVLAN_MODE_BRIDGE 4
408#endif
409
12a50cc6 410static int macvlan_mode(int *valuep, const char *value)
e892973e
DL
411{
412 struct mc_mode {
413 char *name;
414 int mode;
415 } m[] = {
416 { "private", MACVLAN_MODE_PRIVATE },
417 { "vepa", MACVLAN_MODE_VEPA },
418 { "bridge", MACVLAN_MODE_BRIDGE },
419 };
420
421 int i;
422
423 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
424 if (strcmp(m[i].name, value))
425 continue;
426
427 *valuep = m[i].mode;
428 return 0;
429 }
430
431 return -1;
432}
433
12a50cc6 434static int config_network_flags(const char *key, const char *value,
33c945e0 435 struct lxc_conf *lxc_conf)
c2cc9f0a 436{
c2cc9f0a 437 struct lxc_netdev *netdev;
438
16950ecb 439 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 440 if (!netdev)
c2cc9f0a 441 return -1;
c2cc9f0a 442
33c945e0 443 netdev->flags |= IFF_UP;
c2cc9f0a 444
33c945e0
MT
445 return 0;
446}
447
12a50cc6 448static int config_network_link(const char *key, const char *value,
33c945e0
MT
449 struct lxc_conf *lxc_conf)
450{
451 struct lxc_netdev *netdev;
452
16950ecb 453 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 454 if (!netdev)
c2cc9f0a 455 return -1;
c2cc9f0a 456
33c945e0 457 return network_ifname(&netdev->link, value);
c2cc9f0a 458}
459
12a50cc6 460static int config_network_name(const char *key, const char *value,
33c945e0 461 struct lxc_conf *lxc_conf)
c2cc9f0a 462{
c2cc9f0a 463 struct lxc_netdev *netdev;
464
16950ecb 465 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 466 if (!netdev)
c2cc9f0a 467 return -1;
c2cc9f0a 468
33c945e0
MT
469 return network_ifname(&netdev->name, value);
470}
471
12a50cc6 472static int config_network_veth_pair(const char *key, const char *value,
e892973e
DL
473 struct lxc_conf *lxc_conf)
474{
475 struct lxc_netdev *netdev;
476
477 netdev = network_netdev(key, value, &lxc_conf->network);
478 if (!netdev)
479 return -1;
480
481 return network_ifname(&netdev->priv.veth_attr.pair, value);
482}
483
12a50cc6 484static int config_network_macvlan_mode(const char *key, const char *value,
e892973e 485 struct lxc_conf *lxc_conf)
8634bc19
MT
486{
487 struct lxc_netdev *netdev;
488
489 netdev = network_netdev(key, value, &lxc_conf->network);
490 if (!netdev)
491 return -1;
492
e892973e 493 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
8634bc19
MT
494}
495
12a50cc6 496static int config_network_hwaddr(const char *key, const char *value,
33c945e0
MT
497 struct lxc_conf *lxc_conf)
498{
499 struct lxc_netdev *netdev;
d95db067 500 char *hwaddr;
33c945e0 501
16950ecb 502 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 503 if (!netdev)
c2cc9f0a 504 return -1;
c2cc9f0a 505
d95db067
DE
506 hwaddr = strdup(value);
507 if (!hwaddr) {
16950ecb
DL
508 SYSERROR("failed to dup string '%s'", value);
509 return -1;
510 }
33c945e0 511
d95db067
DE
512 if (netdev->hwaddr)
513 free(netdev->hwaddr);
514 netdev->hwaddr = hwaddr;
c2cc9f0a 515 return 0;
516}
517
12a50cc6 518static int config_network_vlan_id(const char *key, const char *value,
26c39028
JHS
519 struct lxc_conf *lxc_conf)
520{
521 struct lxc_netdev *netdev;
522
523 netdev = network_netdev(key, value, &lxc_conf->network);
524 if (!netdev)
525 return -1;
526
f6cc1de1 527 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
26c39028
JHS
528 return -1;
529
530 return 0;
531}
532
12a50cc6 533static int config_network_mtu(const char *key, const char *value,
33c945e0 534 struct lxc_conf *lxc_conf)
442cbbe6 535{
442cbbe6 536 struct lxc_netdev *netdev;
d95db067 537 char *mtu;
442cbbe6 538
16950ecb 539 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 540 if (!netdev)
442cbbe6 541 return -1;
442cbbe6 542
d95db067
DE
543 mtu = strdup(value);
544 if (!mtu) {
16950ecb
DL
545 SYSERROR("failed to dup string '%s'", value);
546 return -1;
547 }
33c945e0 548
d95db067
DE
549 if (netdev->mtu)
550 free(netdev->mtu);
551 netdev->mtu = mtu;
442cbbe6
TR
552 return 0;
553}
554
12a50cc6 555static int config_network_ipv4(const char *key, const char *value,
33c945e0 556 struct lxc_conf *lxc_conf)
c2cc9f0a 557{
c2cc9f0a 558 struct lxc_netdev *netdev;
33c945e0 559 struct lxc_inetdev *inetdev;
c2cc9f0a 560 struct lxc_list *list;
561 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
562
16950ecb 563 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 564 if (!netdev)
c2cc9f0a 565 return -1;
c2cc9f0a 566
567 inetdev = malloc(sizeof(*inetdev));
568 if (!inetdev) {
36eb9bde 569 SYSERROR("failed to allocate ipv4 address");
c2cc9f0a 570 return -1;
571 }
572 memset(inetdev, 0, sizeof(*inetdev));
573
574 list = malloc(sizeof(*list));
575 if (!list) {
36eb9bde 576 SYSERROR("failed to allocate memory");
c2cc9f0a 577 return -1;
578 }
579
580 lxc_list_init(list);
581 list->elem = inetdev;
582
956edc54
SG
583 addr = strdup(value);
584 if (!addr) {
585 ERROR("no address specified");
586 return -1;
587 }
c2cc9f0a 588
589 cursor = strstr(addr, " ");
590 if (cursor) {
591 *cursor = '\0';
592 bcast = cursor + 1;
593 }
594
595 slash = strstr(addr, "/");
596 if (slash) {
597 *slash = '\0';
598 prefix = slash + 1;
599 }
600
c2cc9f0a 601 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
36eb9bde 602 SYSERROR("invalid ipv4 address: %s", value);
956edc54 603 free(addr);
c2cc9f0a 604 return -1;
605 }
606
0093bb8c
DL
607 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
608 SYSERROR("invalid ipv4 broadcast address: %s", value);
956edc54 609 free(addr);
0093bb8c
DL
610 return -1;
611 }
c2cc9f0a 612
a059591e
DL
613 /* no prefix specified, determine it from the network class */
614 inetdev->prefix = prefix ? atoi(prefix) :
615 config_ip_prefix(&inetdev->addr);
616
b3df193c 617 /* if no broadcast address, let compute one from the
0093bb8c
DL
618 * prefix and address
619 */
620 if (!bcast) {
1b7d4743
DL
621 inetdev->bcast.s_addr = inetdev->addr.s_addr;
622 inetdev->bcast.s_addr |=
623 htonl(INADDR_BROADCAST >> inetdev->prefix);
0093bb8c 624 }
c2cc9f0a 625
626 lxc_list_add(&netdev->ipv4, list);
627
956edc54 628 free(addr);
c2cc9f0a 629 return 0;
630}
631
12a50cc6 632static int config_network_ipv4_gateway(const char *key, const char *value,
f8fee0e2
MK
633 struct lxc_conf *lxc_conf)
634{
635 struct lxc_netdev *netdev;
636 struct in_addr *gw;
637
638 netdev = network_netdev(key, value, &lxc_conf->network);
639 if (!netdev)
640 return -1;
641
642 gw = malloc(sizeof(*gw));
643 if (!gw) {
644 SYSERROR("failed to allocate ipv4 gateway address");
645 return -1;
646 }
647
648 if (!value) {
649 ERROR("no ipv4 gateway address specified");
650 return -1;
651 }
652
19a26f82
MK
653 if (!strcmp(value, "auto")) {
654 netdev->ipv4_gateway = NULL;
655 netdev->ipv4_gateway_auto = true;
656 } else {
657 if (!inet_pton(AF_INET, value, gw)) {
658 SYSERROR("invalid ipv4 gateway address: %s", value);
659 return -1;
660 }
661
662 netdev->ipv4_gateway = gw;
663 netdev->ipv4_gateway_auto = false;
f8fee0e2
MK
664 }
665
f8fee0e2
MK
666 return 0;
667}
668
12a50cc6 669static int config_network_ipv6(const char *key, const char *value,
e892973e 670 struct lxc_conf *lxc_conf)
c2cc9f0a 671{
c2cc9f0a 672 struct lxc_netdev *netdev;
673 struct lxc_inet6dev *inet6dev;
674 struct lxc_list *list;
12a50cc6 675 char *slash,*valdup;
c2cc9f0a 676 char *netmask;
677
16950ecb 678 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 679 if (!netdev)
c2cc9f0a 680 return -1;
c2cc9f0a 681
682 inet6dev = malloc(sizeof(*inet6dev));
683 if (!inet6dev) {
36eb9bde 684 SYSERROR("failed to allocate ipv6 address");
c2cc9f0a 685 return -1;
686 }
687 memset(inet6dev, 0, sizeof(*inet6dev));
688
689 list = malloc(sizeof(*list));
690 if (!list) {
36eb9bde 691 SYSERROR("failed to allocate memory");
c2cc9f0a 692 return -1;
693 }
694
695 lxc_list_init(list);
696 list->elem = inet6dev;
697
956edc54
SG
698 valdup = strdup(value);
699 if (!valdup) {
700 ERROR("no address specified");
701 return -1;
702 }
703
a059591e 704 inet6dev->prefix = 64;
12a50cc6 705 slash = strstr(valdup, "/");
c2cc9f0a 706 if (slash) {
707 *slash = '\0';
708 netmask = slash + 1;
709 inet6dev->prefix = atoi(netmask);
710 }
711
712 if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
36eb9bde 713 SYSERROR("invalid ipv6 address: %s", value);
956edc54 714 free(valdup);
c2cc9f0a 715 return -1;
716 }
717
c2cc9f0a 718 lxc_list_add(&netdev->ipv6, list);
719
956edc54 720 free(valdup);
c2cc9f0a 721 return 0;
722}
723
12a50cc6 724static int config_network_ipv6_gateway(const char *key, const char *value,
f8fee0e2
MK
725 struct lxc_conf *lxc_conf)
726{
727 struct lxc_netdev *netdev;
728 struct in6_addr *gw;
729
730 netdev = network_netdev(key, value, &lxc_conf->network);
731 if (!netdev)
732 return -1;
733
734 gw = malloc(sizeof(*gw));
735 if (!gw) {
736 SYSERROR("failed to allocate ipv6 gateway address");
737 return -1;
738 }
739
740 if (!value) {
741 ERROR("no ipv6 gateway address specified");
742 return -1;
743 }
744
19a26f82
MK
745 if (!strcmp(value, "auto")) {
746 netdev->ipv6_gateway = NULL;
747 netdev->ipv6_gateway_auto = true;
748 } else {
749 if (!inet_pton(AF_INET6, value, gw)) {
750 SYSERROR("invalid ipv6 gateway address: %s", value);
751 return -1;
752 }
753
754 netdev->ipv6_gateway = gw;
755 netdev->ipv6_gateway_auto = false;
f8fee0e2
MK
756 }
757
f8fee0e2
MK
758 return 0;
759}
760
12a50cc6 761static int config_network_script(const char *key, const char *value,
e3b4c4c4
ST
762 struct lxc_conf *lxc_conf)
763{
764 struct lxc_netdev *netdev;
765
766 netdev = network_netdev(key, value, &lxc_conf->network);
767 if (!netdev)
768 return -1;
769
770 char *copy = strdup(value);
771 if (!copy) {
772 SYSERROR("failed to dup string '%s'", value);
773 return -1;
774 }
72d0e1cb 775 if (strstr(key, "script.up") != NULL) {
e3b4c4c4
ST
776 netdev->upscript = copy;
777 return 0;
778 }
74a2b586
JK
779 if (strcmp(key, "lxc.network.script.down") == 0) {
780 netdev->downscript = copy;
781 return 0;
782 }
e3b4c4c4
ST
783 SYSERROR("Unknown key: %s", key);
784 free(copy);
785 return -1;
786}
787
26ddeedd
SH
788static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
789{
790 struct lxc_list *hooklist;
791
792 hooklist = malloc(sizeof(*hooklist));
793 if (!hooklist) {
794 free(hook);
795 return -1;
796 }
797 hooklist->elem = hook;
798 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
799 return 0;
800}
801
12a50cc6 802static int config_seccomp(const char *key, const char *value,
8f2c3a70
SH
803 struct lxc_conf *lxc_conf)
804{
805 char *path;
806
807 if (lxc_conf->seccomp) {
808 ERROR("seccomp already defined");
809 return -1;
810 }
811 path = strdup(value);
812 if (!path) {
813 SYSERROR("failed to strdup '%s': %m", value);
814 return -1;
815 }
816
d95db067
DE
817 if (lxc_conf->seccomp)
818 free(lxc_conf->seccomp);
8f2c3a70
SH
819 lxc_conf->seccomp = path;
820
821 return 0;
822}
823
12a50cc6 824static int config_hook(const char *key, const char *value,
26ddeedd
SH
825 struct lxc_conf *lxc_conf)
826{
827 char *copy = strdup(value);
828 if (!copy) {
829 SYSERROR("failed to dup string '%s'", value);
830 return -1;
831 }
832 if (strcmp(key, "lxc.hook.pre-start") == 0)
833 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
5ea6163a
SH
834 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
835 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
26ddeedd
SH
836 else if (strcmp(key, "lxc.hook.mount") == 0)
837 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
838 else if (strcmp(key, "lxc.hook.start") == 0)
839 return add_hook(lxc_conf, LXCHOOK_START, copy);
840 else if (strcmp(key, "lxc.hook.post-stop") == 0)
841 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
842 SYSERROR("Unknown key: %s", key);
843 free(copy);
844 return -1;
845}
846
12a50cc6 847static int config_personality(const char *key, const const char *value,
cccc74b5
DL
848 struct lxc_conf *lxc_conf)
849{
525f0002 850 signed long personality = lxc_config_parse_arch(value);
cccc74b5 851
525f0002
CS
852 if (personality >= 0)
853 lxc_conf->personality = personality;
854 else
855 WARN("unsupported personality '%s'", value);
970ab589
DL
856
857 return 0;
cccc74b5
DL
858}
859
12a50cc6
DE
860static int config_pts(const char *key, const char *value,
861 struct lxc_conf *lxc_conf)
10db618d 862{
863 int maxpts = atoi(value);
864
865 lxc_conf->pts = maxpts;
866
867 return 0;
868}
869
12a50cc6
DE
870static int config_tty(const char *key, const char *value,
871 struct lxc_conf *lxc_conf)
b0a33c1e 872{
873 int nbtty = atoi(value);
874
875 lxc_conf->tty = nbtty;
876
877 return 0;
878}
879
12a50cc6 880static int config_ttydir(const char *key, const char *value,
7c6ef2a2
SH
881 struct lxc_conf *lxc_conf)
882{
883 char *path;
884
885 if (!value || strlen(value) == 0)
886 return 0;
887 path = strdup(value);
888 if (!path) {
889 SYSERROR("failed to strdup '%s': %m", value);
890 return -1;
891 }
892
d95db067
DE
893 if (lxc_conf->ttydir)
894 free(lxc_conf->ttydir);
7c6ef2a2
SH
895 lxc_conf->ttydir = path;
896
897 return 0;
898}
899
e075f5d9 900#if HAVE_APPARMOR
12a50cc6
DE
901static int config_aa_profile(const char *key, const char *value,
902 struct lxc_conf *lxc_conf)
e075f5d9
SH
903{
904 char *path;
905
906 if (!value || strlen(value) == 0)
907 return 0;
908 path = strdup(value);
909 if (!path) {
910 SYSERROR("failed to strdup '%s': %m", value);
911 return -1;
912 }
913
d95db067
DE
914 if (lxc_conf->aa_profile)
915 free(lxc_conf->aa_profile);
e075f5d9
SH
916 lxc_conf->aa_profile = path;
917
918 return 0;
919}
920#endif
921
4a85ce2a
SH
922static int config_logfile(const char *key, const char *value,
923 struct lxc_conf *lxc_conf)
924{
925 char *path;
926
927 // if given a blank entry, null out any previous entries.
928 if (!value || strlen(value) == 0) {
929 if (lxc_conf->logfile) {
930 free(lxc_conf->logfile);
931 lxc_conf->logfile = NULL;
932 }
933 return 0;
934 }
935
936 path = strdup(value);
937 if (!path) {
938 SYSERROR("failed to strdup '%s': %m", value);
939 return -1;
940 }
941
942 if (lxc_log_set_file(path)) {
943 free(path);
944 return -1;
945 }
946
947 if (lxc_conf->logfile)
948 free(lxc_conf->logfile);
949 lxc_conf->logfile = path;
950
951 return 0;
952}
953
954static int config_loglevel(const char *key, const char *value,
955 struct lxc_conf *lxc_conf)
956{
957 if (!value || strlen(value) == 0)
958 return 0;
959
960 if (value[0] >= '0' && value[0] <= '9')
961 lxc_conf->loglevel = atoi(value);
962 else
963 lxc_conf->loglevel = lxc_log_priority_to_int(value);
964 return lxc_log_set_level(lxc_conf->loglevel);
965}
966
12a50cc6 967static int config_autodev(const char *key, const char *value,
c6883f38
SH
968 struct lxc_conf *lxc_conf)
969{
970 int v = atoi(value);
971
972 lxc_conf->autodev = v;
973
974 return 0;
975}
976
12a50cc6
DE
977static int config_cgroup(const char *key, const char *value,
978 struct lxc_conf *lxc_conf)
576f946d 979{
980 char *token = "lxc.cgroup.";
981 char *subkey;
bf83c5b9
MS
982 struct lxc_list *cglist = NULL;
983 struct lxc_cgroup *cgelem = NULL;
576f946d 984
985 subkey = strstr(key, token);
986
987 if (!subkey)
988 return -1;
989
990 if (!strlen(subkey))
991 return -1;
992
993 if (strlen(subkey) == strlen(token))
994 return -1;
a871ff6b 995
576f946d 996 subkey += strlen(token);
997
998 cglist = malloc(sizeof(*cglist));
999 if (!cglist)
bf83c5b9 1000 goto out;
576f946d 1001
1002 cgelem = malloc(sizeof(*cgelem));
bf83c5b9
MS
1003 if (!cgelem)
1004 goto out;
1005 memset(cgelem, 0, sizeof(*cgelem));
576f946d 1006
1007 cgelem->subsystem = strdup(subkey);
1008 cgelem->value = strdup(value);
bf83c5b9
MS
1009
1010 if (!cgelem->subsystem || !cgelem->value)
1011 goto out;
1012
576f946d 1013 cglist->elem = cgelem;
1014
94d12f0a 1015 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
576f946d 1016
1017 return 0;
bf83c5b9
MS
1018
1019out:
1020 if (cglist)
1021 free(cglist);
1022
1023 if (cgelem) {
1024 if (cgelem->subsystem)
1025 free(cgelem->subsystem);
1026
1027 if (cgelem->value)
1028 free(cgelem->value);
1029
1030 free(cgelem);
1031 }
1032
1033 return -1;
576f946d 1034}
1035
d95db067
DE
1036static int config_path_item(const char *key, const char *value,
1037 struct lxc_conf *lxc_conf, char **conf_item)
c2cc9f0a 1038{
d95db067 1039 char *valdup;
c2cc9f0a 1040 if (strlen(value) >= MAXPATHLEN) {
36eb9bde 1041 ERROR("%s path is too long", value);
c2cc9f0a 1042 return -1;
1043 }
1044
d95db067
DE
1045 valdup = strdup(value);
1046 if (!valdup) {
36eb9bde 1047 SYSERROR("failed to duplicate string %s", value);
c2cc9f0a 1048 return -1;
1049 }
d95db067
DE
1050 if (*conf_item)
1051 free(*conf_item);
1052 *conf_item = valdup;
c2cc9f0a 1053
1054 return 0;
1055}
1056
d95db067
DE
1057static int config_fstab(const char *key, const char *value,
1058 struct lxc_conf *lxc_conf)
1059{
1060 return config_path_item(key, value, lxc_conf, &lxc_conf->fstab);
1061}
1062
12a50cc6
DE
1063static int config_mount(const char *key, const char *value,
1064 struct lxc_conf *lxc_conf)
e7938e9e
MN
1065{
1066 char *fstab_token = "lxc.mount";
1067 char *token = "lxc.mount.entry";
1068 char *subkey;
1069 char *mntelem;
1070 struct lxc_list *mntlist;
1071
1072 subkey = strstr(key, token);
1073
1074 if (!subkey) {
1075 subkey = strstr(key, fstab_token);
1076
1077 if (!subkey)
1078 return -1;
1079
1080 return config_fstab(key, value, lxc_conf);
1081 }
1082
1083 if (!strlen(subkey))
1084 return -1;
1085
1086 mntlist = malloc(sizeof(*mntlist));
1087 if (!mntlist)
1088 return -1;
1089
1090 mntelem = strdup(value);
bf83c5b9
MS
1091 if (!mntelem)
1092 return -1;
e7938e9e
MN
1093 mntlist->elem = mntelem;
1094
1095 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1096
1097 return 0;
1098}
1099
12a50cc6 1100static int config_cap_drop(const char *key, const char *value,
81810dd1
DL
1101 struct lxc_conf *lxc_conf)
1102{
d95db067 1103 char *dropcaps, *dropptr, *sptr, *token;
81810dd1
DL
1104 struct lxc_list *droplist;
1105 int ret = -1;
1106
1107 if (!strlen(value))
1108 return -1;
1109
1110 dropcaps = strdup(value);
1111 if (!dropcaps) {
1112 SYSERROR("failed to dup '%s'", value);
1113 return -1;
1114 }
1115
1116 /* in case several capability drop is specified in a single line
1117 * split these caps in a single element for the list */
d95db067
DE
1118 for (dropptr = dropcaps;;dropptr = NULL) {
1119 token = strtok_r(dropptr, " \t", &sptr);
81810dd1
DL
1120 if (!token) {
1121 ret = 0;
1122 break;
1123 }
81810dd1
DL
1124
1125 droplist = malloc(sizeof(*droplist));
1126 if (!droplist) {
1127 SYSERROR("failed to allocate drop list");
1128 break;
1129 }
1130
1131 droplist->elem = strdup(token);
1132 if (!droplist->elem) {
1133 SYSERROR("failed to dup '%s'", token);
1134 free(droplist);
1135 break;
1136 }
1137
1138 lxc_list_add_tail(&lxc_conf->caps, droplist);
1139 }
1140
1141 free(dropcaps);
1142
1143 return ret;
1144}
1145
12a50cc6 1146static int config_console(const char *key, const char *value,
28a4b0e5
DL
1147 struct lxc_conf *lxc_conf)
1148{
1149 char *path;
1150
1151 path = strdup(value);
1152 if (!path) {
1153 SYSERROR("failed to strdup '%s': %m", value);
1154 return -1;
1155 }
1156
d95db067
DE
1157 if (lxc_conf->console.path)
1158 free(lxc_conf->console.path);
28a4b0e5
DL
1159 lxc_conf->console.path = path;
1160
1161 return 0;
1162}
1163
12a50cc6 1164static int config_includefile(const char *key, const char *value,
09ad6246
SH
1165 struct lxc_conf *lxc_conf)
1166{
1167 return lxc_config_read(value, lxc_conf);
1168}
1169
12a50cc6
DE
1170static int config_rootfs(const char *key, const char *value,
1171 struct lxc_conf *lxc_conf)
c2cc9f0a 1172{
d95db067 1173 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.path);
c2cc9f0a 1174}
1175
12a50cc6
DE
1176static int config_rootfs_mount(const char *key, const char *value,
1177 struct lxc_conf *lxc_conf)
23b7ea69 1178{
d95db067 1179 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.mount);
23b7ea69
DL
1180}
1181
12a50cc6
DE
1182static int config_pivotdir(const char *key, const char *value,
1183 struct lxc_conf *lxc_conf)
bf601689 1184{
d95db067 1185 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.pivot);
bf601689
MH
1186}
1187
12a50cc6
DE
1188static int config_utsname(const char *key, const char *value,
1189 struct lxc_conf *lxc_conf)
c2cc9f0a 1190{
1191 struct utsname *utsname;
1192
1193 utsname = malloc(sizeof(*utsname));
1194 if (!utsname) {
36eb9bde 1195 SYSERROR("failed to allocate memory");
c2cc9f0a 1196 return -1;
1197 }
1198
1199 if (strlen(value) >= sizeof(utsname->nodename)) {
36eb9bde 1200 ERROR("node name '%s' is too long",
c2cc9f0a 1201 utsname->nodename);
1202 return -1;
1203 }
1204
1205 strcpy(utsname->nodename, value);
d95db067
DE
1206 if (lxc_conf->utsname)
1207 free(lxc_conf->utsname);
c2cc9f0a 1208 lxc_conf->utsname = utsname;
1209
1210 return 0;
1211}
1212
7a7ff0c6 1213static int parse_line(char *buffer, void *data)
c2cc9f0a 1214{
72d0e1cb 1215 struct lxc_config_t *config;
81192358 1216 char *line, *linep;
c2cc9f0a 1217 char *dot;
1218 char *key;
1219 char *value;
476d4cf1 1220 int ret = 0;
c2cc9f0a 1221
91480a0f 1222 if (lxc_is_line_empty(buffer))
c2cc9f0a 1223 return 0;
1224
81192358
DL
1225 /* we have to dup the buffer otherwise, at the re-exec for
1226 * reboot we modified the original string on the stack by
1227 * replacing '=' by '\0' below
91480a0f 1228 */
81192358 1229 linep = line = strdup(buffer);
91480a0f
DL
1230 if (!line) {
1231 SYSERROR("failed to allocate memory for '%s'", buffer);
81192358 1232 return -1;
91480a0f
DL
1233 }
1234
b2718c72 1235 line += lxc_char_left_gc(line, strlen(line));
476d4cf1
DL
1236
1237 /* martian option - ignoring it, the commented lines beginning by '#'
1238 * fall in this case
1239 */
1240 if (strncmp(line, "lxc.", 4))
91480a0f 1241 goto out;
476d4cf1
DL
1242
1243 ret = -1;
c2cc9f0a 1244
b2718c72 1245 dot = strstr(line, "=");
c2cc9f0a 1246 if (!dot) {
36eb9bde 1247 ERROR("invalid configuration line: %s", line);
91480a0f 1248 goto out;
c2cc9f0a 1249 }
a871ff6b 1250
c2cc9f0a 1251 *dot = '\0';
1252 value = dot + 1;
1253
b2718c72 1254 key = line;
1255 key[lxc_char_right_gc(key, strlen(key))] = '\0';
c2cc9f0a 1256
b2718c72 1257 value += lxc_char_left_gc(value, strlen(value));
1258 value[lxc_char_right_gc(value, strlen(value))] = '\0';
c2cc9f0a 1259
72d0e1cb 1260 config = lxc_getconfig(key);
c2cc9f0a 1261 if (!config) {
6e1d9b94 1262 ERROR("unknown key %s", key);
91480a0f 1263 goto out;
c2cc9f0a 1264 }
1265
91480a0f
DL
1266 ret = config->cb(key, value, data);
1267
1268out:
81192358 1269 free(linep);
91480a0f 1270 return ret;
c2cc9f0a 1271}
1272
af5b0155
CLG
1273int lxc_config_readline(char *buffer, struct lxc_conf *conf)
1274{
1275 return parse_line(buffer, conf);
1276}
1277
b2718c72 1278int lxc_config_read(const char *file, struct lxc_conf *conf)
c2cc9f0a 1279{
2382ecff 1280 return lxc_file_for_each_line(file, parse_line, conf);
c2cc9f0a 1281}
62e46035
CLG
1282
1283int lxc_config_define_add(struct lxc_list *defines, char* arg)
1284{
1285 struct lxc_list *dent;
1286
1287 dent = malloc(sizeof(struct lxc_list));
1288 if (!dent)
1289 return -1;
1290
1291 dent->elem = arg;
1292 lxc_list_add_tail(defines, dent);
1293 return 0;
1294}
1295
226a18d6 1296int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
62e46035 1297{
9ebb03ad 1298 struct lxc_list *it,*next;
62e46035
CLG
1299 int ret = 0;
1300
1301 lxc_list_for_each(it, defines) {
1302 ret = lxc_config_readline(it->elem, conf);
1303 if (ret)
1304 break;
1305 }
1306
9ebb03ad 1307 lxc_list_for_each_safe(it, defines, next) {
62e46035
CLG
1308 lxc_list_del(it);
1309 free(it);
1310 }
1311
1312 return ret;
1313}
525f0002
CS
1314
1315signed long lxc_config_parse_arch(const char *arch)
1316{
6ff05e18 1317 #if HAVE_SYS_PERSONALITY_H
525f0002
CS
1318 struct per_name {
1319 char *name;
1320 unsigned long per;
1321 } pername[4] = {
1322 { "x86", PER_LINUX32 },
1323 { "i686", PER_LINUX32 },
1324 { "x86_64", PER_LINUX },
1325 { "amd64", PER_LINUX },
1326 };
1327 size_t len = sizeof(pername) / sizeof(pername[0]);
1328
1329 int i;
1330
1331 for (i = 0; i < len; i++) {
1332 if (!strcmp(pername[i].name, arch))
1333 return pername[i].per;
1334 }
6ff05e18 1335 #endif
525f0002
CS
1336
1337 return -1;
1338}
72d0e1cb
SG
1339
1340static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
1341{
1342 if (!retv)
1343 inlen = 0;
1344 else
1345 memset(retv, 0, inlen);
1346 return snprintf(retv, inlen, "%d", v);
1347}
1348
1349static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
1350{
6ff05e18 1351 int fulllen = 0;
72d0e1cb
SG
1352
1353 if (!retv)
1354 inlen = 0;
1355 else
1356 memset(retv, 0, inlen);
1357
6ff05e18
SG
1358 #if HAVE_SYS_PERSONALITY_H
1359 int len = 0;
1360
72d0e1cb
SG
1361 switch(c->personality) {
1362 case PER_LINUX32: strprint(retv, inlen, "x86"); break;
1363 case PER_LINUX: strprint(retv, inlen, "x86_64"); break;
1364 default: break;
1365 }
6ff05e18 1366 #endif
72d0e1cb
SG
1367
1368 return fulllen;
1369}
1370
1371/*
1372 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
1373 * then just the value(s) will be printed. Since there still could be
1374 * more than one, it is newline-separated.
1375 * (Maybe that's ambigous, since some values, i.e. devices.list, will
1376 * already have newlines?)
1377 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
1378 * in 'lxc.cgroup.subsystem.key = value' format.
1379 */
12a50cc6
DE
1380static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
1381 const char *key)
72d0e1cb
SG
1382{
1383 int fulllen = 0, len;
1384 int all = 0;
1385 struct lxc_list *it;
1386
1387 if (!retv)
1388 inlen = 0;
1389 else
1390 memset(retv, 0, inlen);
1391
1392 if (strcmp(key, "all") == 0)
1393 all = 1;
1394
1395 lxc_list_for_each(it, &c->cgroup) {
1396 struct lxc_cgroup *cg = it->elem;
1397 if (all) {
1398 strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
1399 } else if (strcmp(cg->subsystem, key) == 0) {
1400 strprint(retv, inlen, "%s\n", cg->value);
1401 }
1402 }
1403 return fulllen;
1404}
1405
12a50cc6
DE
1406static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
1407 const char *key)
72d0e1cb
SG
1408{
1409 char *subkey;
1410 int len, fulllen = 0, found = -1;
1411 struct lxc_list *it;
1412 int i;
1413
1414 /* "lxc.hook.mount" */
1415 subkey = index(key, '.');
1416 if (subkey) subkey = index(subkey+1, '.');
1417 if (!subkey)
1418 return -1;
1419 subkey++;
1420 if (!*subkey)
1421 return -1;
1422 for (i=0; i<NUM_LXC_HOOKS; i++) {
1423 if (strcmp(lxchook_names[i], subkey) == 0) {
1424 found=i;
1425 break;
1426 }
1427 }
1428 if (found == -1)
1429 return -1;
1430
1431 if (!retv)
1432 inlen = 0;
1433 else
1434 memset(retv, 0, inlen);
1435
1436 lxc_list_for_each(it, &c->hooks[found]) {
1437 strprint(retv, inlen, "%s\n", (char *)it->elem);
1438 }
1439 return fulllen;
1440}
1441
1442static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
1443{
1444 int len, fulllen = 0;
1445 struct lxc_list *it;
1446
1447 if (!retv)
1448 inlen = 0;
1449 else
1450 memset(retv, 0, inlen);
1451
1452 lxc_list_for_each(it, &c->caps) {
1453 strprint(retv, inlen, "%s\n", (char *)it->elem);
1454 }
1455 return fulllen;
1456}
1457
1458static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen)
1459{
1460 int len, fulllen = 0;
1461 struct lxc_list *it;
1462
1463 if (!retv)
1464 inlen = 0;
1465 else
1466 memset(retv, 0, inlen);
1467
1468 lxc_list_for_each(it, &c->mount_list) {
1469 strprint(retv, inlen, "%s\n", (char *)it->elem);
1470 }
1471 return fulllen;
1472}
1473
1474/*
1475 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
1476 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, upscript, hwaddr, mtu,
1477 * ipv4_gateway, ipv6_gateway. ipvX_gateway can return 'auto' instead
1478 * of an address. ipv4 and ipv6 return lists (newline-separated).
1479 * things like veth.pair return '' if invalid (i.e. if called for vlan
1480 * type).
1481 */
12a50cc6
DE
1482static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
1483 const char *key)
72d0e1cb
SG
1484{
1485 char *p1;
fe88b9d2 1486 int len, fulllen = 0;
72d0e1cb
SG
1487 struct lxc_netdev *netdev;
1488
1489 if (!retv)
1490 inlen = 0;
1491 else
1492 memset(retv, 0, inlen);
1493
1494 p1 = index(key, '.');
1495 if (!p1 || *(p1+1) == '\0') return -1;
1496 p1++;
1497
1498 netdev = get_netdev_from_key(key, &c->network);
1499 if (!netdev)
1500 return -1;
1501 if (strcmp(p1, "name") == 0) {
1502 if (netdev->name)
1503 strprint(retv, inlen, "%s", netdev->name);
1504 } else if (strcmp(p1, "type") == 0) {
1505 strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
1506 } else if (strcmp(p1, "link") == 0) {
1507 if (netdev->link)
1508 strprint(retv, inlen, "%s", netdev->link);
1509 } else if (strcmp(p1, "flags") == 0) {
1510 if (netdev->flags & IFF_UP)
1511 strprint(retv, inlen, "up");
1512 } else if (strcmp(p1, "upscript") == 0) {
1513 if (netdev->upscript)
1514 strprint(retv, inlen, "%s", netdev->upscript);
1515 } else if (strcmp(p1, "hwaddr") == 0) {
1516 if (netdev->hwaddr)
1517 strprint(retv, inlen, "%s", netdev->hwaddr);
1518 } else if (strcmp(p1, "mtu") == 0) {
1519 if (netdev->mtu)
1520 strprint(retv, inlen, "%s", netdev->mtu);
1521 } else if (strcmp(p1, "macvlan.mode") == 0) {
1522 if (netdev->type == LXC_NET_MACVLAN) {
1523 const char *mode;
1524 switch (netdev->priv.macvlan_attr.mode) {
1525 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
1526 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
1527 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
1528 default: mode = "(invalid)"; break;
1529 }
1530 strprint(retv, inlen, "%s", mode);
1531 }
1532 } else if (strcmp(p1, "veth.pair") == 0) {
1533 if (netdev->type == LXC_NET_VETH && netdev->priv.veth_attr.pair)
1534 strprint(retv, inlen, "%s", netdev->priv.veth_attr.pair);
1535 } else if (strcmp(p1, "vlan") == 0) {
1536 if (netdev->type == LXC_NET_VLAN) {
1537 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
1538 }
1539 } else if (strcmp(p1, "ipv4_gateway") == 0) {
1540 if (netdev->ipv4_gateway_auto) {
1541 strprint(retv, inlen, "auto");
1542 } else if (netdev->ipv4_gateway) {
1543 char buf[INET_ADDRSTRLEN];
1544 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
1545 strprint(retv, inlen, "%s", buf);
1546 }
1547 } else if (strcmp(p1, "ipv4") == 0) {
1548 struct lxc_list *it2;
1549 lxc_list_for_each(it2, &netdev->ipv4) {
1550 struct lxc_inetdev *i = it2->elem;
1551 char buf[INET_ADDRSTRLEN];
1552 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
1553 strprint(retv, inlen, "%s\n", buf);
1554 }
1555 } else if (strcmp(p1, "ipv6_gateway") == 0) {
1556 if (netdev->ipv6_gateway_auto) {
1557 strprint(retv, inlen, "auto");
1558 } else if (netdev->ipv6_gateway) {
1559 char buf[INET_ADDRSTRLEN];
1560 inet_ntop(AF_INET, netdev->ipv6_gateway, buf, sizeof(buf));
1561 strprint(retv, inlen, "%s", buf);
1562 }
1563 } else if (strcmp(p1, "ipv6") == 0) {
1564 struct lxc_list *it2;
1565 lxc_list_for_each(it2, &netdev->ipv6) {
1566 struct lxc_inetdev *i = it2->elem;
1567 char buf[INET_ADDRSTRLEN];
1568 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
1569 strprint(retv, inlen, "%s\n", buf);
1570 }
1571 }
1572 return fulllen;
1573}
1574
1575static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
1576{
1577 int len, fulllen = 0;
1578 struct lxc_list *it;
1579
1580 if (!retv)
1581 inlen = 0;
1582 else
1583 memset(retv, 0, inlen);
1584
1585 lxc_list_for_each(it, &c->network) {
1586 struct lxc_netdev *n = it->elem;
1587 const char *t = lxc_net_type_to_str(n->type);
1588 strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
1589 }
1590 return fulllen;
1591}
1592
12a50cc6
DE
1593int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
1594 int inlen)
72d0e1cb 1595{
4a85ce2a 1596 const char *v = NULL;
72d0e1cb
SG
1597
1598 if (strcmp(key, "lxc.mount.entry") == 0)
1599 return lxc_get_mount_entries(c, retv, inlen);
1600 else if (strcmp(key, "lxc.mount") == 0)
1601 v = c->fstab;
1602 else if (strcmp(key, "lxc.tty") == 0)
1603 return lxc_get_conf_int(c, retv, inlen, c->tty);
1604 else if (strcmp(key, "lxc.pts") == 0)
1605 return lxc_get_conf_int(c, retv, inlen, c->pts);
1606 else if (strcmp(key, "lxc.devttydir") == 0)
1607 v = c->ttydir;
1608 else if (strcmp(key, "lxc.arch") == 0)
1609 return lxc_get_arch_entry(c, retv, inlen);
1f530df6 1610#if HAVE_APPARMOR
72d0e1cb
SG
1611 else if (strcmp(key, "lxc.aa_profile") == 0)
1612 v = c->aa_profile;
1f530df6 1613#endif
4a85ce2a
SH
1614 else if (strcmp(key, "lxc.logfile") == 0)
1615 v = c->logfile;
1616 else if (strcmp(key, "lxc.loglevel") == 0)
1617 v = lxc_log_priority_to_string(c->loglevel);
72d0e1cb
SG
1618 else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
1619 return lxc_get_cgroup_entry(c, retv, inlen, "all");
1620 else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
1621 return lxc_get_cgroup_entry(c, retv, inlen, key + 11);
1622 else if (strcmp(key, "lxc.utsname") == 0)
64fca455 1623 v = c->utsname ? c->utsname->nodename : NULL;
72d0e1cb
SG
1624 else if (strcmp(key, "lxc.console") == 0)
1625 v = c->console.path;
1626 else if (strcmp(key, "lxc.rootfs.mount") == 0)
1627 v = c->rootfs.mount;
1628 else if (strcmp(key, "lxc.rootfs") == 0)
1629 v = c->rootfs.path;
1630 else if (strcmp(key, "lxc.pivotdir") == 0)
1631 v = c->rootfs.pivot;
1632 else if (strcmp(key, "lxc.cap.drop") == 0)
1633 return lxc_get_item_cap_drop(c, retv, inlen);
1634 else if (strncmp(key, "lxc.hook", 8) == 0)
1635 return lxc_get_item_hooks(c, retv, inlen, key);
1636 else if (strcmp(key, "lxc.network") == 0)
1637 return lxc_get_item_network(c, retv, inlen);
1638 else if (strncmp(key, "lxc.network.", 12) == 0)
1639 return lxc_get_item_nic(c, retv, inlen, key + 12);
1640 else return -1;
1641
1642 if (!v)
1643 return 0;
1644 if (retv && inlen >= strlen(v) + 1)
1645 strncpy(retv, v, strlen(v)+1);
1646 return strlen(v);
1647}
1648
12a50cc6 1649int lxc_clear_config_item(struct lxc_conf *c, const char *key)
72d0e1cb
SG
1650{
1651 if (strcmp(key, "lxc.network") == 0)
1652 return lxc_clear_config_network(c);
1653 else if (strncmp(key, "lxc.network.", 12) == 0)
1654 return lxc_clear_nic(c, key + 12);
1655 else if (strcmp(key, "lxc.cap.drop") == 0)
1656 return lxc_clear_config_caps(c);
1657 else if (strncmp(key, "lxc.cgroup", 10) == 0)
1658 return lxc_clear_cgroups(c, key);
1659 else if (strcmp(key, "lxc.mount.entries") == 0)
1660 return lxc_clear_mount_entries(c);
17ed13a3
SH
1661 else if (strncmp(key, "lxc.hook", 8) == 0)
1662 return lxc_clear_hooks(c, key);
72d0e1cb
SG
1663
1664 return -1;
1665}
1666
1667/*
1668 * writing out a confile.
1669 */
1670void write_config(FILE *fout, struct lxc_conf *c)
1671{
1672 struct lxc_list *it;
1673 int i;
1674
1675 if (c->fstab)
1676 fprintf(fout, "lxc.mount = %s\n", c->fstab);
1677 lxc_list_for_each(it, &c->mount_list) {
1678 fprintf(fout, "lxc.mount.entry = %s\n", (char *)it->elem);
1679 }
1680 if (c->tty)
1681 fprintf(fout, "lxc.tty = %d\n", c->tty);
1682 if (c->pts)
1683 fprintf(fout, "lxc.pts = %d\n", c->pts);
1684 if (c->ttydir)
1685 fprintf(fout, "lxc.devttydir = %s\n", c->ttydir);
6ff05e18 1686 #if HAVE_SYS_PERSONALITY_H
72d0e1cb
SG
1687 switch(c->personality) {
1688 case PER_LINUX32: fprintf(fout, "lxc.arch = x86\n"); break;
1689 case PER_LINUX: fprintf(fout, "lxc.arch = x86_64\n"); break;
1690 default: break;
1691 }
6ff05e18 1692 #endif
1f530df6 1693#if HAVE_APPARMOR
72d0e1cb
SG
1694 if (c->aa_profile)
1695 fprintf(fout, "lxc.aa_profile = %s\n", c->aa_profile);
1f530df6 1696#endif
f3c7020a
SH
1697 if (c->loglevel != LXC_LOG_PRIORITY_NOTSET)
1698 fprintf(fout, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c->loglevel));
4a85ce2a
SH
1699 if (c->logfile)
1700 fprintf(fout, "lxc.logfile = %s\n", c->logfile);
72d0e1cb
SG
1701 lxc_list_for_each(it, &c->cgroup) {
1702 struct lxc_cgroup *cg = it->elem;
1703 fprintf(fout, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
1704 }
1705 if (c->utsname)
1706 fprintf(fout, "lxc.utsname = %s\n", c->utsname->nodename);
1707 lxc_list_for_each(it, &c->network) {
1708 struct lxc_netdev *n = it->elem;
1709 const char *t = lxc_net_type_to_str(n->type);
1710 struct lxc_list *it2;
1711 fprintf(fout, "lxc.network.type = %s\n", t ? t : "(invalid)");
1712 if (n->flags & IFF_UP)
1713 fprintf(fout, "lxc.network.flags = up\n");
1714 if (n->link)
1715 fprintf(fout, "lxc.network.link = %s\n", n->link);
1716 if (n->name)
1717 fprintf(fout, "lxc.network.name = %s\n", n->name);
1718 if (n->type == LXC_NET_MACVLAN) {
1719 const char *mode;
1720 switch (n->priv.macvlan_attr.mode) {
1721 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
1722 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
1723 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
1724 default: mode = "(invalid)"; break;
1725 }
1726 fprintf(fout, "lxc.network.macvlan.mode = %s\n", mode);
1727 } else if (n->type == LXC_NET_VETH) {
1728 if (n->priv.veth_attr.pair)
1729 fprintf(fout, "lxc.network.veth.pair = %s\n",
1730 n->priv.veth_attr.pair);
1731 } else if (n->type == LXC_NET_VLAN) {
1732 fprintf(fout, "lxc.network.vlan.id = %d\n", n->priv.vlan_attr.vid);
1733 }
1734 if (n->upscript)
1735 fprintf(fout, "lxc.network.script.up = %s\n", n->upscript);
1736 if (n->hwaddr)
1737 fprintf(fout, "lxc.network.hwaddr = %s\n", n->hwaddr);
1738 if (n->mtu)
1739 fprintf(fout, "lxc.network.mtu = %s\n", n->mtu);
1740 if (n->ipv4_gateway_auto)
1741 fprintf(fout, "lxc.network.ipv4.gateway = auto\n");
1742 else if (n->ipv4_gateway) {
1743 char buf[INET_ADDRSTRLEN];
1744 inet_ntop(AF_INET, n->ipv4_gateway, buf, sizeof(buf));
1745 fprintf(fout, "lxc.network.ipv4.gateway = %s\n", buf);
1746 }
1747 lxc_list_for_each(it2, &n->ipv4) {
1748 struct lxc_inetdev *i = it2->elem;
1749 char buf[INET_ADDRSTRLEN];
1750 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
1751 fprintf(fout, "lxc.network.ipv4 = %s\n", buf);
1752 }
1753 if (n->ipv6_gateway_auto)
1754 fprintf(fout, "lxc.network.ipv6.gateway = auto\n");
1755 else if (n->ipv6_gateway) {
1756 char buf[INET6_ADDRSTRLEN];
1757 inet_ntop(AF_INET6, n->ipv6_gateway, buf, sizeof(buf));
1758 fprintf(fout, "lxc.network.ipv6.gateway = %s\n", buf);
1759 }
1760 lxc_list_for_each(it2, &n->ipv6) {
1761 struct lxc_inet6dev *i = it2->elem;
1762 char buf[INET6_ADDRSTRLEN];
1763 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
1764 fprintf(fout, "lxc.network.ipv6 = %s\n", buf);
1765 }
1766 }
1767 lxc_list_for_each(it, &c->caps)
1768 fprintf(fout, "lxc.cap.drop = %s\n", (char *)it->elem);
1769 for (i=0; i<NUM_LXC_HOOKS; i++) {
1770 lxc_list_for_each(it, &c->hooks[i])
1771 fprintf(fout, "lxc.hook.%s = %s\n",
1772 lxchook_names[i], (char *)it->elem);
1773 }
1774 if (c->console.path)
1775 fprintf(fout, "lxc.console = %s\n", c->console.path);
1776 if (c->rootfs.path)
1777 fprintf(fout, "lxc.rootfs = %s\n", c->rootfs.path);
1778 if (c->rootfs.mount && strcmp(c->rootfs.mount, LXCROOTFSMOUNT) != 0)
1779 fprintf(fout, "lxc.rootfs.mount = %s\n", c->rootfs.mount);
1780 if (c->rootfs.pivot)
1781 fprintf(fout, "lxc.pivotdir = %s\n", c->rootfs.pivot);
1782}