]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
ovl_rsync: make sure to umount
[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 <daniel.lezcano at free.fr>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <signal.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/utsname.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <net/if.h>
39 #include <time.h>
40 #include <dirent.h>
41
42 #include "parse.h"
43 #include "config.h"
44 #include "confile.h"
45 #include "utils.h"
46 #include "log.h"
47 #include "conf.h"
48 #include "network.h"
49 #include "lxcseccomp.h"
50
51 #if HAVE_SYS_PERSONALITY_H
52 #include <sys/personality.h>
53 #endif
54
55 lxc_log_define(lxc_confile, lxc);
56
57 static int config_personality(const char *, const char *, struct lxc_conf *);
58 static int config_pts(const char *, const char *, struct lxc_conf *);
59 static int config_tty(const char *, const char *, struct lxc_conf *);
60 static int config_ttydir(const char *, const char *, struct lxc_conf *);
61 static int config_kmsg(const char *, const char *, struct lxc_conf *);
62 static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
63 static int config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf *);
64 static int config_lsm_se_context(const char *, const char *, struct lxc_conf *);
65 static int config_cgroup(const char *, const char *, struct lxc_conf *);
66 static int config_idmap(const char *, const char *, struct lxc_conf *);
67 static int config_loglevel(const char *, const char *, struct lxc_conf *);
68 static int config_logfile(const char *, const char *, struct lxc_conf *);
69 static int config_mount(const char *, const char *, struct lxc_conf *);
70 static int config_mount_auto(const char *, const char *, struct lxc_conf *);
71 static int config_fstab(const char *, const char *, struct lxc_conf *);
72 static int config_rootfs(const char *, const char *, struct lxc_conf *);
73 static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
74 static int config_rootfs_options(const char *, const char *, struct lxc_conf *);
75 static int config_pivotdir(const char *, const char *, struct lxc_conf *);
76 static int config_utsname(const char *, const char *, struct lxc_conf *);
77 static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
78 static int config_network(const char *, const char *, struct lxc_conf *);
79 static int config_network_type(const char *, const char *, struct lxc_conf *);
80 static int config_network_flags(const char *, const char *, struct lxc_conf *);
81 static int config_network_link(const char *, const char *, struct lxc_conf *);
82 static int config_network_name(const char *, const char *, struct lxc_conf *);
83 static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
84 static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
85 static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
86 static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
87 static int config_network_mtu(const char *, const char *, struct lxc_conf *);
88 static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
89 static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
90 static int config_network_script_up(const char *, const char *, struct lxc_conf *);
91 static int config_network_script_down(const char *, const char *, struct lxc_conf *);
92 static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
93 static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
94 static int config_cap_drop(const char *, const char *, struct lxc_conf *);
95 static int config_cap_keep(const char *, const char *, struct lxc_conf *);
96 static int config_console(const char *, const char *, struct lxc_conf *);
97 static int config_console_logfile(const char *, const char *, struct lxc_conf *);
98 static int config_seccomp(const char *, const char *, struct lxc_conf *);
99 static int config_includefile(const char *, const char *, struct lxc_conf *);
100 static int config_network_nic(const char *, const char *, struct lxc_conf *);
101 static int config_autodev(const char *, const char *, struct lxc_conf *);
102 static int config_haltsignal(const char *, const char *, struct lxc_conf *);
103 static int config_rebootsignal(const char *, const char *, struct lxc_conf *);
104 static int config_stopsignal(const char *, const char *, struct lxc_conf *);
105 static int config_start(const char *, const char *, struct lxc_conf *);
106 static int config_group(const char *, const char *, struct lxc_conf *);
107 static int config_environment(const char *, const char *, struct lxc_conf *);
108 static int config_init_cmd(const char *, const char *, struct lxc_conf *);
109 static int config_init_uid(const char *, const char *, struct lxc_conf *);
110 static int config_init_gid(const char *, const char *, struct lxc_conf *);
111 static int config_ephemeral(const char *, const char *, struct lxc_conf *);
112
113 static struct lxc_config_t config[] = {
114
115 { "lxc.arch", config_personality },
116 { "lxc.pts", config_pts },
117 { "lxc.tty", config_tty },
118 { "lxc.devttydir", config_ttydir },
119 { "lxc.kmsg", config_kmsg },
120 { "lxc.aa_profile", config_lsm_aa_profile },
121 { "lxc.aa_allow_incomplete", config_lsm_aa_incomplete },
122 { "lxc.se_context", config_lsm_se_context },
123 { "lxc.cgroup", config_cgroup },
124 { "lxc.id_map", config_idmap },
125 { "lxc.loglevel", config_loglevel },
126 { "lxc.logfile", config_logfile },
127 { "lxc.mount.entry", config_mount },
128 { "lxc.mount.auto", config_mount_auto },
129 { "lxc.mount", config_fstab },
130 { "lxc.rootfs.mount", config_rootfs_mount },
131 { "lxc.rootfs.options", config_rootfs_options },
132 { "lxc.rootfs", config_rootfs },
133 { "lxc.pivotdir", config_pivotdir },
134 { "lxc.utsname", config_utsname },
135 { "lxc.hook.pre-start", config_hook },
136 { "lxc.hook.pre-mount", config_hook },
137 { "lxc.hook.mount", config_hook },
138 { "lxc.hook.autodev", config_hook },
139 { "lxc.hook.start", config_hook },
140 { "lxc.hook.post-stop", config_hook },
141 { "lxc.hook.clone", config_hook },
142 { "lxc.hook.destroy", config_hook },
143 { "lxc.hook", config_hook },
144 { "lxc.network.type", config_network_type },
145 { "lxc.network.flags", config_network_flags },
146 { "lxc.network.link", config_network_link },
147 { "lxc.network.name", config_network_name },
148 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
149 { "lxc.network.veth.pair", config_network_veth_pair },
150 { "lxc.network.script.up", config_network_script_up },
151 { "lxc.network.script.down", config_network_script_down },
152 { "lxc.network.hwaddr", config_network_hwaddr },
153 { "lxc.network.mtu", config_network_mtu },
154 { "lxc.network.vlan.id", config_network_vlan_id },
155 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
156 { "lxc.network.ipv4", config_network_ipv4 },
157 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
158 { "lxc.network.ipv6", config_network_ipv6 },
159 /* config_network_nic must come after all other 'lxc.network.*' entries */
160 { "lxc.network.", config_network_nic },
161 { "lxc.network", config_network },
162 { "lxc.cap.drop", config_cap_drop },
163 { "lxc.cap.keep", config_cap_keep },
164 { "lxc.console.logfile", config_console_logfile },
165 { "lxc.console", config_console },
166 { "lxc.seccomp", config_seccomp },
167 { "lxc.include", config_includefile },
168 { "lxc.autodev", config_autodev },
169 { "lxc.haltsignal", config_haltsignal },
170 { "lxc.rebootsignal", config_rebootsignal },
171 { "lxc.stopsignal", config_stopsignal },
172 { "lxc.start.auto", config_start },
173 { "lxc.start.delay", config_start },
174 { "lxc.start.order", config_start },
175 { "lxc.group", config_group },
176 { "lxc.environment", config_environment },
177 { "lxc.init_cmd", config_init_cmd },
178 { "lxc.init_uid", config_init_uid },
179 { "lxc.init_gid", config_init_gid },
180 { "lxc.ephemeral", config_ephemeral },
181 };
182
183 struct signame {
184 int num;
185 const char *name;
186 };
187
188 static const struct signame signames[] = {
189 { SIGHUP, "HUP" },
190 { SIGINT, "INT" },
191 { SIGQUIT, "QUIT" },
192 { SIGILL, "ILL" },
193 { SIGABRT, "ABRT" },
194 { SIGFPE, "FPE" },
195 { SIGKILL, "KILL" },
196 { SIGSEGV, "SEGV" },
197 { SIGPIPE, "PIPE" },
198 { SIGALRM, "ALRM" },
199 { SIGTERM, "TERM" },
200 { SIGUSR1, "USR1" },
201 { SIGUSR2, "USR2" },
202 { SIGCHLD, "CHLD" },
203 { SIGCONT, "CONT" },
204 { SIGSTOP, "STOP" },
205 { SIGTSTP, "TSTP" },
206 { SIGTTIN, "TTIN" },
207 { SIGTTOU, "TTOU" },
208 #ifdef SIGTRAP
209 { SIGTRAP, "TRAP" },
210 #endif
211 #ifdef SIGIOT
212 { SIGIOT, "IOT" },
213 #endif
214 #ifdef SIGEMT
215 { SIGEMT, "EMT" },
216 #endif
217 #ifdef SIGBUS
218 { SIGBUS, "BUS" },
219 #endif
220 #ifdef SIGSTKFLT
221 { SIGSTKFLT, "STKFLT" },
222 #endif
223 #ifdef SIGCLD
224 { SIGCLD, "CLD" },
225 #endif
226 #ifdef SIGURG
227 { SIGURG, "URG" },
228 #endif
229 #ifdef SIGXCPU
230 { SIGXCPU, "XCPU" },
231 #endif
232 #ifdef SIGXFSZ
233 { SIGXFSZ, "XFSZ" },
234 #endif
235 #ifdef SIGVTALRM
236 { SIGVTALRM, "VTALRM" },
237 #endif
238 #ifdef SIGPROF
239 { SIGPROF, "PROF" },
240 #endif
241 #ifdef SIGWINCH
242 { SIGWINCH, "WINCH" },
243 #endif
244 #ifdef SIGIO
245 { SIGIO, "IO" },
246 #endif
247 #ifdef SIGPOLL
248 { SIGPOLL, "POLL" },
249 #endif
250 #ifdef SIGINFO
251 { SIGINFO, "INFO" },
252 #endif
253 #ifdef SIGLOST
254 { SIGLOST, "LOST" },
255 #endif
256 #ifdef SIGPWR
257 { SIGPWR, "PWR" },
258 #endif
259 #ifdef SIGUNUSED
260 { SIGUNUSED, "UNUSED" },
261 #endif
262 #ifdef SIGSYS
263 { SIGSYS, "SYS" },
264 #endif
265 };
266
267 static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
268
269 extern struct lxc_config_t *lxc_getconfig(const char *key)
270 {
271 int i;
272
273 for (i = 0; i < config_size; i++)
274 if (!strncmp(config[i].name, key,
275 strlen(config[i].name)))
276 return &config[i];
277 return NULL;
278 }
279
280 #define strprint(str, inlen, ...) \
281 do { \
282 len = snprintf(str, inlen, ##__VA_ARGS__); \
283 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
284 fulllen += len; \
285 if (inlen > 0) { \
286 if (str) str += len; \
287 inlen -= len; \
288 if (inlen < 0) inlen = 0; \
289 } \
290 } while (0);
291
292 int lxc_listconfigs(char *retv, int inlen)
293 {
294 int i, fulllen = 0, len;
295
296 if (!retv)
297 inlen = 0;
298 else
299 memset(retv, 0, inlen);
300 for (i = 0; i < config_size; i++) {
301 char *s = config[i].name;
302 if (s[strlen(s)-1] == '.')
303 continue;
304 strprint(retv, inlen, "%s\n", s);
305 }
306 return fulllen;
307 }
308
309 static int config_string_item(char **conf_item, const char *value)
310 {
311 char *new_value;
312
313 if (!value || strlen(value) == 0) {
314 free(*conf_item);
315 *conf_item = NULL;
316 return 0;
317 }
318
319 new_value = strdup(value);
320 if (!new_value) {
321 SYSERROR("failed to strdup '%s': %m", value);
322 return -1;
323 }
324
325 free(*conf_item);
326 *conf_item = new_value;
327 return 0;
328 }
329
330 static int config_string_item_max(char **conf_item, const char *value,
331 size_t max)
332 {
333 if (strlen(value) >= max) {
334 ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
335 return -1;
336 }
337
338 return config_string_item(conf_item, value);
339 }
340
341 static int config_path_item(char **conf_item, const char *value)
342 {
343 return config_string_item_max(conf_item, value, PATH_MAX);
344 }
345
346 /*
347 * config entry is something like "lxc.network.0.ipv4"
348 * the key 'lxc.network.' was found. So we make sure next
349 * comes an integer, find the right callback (by rewriting
350 * the key), and call it.
351 */
352 static int config_network_nic(const char *key, const char *value,
353 struct lxc_conf *lxc_conf)
354 {
355 char *copy = strdup(key), *p;
356 int ret = -1;
357 struct lxc_config_t *config;
358
359 if (!copy) {
360 SYSERROR("failed to allocate memory");
361 return -1;
362 }
363 /*
364 * ok we know that to get here we've got "lxc.network."
365 * and it isn't any of the other network entries. So
366 * after the second . should come an integer (# of defined
367 * nic) followed by a valid entry.
368 */
369 if (*(key+12) < '0' || *(key+12) > '9')
370 goto out;
371 p = strchr(key+12, '.');
372 if (!p)
373 goto out;
374 strcpy(copy+12, p+1);
375 config = lxc_getconfig(copy);
376 if (!config) {
377 ERROR("unknown key %s", key);
378 goto out;
379 }
380 ret = config->cb(key, value, lxc_conf);
381
382 out:
383 free(copy);
384 return ret;
385 }
386
387 static int config_network(const char *key, const char *value,
388 struct lxc_conf *lxc_conf)
389 {
390 if (value && strlen(value)) {
391 ERROR("lxc.network must not have a value");
392 return -1;
393 }
394
395 return lxc_clear_config_network(lxc_conf);
396 }
397
398 static int macvlan_mode(int *valuep, const char *value);
399
400 static int config_network_type(const char *key, const char *value,
401 struct lxc_conf *lxc_conf)
402 {
403 struct lxc_list *network = &lxc_conf->network;
404 struct lxc_netdev *netdev;
405 struct lxc_list *list;
406
407 if (!value || strlen(value) == 0)
408 return lxc_clear_config_network(lxc_conf);
409
410 netdev = malloc(sizeof(*netdev));
411 if (!netdev) {
412 SYSERROR("failed to allocate memory");
413 return -1;
414 }
415
416 memset(netdev, 0, sizeof(*netdev));
417 lxc_list_init(&netdev->ipv4);
418 lxc_list_init(&netdev->ipv6);
419
420 list = malloc(sizeof(*list));
421 if (!list) {
422 SYSERROR("failed to allocate memory");
423 free(netdev);
424 return -1;
425 }
426
427 lxc_list_init(list);
428 list->elem = netdev;
429
430 lxc_list_add_tail(network, list);
431
432 if (!strcmp(value, "veth"))
433 netdev->type = LXC_NET_VETH;
434 else if (!strcmp(value, "macvlan")) {
435 netdev->type = LXC_NET_MACVLAN;
436 macvlan_mode(&netdev->priv.macvlan_attr.mode, "private");
437 }
438 else if (!strcmp(value, "vlan"))
439 netdev->type = LXC_NET_VLAN;
440 else if (!strcmp(value, "phys"))
441 netdev->type = LXC_NET_PHYS;
442 else if (!strcmp(value, "empty"))
443 netdev->type = LXC_NET_EMPTY;
444 else if (!strcmp(value, "none"))
445 netdev->type = LXC_NET_NONE;
446 else {
447 ERROR("invalid network type %s", value);
448 return -1;
449 }
450 return 0;
451 }
452
453 static int config_ip_prefix(struct in_addr *addr)
454 {
455 if (IN_CLASSA(addr->s_addr))
456 return 32 - IN_CLASSA_NSHIFT;
457 if (IN_CLASSB(addr->s_addr))
458 return 32 - IN_CLASSB_NSHIFT;
459 if (IN_CLASSC(addr->s_addr))
460 return 32 - IN_CLASSC_NSHIFT;
461
462 return 0;
463 }
464
465 /*
466 * if you have p="lxc.network.0.link", pass it p+12
467 * to get back '0' (the index of the nic)
468 */
469 static int get_network_netdev_idx(const char *key)
470 {
471 int ret, idx;
472
473 if (*key < '0' || *key > '9')
474 return -1;
475 ret = sscanf(key, "%d", &idx);
476 if (ret != 1)
477 return -1;
478 return idx;
479 }
480
481 /*
482 * if you have p="lxc.network.0", pass this p+12 and it will return
483 * the netdev of the first configured nic
484 */
485 static struct lxc_netdev *get_netdev_from_key(const char *key,
486 struct lxc_list *network)
487 {
488 int i = 0, idx = get_network_netdev_idx(key);
489 struct lxc_netdev *netdev = NULL;
490 struct lxc_list *it;
491 if (idx == -1)
492 return NULL;
493 lxc_list_for_each(it, network) {
494 if (idx == i++) {
495 netdev = it->elem;
496 break;
497 }
498 }
499 return netdev;
500 }
501
502 extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
503 char *retv, int inlen)
504 {
505 struct lxc_netdev *netdev;
506 int fulllen = 0, len;
507
508 netdev = get_netdev_from_key(key+12, &c->network);
509 if (!netdev)
510 return -1;
511
512 if (!retv)
513 inlen = 0;
514 else
515 memset(retv, 0, inlen);
516
517 strprint(retv, inlen, "script.up\n");
518 strprint(retv, inlen, "script.down\n");
519 if (netdev->type != LXC_NET_EMPTY) {
520 strprint(retv, inlen, "flags\n");
521 strprint(retv, inlen, "link\n");
522 strprint(retv, inlen, "name\n");
523 strprint(retv, inlen, "hwaddr\n");
524 strprint(retv, inlen, "mtu\n");
525 strprint(retv, inlen, "ipv6\n");
526 strprint(retv, inlen, "ipv6.gateway\n");
527 strprint(retv, inlen, "ipv4\n");
528 strprint(retv, inlen, "ipv4.gateway\n");
529 }
530 switch(netdev->type) {
531 case LXC_NET_VETH:
532 strprint(retv, inlen, "veth.pair\n");
533 break;
534 case LXC_NET_MACVLAN:
535 strprint(retv, inlen, "macvlan.mode\n");
536 break;
537 case LXC_NET_VLAN:
538 strprint(retv, inlen, "vlan.id\n");
539 break;
540 case LXC_NET_PHYS:
541 break;
542 }
543 return fulllen;
544 }
545
546 static struct lxc_netdev *network_netdev(const char *key, const char *value,
547 struct lxc_list *network)
548 {
549 struct lxc_netdev *netdev = NULL;
550
551 if (lxc_list_empty(network)) {
552 ERROR("network is not created for '%s' = '%s' option",
553 key, value);
554 return NULL;
555 }
556
557 if (get_network_netdev_idx(key+12) == -1)
558 netdev = lxc_list_last_elem(network);
559 else
560 netdev = get_netdev_from_key(key+12, network);
561
562 if (!netdev) {
563 ERROR("no network device defined for '%s' = '%s' option",
564 key, value);
565 return NULL;
566 }
567
568 return netdev;
569 }
570
571 static int network_ifname(char **valuep, const char *value)
572 {
573 return config_string_item_max(valuep, value, IFNAMSIZ);
574 }
575
576 #ifndef MACVLAN_MODE_PRIVATE
577 # define MACVLAN_MODE_PRIVATE 1
578 #endif
579
580 #ifndef MACVLAN_MODE_VEPA
581 # define MACVLAN_MODE_VEPA 2
582 #endif
583
584 #ifndef MACVLAN_MODE_BRIDGE
585 # define MACVLAN_MODE_BRIDGE 4
586 #endif
587
588 #ifndef MACVLAN_MODE_PASSTHRU
589 # define MACVLAN_MODE_PASSTHRU 8
590 #endif
591
592 static int macvlan_mode(int *valuep, const char *value)
593 {
594 struct mc_mode {
595 char *name;
596 int mode;
597 } m[] = {
598 { "private", MACVLAN_MODE_PRIVATE },
599 { "vepa", MACVLAN_MODE_VEPA },
600 { "bridge", MACVLAN_MODE_BRIDGE },
601 { "passthru", MACVLAN_MODE_PASSTHRU },
602 };
603
604 int i;
605
606 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
607 if (strcmp(m[i].name, value))
608 continue;
609
610 *valuep = m[i].mode;
611 return 0;
612 }
613
614 return -1;
615 }
616
617 static int rand_complete_hwaddr(char *hwaddr)
618 {
619 const char hex[] = "0123456789abcdef";
620 char *curs = hwaddr;
621
622 #ifndef HAVE_RAND_R
623 randseed(true);
624 #else
625 unsigned int seed=randseed(false);
626 #endif
627 while (*curs != '\0' && *curs != '\n')
628 {
629 if ( *curs == 'x' || *curs == 'X' ) {
630 if (curs - hwaddr == 1) {
631 //ensure address is unicast
632 #ifdef HAVE_RAND_R
633 *curs = hex[rand_r(&seed) & 0x0E];
634 } else {
635 *curs = hex[rand_r(&seed) & 0x0F];
636 #else
637 *curs = hex[rand() & 0x0E];
638 } else {
639 *curs = hex[rand() & 0x0F];
640 #endif
641 }
642 }
643 curs++;
644 }
645 return 0;
646 }
647
648 static int config_network_flags(const char *key, const char *value,
649 struct lxc_conf *lxc_conf)
650 {
651 struct lxc_netdev *netdev;
652
653 netdev = network_netdev(key, value, &lxc_conf->network);
654 if (!netdev)
655 return -1;
656
657 netdev->flags |= IFF_UP;
658
659 return 0;
660 }
661
662 static int config_network_link(const char *key, const char *value,
663 struct lxc_conf *lxc_conf)
664 {
665 struct lxc_netdev *netdev;
666
667 netdev = network_netdev(key, value, &lxc_conf->network);
668 if (!netdev)
669 return -1;
670
671 return network_ifname(&netdev->link, value);
672 }
673
674 static int config_network_name(const char *key, const char *value,
675 struct lxc_conf *lxc_conf)
676 {
677 struct lxc_netdev *netdev;
678
679 netdev = network_netdev(key, value, &lxc_conf->network);
680 if (!netdev)
681 return -1;
682
683 return network_ifname(&netdev->name, value);
684 }
685
686 static int config_network_veth_pair(const char *key, const char *value,
687 struct lxc_conf *lxc_conf)
688 {
689 struct lxc_netdev *netdev;
690
691 netdev = network_netdev(key, value, &lxc_conf->network);
692 if (!netdev)
693 return -1;
694
695 if (netdev->type != LXC_NET_VETH) {
696 ERROR("Invalid veth pair for a non-veth netdev");
697 return -1;
698 }
699 return network_ifname(&netdev->priv.veth_attr.pair, value);
700 }
701
702 static int config_network_macvlan_mode(const char *key, const char *value,
703 struct lxc_conf *lxc_conf)
704 {
705 struct lxc_netdev *netdev;
706
707 netdev = network_netdev(key, value, &lxc_conf->network);
708 if (!netdev)
709 return -1;
710
711 if (netdev->type != LXC_NET_MACVLAN) {
712 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
713 return -1;
714 }
715 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
716 }
717
718 static int config_network_hwaddr(const char *key, const char *value,
719 struct lxc_conf *lxc_conf)
720 {
721 struct lxc_netdev *netdev;
722
723 char *new_value = strdup(value);
724 if (!new_value) {
725 SYSERROR("failed to strdup '%s': %m", value);
726 return -1;
727 }
728 rand_complete_hwaddr(new_value);
729
730 netdev = network_netdev(key, new_value, &lxc_conf->network);
731 if (!netdev) {
732 free(new_value);
733 return -1;
734 };
735
736 if (!new_value || strlen(new_value) == 0) {
737 free(new_value);
738 netdev->hwaddr = NULL;
739 return 0;
740 }
741
742 netdev->hwaddr = new_value;
743 return 0;
744 }
745
746 static int config_network_vlan_id(const char *key, const char *value,
747 struct lxc_conf *lxc_conf)
748 {
749 struct lxc_netdev *netdev;
750
751 netdev = network_netdev(key, value, &lxc_conf->network);
752 if (!netdev)
753 return -1;
754
755 if (netdev->type != LXC_NET_VLAN) {
756 ERROR("Invalid vlan.id for a non-macvlan netdev");
757 return -1;
758 }
759 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
760 return -1;
761
762 return 0;
763 }
764
765 static int config_network_mtu(const char *key, const char *value,
766 struct lxc_conf *lxc_conf)
767 {
768 struct lxc_netdev *netdev;
769
770 netdev = network_netdev(key, value, &lxc_conf->network);
771 if (!netdev)
772 return -1;
773
774 return config_string_item(&netdev->mtu, value);
775 }
776
777 static int config_network_ipv4(const char *key, const char *value,
778 struct lxc_conf *lxc_conf)
779 {
780 struct lxc_netdev *netdev;
781 struct lxc_inetdev *inetdev;
782 struct lxc_list *list;
783 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
784
785 netdev = network_netdev(key, value, &lxc_conf->network);
786 if (!netdev)
787 return -1;
788
789 inetdev = malloc(sizeof(*inetdev));
790 if (!inetdev) {
791 SYSERROR("failed to allocate ipv4 address");
792 return -1;
793 }
794 memset(inetdev, 0, sizeof(*inetdev));
795
796 list = malloc(sizeof(*list));
797 if (!list) {
798 SYSERROR("failed to allocate memory");
799 free(inetdev);
800 return -1;
801 }
802
803 lxc_list_init(list);
804 list->elem = inetdev;
805
806 addr = strdup(value);
807 if (!addr) {
808 ERROR("no address specified");
809 free(inetdev);
810 free(list);
811 return -1;
812 }
813
814 cursor = strstr(addr, " ");
815 if (cursor) {
816 *cursor = '\0';
817 bcast = cursor + 1;
818 }
819
820 slash = strstr(addr, "/");
821 if (slash) {
822 *slash = '\0';
823 prefix = slash + 1;
824 }
825
826 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
827 SYSERROR("invalid ipv4 address: %s", value);
828 free(inetdev);
829 free(addr);
830 free(list);
831 return -1;
832 }
833
834 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
835 SYSERROR("invalid ipv4 broadcast address: %s", value);
836 free(inetdev);
837 free(list);
838 free(addr);
839 return -1;
840 }
841
842 /* no prefix specified, determine it from the network class */
843 inetdev->prefix = prefix ? atoi(prefix) :
844 config_ip_prefix(&inetdev->addr);
845
846 /* if no broadcast address, let compute one from the
847 * prefix and address
848 */
849 if (!bcast) {
850 inetdev->bcast.s_addr = inetdev->addr.s_addr;
851 inetdev->bcast.s_addr |=
852 htonl(INADDR_BROADCAST >> inetdev->prefix);
853 }
854
855 lxc_list_add_tail(&netdev->ipv4, list);
856
857 free(addr);
858 return 0;
859 }
860
861 static int config_network_ipv4_gateway(const char *key, const char *value,
862 struct lxc_conf *lxc_conf)
863 {
864 struct lxc_netdev *netdev;
865
866 netdev = network_netdev(key, value, &lxc_conf->network);
867 if (!netdev)
868 return -1;
869
870 free(netdev->ipv4_gateway);
871
872 if (!value || strlen(value) == 0) {
873 netdev->ipv4_gateway = NULL;
874 } else if (!strcmp(value, "auto")) {
875 netdev->ipv4_gateway = NULL;
876 netdev->ipv4_gateway_auto = true;
877 } else {
878 struct in_addr *gw;
879
880 gw = malloc(sizeof(*gw));
881 if (!gw) {
882 SYSERROR("failed to allocate ipv4 gateway address");
883 return -1;
884 }
885
886 if (!inet_pton(AF_INET, value, gw)) {
887 SYSERROR("invalid ipv4 gateway address: %s", value);
888 free(gw);
889 return -1;
890 }
891
892 netdev->ipv4_gateway = gw;
893 netdev->ipv4_gateway_auto = false;
894 }
895
896 return 0;
897 }
898
899 static int config_network_ipv6(const char *key, const char *value,
900 struct lxc_conf *lxc_conf)
901 {
902 struct lxc_netdev *netdev;
903 struct lxc_inet6dev *inet6dev;
904 struct lxc_list *list;
905 char *slash,*valdup;
906 char *netmask;
907
908 netdev = network_netdev(key, value, &lxc_conf->network);
909 if (!netdev)
910 return -1;
911
912 inet6dev = malloc(sizeof(*inet6dev));
913 if (!inet6dev) {
914 SYSERROR("failed to allocate ipv6 address");
915 return -1;
916 }
917 memset(inet6dev, 0, sizeof(*inet6dev));
918
919 list = malloc(sizeof(*list));
920 if (!list) {
921 SYSERROR("failed to allocate memory");
922 free(inet6dev);
923 return -1;
924 }
925
926 lxc_list_init(list);
927 list->elem = inet6dev;
928
929 valdup = strdup(value);
930 if (!valdup) {
931 ERROR("no address specified");
932 free(list);
933 free(inet6dev);
934 return -1;
935 }
936
937 inet6dev->prefix = 64;
938 slash = strstr(valdup, "/");
939 if (slash) {
940 *slash = '\0';
941 netmask = slash + 1;
942 inet6dev->prefix = atoi(netmask);
943 }
944
945 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
946 SYSERROR("invalid ipv6 address: %s", valdup);
947 free(list);
948 free(inet6dev);
949 free(valdup);
950 return -1;
951 }
952
953 lxc_list_add_tail(&netdev->ipv6, list);
954
955 free(valdup);
956 return 0;
957 }
958
959 static int config_network_ipv6_gateway(const char *key, const char *value,
960 struct lxc_conf *lxc_conf)
961 {
962 struct lxc_netdev *netdev;
963
964 netdev = network_netdev(key, value, &lxc_conf->network);
965 if (!netdev)
966 return -1;
967
968 free(netdev->ipv6_gateway);
969
970 if (!value || strlen(value) == 0) {
971 netdev->ipv4_gateway = NULL;
972 } else if (!strcmp(value, "auto")) {
973 netdev->ipv6_gateway = NULL;
974 netdev->ipv6_gateway_auto = true;
975 } else {
976 struct in6_addr *gw;
977
978 gw = malloc(sizeof(*gw));
979 if (!gw) {
980 SYSERROR("failed to allocate ipv6 gateway address");
981 return -1;
982 }
983
984 if (!inet_pton(AF_INET6, value, gw)) {
985 SYSERROR("invalid ipv6 gateway address: %s", value);
986 free(gw);
987 return -1;
988 }
989
990 netdev->ipv6_gateway = gw;
991 netdev->ipv6_gateway_auto = false;
992 }
993
994 return 0;
995 }
996
997 static int config_network_script_up(const char *key, const char *value,
998 struct lxc_conf *lxc_conf)
999 {
1000 struct lxc_netdev *netdev;
1001
1002 netdev = network_netdev(key, value, &lxc_conf->network);
1003 if (!netdev)
1004 return -1;
1005
1006 return config_string_item(&netdev->upscript, value);
1007 }
1008
1009 static int config_network_script_down(const char *key, const char *value,
1010 struct lxc_conf *lxc_conf)
1011 {
1012 struct lxc_netdev *netdev;
1013
1014 netdev = network_netdev(key, value, &lxc_conf->network);
1015 if (!netdev)
1016 return -1;
1017
1018 return config_string_item(&netdev->downscript, value);
1019 }
1020
1021 static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
1022 {
1023 struct lxc_list *hooklist;
1024
1025 hooklist = malloc(sizeof(*hooklist));
1026 if (!hooklist) {
1027 free(hook);
1028 return -1;
1029 }
1030 hooklist->elem = hook;
1031 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
1032 return 0;
1033 }
1034
1035 static int config_seccomp(const char *key, const char *value,
1036 struct lxc_conf *lxc_conf)
1037 {
1038 return config_path_item(&lxc_conf->seccomp, value);
1039 }
1040
1041 static int config_init_cmd(const char *key, const char *value,
1042 struct lxc_conf *lxc_conf)
1043 {
1044 return config_path_item(&lxc_conf->init_cmd, value);
1045 }
1046
1047 static int config_init_uid(const char *key, const char *value,
1048 struct lxc_conf *lxc_conf)
1049 {
1050 lxc_conf->init_uid = atoi(value);
1051 return 0;
1052 }
1053
1054 static int config_init_gid(const char *key, const char *value,
1055 struct lxc_conf *lxc_conf)
1056 {
1057 lxc_conf->init_gid = atoi(value);
1058 return 0;
1059 }
1060
1061 static int config_hook(const char *key, const char *value,
1062 struct lxc_conf *lxc_conf)
1063 {
1064 char *copy;
1065
1066 if (!value || strlen(value) == 0)
1067 return lxc_clear_hooks(lxc_conf, key);
1068
1069 if (strcmp(key, "lxc.hook") == 0) {
1070 ERROR("lxc.hook cannot take a value");
1071 return -1;
1072 }
1073 copy = strdup(value);
1074 if (!copy) {
1075 SYSERROR("failed to dup string '%s'", value);
1076 return -1;
1077 }
1078 if (strcmp(key, "lxc.hook.pre-start") == 0)
1079 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
1080 else if (strcmp(key, "lxc.hook.pre-mount") == 0)
1081 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
1082 else if (strcmp(key, "lxc.hook.autodev") == 0)
1083 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
1084 else if (strcmp(key, "lxc.hook.mount") == 0)
1085 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
1086 else if (strcmp(key, "lxc.hook.start") == 0)
1087 return add_hook(lxc_conf, LXCHOOK_START, copy);
1088 else if (strcmp(key, "lxc.hook.post-stop") == 0)
1089 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
1090 else if (strcmp(key, "lxc.hook.clone") == 0)
1091 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
1092 else if (strcmp(key, "lxc.hook.destroy") == 0)
1093 return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
1094 SYSERROR("Unknown key: %s", key);
1095 free(copy);
1096 return -1;
1097 }
1098
1099 static int config_personality(const char *key, const char *value,
1100 struct lxc_conf *lxc_conf)
1101 {
1102 signed long personality = lxc_config_parse_arch(value);
1103
1104 if (personality >= 0)
1105 lxc_conf->personality = personality;
1106 else
1107 WARN("unsupported personality '%s'", value);
1108
1109 return 0;
1110 }
1111
1112 static int config_pts(const char *key, const char *value,
1113 struct lxc_conf *lxc_conf)
1114 {
1115 int maxpts = atoi(value);
1116
1117 lxc_conf->pts = maxpts;
1118
1119 return 0;
1120 }
1121
1122 static int config_start(const char *key, const char *value,
1123 struct lxc_conf *lxc_conf)
1124 {
1125 if(strcmp(key, "lxc.start.auto") == 0) {
1126 lxc_conf->start_auto = atoi(value);
1127 return 0;
1128 }
1129 else if (strcmp(key, "lxc.start.delay") == 0) {
1130 lxc_conf->start_delay = atoi(value);
1131 return 0;
1132 }
1133 else if (strcmp(key, "lxc.start.order") == 0) {
1134 lxc_conf->start_order = atoi(value);
1135 return 0;
1136 }
1137 SYSERROR("Unknown key: %s", key);
1138 return -1;
1139 }
1140
1141 static int config_group(const char *key, const char *value,
1142 struct lxc_conf *lxc_conf)
1143 {
1144 char *groups, *groupptr, *sptr, *token;
1145 struct lxc_list *grouplist;
1146 int ret = -1;
1147
1148 if (!strlen(value))
1149 return lxc_clear_groups(lxc_conf);
1150
1151 groups = strdup(value);
1152 if (!groups) {
1153 SYSERROR("failed to dup '%s'", value);
1154 return -1;
1155 }
1156
1157 /* in case several groups are specified in a single line
1158 * split these groups in a single element for the list */
1159 for (groupptr = groups;;groupptr = NULL) {
1160 token = strtok_r(groupptr, " \t", &sptr);
1161 if (!token) {
1162 ret = 0;
1163 break;
1164 }
1165
1166 grouplist = malloc(sizeof(*grouplist));
1167 if (!grouplist) {
1168 SYSERROR("failed to allocate groups list");
1169 break;
1170 }
1171
1172 grouplist->elem = strdup(token);
1173 if (!grouplist->elem) {
1174 SYSERROR("failed to dup '%s'", token);
1175 free(grouplist);
1176 break;
1177 }
1178
1179 lxc_list_add_tail(&lxc_conf->groups, grouplist);
1180 }
1181
1182 free(groups);
1183
1184 return ret;
1185 }
1186
1187 static int config_environment(const char *key, const char *value,
1188 struct lxc_conf *lxc_conf)
1189 {
1190 struct lxc_list *list_item = NULL;
1191
1192 if (!strlen(value))
1193 return lxc_clear_environment(lxc_conf);
1194
1195 list_item = malloc(sizeof(*list_item));
1196 if (!list_item)
1197 goto freak_out;
1198
1199 list_item->elem = strdup(value);
1200
1201 if (!list_item->elem)
1202 goto freak_out;
1203
1204 lxc_list_add_tail(&lxc_conf->environment, list_item);
1205
1206 return 0;
1207
1208 freak_out:
1209 free(list_item);
1210
1211 return -1;
1212 }
1213
1214 static int config_tty(const char *key, const char *value,
1215 struct lxc_conf *lxc_conf)
1216 {
1217 int nbtty = atoi(value);
1218
1219 lxc_conf->tty = nbtty;
1220
1221 return 0;
1222 }
1223
1224 static int config_ttydir(const char *key, const char *value,
1225 struct lxc_conf *lxc_conf)
1226 {
1227 return config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1);
1228 }
1229
1230 static int config_kmsg(const char *key, const char *value,
1231 struct lxc_conf *lxc_conf)
1232 {
1233 int v = atoi(value);
1234
1235 lxc_conf->kmsg = v;
1236
1237 return 0;
1238 }
1239
1240 static int config_lsm_aa_profile(const char *key, const char *value,
1241 struct lxc_conf *lxc_conf)
1242 {
1243 return config_string_item(&lxc_conf->lsm_aa_profile, value);
1244 }
1245
1246 static int config_lsm_aa_incomplete(const char *key, const char *value,
1247 struct lxc_conf *lxc_conf)
1248 {
1249 int v = atoi(value);
1250
1251 lxc_conf->lsm_aa_allow_incomplete = v == 1 ? 1 : 0;
1252
1253 return 0;
1254 }
1255
1256 static int config_lsm_se_context(const char *key, const char *value,
1257 struct lxc_conf *lxc_conf)
1258 {
1259 return config_string_item(&lxc_conf->lsm_se_context, value);
1260 }
1261
1262 static int config_logfile(const char *key, const char *value,
1263 struct lxc_conf *c)
1264 {
1265 int ret;
1266
1267 // store these values in the lxc_conf, and then try to set for
1268 // actual current logging.
1269 ret = config_path_item(&c->logfile, value);
1270 if (ret == 0)
1271 ret = lxc_log_set_file(&c->logfd, c->logfile);
1272 return ret;
1273 }
1274
1275 static int config_loglevel(const char *key, const char *value,
1276 struct lxc_conf *lxc_conf)
1277 {
1278 int newlevel;
1279
1280 if (!value || strlen(value) == 0)
1281 return 0;
1282
1283 if (value[0] >= '0' && value[0] <= '9')
1284 newlevel = atoi(value);
1285 else
1286 newlevel = lxc_log_priority_to_int(value);
1287 // store these values in the lxc_conf, and then try to set for
1288 // actual current logging.
1289 lxc_conf->loglevel = newlevel;
1290 return lxc_log_set_level(&lxc_conf->loglevel, newlevel);
1291 }
1292
1293 static int config_autodev(const char *key, const char *value,
1294 struct lxc_conf *lxc_conf)
1295 {
1296 int v = atoi(value);
1297
1298 lxc_conf->autodev = v;
1299
1300 return 0;
1301 }
1302
1303 static int sig_num(const char *sig)
1304 {
1305 int n;
1306 char *endp = NULL;
1307
1308 errno = 0;
1309 n = strtol(sig, &endp, 10);
1310 if (sig == endp || n < 0 || errno != 0)
1311 return -1;
1312 return n;
1313 }
1314
1315 static int rt_sig_num(const char *signame)
1316 {
1317 int sig_n = 0;
1318 int rtmax = 0;
1319
1320 if (strncasecmp(signame, "max-", 4) == 0) {
1321 rtmax = 1;
1322 }
1323 signame += 4;
1324 if (!isdigit(*signame))
1325 return -1;
1326 sig_n = sig_num(signame);
1327 sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
1328 if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
1329 return -1;
1330 return sig_n;
1331 }
1332
1333 static int sig_parse(const char *signame) {
1334 int n;
1335
1336 if (isdigit(*signame)) {
1337 return sig_num(signame);
1338 } else if (strncasecmp(signame, "sig", 3) == 0) {
1339 signame += 3;
1340 if (strncasecmp(signame, "rt", 2) == 0)
1341 return rt_sig_num(signame + 2);
1342 for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
1343 if (strcasecmp (signames[n].name, signame) == 0)
1344 return signames[n].num;
1345 }
1346 }
1347 return -1;
1348 }
1349
1350 static int config_haltsignal(const char *key, const char *value,
1351 struct lxc_conf *lxc_conf)
1352 {
1353 int sig_n = sig_parse(value);
1354
1355 if (sig_n < 0)
1356 return -1;
1357 lxc_conf->haltsignal = sig_n;
1358
1359 return 0;
1360 }
1361
1362 static int config_rebootsignal(const char *key, const char *value,
1363 struct lxc_conf *lxc_conf)
1364 {
1365 int sig_n = sig_parse(value);
1366
1367 if (sig_n < 0)
1368 return -1;
1369 lxc_conf->rebootsignal = sig_n;
1370
1371 return 0;
1372 }
1373
1374 static int config_stopsignal(const char *key, const char *value,
1375 struct lxc_conf *lxc_conf)
1376 {
1377 int sig_n = sig_parse(value);
1378
1379 if (sig_n < 0)
1380 return -1;
1381 lxc_conf->stopsignal = sig_n;
1382
1383 return 0;
1384 }
1385
1386 static int config_cgroup(const char *key, const char *value,
1387 struct lxc_conf *lxc_conf)
1388 {
1389 char *token = "lxc.cgroup.";
1390 char *subkey;
1391 struct lxc_list *cglist = NULL;
1392 struct lxc_cgroup *cgelem = NULL;
1393
1394 if (!value || strlen(value) == 0)
1395 return lxc_clear_cgroups(lxc_conf, key);
1396
1397 subkey = strstr(key, token);
1398
1399 if (!subkey)
1400 return -1;
1401
1402 if (!strlen(subkey))
1403 return -1;
1404
1405 if (strlen(subkey) == strlen(token))
1406 return -1;
1407
1408 subkey += strlen(token);
1409
1410 cglist = malloc(sizeof(*cglist));
1411 if (!cglist)
1412 goto out;
1413
1414 cgelem = malloc(sizeof(*cgelem));
1415 if (!cgelem)
1416 goto out;
1417 memset(cgelem, 0, sizeof(*cgelem));
1418
1419 cgelem->subsystem = strdup(subkey);
1420 cgelem->value = strdup(value);
1421
1422 if (!cgelem->subsystem || !cgelem->value)
1423 goto out;
1424
1425 cglist->elem = cgelem;
1426
1427 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
1428
1429 return 0;
1430
1431 out:
1432 free(cglist);
1433
1434 if (cgelem) {
1435 free(cgelem->subsystem);
1436
1437 free(cgelem->value);
1438
1439 free(cgelem);
1440 }
1441
1442 return -1;
1443 }
1444
1445 static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf)
1446 {
1447 char *token = "lxc.id_map";
1448 char *subkey;
1449 struct lxc_list *idmaplist = NULL;
1450 struct id_map *idmap = NULL;
1451 unsigned long hostid, nsid, range;
1452 char type;
1453 int ret;
1454
1455 if (!value || strlen(value) == 0)
1456 return lxc_clear_idmaps(lxc_conf);
1457
1458 subkey = strstr(key, token);
1459
1460 if (!subkey)
1461 return -1;
1462
1463 if (!strlen(subkey))
1464 return -1;
1465
1466 idmaplist = malloc(sizeof(*idmaplist));
1467 if (!idmaplist)
1468 goto out;
1469
1470 idmap = malloc(sizeof(*idmap));
1471 if (!idmap)
1472 goto out;
1473 memset(idmap, 0, sizeof(*idmap));
1474
1475 ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range);
1476 if (ret != 4)
1477 goto out;
1478
1479 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
1480 if (type == 'u')
1481 idmap->idtype = ID_TYPE_UID;
1482 else if (type == 'g')
1483 idmap->idtype = ID_TYPE_GID;
1484 else
1485 goto out;
1486
1487 idmap->hostid = hostid;
1488 idmap->nsid = nsid;
1489 idmap->range = range;
1490
1491 idmaplist->elem = idmap;
1492 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
1493
1494 return 0;
1495
1496 out:
1497 free(idmaplist);
1498
1499 if (idmap) {
1500 free(idmap);
1501 }
1502
1503 return -1;
1504 }
1505
1506 static int config_fstab(const char *key, const char *value,
1507 struct lxc_conf *lxc_conf)
1508 {
1509 if (!value || strlen(value) == 0)
1510 return -1;
1511 return config_path_item(&lxc_conf->fstab, value);
1512 }
1513
1514 static int config_mount_auto(const char *key, const char *value,
1515 struct lxc_conf *lxc_conf)
1516 {
1517 char *autos, *autoptr, *sptr, *token;
1518 static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = {
1519 { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1520 { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1521 { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
1522 { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
1523 { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
1524 { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
1525 { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
1526 { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
1527 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
1528 { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
1529 { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
1530 { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
1531 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
1532 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
1533 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
1534 /* NB: For adding anything that is just a single on/off, but has
1535 * no options: keep mask and flag identical and just define the
1536 * enum value as an unused bit so far
1537 */
1538 { NULL, 0 }
1539 };
1540 int i;
1541 int ret = -1;
1542
1543 if (!value || strlen(value) == 0) {
1544 lxc_conf->auto_mounts = 0;
1545 return 0;
1546 }
1547
1548 autos = strdup(value);
1549 if (!autos) {
1550 SYSERROR("failed to dup '%s'", value);
1551 return -1;
1552 }
1553
1554 for (autoptr = autos; ; autoptr = NULL) {
1555 token = strtok_r(autoptr, " \t", &sptr);
1556 if (!token) {
1557 ret = 0;
1558 break;
1559 }
1560
1561 for (i = 0; allowed_auto_mounts[i].token; i++) {
1562 if (!strcmp(allowed_auto_mounts[i].token, token))
1563 break;
1564 }
1565
1566 if (!allowed_auto_mounts[i].token) {
1567 ERROR("Invalid filesystem to automount: %s", token);
1568 break;
1569 }
1570
1571 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
1572 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
1573 }
1574
1575 free(autos);
1576
1577 return ret;
1578 }
1579
1580 static int config_mount(const char *key, const char *value,
1581 struct lxc_conf *lxc_conf)
1582 {
1583 char *mntelem;
1584 struct lxc_list *mntlist;
1585
1586 if (!value || strlen(value) == 0)
1587 return lxc_clear_mount_entries(lxc_conf);
1588
1589 mntlist = malloc(sizeof(*mntlist));
1590 if (!mntlist)
1591 return -1;
1592
1593 mntelem = strdup(value);
1594 if (!mntelem) {
1595 free(mntlist);
1596 return -1;
1597 }
1598 mntlist->elem = mntelem;
1599
1600 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1601
1602 return 0;
1603 }
1604
1605 static int config_cap_keep(const char *key, const char *value,
1606 struct lxc_conf *lxc_conf)
1607 {
1608 char *keepcaps, *keepptr, *sptr, *token;
1609 struct lxc_list *keeplist;
1610 int ret = -1;
1611
1612 if (!strlen(value))
1613 return lxc_clear_config_keepcaps(lxc_conf);
1614
1615 keepcaps = strdup(value);
1616 if (!keepcaps) {
1617 SYSERROR("failed to dup '%s'", value);
1618 return -1;
1619 }
1620
1621 /* in case several capability keep is specified in a single line
1622 * split these caps in a single element for the list */
1623 for (keepptr = keepcaps;;keepptr = NULL) {
1624 token = strtok_r(keepptr, " \t", &sptr);
1625 if (!token) {
1626 ret = 0;
1627 break;
1628 }
1629
1630 if (!strcmp(token, "none"))
1631 lxc_clear_config_keepcaps(lxc_conf);
1632
1633 keeplist = malloc(sizeof(*keeplist));
1634 if (!keeplist) {
1635 SYSERROR("failed to allocate keepcap list");
1636 break;
1637 }
1638
1639 keeplist->elem = strdup(token);
1640 if (!keeplist->elem) {
1641 SYSERROR("failed to dup '%s'", token);
1642 free(keeplist);
1643 break;
1644 }
1645
1646 lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
1647 }
1648
1649 free(keepcaps);
1650
1651 return ret;
1652 }
1653
1654 static int config_cap_drop(const char *key, const char *value,
1655 struct lxc_conf *lxc_conf)
1656 {
1657 char *dropcaps, *dropptr, *sptr, *token;
1658 struct lxc_list *droplist;
1659 int ret = -1;
1660
1661 if (!strlen(value))
1662 return lxc_clear_config_caps(lxc_conf);
1663
1664 dropcaps = strdup(value);
1665 if (!dropcaps) {
1666 SYSERROR("failed to dup '%s'", value);
1667 return -1;
1668 }
1669
1670 /* in case several capability drop is specified in a single line
1671 * split these caps in a single element for the list */
1672 for (dropptr = dropcaps;;dropptr = NULL) {
1673 token = strtok_r(dropptr, " \t", &sptr);
1674 if (!token) {
1675 ret = 0;
1676 break;
1677 }
1678
1679 droplist = malloc(sizeof(*droplist));
1680 if (!droplist) {
1681 SYSERROR("failed to allocate drop list");
1682 break;
1683 }
1684
1685 droplist->elem = strdup(token);
1686 if (!droplist->elem) {
1687 SYSERROR("failed to dup '%s'", token);
1688 free(droplist);
1689 break;
1690 }
1691
1692 lxc_list_add_tail(&lxc_conf->caps, droplist);
1693 }
1694
1695 free(dropcaps);
1696
1697 return ret;
1698 }
1699
1700 static int config_console(const char *key, const char *value,
1701 struct lxc_conf *lxc_conf)
1702 {
1703 return config_path_item(&lxc_conf->console.path, value);
1704 }
1705
1706 static int config_console_logfile(const char *key, const char *value,
1707 struct lxc_conf *lxc_conf)
1708 {
1709 return config_path_item(&lxc_conf->console.log_path, value);
1710 }
1711
1712 /*
1713 * If we find a lxc.network.hwaddr in the original config file,
1714 * we expand it in the unexpanded_config, so that after a save_config
1715 * we store the hwaddr for re-use.
1716 * This is only called when reading the config file, not when executing
1717 * a lxc.include.
1718 * 'x' and 'X' are substituted in-place.
1719 */
1720 static void update_hwaddr(const char *line)
1721 {
1722 char *p;
1723
1724 line += lxc_char_left_gc(line, strlen(line));
1725 if (line[0] == '#')
1726 return;
1727 if (strncmp(line, "lxc.network.hwaddr", 18) != 0)
1728 return;
1729 p = strchr(line, '=');
1730 if (!p)
1731 return; // let config_network_hwaddr raise the error
1732 p++;
1733 while (isblank(*p))
1734 p++;
1735 if (!*p)
1736 return;
1737
1738 rand_complete_hwaddr(p);
1739 }
1740
1741 int append_unexp_config_line(const char *line, struct lxc_conf *conf)
1742 {
1743 size_t len = conf->unexpanded_len, linelen = strlen(line);
1744
1745 update_hwaddr(line);
1746
1747 while (conf->unexpanded_alloced <= len + linelen + 2) {
1748 char *tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024);
1749 if (!tmp)
1750 return -1;
1751 if (!conf->unexpanded_config)
1752 *tmp = '\0';
1753 conf->unexpanded_config = tmp;
1754 conf->unexpanded_alloced += 1024;
1755 }
1756 strcat(conf->unexpanded_config, line);
1757 conf->unexpanded_len += linelen;
1758 if (line[linelen-1] != '\n') {
1759 strcat(conf->unexpanded_config, "\n");
1760 conf->unexpanded_len++;
1761 }
1762 return 0;
1763 }
1764
1765 static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
1766 {
1767 struct dirent dirent, *direntp;
1768 DIR *dir;
1769 char path[MAXPATHLEN];
1770 int ret = -1, len;
1771
1772 dir = opendir(dirp);
1773 if (!dir) {
1774 SYSERROR("failed to open '%s'", dirp);
1775 return -1;
1776 }
1777
1778 while (!readdir_r(dir, &dirent, &direntp)) {
1779 const char *fnam;
1780 if (!direntp)
1781 break;
1782
1783 fnam = direntp->d_name;
1784 if (!strcmp(fnam, "."))
1785 continue;
1786
1787 if (!strcmp(fnam, ".."))
1788 continue;
1789
1790 len = strlen(fnam);
1791 if (len < 6 || strncmp(fnam+len-5, ".conf", 5) != 0)
1792 continue;
1793 len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam);
1794 if (len < 0 || len >= MAXPATHLEN) {
1795 ERROR("lxc.include filename too long under '%s'", dirp);
1796 ret = -1;
1797 goto out;
1798 }
1799
1800 ret = lxc_config_read(path, lxc_conf, true);
1801 if (ret < 0)
1802 goto out;
1803 }
1804 ret = 0;
1805
1806 out:
1807 if (closedir(dir))
1808 WARN("lxc.include dir: failed to close directory");
1809
1810 return ret;
1811 }
1812
1813 static int config_includefile(const char *key, const char *value,
1814 struct lxc_conf *lxc_conf)
1815 {
1816 if (is_dir(value))
1817 return do_includedir(value, lxc_conf);
1818
1819 return lxc_config_read(value, lxc_conf, true);
1820 }
1821
1822 static int config_rootfs(const char *key, const char *value,
1823 struct lxc_conf *lxc_conf)
1824 {
1825 return config_path_item(&lxc_conf->rootfs.path, value);
1826 }
1827
1828 static int config_rootfs_mount(const char *key, const char *value,
1829 struct lxc_conf *lxc_conf)
1830 {
1831 return config_path_item(&lxc_conf->rootfs.mount, value);
1832 }
1833
1834 static int config_rootfs_options(const char *key, const char *value,
1835 struct lxc_conf *lxc_conf)
1836 {
1837 return config_string_item(&lxc_conf->rootfs.options, value);
1838 }
1839
1840 static int config_pivotdir(const char *key, const char *value,
1841 struct lxc_conf *lxc_conf)
1842 {
1843 WARN("lxc.pivotdir is ignored. It will soon become an error.");
1844 return config_path_item(&lxc_conf->rootfs.pivot, value);
1845 }
1846
1847 static int config_utsname(const char *key, const char *value,
1848 struct lxc_conf *lxc_conf)
1849 {
1850 struct utsname *utsname;
1851
1852 utsname = malloc(sizeof(*utsname));
1853 if (!utsname) {
1854 SYSERROR("failed to allocate memory");
1855 return -1;
1856 }
1857
1858 if (strlen(value) >= sizeof(utsname->nodename)) {
1859 ERROR("node name '%s' is too long",
1860 value);
1861 free(utsname);
1862 return -1;
1863 }
1864
1865 strcpy(utsname->nodename, value);
1866 free(lxc_conf->utsname);
1867 lxc_conf->utsname = utsname;
1868
1869 return 0;
1870 }
1871
1872 struct parse_line_conf {
1873 struct lxc_conf *conf;
1874 bool from_include;
1875 };
1876
1877 static int parse_line(char *buffer, void *data)
1878 {
1879 struct lxc_config_t *config;
1880 char *line, *linep;
1881 char *dot;
1882 char *key;
1883 char *value;
1884 int ret = 0;
1885 struct parse_line_conf *plc = data;
1886
1887 if (lxc_is_line_empty(buffer))
1888 return 0;
1889
1890 /* we have to dup the buffer otherwise, at the re-exec for
1891 * reboot we modified the original string on the stack by
1892 * replacing '=' by '\0' below
1893 */
1894 linep = line = strdup(buffer);
1895 if (!line) {
1896 SYSERROR("failed to allocate memory for '%s'", buffer);
1897 return -1;
1898 }
1899
1900 if (!plc->from_include)
1901 if ((ret = append_unexp_config_line(line, plc->conf)))
1902 goto out;
1903
1904 line += lxc_char_left_gc(line, strlen(line));
1905
1906 /* ignore comments */
1907 if (line[0] == '#')
1908 goto out;
1909
1910 /* martian option - don't add it to the config itself */
1911 if (strncmp(line, "lxc.", 4))
1912 goto out;
1913
1914 ret = -1;
1915
1916 dot = strstr(line, "=");
1917 if (!dot) {
1918 ERROR("invalid configuration line: %s", line);
1919 goto out;
1920 }
1921
1922 *dot = '\0';
1923 value = dot + 1;
1924
1925 key = line;
1926 key[lxc_char_right_gc(key, strlen(key))] = '\0';
1927
1928 value += lxc_char_left_gc(value, strlen(value));
1929 value[lxc_char_right_gc(value, strlen(value))] = '\0';
1930
1931 config = lxc_getconfig(key);
1932 if (!config) {
1933 ERROR("unknown key %s", key);
1934 goto out;
1935 }
1936
1937 ret = config->cb(key, value, plc->conf);
1938
1939 out:
1940 free(linep);
1941 return ret;
1942 }
1943
1944 static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
1945 {
1946 struct parse_line_conf c;
1947
1948 c.conf = conf;
1949 c.from_include = false;
1950
1951 return parse_line(buffer, &c);
1952 }
1953
1954 int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
1955 {
1956 struct parse_line_conf c;
1957
1958 c.conf = conf;
1959 c.from_include = from_include;
1960
1961 if( access(file, R_OK) == -1 ) {
1962 return -1;
1963 }
1964
1965 /* Catch only the top level config file name in the structure */
1966 if( ! conf->rcfile )
1967 conf->rcfile = strdup( file );
1968
1969 return lxc_file_for_each_line(file, parse_line, &c);
1970 }
1971
1972 int lxc_config_define_add(struct lxc_list *defines, char* arg)
1973 {
1974 struct lxc_list *dent;
1975
1976 dent = malloc(sizeof(struct lxc_list));
1977 if (!dent)
1978 return -1;
1979
1980 dent->elem = arg;
1981 lxc_list_add_tail(defines, dent);
1982 return 0;
1983 }
1984
1985 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
1986 {
1987 struct lxc_list *it,*next;
1988 int ret = 0;
1989
1990 lxc_list_for_each(it, defines) {
1991 ret = lxc_config_readline(it->elem, conf);
1992 if (ret)
1993 break;
1994 }
1995
1996 lxc_list_for_each_safe(it, defines, next) {
1997 lxc_list_del(it);
1998 free(it);
1999 }
2000
2001 return ret;
2002 }
2003
2004 signed long lxc_config_parse_arch(const char *arch)
2005 {
2006 #if HAVE_SYS_PERSONALITY_H
2007 struct per_name {
2008 char *name;
2009 unsigned long per;
2010 } pername[] = {
2011 { "x86", PER_LINUX32 },
2012 { "linux32", PER_LINUX32 },
2013 { "i386", PER_LINUX32 },
2014 { "i486", PER_LINUX32 },
2015 { "i586", PER_LINUX32 },
2016 { "i686", PER_LINUX32 },
2017 { "athlon", PER_LINUX32 },
2018 { "linux64", PER_LINUX },
2019 { "x86_64", PER_LINUX },
2020 { "amd64", PER_LINUX },
2021 };
2022 size_t len = sizeof(pername) / sizeof(pername[0]);
2023
2024 int i;
2025
2026 for (i = 0; i < len; i++) {
2027 if (!strcmp(pername[i].name, arch))
2028 return pername[i].per;
2029 }
2030 #endif
2031
2032 return -1;
2033 }
2034
2035 int lxc_fill_elevated_privileges(char *flaglist, int *flags)
2036 {
2037 char *token, *saveptr = NULL;
2038 int i, aflag;
2039 struct { const char *token; int flag; } all_privs[] = {
2040 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
2041 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
2042 { "LSM", LXC_ATTACH_LSM_EXEC },
2043 { NULL, 0 }
2044 };
2045
2046 if (!flaglist) {
2047 /* for the sake of backward compatibility, drop all privileges
2048 if none is specified */
2049 for (i = 0; all_privs[i].token; i++) {
2050 *flags |= all_privs[i].flag;
2051 }
2052 return 0;
2053 }
2054
2055 token = strtok_r(flaglist, "|", &saveptr);
2056 while (token) {
2057 aflag = -1;
2058 for (i = 0; all_privs[i].token; i++) {
2059 if (!strcmp(all_privs[i].token, token))
2060 aflag = all_privs[i].flag;
2061 }
2062 if (aflag < 0)
2063 return -1;
2064
2065 *flags |= aflag;
2066
2067 token = strtok_r(NULL, "|", &saveptr);
2068 }
2069 return 0;
2070 }
2071
2072 static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
2073 {
2074 if (!retv)
2075 inlen = 0;
2076 else
2077 memset(retv, 0, inlen);
2078 return snprintf(retv, inlen, "%d", v);
2079 }
2080
2081 static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen)
2082 {
2083 int fulllen = 0;
2084
2085 if (!retv)
2086 inlen = 0;
2087 else
2088 memset(retv, 0, inlen);
2089
2090 #if HAVE_SYS_PERSONALITY_H
2091 int len = 0;
2092
2093 switch(c->personality) {
2094 case PER_LINUX32: strprint(retv, inlen, "i686"); break;
2095 case PER_LINUX: strprint(retv, inlen, "x86_64"); break;
2096 default: break;
2097 }
2098 #endif
2099
2100 return fulllen;
2101 }
2102
2103 /*
2104 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
2105 * then just the value(s) will be printed. Since there still could be
2106 * more than one, it is newline-separated.
2107 * (Maybe that's ambigous, since some values, i.e. devices.list, will
2108 * already have newlines?)
2109 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
2110 * in 'lxc.cgroup.subsystem.key = value' format.
2111 */
2112 static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
2113 const char *key)
2114 {
2115 int fulllen = 0, len;
2116 int all = 0;
2117 struct lxc_list *it;
2118
2119 if (!retv)
2120 inlen = 0;
2121 else
2122 memset(retv, 0, inlen);
2123
2124 if (strcmp(key, "all") == 0)
2125 all = 1;
2126
2127 lxc_list_for_each(it, &c->cgroup) {
2128 struct lxc_cgroup *cg = it->elem;
2129 if (all) {
2130 strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
2131 } else if (strcmp(cg->subsystem, key) == 0) {
2132 strprint(retv, inlen, "%s\n", cg->value);
2133 }
2134 }
2135 return fulllen;
2136 }
2137
2138 static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
2139 const char *key)
2140 {
2141 char *subkey;
2142 int len, fulllen = 0, found = -1;
2143 struct lxc_list *it;
2144 int i;
2145
2146 /* "lxc.hook.mount" */
2147 subkey = strchr(key, '.');
2148 if (subkey) subkey = strchr(subkey+1, '.');
2149 if (!subkey)
2150 return -1;
2151 subkey++;
2152 if (!*subkey)
2153 return -1;
2154 for (i=0; i<NUM_LXC_HOOKS; i++) {
2155 if (strcmp(lxchook_names[i], subkey) == 0) {
2156 found=i;
2157 break;
2158 }
2159 }
2160 if (found == -1)
2161 return -1;
2162
2163 if (!retv)
2164 inlen = 0;
2165 else
2166 memset(retv, 0, inlen);
2167
2168 lxc_list_for_each(it, &c->hooks[found]) {
2169 strprint(retv, inlen, "%s\n", (char *)it->elem);
2170 }
2171 return fulllen;
2172 }
2173
2174 static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen)
2175 {
2176 int len, fulllen = 0;
2177 struct lxc_list *it;
2178
2179 if (!retv)
2180 inlen = 0;
2181 else
2182 memset(retv, 0, inlen);
2183
2184 lxc_list_for_each(it, &c->groups) {
2185 strprint(retv, inlen, "%s\n", (char *)it->elem);
2186 }
2187 return fulllen;
2188 }
2189
2190 static int lxc_get_item_environment(struct lxc_conf *c, char *retv, int inlen)
2191 {
2192 int len, fulllen = 0;
2193 struct lxc_list *it;
2194
2195 if (!retv)
2196 inlen = 0;
2197 else
2198 memset(retv, 0, inlen);
2199
2200 lxc_list_for_each(it, &c->environment) {
2201 strprint(retv, inlen, "%s\n", (char *)it->elem);
2202 }
2203 return fulllen;
2204 }
2205
2206 static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen)
2207 {
2208 int len, fulllen = 0;
2209 struct lxc_list *it;
2210
2211 if (!retv)
2212 inlen = 0;
2213 else
2214 memset(retv, 0, inlen);
2215
2216 lxc_list_for_each(it, &c->caps) {
2217 strprint(retv, inlen, "%s\n", (char *)it->elem);
2218 }
2219 return fulllen;
2220 }
2221
2222 static int lxc_get_item_cap_keep(struct lxc_conf *c, char *retv, int inlen)
2223 {
2224 int len, fulllen = 0;
2225 struct lxc_list *it;
2226
2227 if (!retv)
2228 inlen = 0;
2229 else
2230 memset(retv, 0, inlen);
2231
2232 lxc_list_for_each(it, &c->keepcaps) {
2233 strprint(retv, inlen, "%s\n", (char *)it->elem);
2234 }
2235 return fulllen;
2236 }
2237
2238 static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen)
2239 {
2240 int len, fulllen = 0;
2241 struct lxc_list *it;
2242
2243 if (!retv)
2244 inlen = 0;
2245 else
2246 memset(retv, 0, inlen);
2247
2248 lxc_list_for_each(it, &c->mount_list) {
2249 strprint(retv, inlen, "%s\n", (char *)it->elem);
2250 }
2251 return fulllen;
2252 }
2253
2254 static int lxc_get_auto_mounts(struct lxc_conf *c, char *retv, int inlen)
2255 {
2256 int len, fulllen = 0;
2257 const char *sep = "";
2258
2259 if (!retv)
2260 inlen = 0;
2261 else
2262 memset(retv, 0, inlen);
2263
2264 if (!(c->auto_mounts & LXC_AUTO_ALL_MASK))
2265 return 0;
2266
2267 switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
2268 case LXC_AUTO_PROC_MIXED: strprint(retv, inlen, "%sproc:mixed", sep); sep = " "; break;
2269 case LXC_AUTO_PROC_RW: strprint(retv, inlen, "%sproc:rw", sep); sep = " "; break;
2270 default: break;
2271 }
2272 switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
2273 case LXC_AUTO_SYS_RO: strprint(retv, inlen, "%ssys:ro", sep); sep = " "; break;
2274 case LXC_AUTO_SYS_RW: strprint(retv, inlen, "%ssys:rw", sep); sep = " "; break;
2275 case LXC_AUTO_SYS_MIXED: strprint(retv, inlen, "%ssys:mixed", sep); sep = " "; break;
2276 default: break;
2277 }
2278 switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
2279 case LXC_AUTO_CGROUP_NOSPEC: strprint(retv, inlen, "%scgroup", sep); sep = " "; break;
2280 case LXC_AUTO_CGROUP_MIXED: strprint(retv, inlen, "%scgroup:mixed", sep); sep = " "; break;
2281 case LXC_AUTO_CGROUP_RO: strprint(retv, inlen, "%scgroup:ro", sep); sep = " "; break;
2282 case LXC_AUTO_CGROUP_RW: strprint(retv, inlen, "%scgroup:rw", sep); sep = " "; break;
2283 case LXC_AUTO_CGROUP_FULL_NOSPEC: strprint(retv, inlen, "%scgroup-full", sep); sep = " "; break;
2284 case LXC_AUTO_CGROUP_FULL_MIXED: strprint(retv, inlen, "%scgroup-full:mixed", sep); sep = " "; break;
2285 case LXC_AUTO_CGROUP_FULL_RO: strprint(retv, inlen, "%scgroup-full:ro", sep); sep = " "; break;
2286 case LXC_AUTO_CGROUP_FULL_RW: strprint(retv, inlen, "%scgroup-full:rw", sep); sep = " "; break;
2287 default: break;
2288 }
2289
2290 return fulllen;
2291 }
2292
2293 /*
2294 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
2295 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
2296 * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
2297 * of an address. ipv4 and ipv6 return lists (newline-separated).
2298 * things like veth.pair return '' if invalid (i.e. if called for vlan
2299 * type).
2300 */
2301 static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
2302 const char *key)
2303 {
2304 char *p1;
2305 int len, fulllen = 0;
2306 struct lxc_netdev *netdev;
2307
2308 if (!retv)
2309 inlen = 0;
2310 else
2311 memset(retv, 0, inlen);
2312
2313 p1 = strchr(key, '.');
2314 if (!p1 || *(p1+1) == '\0') return -1;
2315 p1++;
2316
2317 netdev = get_netdev_from_key(key, &c->network);
2318 if (!netdev)
2319 return -1;
2320 if (strcmp(p1, "name") == 0) {
2321 if (netdev->name)
2322 strprint(retv, inlen, "%s", netdev->name);
2323 } else if (strcmp(p1, "type") == 0) {
2324 strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
2325 } else if (strcmp(p1, "link") == 0) {
2326 if (netdev->link)
2327 strprint(retv, inlen, "%s", netdev->link);
2328 } else if (strcmp(p1, "flags") == 0) {
2329 if (netdev->flags & IFF_UP)
2330 strprint(retv, inlen, "up");
2331 } else if (strcmp(p1, "script.up") == 0) {
2332 if (netdev->upscript)
2333 strprint(retv, inlen, "%s", netdev->upscript);
2334 } else if (strcmp(p1, "script.down") == 0) {
2335 if (netdev->downscript)
2336 strprint(retv, inlen, "%s", netdev->downscript);
2337 } else if (strcmp(p1, "hwaddr") == 0) {
2338 if (netdev->hwaddr)
2339 strprint(retv, inlen, "%s", netdev->hwaddr);
2340 } else if (strcmp(p1, "mtu") == 0) {
2341 if (netdev->mtu)
2342 strprint(retv, inlen, "%s", netdev->mtu);
2343 } else if (strcmp(p1, "macvlan.mode") == 0) {
2344 if (netdev->type == LXC_NET_MACVLAN) {
2345 const char *mode;
2346 switch (netdev->priv.macvlan_attr.mode) {
2347 case MACVLAN_MODE_PRIVATE: mode = "private"; break;
2348 case MACVLAN_MODE_VEPA: mode = "vepa"; break;
2349 case MACVLAN_MODE_BRIDGE: mode = "bridge"; break;
2350 case MACVLAN_MODE_PASSTHRU: mode = "passthru"; break;
2351 default: mode = "(invalid)"; break;
2352 }
2353 strprint(retv, inlen, "%s", mode);
2354 }
2355 } else if (strcmp(p1, "veth.pair") == 0) {
2356 if (netdev->type == LXC_NET_VETH) {
2357 strprint(retv, inlen, "%s",
2358 netdev->priv.veth_attr.pair ?
2359 netdev->priv.veth_attr.pair :
2360 netdev->priv.veth_attr.veth1);
2361 }
2362 } else if (strcmp(p1, "vlan") == 0) {
2363 if (netdev->type == LXC_NET_VLAN) {
2364 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
2365 }
2366 } else if (strcmp(p1, "ipv4.gateway") == 0) {
2367 if (netdev->ipv4_gateway_auto) {
2368 strprint(retv, inlen, "auto");
2369 } else if (netdev->ipv4_gateway) {
2370 char buf[INET_ADDRSTRLEN];
2371 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
2372 strprint(retv, inlen, "%s", buf);
2373 }
2374 } else if (strcmp(p1, "ipv4") == 0) {
2375 struct lxc_list *it2;
2376 lxc_list_for_each(it2, &netdev->ipv4) {
2377 struct lxc_inetdev *i = it2->elem;
2378 char buf[INET_ADDRSTRLEN];
2379 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
2380 strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
2381 }
2382 } else if (strcmp(p1, "ipv6.gateway") == 0) {
2383 if (netdev->ipv6_gateway_auto) {
2384 strprint(retv, inlen, "auto");
2385 } else if (netdev->ipv6_gateway) {
2386 char buf[INET6_ADDRSTRLEN];
2387 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
2388 strprint(retv, inlen, "%s", buf);
2389 }
2390 } else if (strcmp(p1, "ipv6") == 0) {
2391 struct lxc_list *it2;
2392 lxc_list_for_each(it2, &netdev->ipv6) {
2393 struct lxc_inet6dev *i = it2->elem;
2394 char buf[INET6_ADDRSTRLEN];
2395 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
2396 strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
2397 }
2398 }
2399 return fulllen;
2400 }
2401
2402 static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen)
2403 {
2404 int len, fulllen = 0;
2405 struct lxc_list *it;
2406
2407 if (!retv)
2408 inlen = 0;
2409 else
2410 memset(retv, 0, inlen);
2411
2412 lxc_list_for_each(it, &c->network) {
2413 struct lxc_netdev *n = it->elem;
2414 const char *t = lxc_net_type_to_str(n->type);
2415 strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
2416 }
2417 return fulllen;
2418 }
2419
2420 int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
2421 int inlen)
2422 {
2423 const char *v = NULL;
2424
2425 if (strcmp(key, "lxc.mount.entry") == 0)
2426 return lxc_get_mount_entries(c, retv, inlen);
2427 else if (strcmp(key, "lxc.mount.auto") == 0)
2428 return lxc_get_auto_mounts(c, retv, inlen);
2429 else if (strcmp(key, "lxc.mount") == 0)
2430 v = c->fstab;
2431 else if (strcmp(key, "lxc.tty") == 0)
2432 return lxc_get_conf_int(c, retv, inlen, c->tty);
2433 else if (strcmp(key, "lxc.pts") == 0)
2434 return lxc_get_conf_int(c, retv, inlen, c->pts);
2435 else if (strcmp(key, "lxc.devttydir") == 0)
2436 v = c->ttydir;
2437 else if (strcmp(key, "lxc.arch") == 0)
2438 return lxc_get_arch_entry(c, retv, inlen);
2439 else if (strcmp(key, "lxc.aa_profile") == 0)
2440 v = c->lsm_aa_profile;
2441 else if (strcmp(key, "lxc.aa_allow_incomplete") == 0)
2442 return lxc_get_conf_int(c, retv, inlen, c->lsm_aa_allow_incomplete);
2443 else if (strcmp(key, "lxc.se_context") == 0)
2444 v = c->lsm_se_context;
2445 else if (strcmp(key, "lxc.logfile") == 0)
2446 v = c->logfile;
2447 else if (strcmp(key, "lxc.loglevel") == 0)
2448 v = lxc_log_priority_to_string(c->loglevel);
2449 else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
2450 return lxc_get_cgroup_entry(c, retv, inlen, "all");
2451 else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
2452 return lxc_get_cgroup_entry(c, retv, inlen, key + 11);
2453 else if (strcmp(key, "lxc.utsname") == 0)
2454 v = c->utsname ? c->utsname->nodename : NULL;
2455 else if (strcmp(key, "lxc.console.logfile") == 0)
2456 v = c->console.log_path;
2457 else if (strcmp(key, "lxc.console") == 0)
2458 v = c->console.path;
2459 else if (strcmp(key, "lxc.rootfs.mount") == 0)
2460 v = c->rootfs.mount;
2461 else if (strcmp(key, "lxc.rootfs.options") == 0)
2462 v = c->rootfs.options;
2463 else if (strcmp(key, "lxc.rootfs") == 0)
2464 v = c->rootfs.path;
2465 else if (strcmp(key, "lxc.pivotdir") == 0)
2466 v = c->rootfs.pivot;
2467 else if (strcmp(key, "lxc.cap.drop") == 0)
2468 return lxc_get_item_cap_drop(c, retv, inlen);
2469 else if (strcmp(key, "lxc.cap.keep") == 0)
2470 return lxc_get_item_cap_keep(c, retv, inlen);
2471 else if (strncmp(key, "lxc.hook", 8) == 0)
2472 return lxc_get_item_hooks(c, retv, inlen, key);
2473 else if (strcmp(key, "lxc.network") == 0)
2474 return lxc_get_item_network(c, retv, inlen);
2475 else if (strncmp(key, "lxc.network.", 12) == 0)
2476 return lxc_get_item_nic(c, retv, inlen, key + 12);
2477 else if (strcmp(key, "lxc.start.auto") == 0)
2478 return lxc_get_conf_int(c, retv, inlen, c->start_auto);
2479 else if (strcmp(key, "lxc.start.delay") == 0)
2480 return lxc_get_conf_int(c, retv, inlen, c->start_delay);
2481 else if (strcmp(key, "lxc.start.order") == 0)
2482 return lxc_get_conf_int(c, retv, inlen, c->start_order);
2483 else if (strcmp(key, "lxc.group") == 0)
2484 return lxc_get_item_groups(c, retv, inlen);
2485 else if (strcmp(key, "lxc.seccomp") == 0)
2486 v = c->seccomp;
2487 else if (strcmp(key, "lxc.environment") == 0)
2488 return lxc_get_item_environment(c, retv, inlen);
2489 else if (strcmp(key, "lxc.init_cmd") == 0)
2490 v = c->init_cmd;
2491 else if (strcmp(key, "lxc.init_uid") == 0)
2492 return lxc_get_conf_int(c, retv, inlen, c->init_uid);
2493 else if (strcmp(key, "lxc.init_gid") == 0)
2494 return lxc_get_conf_int(c, retv, inlen, c->init_gid);
2495 else if (strcmp(key, "lxc.ephemeral") == 0)
2496 return lxc_get_conf_int(c, retv, inlen, c->ephemeral);
2497 else return -1;
2498
2499 if (!v)
2500 return 0;
2501 if (retv && inlen >= strlen(v) + 1)
2502 strncpy(retv, v, strlen(v)+1);
2503 return strlen(v);
2504 }
2505
2506 int lxc_clear_config_item(struct lxc_conf *c, const char *key)
2507 {
2508 if (strcmp(key, "lxc.network") == 0)
2509 return lxc_clear_config_network(c);
2510 else if (strncmp(key, "lxc.network.", 12) == 0)
2511 return lxc_clear_nic(c, key + 12);
2512 else if (strcmp(key, "lxc.cap.drop") == 0)
2513 return lxc_clear_config_caps(c);
2514 else if (strcmp(key, "lxc.cap.keep") == 0)
2515 return lxc_clear_config_keepcaps(c);
2516 else if (strncmp(key, "lxc.cgroup", 10) == 0)
2517 return lxc_clear_cgroups(c, key);
2518 else if (strcmp(key, "lxc.mount.entries") == 0)
2519 return lxc_clear_mount_entries(c);
2520 else if (strcmp(key, "lxc.mount.auto") == 0)
2521 return lxc_clear_automounts(c);
2522 else if (strncmp(key, "lxc.hook", 8) == 0)
2523 return lxc_clear_hooks(c, key);
2524 else if (strncmp(key, "lxc.group", 9) == 0)
2525 return lxc_clear_groups(c);
2526 else if (strncmp(key, "lxc.environment", 15) == 0)
2527 return lxc_clear_environment(c);
2528 else if (strncmp(key, "lxc.id_map", 10) == 0)
2529 return lxc_clear_idmaps(c);
2530 return -1;
2531 }
2532
2533 /*
2534 * writing out a confile.
2535 */
2536 void write_config(FILE *fout, struct lxc_conf *c)
2537 {
2538 size_t len = c->unexpanded_len;
2539 int ret;
2540
2541 if (!len)
2542 return;
2543 ret = fwrite(c->unexpanded_config, 1, len, fout);
2544 if (ret != len)
2545 SYSERROR("Error writing configuration file");
2546 }
2547
2548 bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const char *v)
2549 {
2550 int ret;
2551 size_t len = strlen(key) + strlen(v) + 4;
2552 char *tmp = alloca(len);
2553
2554 ret = snprintf(tmp, len, "%s = %s", key, v);
2555 if (ret < 0 || ret >= len)
2556 return false;
2557
2558 /* Save the line verbatim into unexpanded_conf */
2559 if (append_unexp_config_line(tmp, conf))
2560 return false;
2561
2562 return true;
2563 }
2564
2565 void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_subkeys)
2566 {
2567 char *lstart = conf->unexpanded_config, *lend;
2568
2569 if (!conf->unexpanded_config)
2570 return;
2571 while (*lstart) {
2572 lend = strchr(lstart, '\n');
2573 char v;
2574 if (!lend)
2575 lend = lstart + strlen(lstart);
2576 else
2577 lend++;
2578 if (strncmp(lstart, key, strlen(key)) != 0) {
2579 lstart = lend;
2580 continue;
2581 }
2582 if (!rm_subkeys) {
2583 v = lstart[strlen(key)];
2584 if (!isspace(v) && v != '=') {
2585 lstart = lend;
2586 continue;
2587 }
2588 }
2589 conf->unexpanded_len -= (lend - lstart);
2590 if (*lend == '\0') {
2591 *lstart = '\0';
2592 return;
2593 }
2594 memmove(lstart, lend, strlen(lend)+1);
2595 }
2596 }
2597
2598 bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
2599 const char *newpath, const char *oldname, const char *newname)
2600 {
2601 const char *key = "lxc.hook";
2602 int ret;
2603 char *lstart = conf->unexpanded_config, *lend, *p;
2604 size_t newdirlen = strlen(newpath) + strlen(newname) + 1;
2605 size_t olddirlen = strlen(oldpath) + strlen(oldname) + 1;
2606 char *olddir = alloca(olddirlen + 1);
2607 char *newdir = alloca(newdirlen + 1);
2608
2609 ret = snprintf(olddir, olddirlen+1, "%s/%s", oldpath, oldname);
2610 if (ret < 0 || ret >= olddirlen+1) {
2611 ERROR("Bug in %s", __func__);
2612 return false;
2613 }
2614 ret = snprintf(newdir, newdirlen+1, "%s/%s", newpath, newname);
2615 if (ret < 0 || ret >= newdirlen+1) {
2616 ERROR("Bug in %s", __func__);
2617 return false;
2618 }
2619 if (!conf->unexpanded_config)
2620 return true;
2621 while (*lstart) {
2622 lend = strchr(lstart, '\n');
2623 if (!lend)
2624 lend = lstart + strlen(lstart);
2625 else
2626 lend++;
2627 if (strncmp(lstart, key, strlen(key)) != 0) {
2628 lstart = lend;
2629 continue;
2630 }
2631 p = strchr(lstart+strlen(key), '=');
2632 if (!p) {
2633 lstart = lend;
2634 continue;
2635 }
2636 p++;
2637 while (isblank(*p))
2638 p++;
2639 if (!*p)
2640 return true;
2641 if (strncmp(p, olddir, strlen(olddir)) != 0) {
2642 lstart = lend;
2643 continue;
2644 }
2645 /* replace the olddir with newdir */
2646 if (olddirlen >= newdirlen) {
2647 size_t diff = olddirlen - newdirlen;
2648 memcpy(p, newdir, newdirlen);
2649 if (olddirlen != newdirlen) {
2650 memmove(lend-diff, lend, strlen(lend)+1);
2651 lend -= diff;
2652 conf->unexpanded_len -= diff;
2653 }
2654 lstart = lend;
2655 } else {
2656 char *new;
2657 size_t diff = newdirlen - olddirlen;
2658 size_t oldlen = conf->unexpanded_len;
2659 size_t newlen = oldlen + diff;
2660 size_t poffset = p - conf->unexpanded_config;
2661 new = realloc(conf->unexpanded_config, newlen);
2662 if (!new) {
2663 ERROR("Out of memory");
2664 return false;
2665 }
2666 conf->unexpanded_len = newlen;
2667 new[newlen-1] = '\0';
2668 lend = new + (lend - conf->unexpanded_config);
2669 /* move over the remainder, /$hookname\n$rest */
2670 memmove(new+poffset+newdirlen,
2671 new+poffset+olddirlen,
2672 oldlen-poffset-olddirlen);
2673 conf->unexpanded_config = new;
2674 memcpy(new+poffset, newdir, newdirlen);
2675 lstart = lend + diff;
2676 }
2677 }
2678 return true;
2679 }
2680
2681 #define DO(cmd) { \
2682 if (!(cmd)) { \
2683 ERROR("Error writing to new config"); \
2684 return false; \
2685 } \
2686 }
2687
2688 static void new_hwaddr(char *hwaddr)
2689 {
2690 FILE *f;
2691 f = fopen("/dev/urandom", "r");
2692 if (f) {
2693 unsigned int seed;
2694 int ret = fread(&seed, sizeof(seed), 1, f);
2695 if (ret != 1)
2696 seed = time(NULL);
2697 fclose(f);
2698 srand(seed);
2699 } else
2700 srand(time(NULL));
2701 snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x",
2702 rand() % 255, rand() % 255, rand() % 255);
2703 }
2704
2705 /*
2706 * This is called only from clone.
2707 * We wish to update all hwaddrs in the unexpanded config file. We
2708 * can't/don't want to update any which come from lxc.includes (there
2709 * shouldn't be any).
2710 * We can't just walk the c->lxc-conf->network list because that includes
2711 * netifs from the include files. So we update the ones which we find in
2712 * the unexp config file, then find the original macaddr in the
2713 * conf->network, and update that to the same value.
2714 */
2715 bool network_new_hwaddrs(struct lxc_conf *conf)
2716 {
2717 struct lxc_list *it;
2718
2719 const char *key = "lxc.network.hwaddr";
2720 char *lstart = conf->unexpanded_config, *lend, *p, *p2;
2721
2722 if (!conf->unexpanded_config)
2723 return true;
2724 while (*lstart) {
2725 char newhwaddr[18], oldhwaddr[17];
2726 lend = strchr(lstart, '\n');
2727 if (!lend)
2728 lend = lstart + strlen(lstart);
2729 else
2730 lend++;
2731 if (strncmp(lstart, key, strlen(key)) != 0) {
2732 lstart = lend;
2733 continue;
2734 }
2735 p = strchr(lstart+strlen(key), '=');
2736 if (!p) {
2737 lstart = lend;
2738 continue;
2739 }
2740 p++;
2741 while (isblank(*p))
2742 p++;
2743 if (!*p)
2744 return true;
2745 p2 = p;
2746 while (*p2 && !isblank(*p2) && *p2 != '\n')
2747 p2++;
2748 if (p2-p != 17) {
2749 WARN("Bad hwaddr entry");
2750 lstart = lend;
2751 continue;
2752 }
2753 memcpy(oldhwaddr, p, 17);
2754 new_hwaddr(newhwaddr);
2755 memcpy(p, newhwaddr, 17);
2756 lxc_list_for_each(it, &conf->network) {
2757 struct lxc_netdev *n = it->elem;
2758 if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0)
2759 memcpy(n->hwaddr, newhwaddr, 17);
2760 }
2761
2762 lstart = lend;
2763 }
2764 return true;
2765 }
2766
2767 static int config_ephemeral(const char *key, const char *value,
2768 struct lxc_conf *lxc_conf)
2769 {
2770 int v = atoi(value);
2771
2772 if (v != 0 && v != 1) {
2773 ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
2774 return -1;
2775 } else {
2776 lxc_conf->ephemeral = v;
2777 }
2778
2779 return 0;
2780 }
2781