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