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