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