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