]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
allocate a console to be proxied
[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 <arpa/inet.h>
35 #include <netinet/in.h>
36 #include <net/if.h>
37
38 #include "parse.h"
39 #include "utils.h"
40
41 #include <lxc/log.h>
42 #include <lxc/conf.h>
43
44 lxc_log_define(lxc_confile, lxc);
45
46 static int config_pts(const char *, char *, struct lxc_conf *);
47 static int config_tty(const char *, char *, struct lxc_conf *);
48 static int config_cgroup(const char *, char *, struct lxc_conf *);
49 static int config_mount(const char *, char *, struct lxc_conf *);
50 static int config_rootfs(const char *, char *, struct lxc_conf *);
51 static int config_pivotdir(const char *, char *, struct lxc_conf *);
52 static int config_utsname(const char *, char *, struct lxc_conf *);
53 static int config_network_type(const char *, char *, struct lxc_conf *);
54 static int config_network_flags(const char *, char *, struct lxc_conf *);
55 static int config_network_link(const char *, char *, struct lxc_conf *);
56 static int config_network_name(const char *, char *, struct lxc_conf *);
57 static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
58 static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
59 static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
60 static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
61 static int config_network_mtu(const char *, char *, struct lxc_conf *);
62 static int config_network_ipv4(const char *, char *, struct lxc_conf *);
63 static int config_network_ipv6(const char *, char *, struct lxc_conf *);
64 static int config_cap_drop(const char *, char *, struct lxc_conf *);
65 static int config_console(const char *, char *, struct lxc_conf *);
66
67 typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
68
69 struct config {
70 char *name;
71 config_cb cb;
72 };
73
74 static struct config config[] = {
75
76 { "lxc.pts", config_pts },
77 { "lxc.tty", config_tty },
78 { "lxc.cgroup", config_cgroup },
79 { "lxc.mount", config_mount },
80 { "lxc.rootfs", config_rootfs },
81 { "lxc.pivotdir", config_pivotdir },
82 { "lxc.utsname", config_utsname },
83 { "lxc.network.type", config_network_type },
84 { "lxc.network.flags", config_network_flags },
85 { "lxc.network.link", config_network_link },
86 { "lxc.network.name", config_network_name },
87 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
88 { "lxc.network.veth.pair", config_network_veth_pair },
89 { "lxc.network.hwaddr", config_network_hwaddr },
90 { "lxc.network.mtu", config_network_mtu },
91 { "lxc.network.vlan.id", config_network_vlan_id },
92 { "lxc.network.ipv4", config_network_ipv4 },
93 { "lxc.network.ipv6", config_network_ipv6 },
94 { "lxc.cap.drop", config_cap_drop },
95 { "lxc.console", config_console },
96 };
97
98 static const size_t config_size = sizeof(config)/sizeof(struct config);
99
100 static struct config *getconfig(const char *key)
101 {
102 int i;
103
104 for (i = 0; i < config_size; i++)
105 if (!strncmp(config[i].name, key,
106 strlen(config[i].name)))
107 return &config[i];
108 return NULL;
109 }
110
111 static int config_network_type(const char *key, char *value,
112 struct lxc_conf *lxc_conf)
113 {
114 struct lxc_list *network = &lxc_conf->network;
115 struct lxc_netdev *netdev;
116 struct lxc_list *list;
117
118 netdev = malloc(sizeof(*netdev));
119 if (!netdev) {
120 SYSERROR("failed to allocate memory");
121 return -1;
122 }
123
124 memset(netdev, 0, sizeof(*netdev));
125 lxc_list_init(&netdev->ipv4);
126 lxc_list_init(&netdev->ipv6);
127
128 list = malloc(sizeof(*list));
129 if (!list) {
130 SYSERROR("failed to allocate memory");
131 return -1;
132 }
133
134 lxc_list_init(list);
135 list->elem = netdev;
136
137 lxc_list_add(network, list);
138
139 if (!strcmp(value, "veth"))
140 netdev->type = LXC_NET_VETH;
141 else if (!strcmp(value, "macvlan"))
142 netdev->type = LXC_NET_MACVLAN;
143 else if (!strcmp(value, "vlan"))
144 netdev->type = LXC_NET_VLAN;
145 else if (!strcmp(value, "phys"))
146 netdev->type = LXC_NET_PHYS;
147 else if (!strcmp(value, "empty"))
148 netdev->type = LXC_NET_EMPTY;
149 else {
150 ERROR("invalid network type %s", value);
151 return -1;
152 }
153 return 0;
154 }
155
156 static int config_ip_prefix(struct in_addr *addr)
157 {
158 if (IN_CLASSA(addr->s_addr))
159 return 32 - IN_CLASSA_NSHIFT;
160 if (IN_CLASSB(addr->s_addr))
161 return 32 - IN_CLASSB_NSHIFT;
162 if (IN_CLASSC(addr->s_addr))
163 return 32 - IN_CLASSC_NSHIFT;
164
165 return 0;
166 }
167
168 static struct lxc_netdev *network_netdev(const char *key, const char *value,
169 struct lxc_list *network)
170 {
171 struct lxc_netdev *netdev;
172
173 if (lxc_list_empty(network)) {
174 ERROR("network is not created for '%s' = '%s' option",
175 key, value);
176 return NULL;
177 }
178
179 netdev = lxc_list_first_elem(network);
180 if (!netdev) {
181 ERROR("no network device defined for '%s' = '%s' option",
182 key, value);
183 return NULL;
184 }
185
186 return netdev;
187 }
188
189 static int network_ifname(char **valuep, char *value)
190 {
191 if (strlen(value) > IFNAMSIZ) {
192 ERROR("invalid interface name: %s", value);
193 return -1;
194 }
195
196 *valuep = strdup(value);
197 if (!*valuep) {
198 ERROR("failed to dup string '%s'", value);
199 return -1;
200 }
201
202 return 0;
203 }
204
205 #ifndef MACVLAN_MODE_PRIVATE
206 # define MACVLAN_MODE_PRIVATE 1
207 #endif
208
209 #ifndef MACVLAN_MODE_VEPA
210 # define MACVLAN_MODE_VEPA 2
211 #endif
212
213 #ifndef MACVLAN_MODE_BRIDGE
214 # define MACVLAN_MODE_BRIDGE 4
215 #endif
216
217 static int macvlan_mode(int *valuep, char *value)
218 {
219 struct mc_mode {
220 char *name;
221 int mode;
222 } m[] = {
223 { "private", MACVLAN_MODE_PRIVATE },
224 { "vepa", MACVLAN_MODE_VEPA },
225 { "bridge", MACVLAN_MODE_BRIDGE },
226 };
227
228 int i;
229
230 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
231 if (strcmp(m[i].name, value))
232 continue;
233
234 *valuep = m[i].mode;
235 return 0;
236 }
237
238 return -1;
239 }
240
241 static int config_network_flags(const char *key, char *value,
242 struct lxc_conf *lxc_conf)
243 {
244 struct lxc_netdev *netdev;
245
246 netdev = network_netdev(key, value, &lxc_conf->network);
247 if (!netdev)
248 return -1;
249
250 netdev->flags |= IFF_UP;
251
252 return 0;
253 }
254
255 static int config_network_link(const char *key, char *value,
256 struct lxc_conf *lxc_conf)
257 {
258 struct lxc_netdev *netdev;
259
260 netdev = network_netdev(key, value, &lxc_conf->network);
261 if (!netdev)
262 return -1;
263
264 return network_ifname(&netdev->link, value);
265 }
266
267 static int config_network_name(const char *key, char *value,
268 struct lxc_conf *lxc_conf)
269 {
270 struct lxc_netdev *netdev;
271
272 netdev = network_netdev(key, value, &lxc_conf->network);
273 if (!netdev)
274 return -1;
275
276 return network_ifname(&netdev->name, value);
277 }
278
279 static int config_network_veth_pair(const char *key, char *value,
280 struct lxc_conf *lxc_conf)
281 {
282 struct lxc_netdev *netdev;
283
284 netdev = network_netdev(key, value, &lxc_conf->network);
285 if (!netdev)
286 return -1;
287
288 return network_ifname(&netdev->priv.veth_attr.pair, value);
289 }
290
291 static int config_network_macvlan_mode(const char *key, char *value,
292 struct lxc_conf *lxc_conf)
293 {
294 struct lxc_netdev *netdev;
295
296 netdev = network_netdev(key, value, &lxc_conf->network);
297 if (!netdev)
298 return -1;
299
300 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
301 }
302
303 static int config_network_hwaddr(const char *key, char *value,
304 struct lxc_conf *lxc_conf)
305 {
306 struct lxc_netdev *netdev;
307
308 netdev = network_netdev(key, value, &lxc_conf->network);
309 if (!netdev)
310 return -1;
311
312 netdev->hwaddr = strdup(value);
313 if (!netdev->hwaddr) {
314 SYSERROR("failed to dup string '%s'", value);
315 return -1;
316 }
317
318 return 0;
319 }
320
321 static int config_network_vlan_id(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 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
331 return -1;
332
333 return 0;
334 }
335
336 static int config_network_mtu(const char *key, char *value,
337 struct lxc_conf *lxc_conf)
338 {
339 struct lxc_netdev *netdev;
340
341 netdev = network_netdev(key, value, &lxc_conf->network);
342 if (!netdev)
343 return -1;
344
345 netdev->mtu = strdup(value);
346 if (!netdev->mtu) {
347 SYSERROR("failed to dup string '%s'", value);
348 return -1;
349 }
350
351 return 0;
352 }
353
354 static int config_network_ipv4(const char *key, char *value,
355 struct lxc_conf *lxc_conf)
356 {
357 struct lxc_netdev *netdev;
358 struct lxc_inetdev *inetdev;
359 struct lxc_list *list;
360 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
361
362 netdev = network_netdev(key, value, &lxc_conf->network);
363 if (!netdev)
364 return -1;
365
366 inetdev = malloc(sizeof(*inetdev));
367 if (!inetdev) {
368 SYSERROR("failed to allocate ipv4 address");
369 return -1;
370 }
371 memset(inetdev, 0, sizeof(*inetdev));
372
373 list = malloc(sizeof(*list));
374 if (!list) {
375 SYSERROR("failed to allocate memory");
376 return -1;
377 }
378
379 lxc_list_init(list);
380 list->elem = inetdev;
381
382 addr = value;
383
384 cursor = strstr(addr, " ");
385 if (cursor) {
386 *cursor = '\0';
387 bcast = cursor + 1;
388 }
389
390 slash = strstr(addr, "/");
391 if (slash) {
392 *slash = '\0';
393 prefix = slash + 1;
394 }
395
396 if (!addr) {
397 ERROR("no address specified");
398 return -1;
399 }
400
401 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
402 SYSERROR("invalid ipv4 address: %s", value);
403 return -1;
404 }
405
406 if (bcast)
407 if (!inet_pton(AF_INET, bcast, &inetdev->bcast)) {
408 SYSERROR("invalid ipv4 address: %s", value);
409 return -1;
410 }
411
412 /* no prefix specified, determine it from the network class */
413 inetdev->prefix = prefix ? atoi(prefix) :
414 config_ip_prefix(&inetdev->addr);
415
416
417 lxc_list_add(&netdev->ipv4, list);
418
419 return 0;
420 }
421
422 static int config_network_ipv6(const char *key, char *value,
423 struct lxc_conf *lxc_conf)
424 {
425 struct lxc_netdev *netdev;
426 struct lxc_inet6dev *inet6dev;
427 struct lxc_list *list;
428 char *slash;
429 char *netmask;
430
431 netdev = network_netdev(key, value, &lxc_conf->network);
432 if (!netdev)
433 return -1;
434
435 inet6dev = malloc(sizeof(*inet6dev));
436 if (!inet6dev) {
437 SYSERROR("failed to allocate ipv6 address");
438 return -1;
439 }
440 memset(inet6dev, 0, sizeof(*inet6dev));
441
442 list = malloc(sizeof(*list));
443 if (!list) {
444 SYSERROR("failed to allocate memory");
445 return -1;
446 }
447
448 lxc_list_init(list);
449 list->elem = inet6dev;
450
451 inet6dev->prefix = 64;
452 slash = strstr(value, "/");
453 if (slash) {
454 *slash = '\0';
455 netmask = slash + 1;
456 inet6dev->prefix = atoi(netmask);
457 }
458
459 if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
460 SYSERROR("invalid ipv6 address: %s", value);
461 return -1;
462 }
463
464 lxc_list_add(&netdev->ipv6, list);
465
466 return 0;
467 }
468
469 static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
470 {
471 int maxpts = atoi(value);
472
473 lxc_conf->pts = maxpts;
474
475 return 0;
476 }
477
478 static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
479 {
480 int nbtty = atoi(value);
481
482 lxc_conf->tty = nbtty;
483
484 return 0;
485 }
486
487 static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
488 {
489 char *token = "lxc.cgroup.";
490 char *subkey;
491 struct lxc_list *cglist;
492 struct lxc_cgroup *cgelem;
493
494 subkey = strstr(key, token);
495
496 if (!subkey)
497 return -1;
498
499 if (!strlen(subkey))
500 return -1;
501
502 if (strlen(subkey) == strlen(token))
503 return -1;
504
505 subkey += strlen(token);
506
507 cglist = malloc(sizeof(*cglist));
508 if (!cglist)
509 return -1;
510
511 cgelem = malloc(sizeof(*cgelem));
512 if (!cgelem) {
513 free(cglist);
514 return -1;
515 }
516
517 cgelem->subsystem = strdup(subkey);
518 cgelem->value = strdup(value);
519 cglist->elem = cgelem;
520
521 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
522
523 return 0;
524 }
525
526 static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
527 {
528 if (strlen(value) >= MAXPATHLEN) {
529 ERROR("%s path is too long", value);
530 return -1;
531 }
532
533 lxc_conf->fstab = strdup(value);
534 if (!lxc_conf->fstab) {
535 SYSERROR("failed to duplicate string %s", value);
536 return -1;
537 }
538
539 return 0;
540 }
541
542 static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
543 {
544 char *fstab_token = "lxc.mount";
545 char *token = "lxc.mount.entry";
546 char *subkey;
547 char *mntelem;
548 struct lxc_list *mntlist;
549
550 subkey = strstr(key, token);
551
552 if (!subkey) {
553 subkey = strstr(key, fstab_token);
554
555 if (!subkey)
556 return -1;
557
558 return config_fstab(key, value, lxc_conf);
559 }
560
561 if (!strlen(subkey))
562 return -1;
563
564 mntlist = malloc(sizeof(*mntlist));
565 if (!mntlist)
566 return -1;
567
568 mntelem = strdup(value);
569 mntlist->elem = mntelem;
570
571 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
572
573 return 0;
574 }
575
576 static int config_cap_drop(const char *key, char *value,
577 struct lxc_conf *lxc_conf)
578 {
579 char *dropcaps, *sptr, *token;
580 struct lxc_list *droplist;
581 int ret = -1;
582
583 if (!strlen(value))
584 return -1;
585
586 dropcaps = strdup(value);
587 if (!dropcaps) {
588 SYSERROR("failed to dup '%s'", value);
589 return -1;
590 }
591
592 /* in case several capability drop is specified in a single line
593 * split these caps in a single element for the list */
594 for (;;) {
595 token = strtok_r(dropcaps, " \t", &sptr);
596 if (!token) {
597 ret = 0;
598 break;
599 }
600 dropcaps = NULL;
601
602 droplist = malloc(sizeof(*droplist));
603 if (!droplist) {
604 SYSERROR("failed to allocate drop list");
605 break;
606 }
607
608 droplist->elem = strdup(token);
609 if (!droplist->elem) {
610 SYSERROR("failed to dup '%s'", token);
611 free(droplist);
612 break;
613 }
614
615 lxc_list_add_tail(&lxc_conf->caps, droplist);
616 }
617
618 free(dropcaps);
619
620 return ret;
621 }
622
623 static int config_console(const char *key, char *value, struct lxc_conf *lxc_conf)
624 {
625 int fd;
626
627 fd = open(value, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600);
628 if (fd < 0) {
629 SYSERROR("failed to open '%s'", value);
630 return -1;
631 }
632
633 lxc_conf->console.peer = fd;
634
635 return 0;
636 }
637
638 static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
639 {
640 if (strlen(value) >= MAXPATHLEN) {
641 ERROR("%s path is too long", value);
642 return -1;
643 }
644
645 lxc_conf->rootfs = strdup(value);
646 if (!lxc_conf->rootfs) {
647 SYSERROR("failed to duplicate string %s", value);
648 return -1;
649 }
650
651 return 0;
652 }
653
654 static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
655 {
656 if (strlen(value) >= MAXPATHLEN) {
657 ERROR("%s path is too long", value);
658 return -1;
659 }
660
661 lxc_conf->pivotdir = strdup(value);
662 if (!lxc_conf->pivotdir) {
663 SYSERROR("failed to duplicate string %s", value);
664 return -1;
665 }
666
667 return 0;
668 }
669
670 static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
671 {
672 struct utsname *utsname;
673
674 utsname = malloc(sizeof(*utsname));
675 if (!utsname) {
676 SYSERROR("failed to allocate memory");
677 return -1;
678 }
679
680 if (strlen(value) >= sizeof(utsname->nodename)) {
681 ERROR("node name '%s' is too long",
682 utsname->nodename);
683 return -1;
684 }
685
686 strcpy(utsname->nodename, value);
687 lxc_conf->utsname = utsname;
688
689 return 0;
690 }
691
692 static int parse_line(char *buffer, void *data)
693 {
694 struct config *config;
695 char *line = buffer;
696 char *dot;
697 char *key;
698 char *value;
699
700 if (lxc_is_line_empty(line))
701 return 0;
702
703 line += lxc_char_left_gc(line, strlen(line));
704 if (line[0] == '#')
705 return 0;
706
707 dot = strstr(line, "=");
708 if (!dot) {
709 ERROR("invalid configuration line: %s", line);
710 return -1;
711 }
712
713 *dot = '\0';
714 value = dot + 1;
715
716 key = line;
717 key[lxc_char_right_gc(key, strlen(key))] = '\0';
718
719 value += lxc_char_left_gc(value, strlen(value));
720 value[lxc_char_right_gc(value, strlen(value))] = '\0';
721
722 config = getconfig(key);
723 if (!config) {
724 ERROR("unknow key %s", key);
725 return -1;
726 }
727
728 return config->cb(key, value, data);
729 }
730
731 int lxc_config_readline(char *buffer, struct lxc_conf *conf)
732 {
733 return parse_line(buffer, conf);
734 }
735
736 int lxc_config_read(const char *file, struct lxc_conf *conf)
737 {
738 return lxc_file_for_each_line(file, parse_line, conf);
739 }
740
741 int lxc_config_define_add(struct lxc_list *defines, char* arg)
742 {
743 struct lxc_list *dent;
744
745 dent = malloc(sizeof(struct lxc_list));
746 if (!dent)
747 return -1;
748
749 dent->elem = arg;
750 lxc_list_add_tail(defines, dent);
751 return 0;
752 }
753
754 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
755 {
756 struct lxc_list *it;
757 int ret = 0;
758
759 lxc_list_for_each(it, defines) {
760 ret = lxc_config_readline(it->elem, conf);
761 if (ret)
762 break;
763 }
764
765 lxc_list_for_each(it, defines) {
766 lxc_list_del(it);
767 free(it);
768 }
769
770 return ret;
771 }