]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/confile.c
add macvlan vepa and bridge mode
[mirror_lxc.git] / src / lxc / confile.c
CommitLineData
c2cc9f0a 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 <sys/types.h>
29#include <sys/param.h>
30#include <sys/utsname.h>
31#include <arpa/inet.h>
32#include <netinet/in.h>
33#include <net/if.h>
34
b2718c72 35#include "parse.h"
26c39028 36#include "utils.h"
c2cc9f0a 37
36eb9bde 38#include <lxc/log.h>
00b3c2e2 39#include <lxc/conf.h>
36eb9bde
CLG
40
41lxc_log_define(lxc_confile, lxc);
576f946d 42
10db618d 43static int config_pts(const char *, char *, struct lxc_conf *);
b0a33c1e 44static int config_tty(const char *, char *, struct lxc_conf *);
576f946d 45static int config_cgroup(const char *, char *, struct lxc_conf *);
46static int config_mount(const char *, char *, struct lxc_conf *);
47static int config_rootfs(const char *, char *, struct lxc_conf *);
48static int config_utsname(const char *, char *, struct lxc_conf *);
49static int config_network_type(const char *, char *, struct lxc_conf *);
50static int config_network_flags(const char *, char *, struct lxc_conf *);
51static int config_network_link(const char *, char *, struct lxc_conf *);
52static int config_network_name(const char *, char *, struct lxc_conf *);
e892973e
DL
53static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
54static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
576f946d 55static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
e892973e 56static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
442cbbe6 57static int config_network_mtu(const char *, char *, struct lxc_conf *);
576f946d 58static int config_network_ipv4(const char *, char *, struct lxc_conf *);
59static int config_network_ipv6(const char *, char *, struct lxc_conf *);
c2cc9f0a 60
b2718c72 61typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
62
c2cc9f0a 63struct config {
64 char *name;
c2cc9f0a 65 config_cb cb;
66};
67
576f946d 68static struct config config[] = {
69
e892973e
DL
70 { "lxc.pts", config_pts },
71 { "lxc.tty", config_tty },
72 { "lxc.cgroup", config_cgroup },
73 { "lxc.mount", config_mount },
74 { "lxc.rootfs", config_rootfs },
75 { "lxc.utsname", config_utsname },
76 { "lxc.network.type", config_network_type },
77 { "lxc.network.flags", config_network_flags },
78 { "lxc.network.link", config_network_link },
79 { "lxc.network.name", config_network_name },
80 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
81 { "lxc.network.veth.pair", config_network_veth_pair },
82 { "lxc.network.hwaddr", config_network_hwaddr },
83 { "lxc.network.mtu", config_network_mtu },
84 { "lxc.network.vlan.id", config_network_vlan_id },
85 { "lxc.network.ipv4", config_network_ipv4 },
86 { "lxc.network.ipv6", config_network_ipv6 },
c2cc9f0a 87};
88
89static const size_t config_size = sizeof(config)/sizeof(struct config);
90
91static struct config *getconfig(const char *key)
92{
93 int i;
94
95 for (i = 0; i < config_size; i++)
a871ff6b 96 if (!strncmp(config[i].name, key,
c2cc9f0a 97 strlen(config[i].name)))
98 return &config[i];
99 return NULL;
100}
101
e892973e
DL
102static int config_network_type(const char *key, char *value,
103 struct lxc_conf *lxc_conf)
c2cc9f0a 104{
5f4535a3 105 struct lxc_list *network = &lxc_conf->network;
c2cc9f0a 106 struct lxc_netdev *netdev;
107 struct lxc_list *list;
c2cc9f0a 108
109 netdev = malloc(sizeof(*netdev));
110 if (!netdev) {
36eb9bde 111 SYSERROR("failed to allocate memory");
c2cc9f0a 112 return -1;
113 }
114
82d5ae15 115 memset(netdev, 0, sizeof(*netdev));
c2cc9f0a 116 lxc_list_init(&netdev->ipv4);
117 lxc_list_init(&netdev->ipv6);
c2cc9f0a 118
119 list = malloc(sizeof(*list));
120 if (!list) {
36eb9bde 121 SYSERROR("failed to allocate memory");
c2cc9f0a 122 return -1;
123 }
124
125 lxc_list_init(list);
5f4535a3 126 list->elem = netdev;
c2cc9f0a 127
5f4535a3 128 lxc_list_add(network, list);
a871ff6b 129
c2cc9f0a 130 if (!strcmp(value, "veth"))
5f4535a3 131 netdev->type = VETH;
c2cc9f0a 132 else if (!strcmp(value, "macvlan"))
5f4535a3 133 netdev->type = MACVLAN;
26c39028
JHS
134 else if (!strcmp(value, "vlan"))
135 netdev->type = VLAN;
c2cc9f0a 136 else if (!strcmp(value, "phys"))
5f4535a3 137 netdev->type = PHYS;
5f58350a 138 else if (!strcmp(value, "empty"))
5f4535a3 139 netdev->type = EMPTY;
c2cc9f0a 140 else {
36eb9bde 141 ERROR("invalid network type %s", value);
c2cc9f0a 142 return -1;
143 }
144 return 0;
145}
146
a059591e
DL
147static int config_ip_prefix(struct in_addr *addr)
148{
149 if (IN_CLASSA(addr->s_addr))
150 return 32 - IN_CLASSA_NSHIFT;
151 if (IN_CLASSB(addr->s_addr))
152 return 32 - IN_CLASSB_NSHIFT;
153 if (IN_CLASSC(addr->s_addr))
154 return 32 - IN_CLASSC_NSHIFT;
155
156 return 0;
157}
158
16950ecb
DL
159static struct lxc_netdev *network_netdev(const char *key, const char *value,
160 struct lxc_list *network)
c2cc9f0a 161{
c2cc9f0a 162 struct lxc_netdev *netdev;
163
5f4535a3 164 if (lxc_list_empty(network)) {
16950ecb
DL
165 ERROR("network is not created for '%s' = '%s' option",
166 key, value);
33c945e0 167 return NULL;
c2cc9f0a 168 }
169
5f4535a3
DL
170 netdev = lxc_list_first_elem(network);
171 if (!netdev) {
16950ecb
DL
172 ERROR("no network device defined for '%s' = '%s' option",
173 key, value);
33c945e0 174 return NULL;
c2cc9f0a 175 }
176
33c945e0 177 return netdev;
c2cc9f0a 178}
179
33c945e0 180static int network_ifname(char **valuep, char *value)
c2cc9f0a 181{
c2cc9f0a 182 if (strlen(value) > IFNAMSIZ) {
36eb9bde 183 ERROR("invalid interface name: %s", value);
c2cc9f0a 184 return -1;
185 }
186
33c945e0 187 *valuep = strdup(value);
16950ecb
DL
188 if (!*valuep) {
189 ERROR("failed to dup string '%s'", value);
190 return -1;
191 }
33c945e0 192
c2cc9f0a 193 return 0;
194}
195
e892973e
DL
196#ifndef MACVLAN_MODE_PRIVATE
197# define MACVLAN_MODE_PRIVATE 1
198#endif
199
200#ifndef MACVLAN_MODE_VEPA
201# define MACVLAN_MODE_VEPA 2
202#endif
203
204#ifndef MACVLAN_MODE_BRIDGE
205# define MACVLAN_MODE_BRIDGE 4
206#endif
207
208static int macvlan_mode(int *valuep, char *value)
209{
210 struct mc_mode {
211 char *name;
212 int mode;
213 } m[] = {
214 { "private", MACVLAN_MODE_PRIVATE },
215 { "vepa", MACVLAN_MODE_VEPA },
216 { "bridge", MACVLAN_MODE_BRIDGE },
217 };
218
219 int i;
220
221 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
222 if (strcmp(m[i].name, value))
223 continue;
224
225 *valuep = m[i].mode;
226 return 0;
227 }
228
229 return -1;
230}
231
33c945e0
MT
232static int config_network_flags(const char *key, char *value,
233 struct lxc_conf *lxc_conf)
c2cc9f0a 234{
c2cc9f0a 235 struct lxc_netdev *netdev;
236
16950ecb 237 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 238 if (!netdev)
c2cc9f0a 239 return -1;
c2cc9f0a 240
33c945e0 241 netdev->flags |= IFF_UP;
c2cc9f0a 242
33c945e0
MT
243 return 0;
244}
245
246static int config_network_link(const char *key, char *value,
247 struct lxc_conf *lxc_conf)
248{
249 struct lxc_netdev *netdev;
250
16950ecb 251 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 252 if (!netdev)
c2cc9f0a 253 return -1;
c2cc9f0a 254
33c945e0 255 return network_ifname(&netdev->link, value);
c2cc9f0a 256}
257
33c945e0
MT
258static int config_network_name(const char *key, char *value,
259 struct lxc_conf *lxc_conf)
c2cc9f0a 260{
c2cc9f0a 261 struct lxc_netdev *netdev;
262
16950ecb 263 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 264 if (!netdev)
c2cc9f0a 265 return -1;
c2cc9f0a 266
33c945e0
MT
267 return network_ifname(&netdev->name, value);
268}
269
e892973e
DL
270static int config_network_veth_pair(const char *key, char *value,
271 struct lxc_conf *lxc_conf)
272{
273 struct lxc_netdev *netdev;
274
275 netdev = network_netdev(key, value, &lxc_conf->network);
276 if (!netdev)
277 return -1;
278
279 return network_ifname(&netdev->priv.veth_attr.pair, value);
280}
281
282static int config_network_macvlan_mode(const char *key, char *value,
283 struct lxc_conf *lxc_conf)
8634bc19
MT
284{
285 struct lxc_netdev *netdev;
286
287 netdev = network_netdev(key, value, &lxc_conf->network);
288 if (!netdev)
289 return -1;
290
e892973e 291 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
8634bc19
MT
292}
293
33c945e0
MT
294static int config_network_hwaddr(const char *key, char *value,
295 struct lxc_conf *lxc_conf)
296{
297 struct lxc_netdev *netdev;
298
16950ecb 299 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 300 if (!netdev)
c2cc9f0a 301 return -1;
c2cc9f0a 302
c2cc9f0a 303 netdev->hwaddr = strdup(value);
16950ecb
DL
304 if (!netdev->hwaddr) {
305 SYSERROR("failed to dup string '%s'", value);
306 return -1;
307 }
33c945e0 308
c2cc9f0a 309 return 0;
310}
311
e892973e 312static int config_network_vlan_id(const char *key, char *value,
26c39028
JHS
313 struct lxc_conf *lxc_conf)
314{
315 struct lxc_netdev *netdev;
316
317 netdev = network_netdev(key, value, &lxc_conf->network);
318 if (!netdev)
319 return -1;
320
f6cc1de1 321 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
26c39028
JHS
322 return -1;
323
324 return 0;
325}
326
33c945e0
MT
327static int config_network_mtu(const char *key, char *value,
328 struct lxc_conf *lxc_conf)
442cbbe6 329{
442cbbe6
TR
330 struct lxc_netdev *netdev;
331
16950ecb 332 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 333 if (!netdev)
442cbbe6 334 return -1;
442cbbe6 335
442cbbe6 336 netdev->mtu = strdup(value);
16950ecb
DL
337 if (!netdev->mtu) {
338 SYSERROR("failed to dup string '%s'", value);
339 return -1;
340 }
33c945e0 341
442cbbe6
TR
342 return 0;
343}
344
33c945e0
MT
345static int config_network_ipv4(const char *key, char *value,
346 struct lxc_conf *lxc_conf)
c2cc9f0a 347{
c2cc9f0a 348 struct lxc_netdev *netdev;
33c945e0 349 struct lxc_inetdev *inetdev;
c2cc9f0a 350 struct lxc_list *list;
351 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
352
16950ecb 353 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 354 if (!netdev)
c2cc9f0a 355 return -1;
c2cc9f0a 356
357 inetdev = malloc(sizeof(*inetdev));
358 if (!inetdev) {
36eb9bde 359 SYSERROR("failed to allocate ipv4 address");
c2cc9f0a 360 return -1;
361 }
362 memset(inetdev, 0, sizeof(*inetdev));
363
364 list = malloc(sizeof(*list));
365 if (!list) {
36eb9bde 366 SYSERROR("failed to allocate memory");
c2cc9f0a 367 return -1;
368 }
369
370 lxc_list_init(list);
371 list->elem = inetdev;
372
373 addr = value;
374
375 cursor = strstr(addr, " ");
376 if (cursor) {
377 *cursor = '\0';
378 bcast = cursor + 1;
379 }
380
381 slash = strstr(addr, "/");
382 if (slash) {
383 *slash = '\0';
384 prefix = slash + 1;
385 }
386
387 if (!addr) {
36eb9bde 388 ERROR("no address specified");
c2cc9f0a 389 return -1;
390 }
391
392 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
36eb9bde 393 SYSERROR("invalid ipv4 address: %s", value);
c2cc9f0a 394 return -1;
395 }
396
397 if (bcast)
398 if (!inet_pton(AF_INET, bcast, &inetdev->bcast)) {
36eb9bde 399 SYSERROR("invalid ipv4 address: %s", value);
c2cc9f0a 400 return -1;
401 }
402
a059591e
DL
403 /* no prefix specified, determine it from the network class */
404 inetdev->prefix = prefix ? atoi(prefix) :
405 config_ip_prefix(&inetdev->addr);
406
c2cc9f0a 407
408 lxc_list_add(&netdev->ipv4, list);
409
410 return 0;
411}
412
e892973e
DL
413static int config_network_ipv6(const char *key, char *value,
414 struct lxc_conf *lxc_conf)
c2cc9f0a 415{
c2cc9f0a 416 struct lxc_netdev *netdev;
417 struct lxc_inet6dev *inet6dev;
418 struct lxc_list *list;
419 char *slash;
420 char *netmask;
421
16950ecb 422 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 423 if (!netdev)
c2cc9f0a 424 return -1;
c2cc9f0a 425
426 inet6dev = malloc(sizeof(*inet6dev));
427 if (!inet6dev) {
36eb9bde 428 SYSERROR("failed to allocate ipv6 address");
c2cc9f0a 429 return -1;
430 }
431 memset(inet6dev, 0, sizeof(*inet6dev));
432
433 list = malloc(sizeof(*list));
434 if (!list) {
36eb9bde 435 SYSERROR("failed to allocate memory");
c2cc9f0a 436 return -1;
437 }
438
439 lxc_list_init(list);
440 list->elem = inet6dev;
441
a059591e 442 inet6dev->prefix = 64;
c2cc9f0a 443 slash = strstr(value, "/");
444 if (slash) {
445 *slash = '\0';
446 netmask = slash + 1;
447 inet6dev->prefix = atoi(netmask);
448 }
449
450 if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
36eb9bde 451 SYSERROR("invalid ipv6 address: %s", value);
c2cc9f0a 452 return -1;
453 }
454
c2cc9f0a 455 lxc_list_add(&netdev->ipv6, list);
456
457 return 0;
458}
459
10db618d 460static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
461{
462 int maxpts = atoi(value);
463
464 lxc_conf->pts = maxpts;
465
466 return 0;
467}
468
b0a33c1e 469static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
470{
471 int nbtty = atoi(value);
472
473 lxc_conf->tty = nbtty;
474
475 return 0;
476}
477
576f946d 478static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
479{
480 char *token = "lxc.cgroup.";
481 char *subkey;
482 struct lxc_list *cglist;
483 struct lxc_cgroup *cgelem;
484
485 subkey = strstr(key, token);
486
487 if (!subkey)
488 return -1;
489
490 if (!strlen(subkey))
491 return -1;
492
493 if (strlen(subkey) == strlen(token))
494 return -1;
a871ff6b 495
576f946d 496 subkey += strlen(token);
497
498 cglist = malloc(sizeof(*cglist));
499 if (!cglist)
500 return -1;
501
502 cgelem = malloc(sizeof(*cgelem));
503 if (!cgelem) {
504 free(cglist);
505 return -1;
506 }
507
508 cgelem->subsystem = strdup(subkey);
509 cgelem->value = strdup(value);
510 cglist->elem = cgelem;
511
94d12f0a 512 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
576f946d 513
514 return 0;
515}
516
e7938e9e 517static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
c2cc9f0a 518{
519 if (strlen(value) >= MAXPATHLEN) {
36eb9bde 520 ERROR("%s path is too long", value);
c2cc9f0a 521 return -1;
522 }
523
524 lxc_conf->fstab = strdup(value);
525 if (!lxc_conf->fstab) {
36eb9bde 526 SYSERROR("failed to duplicate string %s", value);
c2cc9f0a 527 return -1;
528 }
529
530 return 0;
531}
532
e7938e9e
MN
533static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
534{
535 char *fstab_token = "lxc.mount";
536 char *token = "lxc.mount.entry";
537 char *subkey;
538 char *mntelem;
539 struct lxc_list *mntlist;
540
541 subkey = strstr(key, token);
542
543 if (!subkey) {
544 subkey = strstr(key, fstab_token);
545
546 if (!subkey)
547 return -1;
548
549 return config_fstab(key, value, lxc_conf);
550 }
551
552 if (!strlen(subkey))
553 return -1;
554
555 mntlist = malloc(sizeof(*mntlist));
556 if (!mntlist)
557 return -1;
558
559 mntelem = strdup(value);
560 mntlist->elem = mntelem;
561
562 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
563
564 return 0;
565}
566
576f946d 567static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
c2cc9f0a 568{
569 if (strlen(value) >= MAXPATHLEN) {
36eb9bde 570 ERROR("%s path is too long", value);
c2cc9f0a 571 return -1;
572 }
573
eae6543d 574 lxc_conf->rootfs = strdup(value);
575 if (!lxc_conf->rootfs) {
36eb9bde 576 SYSERROR("failed to duplicate string %s", value);
c2cc9f0a 577 return -1;
578 }
579
580 return 0;
581}
582
576f946d 583static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
c2cc9f0a 584{
585 struct utsname *utsname;
586
587 utsname = malloc(sizeof(*utsname));
588 if (!utsname) {
36eb9bde 589 SYSERROR("failed to allocate memory");
c2cc9f0a 590 return -1;
591 }
592
593 if (strlen(value) >= sizeof(utsname->nodename)) {
36eb9bde 594 ERROR("node name '%s' is too long",
c2cc9f0a 595 utsname->nodename);
596 return -1;
597 }
598
599 strcpy(utsname->nodename, value);
600 lxc_conf->utsname = utsname;
601
602 return 0;
603}
604
b2718c72 605static int parse_line(void *buffer, void *data)
c2cc9f0a 606{
607 struct config *config;
b2718c72 608 char *line = buffer;
c2cc9f0a 609 char *dot;
610 char *key;
611 char *value;
612
b2718c72 613 if (lxc_is_line_empty(line))
c2cc9f0a 614 return 0;
615
b2718c72 616 line += lxc_char_left_gc(line, strlen(line));
617 if (line[0] == '#')
c2cc9f0a 618 return 0;
619
b2718c72 620 dot = strstr(line, "=");
c2cc9f0a 621 if (!dot) {
36eb9bde 622 ERROR("invalid configuration line: %s", line);
c2cc9f0a 623 return -1;
624 }
a871ff6b 625
c2cc9f0a 626 *dot = '\0';
627 value = dot + 1;
628
b2718c72 629 key = line;
630 key[lxc_char_right_gc(key, strlen(key))] = '\0';
c2cc9f0a 631
b2718c72 632 value += lxc_char_left_gc(value, strlen(value));
633 value[lxc_char_right_gc(value, strlen(value))] = '\0';
c2cc9f0a 634
635 config = getconfig(key);
636 if (!config) {
36eb9bde 637 ERROR("unknow key %s", key);
c2cc9f0a 638 return -1;
639 }
640
576f946d 641 return config->cb(key, value, data);
c2cc9f0a 642}
643
b2718c72 644int lxc_config_read(const char *file, struct lxc_conf *conf)
c2cc9f0a 645{
646 char buffer[MAXPATHLEN];
c2cc9f0a 647
b2718c72 648 return lxc_file_for_each_line(file, parse_line, buffer,
649 sizeof(buffer), conf);
c2cc9f0a 650}