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