]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
Replace strdupa call by standard strdup
[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 #define _GNU_SOURCE
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <sys/stat.h>
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
38 #include "parse.h"
39 #include "config.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 #if HAVE_SYS_PERSONALITY_H
48 #include <sys/personality.h>
49 #endif
50
51 lxc_log_define(lxc_confile, lxc);
52
53 static int config_personality(const char *, const char *, struct lxc_conf *);
54 static int config_pts(const char *, const char *, struct lxc_conf *);
55 static int config_tty(const char *, const char *, struct lxc_conf *);
56 static int config_ttydir(const char *, const char *, struct lxc_conf *);
57 #if HAVE_APPARMOR
58 static int config_aa_profile(const char *, const char *, struct lxc_conf *);
59 #endif
60 static int config_cgroup(const char *, const char *, struct lxc_conf *);
61 static int config_loglevel(const char *, const char *, struct lxc_conf *);
62 static int config_logfile(const char *, const char *, struct lxc_conf *);
63 static int config_mount(const char *, const char *, struct lxc_conf *);
64 static int config_rootfs(const char *, const char *, struct lxc_conf *);
65 static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
66 static int config_pivotdir(const char *, const char *, struct lxc_conf *);
67 static int config_utsname(const char *, const char *, struct lxc_conf *);
68 static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
69 static int config_network_type(const char *, const char *, struct lxc_conf *);
70 static int config_network_flags(const char *, const char *, struct lxc_conf *);
71 static int config_network_link(const char *, const char *, struct lxc_conf *);
72 static int config_network_name(const char *, const char *, struct lxc_conf *);
73 static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
74 static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
75 static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
76 static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
77 static int config_network_mtu(const char *, const char *, struct lxc_conf *);
78 static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
79 static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
80 static int config_network_script(const char *, const char *, struct lxc_conf *);
81 static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
82 static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
83 static int config_cap_drop(const char *, const char *, struct lxc_conf *);
84 static int config_console(const char *, const char *, struct lxc_conf *);
85 static int config_seccomp(const char *, const char *, struct lxc_conf *);
86 static int config_includefile(const char *, const char *, struct lxc_conf *);
87 static int config_network_nic(const char *, const char *, struct lxc_conf *);
88 static int config_autodev(const char *, const char *, struct lxc_conf *);
89
90 static struct lxc_config_t config[] = {
91
92 { "lxc.arch", config_personality },
93 { "lxc.pts", config_pts },
94 { "lxc.tty", config_tty },
95 { "lxc.devttydir", config_ttydir },
96 #if HAVE_APPARMOR
97 { "lxc.aa_profile", config_aa_profile },
98 #endif
99 { "lxc.cgroup", config_cgroup },
100 { "lxc.loglevel", config_loglevel },
101 { "lxc.logfile", config_logfile },
102 { "lxc.mount", config_mount },
103 { "lxc.rootfs.mount", config_rootfs_mount },
104 { "lxc.rootfs", config_rootfs },
105 { "lxc.pivotdir", config_pivotdir },
106 { "lxc.utsname", config_utsname },
107 { "lxc.hook.pre-start", config_hook },
108 { "lxc.hook.pre-mount", config_hook },
109 { "lxc.hook.mount", config_hook },
110 { "lxc.hook.start", config_hook },
111 { "lxc.hook.post-stop", config_hook },
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 },
118 { "lxc.network.script.up", config_network_script },
119 { "lxc.network.script.down", config_network_script },
120 { "lxc.network.hwaddr", config_network_hwaddr },
121 { "lxc.network.mtu", config_network_mtu },
122 { "lxc.network.vlan.id", config_network_vlan_id },
123 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
124 { "lxc.network.ipv4", config_network_ipv4 },
125 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
126 { "lxc.network.ipv6", config_network_ipv6 },
127 /* config_network_nic must come after all other 'lxc.network.*' entries */
128 { "lxc.network.", config_network_nic },
129 { "lxc.cap.drop", config_cap_drop },
130 { "lxc.console", config_console },
131 { "lxc.seccomp", config_seccomp },
132 { "lxc.include", config_includefile },
133 { "lxc.autodev", config_autodev },
134 };
135
136 static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
137
138 extern struct lxc_config_t *lxc_getconfig(const char *key)
139 {
140 int i;
141
142 for (i = 0; i < config_size; i++)
143 if (!strncmp(config[i].name, key,
144 strlen(config[i].name)))
145 return &config[i];
146 return NULL;
147 }
148
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
161 int 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 */
184 static int config_network_nic(const char *key, const char *value,
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
214 out:
215 free(copy);
216 return ret;
217 }
218
219 static int config_network_type(const char *key, const char *value,
220 struct lxc_conf *lxc_conf)
221 {
222 struct lxc_list *network = &lxc_conf->network;
223 struct lxc_netdev *netdev;
224 struct lxc_list *list;
225
226 netdev = malloc(sizeof(*netdev));
227 if (!netdev) {
228 SYSERROR("failed to allocate memory");
229 return -1;
230 }
231
232 memset(netdev, 0, sizeof(*netdev));
233 lxc_list_init(&netdev->ipv4);
234 lxc_list_init(&netdev->ipv6);
235
236 list = malloc(sizeof(*list));
237 if (!list) {
238 SYSERROR("failed to allocate memory");
239 return -1;
240 }
241
242 lxc_list_init(list);
243 list->elem = netdev;
244
245 lxc_list_add_tail(network, list);
246
247 if (!strcmp(value, "veth"))
248 netdev->type = LXC_NET_VETH;
249 else if (!strcmp(value, "macvlan"))
250 netdev->type = LXC_NET_MACVLAN;
251 else if (!strcmp(value, "vlan"))
252 netdev->type = LXC_NET_VLAN;
253 else if (!strcmp(value, "phys"))
254 netdev->type = LXC_NET_PHYS;
255 else if (!strcmp(value, "empty"))
256 netdev->type = LXC_NET_EMPTY;
257 else {
258 ERROR("invalid network type %s", value);
259 return -1;
260 }
261 return 0;
262 }
263
264 static 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
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 */
280 static 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 */
296 static 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
313 extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
314 char *retv, int inlen)
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
356 static struct lxc_netdev *network_netdev(const char *key, const char *value,
357 struct lxc_list *network)
358 {
359 struct lxc_netdev *netdev = NULL;
360
361 if (lxc_list_empty(network)) {
362 ERROR("network is not created for '%s' = '%s' option",
363 key, value);
364 return NULL;
365 }
366
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
372 if (!netdev) {
373 ERROR("no network device defined for '%s' = '%s' option",
374 key, value);
375 return NULL;
376 }
377
378 return netdev;
379 }
380
381 static int network_ifname(char **valuep, const char *value)
382 {
383 if (strlen(value) >= IFNAMSIZ) {
384 ERROR("interface name '%s' too long (>%d)\n",
385 value, IFNAMSIZ - 1);
386 return -1;
387 }
388
389 *valuep = strdup(value);
390 if (!*valuep) {
391 ERROR("failed to dup string '%s'", value);
392 return -1;
393 }
394
395 return 0;
396 }
397
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
410 static int macvlan_mode(int *valuep, const char *value)
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
434 static int config_network_flags(const char *key, const char *value,
435 struct lxc_conf *lxc_conf)
436 {
437 struct lxc_netdev *netdev;
438
439 netdev = network_netdev(key, value, &lxc_conf->network);
440 if (!netdev)
441 return -1;
442
443 netdev->flags |= IFF_UP;
444
445 return 0;
446 }
447
448 static int config_network_link(const char *key, const char *value,
449 struct lxc_conf *lxc_conf)
450 {
451 struct lxc_netdev *netdev;
452
453 netdev = network_netdev(key, value, &lxc_conf->network);
454 if (!netdev)
455 return -1;
456
457 return network_ifname(&netdev->link, value);
458 }
459
460 static int config_network_name(const char *key, const char *value,
461 struct lxc_conf *lxc_conf)
462 {
463 struct lxc_netdev *netdev;
464
465 netdev = network_netdev(key, value, &lxc_conf->network);
466 if (!netdev)
467 return -1;
468
469 return network_ifname(&netdev->name, value);
470 }
471
472 static int config_network_veth_pair(const char *key, const char *value,
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
484 static int config_network_macvlan_mode(const char *key, const char *value,
485 struct lxc_conf *lxc_conf)
486 {
487 struct lxc_netdev *netdev;
488
489 netdev = network_netdev(key, value, &lxc_conf->network);
490 if (!netdev)
491 return -1;
492
493 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
494 }
495
496 static int config_network_hwaddr(const char *key, const char *value,
497 struct lxc_conf *lxc_conf)
498 {
499 struct lxc_netdev *netdev;
500 char *hwaddr;
501
502 netdev = network_netdev(key, value, &lxc_conf->network);
503 if (!netdev)
504 return -1;
505
506 hwaddr = strdup(value);
507 if (!hwaddr) {
508 SYSERROR("failed to dup string '%s'", value);
509 return -1;
510 }
511
512 if (netdev->hwaddr)
513 free(netdev->hwaddr);
514 netdev->hwaddr = hwaddr;
515 return 0;
516 }
517
518 static int config_network_vlan_id(const char *key, const char *value,
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
527 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
528 return -1;
529
530 return 0;
531 }
532
533 static int config_network_mtu(const char *key, const char *value,
534 struct lxc_conf *lxc_conf)
535 {
536 struct lxc_netdev *netdev;
537 char *mtu;
538
539 netdev = network_netdev(key, value, &lxc_conf->network);
540 if (!netdev)
541 return -1;
542
543 mtu = strdup(value);
544 if (!mtu) {
545 SYSERROR("failed to dup string '%s'", value);
546 return -1;
547 }
548
549 if (netdev->mtu)
550 free(netdev->mtu);
551 netdev->mtu = mtu;
552 return 0;
553 }
554
555 static int config_network_ipv4(const char *key, const char *value,
556 struct lxc_conf *lxc_conf)
557 {
558 struct lxc_netdev *netdev;
559 struct lxc_inetdev *inetdev;
560 struct lxc_list *list;
561 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
562
563 netdev = network_netdev(key, value, &lxc_conf->network);
564 if (!netdev)
565 return -1;
566
567 inetdev = malloc(sizeof(*inetdev));
568 if (!inetdev) {
569 SYSERROR("failed to allocate ipv4 address");
570 return -1;
571 }
572 memset(inetdev, 0, sizeof(*inetdev));
573
574 list = malloc(sizeof(*list));
575 if (!list) {
576 SYSERROR("failed to allocate memory");
577 return -1;
578 }
579
580 lxc_list_init(list);
581 list->elem = inetdev;
582
583 addr = strdup(value);
584 if (!addr) {
585 ERROR("no address specified");
586 return -1;
587 }
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
601 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
602 SYSERROR("invalid ipv4 address: %s", value);
603 free(addr);
604 return -1;
605 }
606
607 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
608 SYSERROR("invalid ipv4 broadcast address: %s", value);
609 free(addr);
610 return -1;
611 }
612
613 /* no prefix specified, determine it from the network class */
614 inetdev->prefix = prefix ? atoi(prefix) :
615 config_ip_prefix(&inetdev->addr);
616
617 /* if no broadcast address, let compute one from the
618 * prefix and address
619 */
620 if (!bcast) {
621 inetdev->bcast.s_addr = inetdev->addr.s_addr;
622 inetdev->bcast.s_addr |=
623 htonl(INADDR_BROADCAST >> inetdev->prefix);
624 }
625
626 lxc_list_add(&netdev->ipv4, list);
627
628 free(addr);
629 return 0;
630 }
631
632 static int config_network_ipv4_gateway(const char *key, const char *value,
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
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;
664 }
665
666 return 0;
667 }
668
669 static int config_network_ipv6(const char *key, const char *value,
670 struct lxc_conf *lxc_conf)
671 {
672 struct lxc_netdev *netdev;
673 struct lxc_inet6dev *inet6dev;
674 struct lxc_list *list;
675 char *slash,*valdup;
676 char *netmask;
677
678 netdev = network_netdev(key, value, &lxc_conf->network);
679 if (!netdev)
680 return -1;
681
682 inet6dev = malloc(sizeof(*inet6dev));
683 if (!inet6dev) {
684 SYSERROR("failed to allocate ipv6 address");
685 return -1;
686 }
687 memset(inet6dev, 0, sizeof(*inet6dev));
688
689 list = malloc(sizeof(*list));
690 if (!list) {
691 SYSERROR("failed to allocate memory");
692 return -1;
693 }
694
695 lxc_list_init(list);
696 list->elem = inet6dev;
697
698 valdup = strdup(value);
699 if (!valdup) {
700 ERROR("no address specified");
701 return -1;
702 }
703
704 inet6dev->prefix = 64;
705 slash = strstr(valdup, "/");
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)) {
713 SYSERROR("invalid ipv6 address: %s", value);
714 free(valdup);
715 return -1;
716 }
717
718 lxc_list_add(&netdev->ipv6, list);
719
720 free(valdup);
721 return 0;
722 }
723
724 static int config_network_ipv6_gateway(const char *key, const char *value,
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
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;
756 }
757
758 return 0;
759 }
760
761 static int config_network_script(const char *key, const char *value,
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 }
775 if (strstr(key, "script.up") != NULL) {
776 netdev->upscript = copy;
777 return 0;
778 }
779 if (strcmp(key, "lxc.network.script.down") == 0) {
780 netdev->downscript = copy;
781 return 0;
782 }
783 SYSERROR("Unknown key: %s", key);
784 free(copy);
785 return -1;
786 }
787
788 static 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
802 static int config_seccomp(const char *key, const char *value,
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
817 if (lxc_conf->seccomp)
818 free(lxc_conf->seccomp);
819 lxc_conf->seccomp = path;
820
821 return 0;
822 }
823
824 static int config_hook(const char *key, const char *value,
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);
834 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
835 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
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
847 static int config_personality(const char *key, const const char *value,
848 struct lxc_conf *lxc_conf)
849 {
850 signed long personality = lxc_config_parse_arch(value);
851
852 if (personality >= 0)
853 lxc_conf->personality = personality;
854 else
855 WARN("unsupported personality '%s'", value);
856
857 return 0;
858 }
859
860 static int config_pts(const char *key, const char *value,
861 struct lxc_conf *lxc_conf)
862 {
863 int maxpts = atoi(value);
864
865 lxc_conf->pts = maxpts;
866
867 return 0;
868 }
869
870 static int config_tty(const char *key, const char *value,
871 struct lxc_conf *lxc_conf)
872 {
873 int nbtty = atoi(value);
874
875 lxc_conf->tty = nbtty;
876
877 return 0;
878 }
879
880 static int config_ttydir(const char *key, const char *value,
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
893 if (lxc_conf->ttydir)
894 free(lxc_conf->ttydir);
895 lxc_conf->ttydir = path;
896
897 return 0;
898 }
899
900 #if HAVE_APPARMOR
901 static int config_aa_profile(const char *key, const char *value,
902 struct lxc_conf *lxc_conf)
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
914 if (lxc_conf->aa_profile)
915 free(lxc_conf->aa_profile);
916 lxc_conf->aa_profile = path;
917
918 return 0;
919 }
920 #endif
921
922 static 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
954 static 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
967 static int config_autodev(const char *key, const char *value,
968 struct lxc_conf *lxc_conf)
969 {
970 int v = atoi(value);
971
972 lxc_conf->autodev = v;
973
974 return 0;
975 }
976
977 static int config_cgroup(const char *key, const char *value,
978 struct lxc_conf *lxc_conf)
979 {
980 char *token = "lxc.cgroup.";
981 char *subkey;
982 struct lxc_list *cglist = NULL;
983 struct lxc_cgroup *cgelem = NULL;
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;
995
996 subkey += strlen(token);
997
998 cglist = malloc(sizeof(*cglist));
999 if (!cglist)
1000 goto out;
1001
1002 cgelem = malloc(sizeof(*cgelem));
1003 if (!cgelem)
1004 goto out;
1005 memset(cgelem, 0, sizeof(*cgelem));
1006
1007 cgelem->subsystem = strdup(subkey);
1008 cgelem->value = strdup(value);
1009
1010 if (!cgelem->subsystem || !cgelem->value)
1011 goto out;
1012
1013 cglist->elem = cgelem;
1014
1015 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
1016
1017 return 0;
1018
1019 out:
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;
1034 }
1035
1036 static int config_path_item(const char *key, const char *value,
1037 struct lxc_conf *lxc_conf, char **conf_item)
1038 {
1039 char *valdup;
1040 if (strlen(value) >= MAXPATHLEN) {
1041 ERROR("%s path is too long", value);
1042 return -1;
1043 }
1044
1045 valdup = strdup(value);
1046 if (!valdup) {
1047 SYSERROR("failed to duplicate string %s", value);
1048 return -1;
1049 }
1050 if (*conf_item)
1051 free(*conf_item);
1052 *conf_item = valdup;
1053
1054 return 0;
1055 }
1056
1057 static 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
1063 static int config_mount(const char *key, const char *value,
1064 struct lxc_conf *lxc_conf)
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);
1091 if (!mntelem)
1092 return -1;
1093 mntlist->elem = mntelem;
1094
1095 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1096
1097 return 0;
1098 }
1099
1100 static int config_cap_drop(const char *key, const char *value,
1101 struct lxc_conf *lxc_conf)
1102 {
1103 char *dropcaps, *dropptr, *sptr, *token;
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 */
1118 for (dropptr = dropcaps;;dropptr = NULL) {
1119 token = strtok_r(dropptr, " \t", &sptr);
1120 if (!token) {
1121 ret = 0;
1122 break;
1123 }
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
1146 static int config_console(const char *key, const char *value,
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
1157 if (lxc_conf->console.path)
1158 free(lxc_conf->console.path);
1159 lxc_conf->console.path = path;
1160
1161 return 0;
1162 }
1163
1164 static int config_includefile(const char *key, const char *value,
1165 struct lxc_conf *lxc_conf)
1166 {
1167 return lxc_config_read(value, lxc_conf);
1168 }
1169
1170 static int config_rootfs(const char *key, const char *value,
1171 struct lxc_conf *lxc_conf)
1172 {
1173 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.path);
1174 }
1175
1176 static int config_rootfs_mount(const char *key, const char *value,
1177 struct lxc_conf *lxc_conf)
1178 {
1179 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.mount);
1180 }
1181
1182 static int config_pivotdir(const char *key, const char *value,
1183 struct lxc_conf *lxc_conf)
1184 {
1185 return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.pivot);
1186 }
1187
1188 static int config_utsname(const char *key, const char *value,
1189 struct lxc_conf *lxc_conf)
1190 {
1191 struct utsname *utsname;
1192
1193 utsname = malloc(sizeof(*utsname));
1194 if (!utsname) {
1195 SYSERROR("failed to allocate memory");
1196 return -1;
1197 }
1198
1199 if (strlen(value) >= sizeof(utsname->nodename)) {
1200 ERROR("node name '%s' is too long",
1201 utsname->nodename);
1202 return -1;
1203 }
1204
1205 strcpy(utsname->nodename, value);
1206 if (lxc_conf->utsname)
1207 free(lxc_conf->utsname);
1208 lxc_conf->utsname = utsname;
1209
1210 return 0;
1211 }
1212
1213 static int parse_line(char *buffer, void *data)
1214 {
1215 struct lxc_config_t *config;
1216 char *line, *linep;
1217 char *dot;
1218 char *key;
1219 char *value;
1220 int ret = 0;
1221
1222 if (lxc_is_line_empty(buffer))
1223 return 0;
1224
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
1228 */
1229 linep = line = strdup(buffer);
1230 if (!line) {
1231 SYSERROR("failed to allocate memory for '%s'", buffer);
1232 return -1;
1233 }
1234
1235 line += lxc_char_left_gc(line, strlen(line));
1236
1237 /* martian option - ignoring it, the commented lines beginning by '#'
1238 * fall in this case
1239 */
1240 if (strncmp(line, "lxc.", 4))
1241 goto out;
1242
1243 ret = -1;
1244
1245 dot = strstr(line, "=");
1246 if (!dot) {
1247 ERROR("invalid configuration line: %s", line);
1248 goto out;
1249 }
1250
1251 *dot = '\0';
1252 value = dot + 1;
1253
1254 key = line;
1255 key[lxc_char_right_gc(key, strlen(key))] = '\0';
1256
1257 value += lxc_char_left_gc(value, strlen(value));
1258 value[lxc_char_right_gc(value, strlen(value))] = '\0';
1259
1260 config = lxc_getconfig(key);
1261 if (!config) {
1262 ERROR("unknown key %s", key);
1263 goto out;
1264 }
1265
1266 ret = config->cb(key, value, data);
1267
1268 out:
1269 free(linep);
1270 return ret;
1271 }
1272
1273 int lxc_config_readline(char *buffer, struct lxc_conf *conf)
1274 {
1275 return parse_line(buffer, conf);
1276 }
1277
1278 int lxc_config_read(const char *file, struct lxc_conf *conf)
1279 {
1280 return lxc_file_for_each_line(file, parse_line, conf);
1281 }
1282
1283 int 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
1296 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
1297 {
1298 struct lxc_list *it,*next;
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
1307 lxc_list_for_each_safe(it, defines, next) {
1308 lxc_list_del(it);
1309 free(it);
1310 }
1311
1312 return ret;
1313 }
1314
1315 signed long lxc_config_parse_arch(const char *arch)
1316 {
1317 #if HAVE_SYS_PERSONALITY_H
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 }
1335 #endif
1336
1337 return -1;
1338 }
1339
1340 static 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
1349 static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
1350 {
1351 int fulllen = 0;
1352
1353 if (!retv)
1354 inlen = 0;
1355 else
1356 memset(retv, 0, inlen);
1357
1358 #if HAVE_SYS_PERSONALITY_H
1359 int len = 0;
1360
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 }
1366 #endif
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 */
1380 static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
1381 const char *key)
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
1406 static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
1407 const char *key)
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
1442 static 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
1458 static 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 */
1482 static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
1483 const char *key)
1484 {
1485 char *p1;
1486 int len, fulllen = 0;
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
1575 static 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
1593 int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
1594 int inlen)
1595 {
1596 const char *v = NULL;
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);
1610 #if HAVE_APPARMOR
1611 else if (strcmp(key, "lxc.aa_profile") == 0)
1612 v = c->aa_profile;
1613 #endif
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);
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)
1623 v = c->utsname ? c->utsname->nodename : NULL;
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
1649 int lxc_clear_config_item(struct lxc_conf *c, const char *key)
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);
1661 else if (strncmp(key, "lxc.hook", 8) == 0)
1662 return lxc_clear_hooks(c, key);
1663
1664 return -1;
1665 }
1666
1667 /*
1668 * writing out a confile.
1669 */
1670 void 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);
1686 #if HAVE_SYS_PERSONALITY_H
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 }
1692 #endif
1693 #if HAVE_APPARMOR
1694 if (c->aa_profile)
1695 fprintf(fout, "lxc.aa_profile = %s\n", c->aa_profile);
1696 #endif
1697 if (c->loglevel != LXC_LOG_PRIORITY_NOTSET)
1698 fprintf(fout, "lxc.loglevel = %s\n", lxc_log_priority_to_string(c->loglevel));
1699 if (c->logfile)
1700 fprintf(fout, "lxc.logfile = %s\n", c->logfile);
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 }