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