]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
Makefile.am: use right .h file name for seccomp
[mirror_lxc.git] / src / lxc / confile.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <pty.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/utsname.h>
34 #include <sys/personality.h>
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
37 #include <net/if.h>
38
39 #include "parse.h"
40 #include "confile.h"
41 #include "utils.h"
42
43 #include <lxc/log.h>
44 #include <lxc/conf.h>
45
46 lxc_log_define(lxc_confile, lxc);
47
48 static int config_personality(const char *, char *, struct lxc_conf *);
49 static int config_pts(const char *, char *, struct lxc_conf *);
50 static int config_tty(const char *, char *, struct lxc_conf *);
51 static int config_ttydir(const char *, char *, struct lxc_conf *);
52 #if HAVE_APPARMOR
53 static int config_aa_profile(const char *, char *, struct lxc_conf *);
54 #endif
55 static int config_cgroup(const char *, char *, struct lxc_conf *);
56 static int config_mount(const char *, char *, struct lxc_conf *);
57 static int config_rootfs(const char *, char *, struct lxc_conf *);
58 static int config_rootfs_mount(const char *, char *, struct lxc_conf *);
59 static int config_pivotdir(const char *, char *, struct lxc_conf *);
60 static int config_utsname(const char *, char *, struct lxc_conf *);
61 static int config_hook(const char *key, char *value, struct lxc_conf *lxc_conf);
62 static int config_network_type(const char *, char *, struct lxc_conf *);
63 static int config_network_flags(const char *, char *, struct lxc_conf *);
64 static int config_network_link(const char *, char *, struct lxc_conf *);
65 static int config_network_name(const char *, char *, struct lxc_conf *);
66 static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
67 static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
68 static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
69 static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
70 static int config_network_mtu(const char *, char *, struct lxc_conf *);
71 static int config_network_ipv4(const char *, char *, struct lxc_conf *);
72 static int config_network_ipv4_gateway(const char *, char *, struct lxc_conf *);
73 static int config_network_script(const char *, char *, struct lxc_conf *);
74 static int config_network_ipv6(const char *, char *, struct lxc_conf *);
75 static int config_network_ipv6_gateway(const char *, char *, struct lxc_conf *);
76 static int config_cap_drop(const char *, char *, struct lxc_conf *);
77 static int config_console(const char *, char *, struct lxc_conf *);
78 static int config_seccomp(const char *, char *, struct lxc_conf *);
79 static int config_includefile(const char *, char *, struct lxc_conf *);
80
81 typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
82
83 struct config {
84 char *name;
85 config_cb cb;
86 };
87
88 static struct config config[] = {
89
90 { "lxc.arch", config_personality },
91 { "lxc.pts", config_pts },
92 { "lxc.tty", config_tty },
93 { "lxc.devttydir", config_ttydir },
94 #if HAVE_APPARMOR
95 { "lxc.aa_profile", config_aa_profile },
96 #endif
97 { "lxc.cgroup", config_cgroup },
98 { "lxc.mount", config_mount },
99 { "lxc.rootfs.mount", config_rootfs_mount },
100 { "lxc.rootfs", config_rootfs },
101 { "lxc.pivotdir", config_pivotdir },
102 { "lxc.utsname", config_utsname },
103 { "lxc.hook.pre-start", config_hook },
104 { "lxc.hook.mount", config_hook },
105 { "lxc.hook.start", config_hook },
106 { "lxc.hook.post-stop", config_hook },
107 { "lxc.network.type", config_network_type },
108 { "lxc.network.flags", config_network_flags },
109 { "lxc.network.link", config_network_link },
110 { "lxc.network.name", config_network_name },
111 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
112 { "lxc.network.veth.pair", config_network_veth_pair },
113 { "lxc.network.script.up", config_network_script },
114 { "lxc.network.hwaddr", config_network_hwaddr },
115 { "lxc.network.mtu", config_network_mtu },
116 { "lxc.network.vlan.id", config_network_vlan_id },
117 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
118 { "lxc.network.ipv4", config_network_ipv4 },
119 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
120 { "lxc.network.ipv6", config_network_ipv6 },
121 { "lxc.cap.drop", config_cap_drop },
122 { "lxc.console", config_console },
123 { "lxc.seccomp", config_seccomp },
124 { "lxc.include", config_includefile },
125 };
126
127 static const size_t config_size = sizeof(config)/sizeof(struct config);
128
129 static struct config *getconfig(const char *key)
130 {
131 int i;
132
133 for (i = 0; i < config_size; i++)
134 if (!strncmp(config[i].name, key,
135 strlen(config[i].name)))
136 return &config[i];
137 return NULL;
138 }
139
140 static int config_network_type(const char *key, char *value,
141 struct lxc_conf *lxc_conf)
142 {
143 struct lxc_list *network = &lxc_conf->network;
144 struct lxc_netdev *netdev;
145 struct lxc_list *list;
146
147 netdev = malloc(sizeof(*netdev));
148 if (!netdev) {
149 SYSERROR("failed to allocate memory");
150 return -1;
151 }
152
153 memset(netdev, 0, sizeof(*netdev));
154 lxc_list_init(&netdev->ipv4);
155 lxc_list_init(&netdev->ipv6);
156
157 list = malloc(sizeof(*list));
158 if (!list) {
159 SYSERROR("failed to allocate memory");
160 return -1;
161 }
162
163 lxc_list_init(list);
164 list->elem = netdev;
165
166 lxc_list_add_tail(network, list);
167
168 if (!strcmp(value, "veth"))
169 netdev->type = LXC_NET_VETH;
170 else if (!strcmp(value, "macvlan"))
171 netdev->type = LXC_NET_MACVLAN;
172 else if (!strcmp(value, "vlan"))
173 netdev->type = LXC_NET_VLAN;
174 else if (!strcmp(value, "phys"))
175 netdev->type = LXC_NET_PHYS;
176 else if (!strcmp(value, "empty"))
177 netdev->type = LXC_NET_EMPTY;
178 else {
179 ERROR("invalid network type %s", value);
180 return -1;
181 }
182 return 0;
183 }
184
185 static int config_ip_prefix(struct in_addr *addr)
186 {
187 if (IN_CLASSA(addr->s_addr))
188 return 32 - IN_CLASSA_NSHIFT;
189 if (IN_CLASSB(addr->s_addr))
190 return 32 - IN_CLASSB_NSHIFT;
191 if (IN_CLASSC(addr->s_addr))
192 return 32 - IN_CLASSC_NSHIFT;
193
194 return 0;
195 }
196
197 static struct lxc_netdev *network_netdev(const char *key, const char *value,
198 struct lxc_list *network)
199 {
200 struct lxc_netdev *netdev;
201
202 if (lxc_list_empty(network)) {
203 ERROR("network is not created for '%s' = '%s' option",
204 key, value);
205 return NULL;
206 }
207
208 netdev = lxc_list_last_elem(network);
209 if (!netdev) {
210 ERROR("no network device defined for '%s' = '%s' option",
211 key, value);
212 return NULL;
213 }
214
215 return netdev;
216 }
217
218 static int network_ifname(char **valuep, char *value)
219 {
220 if (strlen(value) >= IFNAMSIZ) {
221 ERROR("interface name '%s' too long (>%d)\n",
222 value, IFNAMSIZ - 1);
223 return -1;
224 }
225
226 *valuep = strdup(value);
227 if (!*valuep) {
228 ERROR("failed to dup string '%s'", value);
229 return -1;
230 }
231
232 return 0;
233 }
234
235 #ifndef MACVLAN_MODE_PRIVATE
236 # define MACVLAN_MODE_PRIVATE 1
237 #endif
238
239 #ifndef MACVLAN_MODE_VEPA
240 # define MACVLAN_MODE_VEPA 2
241 #endif
242
243 #ifndef MACVLAN_MODE_BRIDGE
244 # define MACVLAN_MODE_BRIDGE 4
245 #endif
246
247 static int macvlan_mode(int *valuep, char *value)
248 {
249 struct mc_mode {
250 char *name;
251 int mode;
252 } m[] = {
253 { "private", MACVLAN_MODE_PRIVATE },
254 { "vepa", MACVLAN_MODE_VEPA },
255 { "bridge", MACVLAN_MODE_BRIDGE },
256 };
257
258 int i;
259
260 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
261 if (strcmp(m[i].name, value))
262 continue;
263
264 *valuep = m[i].mode;
265 return 0;
266 }
267
268 return -1;
269 }
270
271 static int config_network_flags(const char *key, char *value,
272 struct lxc_conf *lxc_conf)
273 {
274 struct lxc_netdev *netdev;
275
276 netdev = network_netdev(key, value, &lxc_conf->network);
277 if (!netdev)
278 return -1;
279
280 netdev->flags |= IFF_UP;
281
282 return 0;
283 }
284
285 static int config_network_link(const char *key, char *value,
286 struct lxc_conf *lxc_conf)
287 {
288 struct lxc_netdev *netdev;
289
290 netdev = network_netdev(key, value, &lxc_conf->network);
291 if (!netdev)
292 return -1;
293
294 return network_ifname(&netdev->link, value);
295 }
296
297 static int config_network_name(const char *key, char *value,
298 struct lxc_conf *lxc_conf)
299 {
300 struct lxc_netdev *netdev;
301
302 netdev = network_netdev(key, value, &lxc_conf->network);
303 if (!netdev)
304 return -1;
305
306 return network_ifname(&netdev->name, value);
307 }
308
309 static int config_network_veth_pair(const char *key, char *value,
310 struct lxc_conf *lxc_conf)
311 {
312 struct lxc_netdev *netdev;
313
314 netdev = network_netdev(key, value, &lxc_conf->network);
315 if (!netdev)
316 return -1;
317
318 return network_ifname(&netdev->priv.veth_attr.pair, value);
319 }
320
321 static int config_network_macvlan_mode(const char *key, char *value,
322 struct lxc_conf *lxc_conf)
323 {
324 struct lxc_netdev *netdev;
325
326 netdev = network_netdev(key, value, &lxc_conf->network);
327 if (!netdev)
328 return -1;
329
330 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
331 }
332
333 static int config_network_hwaddr(const char *key, char *value,
334 struct lxc_conf *lxc_conf)
335 {
336 struct lxc_netdev *netdev;
337
338 netdev = network_netdev(key, value, &lxc_conf->network);
339 if (!netdev)
340 return -1;
341
342 netdev->hwaddr = strdup(value);
343 if (!netdev->hwaddr) {
344 SYSERROR("failed to dup string '%s'", value);
345 return -1;
346 }
347
348 return 0;
349 }
350
351 static int config_network_vlan_id(const char *key, char *value,
352 struct lxc_conf *lxc_conf)
353 {
354 struct lxc_netdev *netdev;
355
356 netdev = network_netdev(key, value, &lxc_conf->network);
357 if (!netdev)
358 return -1;
359
360 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
361 return -1;
362
363 return 0;
364 }
365
366 static int config_network_mtu(const char *key, char *value,
367 struct lxc_conf *lxc_conf)
368 {
369 struct lxc_netdev *netdev;
370
371 netdev = network_netdev(key, value, &lxc_conf->network);
372 if (!netdev)
373 return -1;
374
375 netdev->mtu = strdup(value);
376 if (!netdev->mtu) {
377 SYSERROR("failed to dup string '%s'", value);
378 return -1;
379 }
380
381 return 0;
382 }
383
384 static int config_network_ipv4(const char *key, char *value,
385 struct lxc_conf *lxc_conf)
386 {
387 struct lxc_netdev *netdev;
388 struct lxc_inetdev *inetdev;
389 struct lxc_list *list;
390 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
391
392 netdev = network_netdev(key, value, &lxc_conf->network);
393 if (!netdev)
394 return -1;
395
396 inetdev = malloc(sizeof(*inetdev));
397 if (!inetdev) {
398 SYSERROR("failed to allocate ipv4 address");
399 return -1;
400 }
401 memset(inetdev, 0, sizeof(*inetdev));
402
403 list = malloc(sizeof(*list));
404 if (!list) {
405 SYSERROR("failed to allocate memory");
406 return -1;
407 }
408
409 lxc_list_init(list);
410 list->elem = inetdev;
411
412 addr = value;
413
414 cursor = strstr(addr, " ");
415 if (cursor) {
416 *cursor = '\0';
417 bcast = cursor + 1;
418 }
419
420 slash = strstr(addr, "/");
421 if (slash) {
422 *slash = '\0';
423 prefix = slash + 1;
424 }
425
426 if (!addr) {
427 ERROR("no address specified");
428 return -1;
429 }
430
431 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
432 SYSERROR("invalid ipv4 address: %s", value);
433 return -1;
434 }
435
436 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
437 SYSERROR("invalid ipv4 broadcast address: %s", value);
438 return -1;
439 }
440
441 /* no prefix specified, determine it from the network class */
442 inetdev->prefix = prefix ? atoi(prefix) :
443 config_ip_prefix(&inetdev->addr);
444
445 /* if no broadcast address, let compute one from the
446 * prefix and address
447 */
448 if (!bcast) {
449 inetdev->bcast.s_addr = inetdev->addr.s_addr;
450 inetdev->bcast.s_addr |=
451 htonl(INADDR_BROADCAST >> inetdev->prefix);
452 }
453
454 lxc_list_add(&netdev->ipv4, list);
455
456 return 0;
457 }
458
459 static int config_network_ipv4_gateway(const char *key, char *value,
460 struct lxc_conf *lxc_conf)
461 {
462 struct lxc_netdev *netdev;
463 struct in_addr *gw;
464
465 netdev = network_netdev(key, value, &lxc_conf->network);
466 if (!netdev)
467 return -1;
468
469 gw = malloc(sizeof(*gw));
470 if (!gw) {
471 SYSERROR("failed to allocate ipv4 gateway address");
472 return -1;
473 }
474
475 if (!value) {
476 ERROR("no ipv4 gateway address specified");
477 return -1;
478 }
479
480 if (!strcmp(value, "auto")) {
481 netdev->ipv4_gateway = NULL;
482 netdev->ipv4_gateway_auto = true;
483 } else {
484 if (!inet_pton(AF_INET, value, gw)) {
485 SYSERROR("invalid ipv4 gateway address: %s", value);
486 return -1;
487 }
488
489 netdev->ipv4_gateway = gw;
490 netdev->ipv4_gateway_auto = false;
491 }
492
493 return 0;
494 }
495
496 static int config_network_ipv6(const char *key, char *value,
497 struct lxc_conf *lxc_conf)
498 {
499 struct lxc_netdev *netdev;
500 struct lxc_inet6dev *inet6dev;
501 struct lxc_list *list;
502 char *slash;
503 char *netmask;
504
505 netdev = network_netdev(key, value, &lxc_conf->network);
506 if (!netdev)
507 return -1;
508
509 inet6dev = malloc(sizeof(*inet6dev));
510 if (!inet6dev) {
511 SYSERROR("failed to allocate ipv6 address");
512 return -1;
513 }
514 memset(inet6dev, 0, sizeof(*inet6dev));
515
516 list = malloc(sizeof(*list));
517 if (!list) {
518 SYSERROR("failed to allocate memory");
519 return -1;
520 }
521
522 lxc_list_init(list);
523 list->elem = inet6dev;
524
525 inet6dev->prefix = 64;
526 slash = strstr(value, "/");
527 if (slash) {
528 *slash = '\0';
529 netmask = slash + 1;
530 inet6dev->prefix = atoi(netmask);
531 }
532
533 if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
534 SYSERROR("invalid ipv6 address: %s", value);
535 return -1;
536 }
537
538 lxc_list_add(&netdev->ipv6, list);
539
540 return 0;
541 }
542
543 static int config_network_ipv6_gateway(const char *key, char *value,
544 struct lxc_conf *lxc_conf)
545 {
546 struct lxc_netdev *netdev;
547 struct in6_addr *gw;
548
549 netdev = network_netdev(key, value, &lxc_conf->network);
550 if (!netdev)
551 return -1;
552
553 gw = malloc(sizeof(*gw));
554 if (!gw) {
555 SYSERROR("failed to allocate ipv6 gateway address");
556 return -1;
557 }
558
559 if (!value) {
560 ERROR("no ipv6 gateway address specified");
561 return -1;
562 }
563
564 if (!strcmp(value, "auto")) {
565 netdev->ipv6_gateway = NULL;
566 netdev->ipv6_gateway_auto = true;
567 } else {
568 if (!inet_pton(AF_INET6, value, gw)) {
569 SYSERROR("invalid ipv6 gateway address: %s", value);
570 return -1;
571 }
572
573 netdev->ipv6_gateway = gw;
574 netdev->ipv6_gateway_auto = false;
575 }
576
577 return 0;
578 }
579
580 static int config_network_script(const char *key, char *value,
581 struct lxc_conf *lxc_conf)
582 {
583 struct lxc_netdev *netdev;
584
585 netdev = network_netdev(key, value, &lxc_conf->network);
586 if (!netdev)
587 return -1;
588
589 char *copy = strdup(value);
590 if (!copy) {
591 SYSERROR("failed to dup string '%s'", value);
592 return -1;
593 }
594 if (strcmp(key, "lxc.network.script.up") == 0) {
595 netdev->upscript = copy;
596 return 0;
597 }
598 SYSERROR("Unknown key: %s", key);
599 free(copy);
600 return -1;
601 }
602
603 static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
604 {
605 struct lxc_list *hooklist;
606
607 hooklist = malloc(sizeof(*hooklist));
608 if (!hooklist) {
609 free(hook);
610 return -1;
611 }
612 hooklist->elem = hook;
613 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
614 return 0;
615 }
616
617 static int config_seccomp(const char *key, char *value,
618 struct lxc_conf *lxc_conf)
619 {
620 char *path;
621
622 if (lxc_conf->seccomp) {
623 ERROR("seccomp already defined");
624 return -1;
625 }
626 path = strdup(value);
627 if (!path) {
628 SYSERROR("failed to strdup '%s': %m", value);
629 return -1;
630 }
631
632 lxc_conf->seccomp = path;
633
634 return 0;
635 }
636
637 static int config_hook(const char *key, char *value,
638 struct lxc_conf *lxc_conf)
639 {
640 char *copy = strdup(value);
641 if (!copy) {
642 SYSERROR("failed to dup string '%s'", value);
643 return -1;
644 }
645 if (strcmp(key, "lxc.hook.pre-start") == 0)
646 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
647 else if (strcmp(key, "lxc.hook.mount") == 0)
648 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
649 else if (strcmp(key, "lxc.hook.start") == 0)
650 return add_hook(lxc_conf, LXCHOOK_START, copy);
651 else if (strcmp(key, "lxc.hook.post-stop") == 0)
652 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
653 SYSERROR("Unknown key: %s", key);
654 free(copy);
655 return -1;
656 }
657
658 static int config_personality(const char *key, char *value,
659 struct lxc_conf *lxc_conf)
660 {
661 signed long personality = lxc_config_parse_arch(value);
662
663 if (personality >= 0)
664 lxc_conf->personality = personality;
665 else
666 WARN("unsupported personality '%s'", value);
667
668 return 0;
669 }
670
671 static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
672 {
673 int maxpts = atoi(value);
674
675 lxc_conf->pts = maxpts;
676
677 return 0;
678 }
679
680 static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
681 {
682 int nbtty = atoi(value);
683
684 lxc_conf->tty = nbtty;
685
686 return 0;
687 }
688
689 static int config_ttydir(const char *key, char *value,
690 struct lxc_conf *lxc_conf)
691 {
692 char *path;
693
694 if (!value || strlen(value) == 0)
695 return 0;
696 path = strdup(value);
697 if (!path) {
698 SYSERROR("failed to strdup '%s': %m", value);
699 return -1;
700 }
701
702 lxc_conf->ttydir = path;
703
704 return 0;
705 }
706
707 #if HAVE_APPARMOR
708 static int config_aa_profile(const char *key, char *value, struct lxc_conf *lxc_conf)
709 {
710 char *path;
711
712 if (!value || strlen(value) == 0)
713 return 0;
714 path = strdup(value);
715 if (!path) {
716 SYSERROR("failed to strdup '%s': %m", value);
717 return -1;
718 }
719
720 lxc_conf->aa_profile = path;
721
722 return 0;
723 }
724 #endif
725
726 static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
727 {
728 char *token = "lxc.cgroup.";
729 char *subkey;
730 struct lxc_list *cglist = NULL;
731 struct lxc_cgroup *cgelem = NULL;
732
733 subkey = strstr(key, token);
734
735 if (!subkey)
736 return -1;
737
738 if (!strlen(subkey))
739 return -1;
740
741 if (strlen(subkey) == strlen(token))
742 return -1;
743
744 subkey += strlen(token);
745
746 cglist = malloc(sizeof(*cglist));
747 if (!cglist)
748 goto out;
749
750 cgelem = malloc(sizeof(*cgelem));
751 if (!cgelem)
752 goto out;
753 memset(cgelem, 0, sizeof(*cgelem));
754
755 cgelem->subsystem = strdup(subkey);
756 cgelem->value = strdup(value);
757
758 if (!cgelem->subsystem || !cgelem->value)
759 goto out;
760
761 cglist->elem = cgelem;
762
763 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
764
765 return 0;
766
767 out:
768 if (cglist)
769 free(cglist);
770
771 if (cgelem) {
772 if (cgelem->subsystem)
773 free(cgelem->subsystem);
774
775 if (cgelem->value)
776 free(cgelem->value);
777
778 free(cgelem);
779 }
780
781 return -1;
782 }
783
784 static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
785 {
786 if (strlen(value) >= MAXPATHLEN) {
787 ERROR("%s path is too long", value);
788 return -1;
789 }
790
791 lxc_conf->fstab = strdup(value);
792 if (!lxc_conf->fstab) {
793 SYSERROR("failed to duplicate string %s", value);
794 return -1;
795 }
796
797 return 0;
798 }
799
800 static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
801 {
802 char *fstab_token = "lxc.mount";
803 char *token = "lxc.mount.entry";
804 char *subkey;
805 char *mntelem;
806 struct lxc_list *mntlist;
807
808 subkey = strstr(key, token);
809
810 if (!subkey) {
811 subkey = strstr(key, fstab_token);
812
813 if (!subkey)
814 return -1;
815
816 return config_fstab(key, value, lxc_conf);
817 }
818
819 if (!strlen(subkey))
820 return -1;
821
822 mntlist = malloc(sizeof(*mntlist));
823 if (!mntlist)
824 return -1;
825
826 mntelem = strdup(value);
827 if (!mntelem)
828 return -1;
829 mntlist->elem = mntelem;
830
831 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
832
833 return 0;
834 }
835
836 static int config_cap_drop(const char *key, char *value,
837 struct lxc_conf *lxc_conf)
838 {
839 char *dropcaps, *sptr, *token;
840 struct lxc_list *droplist;
841 int ret = -1;
842
843 if (!strlen(value))
844 return -1;
845
846 dropcaps = strdup(value);
847 if (!dropcaps) {
848 SYSERROR("failed to dup '%s'", value);
849 return -1;
850 }
851
852 /* in case several capability drop is specified in a single line
853 * split these caps in a single element for the list */
854 for (;;) {
855 token = strtok_r(dropcaps, " \t", &sptr);
856 if (!token) {
857 ret = 0;
858 break;
859 }
860 dropcaps = NULL;
861
862 droplist = malloc(sizeof(*droplist));
863 if (!droplist) {
864 SYSERROR("failed to allocate drop list");
865 break;
866 }
867
868 droplist->elem = strdup(token);
869 if (!droplist->elem) {
870 SYSERROR("failed to dup '%s'", token);
871 free(droplist);
872 break;
873 }
874
875 lxc_list_add_tail(&lxc_conf->caps, droplist);
876 }
877
878 free(dropcaps);
879
880 return ret;
881 }
882
883 static int config_console(const char *key, char *value,
884 struct lxc_conf *lxc_conf)
885 {
886 char *path;
887
888 path = strdup(value);
889 if (!path) {
890 SYSERROR("failed to strdup '%s': %m", value);
891 return -1;
892 }
893
894 lxc_conf->console.path = path;
895
896 return 0;
897 }
898
899 static int config_includefile(const char *key, char *value,
900 struct lxc_conf *lxc_conf)
901 {
902 return lxc_config_read(value, lxc_conf);
903 }
904
905 static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
906 {
907 if (strlen(value) >= MAXPATHLEN) {
908 ERROR("%s path is too long", value);
909 return -1;
910 }
911
912 lxc_conf->rootfs.path = strdup(value);
913 if (!lxc_conf->rootfs.path) {
914 SYSERROR("failed to duplicate string %s", value);
915 return -1;
916 }
917
918 return 0;
919 }
920
921 static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
922 {
923 if (strlen(value) >= MAXPATHLEN) {
924 ERROR("%s path is too long", value);
925 return -1;
926 }
927
928 lxc_conf->rootfs.mount = strdup(value);
929 if (!lxc_conf->rootfs.mount) {
930 SYSERROR("failed to duplicate string '%s'", value);
931 return -1;
932 }
933
934 return 0;
935 }
936
937 static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
938 {
939 if (strlen(value) >= MAXPATHLEN) {
940 ERROR("%s path is too long", value);
941 return -1;
942 }
943
944 lxc_conf->rootfs.pivot = strdup(value);
945 if (!lxc_conf->rootfs.pivot) {
946 SYSERROR("failed to duplicate string %s", value);
947 return -1;
948 }
949
950 return 0;
951 }
952
953 static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
954 {
955 struct utsname *utsname;
956
957 utsname = malloc(sizeof(*utsname));
958 if (!utsname) {
959 SYSERROR("failed to allocate memory");
960 return -1;
961 }
962
963 if (strlen(value) >= sizeof(utsname->nodename)) {
964 ERROR("node name '%s' is too long",
965 utsname->nodename);
966 return -1;
967 }
968
969 strcpy(utsname->nodename, value);
970 lxc_conf->utsname = utsname;
971
972 return 0;
973 }
974
975 static int parse_line(char *buffer, void *data)
976 {
977 struct config *config;
978 char *line, *linep;
979 char *dot;
980 char *key;
981 char *value;
982 int ret = 0;
983
984 if (lxc_is_line_empty(buffer))
985 return 0;
986
987 /* we have to dup the buffer otherwise, at the re-exec for
988 * reboot we modified the original string on the stack by
989 * replacing '=' by '\0' below
990 */
991 linep = line = strdup(buffer);
992 if (!line) {
993 SYSERROR("failed to allocate memory for '%s'", buffer);
994 return -1;
995 }
996
997 line += lxc_char_left_gc(line, strlen(line));
998
999 /* martian option - ignoring it, the commented lines beginning by '#'
1000 * fall in this case
1001 */
1002 if (strncmp(line, "lxc.", 4))
1003 goto out;
1004
1005 ret = -1;
1006
1007 dot = strstr(line, "=");
1008 if (!dot) {
1009 ERROR("invalid configuration line: %s", line);
1010 goto out;
1011 }
1012
1013 *dot = '\0';
1014 value = dot + 1;
1015
1016 key = line;
1017 key[lxc_char_right_gc(key, strlen(key))] = '\0';
1018
1019 value += lxc_char_left_gc(value, strlen(value));
1020 value[lxc_char_right_gc(value, strlen(value))] = '\0';
1021
1022 config = getconfig(key);
1023 if (!config) {
1024 ERROR("unknown key %s", key);
1025 goto out;
1026 }
1027
1028 ret = config->cb(key, value, data);
1029
1030 out:
1031 free(linep);
1032 return ret;
1033 }
1034
1035 int lxc_config_readline(char *buffer, struct lxc_conf *conf)
1036 {
1037 return parse_line(buffer, conf);
1038 }
1039
1040 int lxc_config_read(const char *file, struct lxc_conf *conf)
1041 {
1042 return lxc_file_for_each_line(file, parse_line, conf);
1043 }
1044
1045 int lxc_config_define_add(struct lxc_list *defines, char* arg)
1046 {
1047 struct lxc_list *dent;
1048
1049 dent = malloc(sizeof(struct lxc_list));
1050 if (!dent)
1051 return -1;
1052
1053 dent->elem = arg;
1054 lxc_list_add_tail(defines, dent);
1055 return 0;
1056 }
1057
1058 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
1059 {
1060 struct lxc_list *it;
1061 int ret = 0;
1062
1063 lxc_list_for_each(it, defines) {
1064 ret = lxc_config_readline(it->elem, conf);
1065 if (ret)
1066 break;
1067 }
1068
1069 lxc_list_for_each(it, defines) {
1070 lxc_list_del(it);
1071 free(it);
1072 }
1073
1074 return ret;
1075 }
1076
1077 signed long lxc_config_parse_arch(const char *arch)
1078 {
1079 struct per_name {
1080 char *name;
1081 unsigned long per;
1082 } pername[4] = {
1083 { "x86", PER_LINUX32 },
1084 { "i686", PER_LINUX32 },
1085 { "x86_64", PER_LINUX },
1086 { "amd64", PER_LINUX },
1087 };
1088 size_t len = sizeof(pername) / sizeof(pername[0]);
1089
1090 int i;
1091
1092 for (i = 0; i < len; i++) {
1093 if (!strcmp(pername[i].name, arch))
1094 return pername[i].per;
1095 }
1096
1097 return -1;
1098 }