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