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