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