2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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.
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.
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
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>
49 #include "lxcseccomp.h"
51 #if HAVE_SYS_PERSONALITY_H
52 #include <sys/personality.h>
55 lxc_log_define(lxc_confile
, lxc
);
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
*);
113 static struct lxc_config_t config
[] = {
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
},
188 static const struct signame signames
[] = {
221 { SIGSTKFLT
, "STKFLT" },
236 { SIGVTALRM
, "VTALRM" },
242 { SIGWINCH
, "WINCH" },
260 { SIGUNUSED
, "UNUSED" },
267 static const size_t config_size
= sizeof(config
)/sizeof(struct lxc_config_t
);
269 extern struct lxc_config_t
*lxc_getconfig(const char *key
)
273 for (i
= 0; i
< config_size
; i
++)
274 if (!strncmp(config
[i
].name
, key
,
275 strlen(config
[i
].name
)))
280 #define strprint(str, inlen, ...) \
282 len = snprintf(str, inlen, ##__VA_ARGS__); \
283 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
286 if (str) str += len; \
288 if (inlen < 0) inlen = 0; \
292 int lxc_listconfigs(char *retv
, int inlen
)
294 int i
, fulllen
= 0, len
;
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] == '.')
304 strprint(retv
, inlen
, "%s\n", s
);
309 static int config_string_item(char **conf_item
, const char *value
)
313 if (!value
|| strlen(value
) == 0) {
319 new_value
= strdup(value
);
321 SYSERROR("failed to strdup '%s': %m", value
);
326 *conf_item
= new_value
;
330 static int config_string_item_max(char **conf_item
, const char *value
,
333 if (strlen(value
) >= max
) {
334 ERROR("%s is too long (>= %lu)", value
, (unsigned long)max
);
338 return config_string_item(conf_item
, value
);
341 static int config_path_item(char **conf_item
, const char *value
)
343 return config_string_item_max(conf_item
, value
, PATH_MAX
);
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.
352 static int config_network_nic(const char *key
, const char *value
,
353 struct lxc_conf
*lxc_conf
)
355 char *copy
= strdup(key
), *p
;
357 struct lxc_config_t
*config
;
360 SYSERROR("failed to allocate memory");
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.
369 if (*(key
+12) < '0' || *(key
+12) > '9')
371 p
= strchr(key
+12, '.');
374 strcpy(copy
+12, p
+1);
375 config
= lxc_getconfig(copy
);
377 ERROR("unknown key %s", key
);
380 ret
= config
->cb(key
, value
, lxc_conf
);
387 static int config_network(const char *key
, const char *value
,
388 struct lxc_conf
*lxc_conf
)
390 if (value
&& strlen(value
)) {
391 ERROR("lxc.network must not have a value");
395 return lxc_clear_config_network(lxc_conf
);
398 static int macvlan_mode(int *valuep
, const char *value
);
400 static int config_network_type(const char *key
, const char *value
,
401 struct lxc_conf
*lxc_conf
)
403 struct lxc_list
*network
= &lxc_conf
->network
;
404 struct lxc_netdev
*netdev
;
405 struct lxc_list
*list
;
407 if (!value
|| strlen(value
) == 0)
408 return lxc_clear_config_network(lxc_conf
);
410 netdev
= malloc(sizeof(*netdev
));
412 SYSERROR("failed to allocate memory");
416 memset(netdev
, 0, sizeof(*netdev
));
417 lxc_list_init(&netdev
->ipv4
);
418 lxc_list_init(&netdev
->ipv6
);
420 list
= malloc(sizeof(*list
));
422 SYSERROR("failed to allocate memory");
430 lxc_list_add_tail(network
, list
);
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");
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
;
447 ERROR("invalid network type %s", value
);
453 static int config_ip_prefix(struct in_addr
*addr
)
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
;
466 * if you have p="lxc.network.0.link", pass it p+12
467 * to get back '0' (the index of the nic)
469 static int get_network_netdev_idx(const char *key
)
473 if (*key
< '0' || *key
> '9')
475 ret
= sscanf(key
, "%d", &idx
);
482 * if you have p="lxc.network.0", pass this p+12 and it will return
483 * the netdev of the first configured nic
485 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
486 struct lxc_list
*network
)
488 int i
= 0, idx
= get_network_netdev_idx(key
);
489 struct lxc_netdev
*netdev
= NULL
;
493 lxc_list_for_each(it
, network
) {
502 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, const char *key
,
503 char *retv
, int inlen
)
505 struct lxc_netdev
*netdev
;
506 int fulllen
= 0, len
;
508 netdev
= get_netdev_from_key(key
+12, &c
->network
);
515 memset(retv
, 0, inlen
);
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");
530 switch(netdev
->type
) {
532 strprint(retv
, inlen
, "veth.pair\n");
534 case LXC_NET_MACVLAN
:
535 strprint(retv
, inlen
, "macvlan.mode\n");
538 strprint(retv
, inlen
, "vlan.id\n");
546 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
547 struct lxc_list
*network
)
549 struct lxc_netdev
*netdev
= NULL
;
551 if (lxc_list_empty(network
)) {
552 ERROR("network is not created for '%s' = '%s' option",
557 if (get_network_netdev_idx(key
+12) == -1)
558 netdev
= lxc_list_last_elem(network
);
560 netdev
= get_netdev_from_key(key
+12, network
);
563 ERROR("no network device defined for '%s' = '%s' option",
571 static int network_ifname(char **valuep
, const char *value
)
573 return config_string_item_max(valuep
, value
, IFNAMSIZ
);
576 #ifndef MACVLAN_MODE_PRIVATE
577 # define MACVLAN_MODE_PRIVATE 1
580 #ifndef MACVLAN_MODE_VEPA
581 # define MACVLAN_MODE_VEPA 2
584 #ifndef MACVLAN_MODE_BRIDGE
585 # define MACVLAN_MODE_BRIDGE 4
588 #ifndef MACVLAN_MODE_PASSTHRU
589 # define MACVLAN_MODE_PASSTHRU 8
592 static int macvlan_mode(int *valuep
, const char *value
)
598 { "private", MACVLAN_MODE_PRIVATE
},
599 { "vepa", MACVLAN_MODE_VEPA
},
600 { "bridge", MACVLAN_MODE_BRIDGE
},
601 { "passthru", MACVLAN_MODE_PASSTHRU
},
606 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
607 if (strcmp(m
[i
].name
, value
))
617 static int rand_complete_hwaddr(char *hwaddr
)
619 const char hex
[] = "0123456789abcdef";
625 unsigned int seed
=randseed(false);
627 while (*curs
!= '\0' && *curs
!= '\n')
629 if ( *curs
== 'x' || *curs
== 'X' ) {
630 if (curs
- hwaddr
== 1) {
631 //ensure address is unicast
633 *curs
= hex
[rand_r(&seed
) & 0x0E];
635 *curs
= hex
[rand_r(&seed
) & 0x0F];
637 *curs
= hex
[rand() & 0x0E];
639 *curs
= hex
[rand() & 0x0F];
648 static int config_network_flags(const char *key
, const char *value
,
649 struct lxc_conf
*lxc_conf
)
651 struct lxc_netdev
*netdev
;
653 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
657 netdev
->flags
|= IFF_UP
;
662 static int config_network_link(const char *key
, const char *value
,
663 struct lxc_conf
*lxc_conf
)
665 struct lxc_netdev
*netdev
;
667 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
671 return network_ifname(&netdev
->link
, value
);
674 static int config_network_name(const char *key
, const char *value
,
675 struct lxc_conf
*lxc_conf
)
677 struct lxc_netdev
*netdev
;
679 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
683 return network_ifname(&netdev
->name
, value
);
686 static int config_network_veth_pair(const char *key
, const char *value
,
687 struct lxc_conf
*lxc_conf
)
689 struct lxc_netdev
*netdev
;
691 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
695 if (netdev
->type
!= LXC_NET_VETH
) {
696 ERROR("Invalid veth pair for a non-veth netdev");
699 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
702 static int config_network_macvlan_mode(const char *key
, const char *value
,
703 struct lxc_conf
*lxc_conf
)
705 struct lxc_netdev
*netdev
;
707 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
711 if (netdev
->type
!= LXC_NET_MACVLAN
) {
712 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
715 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
718 static int config_network_hwaddr(const char *key
, const char *value
,
719 struct lxc_conf
*lxc_conf
)
721 struct lxc_netdev
*netdev
;
723 char *new_value
= strdup(value
);
725 SYSERROR("failed to strdup '%s': %m", value
);
728 rand_complete_hwaddr(new_value
);
730 netdev
= network_netdev(key
, new_value
, &lxc_conf
->network
);
736 if (!new_value
|| strlen(new_value
) == 0) {
738 netdev
->hwaddr
= NULL
;
742 netdev
->hwaddr
= new_value
;
746 static int config_network_vlan_id(const char *key
, const char *value
,
747 struct lxc_conf
*lxc_conf
)
749 struct lxc_netdev
*netdev
;
751 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
755 if (netdev
->type
!= LXC_NET_VLAN
) {
756 ERROR("Invalid vlan.id for a non-macvlan netdev");
759 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
765 static int config_network_mtu(const char *key
, const char *value
,
766 struct lxc_conf
*lxc_conf
)
768 struct lxc_netdev
*netdev
;
770 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
774 return config_string_item(&netdev
->mtu
, value
);
777 static int config_network_ipv4(const char *key
, const char *value
,
778 struct lxc_conf
*lxc_conf
)
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
;
785 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
789 inetdev
= malloc(sizeof(*inetdev
));
791 SYSERROR("failed to allocate ipv4 address");
794 memset(inetdev
, 0, sizeof(*inetdev
));
796 list
= malloc(sizeof(*list
));
798 SYSERROR("failed to allocate memory");
804 list
->elem
= inetdev
;
806 addr
= strdup(value
);
808 ERROR("no address specified");
814 cursor
= strstr(addr
, " ");
820 slash
= strstr(addr
, "/");
826 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
827 SYSERROR("invalid ipv4 address: %s", value
);
834 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
835 SYSERROR("invalid ipv4 broadcast address: %s", value
);
842 /* no prefix specified, determine it from the network class */
843 inetdev
->prefix
= prefix
? atoi(prefix
) :
844 config_ip_prefix(&inetdev
->addr
);
846 /* if no broadcast address, let compute one from the
850 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
851 inetdev
->bcast
.s_addr
|=
852 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
855 lxc_list_add_tail(&netdev
->ipv4
, list
);
861 static int config_network_ipv4_gateway(const char *key
, const char *value
,
862 struct lxc_conf
*lxc_conf
)
864 struct lxc_netdev
*netdev
;
866 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
870 free(netdev
->ipv4_gateway
);
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;
880 gw
= malloc(sizeof(*gw
));
882 SYSERROR("failed to allocate ipv4 gateway address");
886 if (!inet_pton(AF_INET
, value
, gw
)) {
887 SYSERROR("invalid ipv4 gateway address: %s", value
);
892 netdev
->ipv4_gateway
= gw
;
893 netdev
->ipv4_gateway_auto
= false;
899 static int config_network_ipv6(const char *key
, const char *value
,
900 struct lxc_conf
*lxc_conf
)
902 struct lxc_netdev
*netdev
;
903 struct lxc_inet6dev
*inet6dev
;
904 struct lxc_list
*list
;
908 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
912 inet6dev
= malloc(sizeof(*inet6dev
));
914 SYSERROR("failed to allocate ipv6 address");
917 memset(inet6dev
, 0, sizeof(*inet6dev
));
919 list
= malloc(sizeof(*list
));
921 SYSERROR("failed to allocate memory");
927 list
->elem
= inet6dev
;
929 valdup
= strdup(value
);
931 ERROR("no address specified");
937 inet6dev
->prefix
= 64;
938 slash
= strstr(valdup
, "/");
942 inet6dev
->prefix
= atoi(netmask
);
945 if (!inet_pton(AF_INET6
, valdup
, &inet6dev
->addr
)) {
946 SYSERROR("invalid ipv6 address: %s", valdup
);
953 lxc_list_add_tail(&netdev
->ipv6
, list
);
959 static int config_network_ipv6_gateway(const char *key
, const char *value
,
960 struct lxc_conf
*lxc_conf
)
962 struct lxc_netdev
*netdev
;
964 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
968 free(netdev
->ipv6_gateway
);
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;
978 gw
= malloc(sizeof(*gw
));
980 SYSERROR("failed to allocate ipv6 gateway address");
984 if (!inet_pton(AF_INET6
, value
, gw
)) {
985 SYSERROR("invalid ipv6 gateway address: %s", value
);
990 netdev
->ipv6_gateway
= gw
;
991 netdev
->ipv6_gateway_auto
= false;
997 static int config_network_script_up(const char *key
, const char *value
,
998 struct lxc_conf
*lxc_conf
)
1000 struct lxc_netdev
*netdev
;
1002 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1006 return config_string_item(&netdev
->upscript
, value
);
1009 static int config_network_script_down(const char *key
, const char *value
,
1010 struct lxc_conf
*lxc_conf
)
1012 struct lxc_netdev
*netdev
;
1014 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1018 return config_string_item(&netdev
->downscript
, value
);
1021 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
1023 struct lxc_list
*hooklist
;
1025 hooklist
= malloc(sizeof(*hooklist
));
1030 hooklist
->elem
= hook
;
1031 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
1035 static int config_seccomp(const char *key
, const char *value
,
1036 struct lxc_conf
*lxc_conf
)
1038 return config_path_item(&lxc_conf
->seccomp
, value
);
1041 static int config_init_cmd(const char *key
, const char *value
,
1042 struct lxc_conf
*lxc_conf
)
1044 return config_path_item(&lxc_conf
->init_cmd
, value
);
1047 static int config_init_uid(const char *key
, const char *value
,
1048 struct lxc_conf
*lxc_conf
)
1050 lxc_conf
->init_uid
= atoi(value
);
1054 static int config_init_gid(const char *key
, const char *value
,
1055 struct lxc_conf
*lxc_conf
)
1057 lxc_conf
->init_gid
= atoi(value
);
1061 static int config_hook(const char *key
, const char *value
,
1062 struct lxc_conf
*lxc_conf
)
1066 if (!value
|| strlen(value
) == 0)
1067 return lxc_clear_hooks(lxc_conf
, key
);
1069 if (strcmp(key
, "lxc.hook") == 0) {
1070 ERROR("lxc.hook cannot take a value");
1073 copy
= strdup(value
);
1075 SYSERROR("failed to dup string '%s'", value
);
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
);
1099 static int config_personality(const char *key
, const char *value
,
1100 struct lxc_conf
*lxc_conf
)
1102 signed long personality
= lxc_config_parse_arch(value
);
1104 if (personality
>= 0)
1105 lxc_conf
->personality
= personality
;
1107 WARN("unsupported personality '%s'", value
);
1112 static int config_pts(const char *key
, const char *value
,
1113 struct lxc_conf
*lxc_conf
)
1115 int maxpts
= atoi(value
);
1117 lxc_conf
->pts
= maxpts
;
1122 static int config_start(const char *key
, const char *value
,
1123 struct lxc_conf
*lxc_conf
)
1125 if(strcmp(key
, "lxc.start.auto") == 0) {
1126 lxc_conf
->start_auto
= atoi(value
);
1129 else if (strcmp(key
, "lxc.start.delay") == 0) {
1130 lxc_conf
->start_delay
= atoi(value
);
1133 else if (strcmp(key
, "lxc.start.order") == 0) {
1134 lxc_conf
->start_order
= atoi(value
);
1137 SYSERROR("Unknown key: %s", key
);
1141 static int config_group(const char *key
, const char *value
,
1142 struct lxc_conf
*lxc_conf
)
1144 char *groups
, *groupptr
, *sptr
, *token
;
1145 struct lxc_list
*grouplist
;
1149 return lxc_clear_groups(lxc_conf
);
1151 groups
= strdup(value
);
1153 SYSERROR("failed to dup '%s'", value
);
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
);
1166 grouplist
= malloc(sizeof(*grouplist
));
1168 SYSERROR("failed to allocate groups list");
1172 grouplist
->elem
= strdup(token
);
1173 if (!grouplist
->elem
) {
1174 SYSERROR("failed to dup '%s'", token
);
1179 lxc_list_add_tail(&lxc_conf
->groups
, grouplist
);
1187 static int config_environment(const char *key
, const char *value
,
1188 struct lxc_conf
*lxc_conf
)
1190 struct lxc_list
*list_item
= NULL
;
1193 return lxc_clear_environment(lxc_conf
);
1195 list_item
= malloc(sizeof(*list_item
));
1199 list_item
->elem
= strdup(value
);
1201 if (!list_item
->elem
)
1204 lxc_list_add_tail(&lxc_conf
->environment
, list_item
);
1214 static int config_tty(const char *key
, const char *value
,
1215 struct lxc_conf
*lxc_conf
)
1217 int nbtty
= atoi(value
);
1219 lxc_conf
->tty
= nbtty
;
1224 static int config_ttydir(const char *key
, const char *value
,
1225 struct lxc_conf
*lxc_conf
)
1227 return config_string_item_max(&lxc_conf
->ttydir
, value
, NAME_MAX
+1);
1230 static int config_kmsg(const char *key
, const char *value
,
1231 struct lxc_conf
*lxc_conf
)
1233 int v
= atoi(value
);
1240 static int config_lsm_aa_profile(const char *key
, const char *value
,
1241 struct lxc_conf
*lxc_conf
)
1243 return config_string_item(&lxc_conf
->lsm_aa_profile
, value
);
1246 static int config_lsm_aa_incomplete(const char *key
, const char *value
,
1247 struct lxc_conf
*lxc_conf
)
1249 int v
= atoi(value
);
1251 lxc_conf
->lsm_aa_allow_incomplete
= v
== 1 ? 1 : 0;
1256 static int config_lsm_se_context(const char *key
, const char *value
,
1257 struct lxc_conf
*lxc_conf
)
1259 return config_string_item(&lxc_conf
->lsm_se_context
, value
);
1262 static int config_logfile(const char *key
, const char *value
,
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
);
1271 ret
= lxc_log_set_file(&c
->logfd
, c
->logfile
);
1275 static int config_loglevel(const char *key
, const char *value
,
1276 struct lxc_conf
*lxc_conf
)
1280 if (!value
|| strlen(value
) == 0)
1283 if (value
[0] >= '0' && value
[0] <= '9')
1284 newlevel
= atoi(value
);
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
);
1293 static int config_autodev(const char *key
, const char *value
,
1294 struct lxc_conf
*lxc_conf
)
1296 int v
= atoi(value
);
1298 lxc_conf
->autodev
= v
;
1303 static int sig_num(const char *sig
)
1309 n
= strtol(sig
, &endp
, 10);
1310 if (sig
== endp
|| n
< 0 || errno
!= 0)
1315 static int rt_sig_num(const char *signame
)
1320 if (strncasecmp(signame
, "max-", 4) == 0) {
1324 if (!isdigit(*signame
))
1326 sig_n
= sig_num(signame
);
1327 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1328 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1333 static int sig_parse(const char *signame
) {
1336 if (isdigit(*signame
)) {
1337 return sig_num(signame
);
1338 } else if (strncasecmp(signame
, "sig", 3) == 0) {
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
;
1350 static int config_haltsignal(const char *key
, const char *value
,
1351 struct lxc_conf
*lxc_conf
)
1353 int sig_n
= sig_parse(value
);
1357 lxc_conf
->haltsignal
= sig_n
;
1362 static int config_rebootsignal(const char *key
, const char *value
,
1363 struct lxc_conf
*lxc_conf
)
1365 int sig_n
= sig_parse(value
);
1369 lxc_conf
->rebootsignal
= sig_n
;
1374 static int config_stopsignal(const char *key
, const char *value
,
1375 struct lxc_conf
*lxc_conf
)
1377 int sig_n
= sig_parse(value
);
1381 lxc_conf
->stopsignal
= sig_n
;
1386 static int config_cgroup(const char *key
, const char *value
,
1387 struct lxc_conf
*lxc_conf
)
1389 char *token
= "lxc.cgroup.";
1391 struct lxc_list
*cglist
= NULL
;
1392 struct lxc_cgroup
*cgelem
= NULL
;
1394 if (!value
|| strlen(value
) == 0)
1395 return lxc_clear_cgroups(lxc_conf
, key
);
1397 subkey
= strstr(key
, token
);
1402 if (!strlen(subkey
))
1405 if (strlen(subkey
) == strlen(token
))
1408 subkey
+= strlen(token
);
1410 cglist
= malloc(sizeof(*cglist
));
1414 cgelem
= malloc(sizeof(*cgelem
));
1417 memset(cgelem
, 0, sizeof(*cgelem
));
1419 cgelem
->subsystem
= strdup(subkey
);
1420 cgelem
->value
= strdup(value
);
1422 if (!cgelem
->subsystem
|| !cgelem
->value
)
1425 cglist
->elem
= cgelem
;
1427 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1435 free(cgelem
->subsystem
);
1437 free(cgelem
->value
);
1445 static int config_idmap(const char *key
, const char *value
, struct lxc_conf
*lxc_conf
)
1447 char *token
= "lxc.id_map";
1449 struct lxc_list
*idmaplist
= NULL
;
1450 struct id_map
*idmap
= NULL
;
1451 unsigned long hostid
, nsid
, range
;
1455 if (!value
|| strlen(value
) == 0)
1456 return lxc_clear_idmaps(lxc_conf
);
1458 subkey
= strstr(key
, token
);
1463 if (!strlen(subkey
))
1466 idmaplist
= malloc(sizeof(*idmaplist
));
1470 idmap
= malloc(sizeof(*idmap
));
1473 memset(idmap
, 0, sizeof(*idmap
));
1475 ret
= sscanf(value
, "%c %lu %lu %lu", &type
, &nsid
, &hostid
, &range
);
1479 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
1481 idmap
->idtype
= ID_TYPE_UID
;
1482 else if (type
== 'g')
1483 idmap
->idtype
= ID_TYPE_GID
;
1487 idmap
->hostid
= hostid
;
1489 idmap
->range
= range
;
1491 idmaplist
->elem
= idmap
;
1492 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
1506 static int config_fstab(const char *key
, const char *value
,
1507 struct lxc_conf
*lxc_conf
)
1509 if (!value
|| strlen(value
) == 0)
1511 return config_path_item(&lxc_conf
->fstab
, value
);
1514 static int config_mount_auto(const char *key
, const char *value
,
1515 struct lxc_conf
*lxc_conf
)
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
1543 if (!value
|| strlen(value
) == 0) {
1544 lxc_conf
->auto_mounts
= 0;
1548 autos
= strdup(value
);
1550 SYSERROR("failed to dup '%s'", value
);
1554 for (autoptr
= autos
; ; autoptr
= NULL
) {
1555 token
= strtok_r(autoptr
, " \t", &sptr
);
1561 for (i
= 0; allowed_auto_mounts
[i
].token
; i
++) {
1562 if (!strcmp(allowed_auto_mounts
[i
].token
, token
))
1566 if (!allowed_auto_mounts
[i
].token
) {
1567 ERROR("Invalid filesystem to automount: %s", token
);
1571 lxc_conf
->auto_mounts
&= ~allowed_auto_mounts
[i
].mask
;
1572 lxc_conf
->auto_mounts
|= allowed_auto_mounts
[i
].flag
;
1580 static int config_mount(const char *key
, const char *value
,
1581 struct lxc_conf
*lxc_conf
)
1584 struct lxc_list
*mntlist
;
1586 if (!value
|| strlen(value
) == 0)
1587 return lxc_clear_mount_entries(lxc_conf
);
1589 mntlist
= malloc(sizeof(*mntlist
));
1593 mntelem
= strdup(value
);
1598 mntlist
->elem
= mntelem
;
1600 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
1605 static int config_cap_keep(const char *key
, const char *value
,
1606 struct lxc_conf
*lxc_conf
)
1608 char *keepcaps
, *keepptr
, *sptr
, *token
;
1609 struct lxc_list
*keeplist
;
1613 return lxc_clear_config_keepcaps(lxc_conf
);
1615 keepcaps
= strdup(value
);
1617 SYSERROR("failed to dup '%s'", value
);
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
);
1630 if (!strcmp(token
, "none"))
1631 lxc_clear_config_keepcaps(lxc_conf
);
1633 keeplist
= malloc(sizeof(*keeplist
));
1635 SYSERROR("failed to allocate keepcap list");
1639 keeplist
->elem
= strdup(token
);
1640 if (!keeplist
->elem
) {
1641 SYSERROR("failed to dup '%s'", token
);
1646 lxc_list_add_tail(&lxc_conf
->keepcaps
, keeplist
);
1654 static int config_cap_drop(const char *key
, const char *value
,
1655 struct lxc_conf
*lxc_conf
)
1657 char *dropcaps
, *dropptr
, *sptr
, *token
;
1658 struct lxc_list
*droplist
;
1662 return lxc_clear_config_caps(lxc_conf
);
1664 dropcaps
= strdup(value
);
1666 SYSERROR("failed to dup '%s'", value
);
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
);
1679 droplist
= malloc(sizeof(*droplist
));
1681 SYSERROR("failed to allocate drop list");
1685 droplist
->elem
= strdup(token
);
1686 if (!droplist
->elem
) {
1687 SYSERROR("failed to dup '%s'", token
);
1692 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
1700 static int config_console(const char *key
, const char *value
,
1701 struct lxc_conf
*lxc_conf
)
1703 return config_path_item(&lxc_conf
->console
.path
, value
);
1706 static int config_console_logfile(const char *key
, const char *value
,
1707 struct lxc_conf
*lxc_conf
)
1709 return config_path_item(&lxc_conf
->console
.log_path
, value
);
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
1718 * 'x' and 'X' are substituted in-place.
1720 static void update_hwaddr(const char *line
)
1724 line
+= lxc_char_left_gc(line
, strlen(line
));
1727 if (strncmp(line
, "lxc.network.hwaddr", 18) != 0)
1729 p
= strchr(line
, '=');
1731 return; // let config_network_hwaddr raise the error
1738 rand_complete_hwaddr(p
);
1741 int append_unexp_config_line(const char *line
, struct lxc_conf
*conf
)
1743 size_t len
= conf
->unexpanded_len
, linelen
= strlen(line
);
1745 update_hwaddr(line
);
1747 while (conf
->unexpanded_alloced
<= len
+ linelen
+ 2) {
1748 char *tmp
= realloc(conf
->unexpanded_config
, conf
->unexpanded_alloced
+ 1024);
1751 if (!conf
->unexpanded_config
)
1753 conf
->unexpanded_config
= tmp
;
1754 conf
->unexpanded_alloced
+= 1024;
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
++;
1765 static int do_includedir(const char *dirp
, struct lxc_conf
*lxc_conf
)
1767 struct dirent dirent
, *direntp
;
1769 char path
[MAXPATHLEN
];
1772 dir
= opendir(dirp
);
1774 SYSERROR("failed to open '%s'", dirp
);
1778 while (!readdir_r(dir
, &dirent
, &direntp
)) {
1783 fnam
= direntp
->d_name
;
1784 if (!strcmp(fnam
, "."))
1787 if (!strcmp(fnam
, ".."))
1791 if (len
< 6 || strncmp(fnam
+len
-5, ".conf", 5) != 0)
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
);
1800 ret
= lxc_config_read(path
, lxc_conf
, true);
1808 WARN("lxc.include dir: failed to close directory");
1813 static int config_includefile(const char *key
, const char *value
,
1814 struct lxc_conf
*lxc_conf
)
1817 return do_includedir(value
, lxc_conf
);
1819 return lxc_config_read(value
, lxc_conf
, true);
1822 static int config_rootfs(const char *key
, const char *value
,
1823 struct lxc_conf
*lxc_conf
)
1825 return config_path_item(&lxc_conf
->rootfs
.path
, value
);
1828 static int config_rootfs_mount(const char *key
, const char *value
,
1829 struct lxc_conf
*lxc_conf
)
1831 return config_path_item(&lxc_conf
->rootfs
.mount
, value
);
1834 static int config_rootfs_options(const char *key
, const char *value
,
1835 struct lxc_conf
*lxc_conf
)
1837 return config_string_item(&lxc_conf
->rootfs
.options
, value
);
1840 static int config_pivotdir(const char *key
, const char *value
,
1841 struct lxc_conf
*lxc_conf
)
1843 WARN("lxc.pivotdir is ignored. It will soon become an error.");
1844 return config_path_item(&lxc_conf
->rootfs
.pivot
, value
);
1847 static int config_utsname(const char *key
, const char *value
,
1848 struct lxc_conf
*lxc_conf
)
1850 struct utsname
*utsname
;
1852 utsname
= malloc(sizeof(*utsname
));
1854 SYSERROR("failed to allocate memory");
1858 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
1859 ERROR("node name '%s' is too long",
1865 strcpy(utsname
->nodename
, value
);
1866 free(lxc_conf
->utsname
);
1867 lxc_conf
->utsname
= utsname
;
1872 struct parse_line_conf
{
1873 struct lxc_conf
*conf
;
1877 static int parse_line(char *buffer
, void *data
)
1879 struct lxc_config_t
*config
;
1885 struct parse_line_conf
*plc
= data
;
1887 if (lxc_is_line_empty(buffer
))
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
1894 linep
= line
= strdup(buffer
);
1896 SYSERROR("failed to allocate memory for '%s'", buffer
);
1900 if (!plc
->from_include
)
1901 if ((ret
= append_unexp_config_line(line
, plc
->conf
)))
1904 line
+= lxc_char_left_gc(line
, strlen(line
));
1906 /* ignore comments */
1910 /* martian option - don't add it to the config itself */
1911 if (strncmp(line
, "lxc.", 4))
1916 dot
= strstr(line
, "=");
1918 ERROR("invalid configuration line: %s", line
);
1926 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1928 value
+= lxc_char_left_gc(value
, strlen(value
));
1929 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1931 config
= lxc_getconfig(key
);
1933 ERROR("unknown key %s", key
);
1937 ret
= config
->cb(key
, value
, plc
->conf
);
1944 static int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1946 struct parse_line_conf c
;
1949 c
.from_include
= false;
1951 return parse_line(buffer
, &c
);
1954 int lxc_config_read(const char *file
, struct lxc_conf
*conf
, bool from_include
)
1956 struct parse_line_conf c
;
1959 c
.from_include
= from_include
;
1961 if( access(file
, R_OK
) == -1 ) {
1965 /* Catch only the top level config file name in the structure */
1966 if( ! conf
->rcfile
)
1967 conf
->rcfile
= strdup( file
);
1969 return lxc_file_for_each_line(file
, parse_line
, &c
);
1972 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1974 struct lxc_list
*dent
;
1976 dent
= malloc(sizeof(struct lxc_list
));
1981 lxc_list_add_tail(defines
, dent
);
1985 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1987 struct lxc_list
*it
,*next
;
1990 lxc_list_for_each(it
, defines
) {
1991 ret
= lxc_config_readline(it
->elem
, conf
);
1996 lxc_list_for_each_safe(it
, defines
, next
) {
2004 signed long lxc_config_parse_arch(const char *arch
)
2006 #if HAVE_SYS_PERSONALITY_H
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
},
2022 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
2026 for (i
= 0; i
< len
; i
++) {
2027 if (!strcmp(pername
[i
].name
, arch
))
2028 return pername
[i
].per
;
2035 int lxc_fill_elevated_privileges(char *flaglist
, int *flags
)
2037 char *token
, *saveptr
= NULL
;
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
},
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
;
2055 token
= strtok_r(flaglist
, "|", &saveptr
);
2058 for (i
= 0; all_privs
[i
].token
; i
++) {
2059 if (!strcmp(all_privs
[i
].token
, token
))
2060 aflag
= all_privs
[i
].flag
;
2067 token
= strtok_r(NULL
, "|", &saveptr
);
2072 static int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
, int v
)
2077 memset(retv
, 0, inlen
);
2078 return snprintf(retv
, inlen
, "%d", v
);
2081 static int lxc_get_arch_entry(struct lxc_conf
*c
, char *retv
, int inlen
)
2088 memset(retv
, 0, inlen
);
2090 #if HAVE_SYS_PERSONALITY_H
2093 switch(c
->personality
) {
2094 case PER_LINUX32
: strprint(retv
, inlen
, "i686"); break;
2095 case PER_LINUX
: strprint(retv
, inlen
, "x86_64"); break;
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.
2112 static int lxc_get_cgroup_entry(struct lxc_conf
*c
, char *retv
, int inlen
,
2115 int fulllen
= 0, len
;
2117 struct lxc_list
*it
;
2122 memset(retv
, 0, inlen
);
2124 if (strcmp(key
, "all") == 0)
2127 lxc_list_for_each(it
, &c
->cgroup
) {
2128 struct lxc_cgroup
*cg
= it
->elem
;
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
);
2138 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
,
2142 int len
, fulllen
= 0, found
= -1;
2143 struct lxc_list
*it
;
2146 /* "lxc.hook.mount" */
2147 subkey
= strchr(key
, '.');
2148 if (subkey
) subkey
= strchr(subkey
+1, '.');
2154 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
2155 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
2166 memset(retv
, 0, inlen
);
2168 lxc_list_for_each(it
, &c
->hooks
[found
]) {
2169 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2174 static int lxc_get_item_groups(struct lxc_conf
*c
, char *retv
, int inlen
)
2176 int len
, fulllen
= 0;
2177 struct lxc_list
*it
;
2182 memset(retv
, 0, inlen
);
2184 lxc_list_for_each(it
, &c
->groups
) {
2185 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2190 static int lxc_get_item_environment(struct lxc_conf
*c
, char *retv
, int inlen
)
2192 int len
, fulllen
= 0;
2193 struct lxc_list
*it
;
2198 memset(retv
, 0, inlen
);
2200 lxc_list_for_each(it
, &c
->environment
) {
2201 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2206 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
2208 int len
, fulllen
= 0;
2209 struct lxc_list
*it
;
2214 memset(retv
, 0, inlen
);
2216 lxc_list_for_each(it
, &c
->caps
) {
2217 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2222 static int lxc_get_item_cap_keep(struct lxc_conf
*c
, char *retv
, int inlen
)
2224 int len
, fulllen
= 0;
2225 struct lxc_list
*it
;
2230 memset(retv
, 0, inlen
);
2232 lxc_list_for_each(it
, &c
->keepcaps
) {
2233 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2238 static int lxc_get_mount_entries(struct lxc_conf
*c
, char *retv
, int inlen
)
2240 int len
, fulllen
= 0;
2241 struct lxc_list
*it
;
2246 memset(retv
, 0, inlen
);
2248 lxc_list_for_each(it
, &c
->mount_list
) {
2249 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2254 static int lxc_get_auto_mounts(struct lxc_conf
*c
, char *retv
, int inlen
)
2256 int len
, fulllen
= 0;
2257 const char *sep
= "";
2262 memset(retv
, 0, inlen
);
2264 if (!(c
->auto_mounts
& LXC_AUTO_ALL_MASK
))
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;
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;
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;
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
2301 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
,
2305 int len
, fulllen
= 0;
2306 struct lxc_netdev
*netdev
;
2311 memset(retv
, 0, inlen
);
2313 p1
= strchr(key
, '.');
2314 if (!p1
|| *(p1
+1) == '\0') return -1;
2317 netdev
= get_netdev_from_key(key
, &c
->network
);
2320 if (strcmp(p1
, "name") == 0) {
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) {
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) {
2339 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
2340 } else if (strcmp(p1
, "mtu") == 0) {
2342 strprint(retv
, inlen
, "%s", netdev
->mtu
);
2343 } else if (strcmp(p1
, "macvlan.mode") == 0) {
2344 if (netdev
->type
== LXC_NET_MACVLAN
) {
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;
2353 strprint(retv
, inlen
, "%s", mode
);
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
);
2362 } else if (strcmp(p1
, "vlan") == 0) {
2363 if (netdev
->type
== LXC_NET_VLAN
) {
2364 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
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
);
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
);
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
);
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
);
2402 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
2404 int len
, fulllen
= 0;
2405 struct lxc_list
*it
;
2410 memset(retv
, 0, inlen
);
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)");
2420 int lxc_get_config_item(struct lxc_conf
*c
, const char *key
, char *retv
,
2423 const char *v
= NULL
;
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)
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)
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)
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)
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)
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)
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
);
2501 if (retv
&& inlen
>= strlen(v
) + 1)
2502 strncpy(retv
, v
, strlen(v
)+1);
2506 int lxc_clear_config_item(struct lxc_conf
*c
, const char *key
)
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
);
2534 * writing out a confile.
2536 void write_config(FILE *fout
, struct lxc_conf
*c
)
2538 size_t len
= c
->unexpanded_len
;
2543 ret
= fwrite(c
->unexpanded_config
, 1, len
, fout
);
2545 SYSERROR("Error writing configuration file");
2548 bool do_append_unexp_config_line(struct lxc_conf
*conf
, const char *key
, const char *v
)
2551 size_t len
= strlen(key
) + strlen(v
) + 4;
2552 char *tmp
= alloca(len
);
2554 ret
= snprintf(tmp
, len
, "%s = %s", key
, v
);
2555 if (ret
< 0 || ret
>= len
)
2558 /* Save the line verbatim into unexpanded_conf */
2559 if (append_unexp_config_line(tmp
, conf
))
2565 void clear_unexp_config_line(struct lxc_conf
*conf
, const char *key
, bool rm_subkeys
)
2567 char *lstart
= conf
->unexpanded_config
, *lend
;
2569 if (!conf
->unexpanded_config
)
2572 lend
= strchr(lstart
, '\n');
2575 lend
= lstart
+ strlen(lstart
);
2578 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
2583 v
= lstart
[strlen(key
)];
2584 if (!isspace(v
) && v
!= '=') {
2589 conf
->unexpanded_len
-= (lend
- lstart
);
2590 if (*lend
== '\0') {
2594 memmove(lstart
, lend
, strlen(lend
)+1);
2598 bool clone_update_unexp_hooks(struct lxc_conf
*conf
, const char *oldpath
,
2599 const char *newpath
, const char *oldname
, const char *newname
)
2601 const char *key
= "lxc.hook";
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);
2609 ret
= snprintf(olddir
, olddirlen
+1, "%s/%s", oldpath
, oldname
);
2610 if (ret
< 0 || ret
>= olddirlen
+1) {
2611 ERROR("Bug in %s", __func__
);
2614 ret
= snprintf(newdir
, newdirlen
+1, "%s/%s", newpath
, newname
);
2615 if (ret
< 0 || ret
>= newdirlen
+1) {
2616 ERROR("Bug in %s", __func__
);
2619 if (!conf
->unexpanded_config
)
2622 lend
= strchr(lstart
, '\n');
2624 lend
= lstart
+ strlen(lstart
);
2627 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
2631 p
= strchr(lstart
+strlen(key
), '=');
2641 if (strncmp(p
, olddir
, strlen(olddir
)) != 0) {
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);
2652 conf
->unexpanded_len
-= diff
;
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
);
2663 ERROR("Out of memory");
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
;
2683 ERROR("Error writing to new config"); \
2688 static void new_hwaddr(char *hwaddr
)
2691 f
= fopen("/dev/urandom", "r");
2694 int ret
= fread(&seed
, sizeof(seed
), 1, f
);
2701 snprintf(hwaddr
, 18, "00:16:3e:%02x:%02x:%02x",
2702 rand() % 255, rand() % 255, rand() % 255);
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.
2715 bool network_new_hwaddrs(struct lxc_conf
*conf
)
2717 struct lxc_list
*it
;
2719 const char *key
= "lxc.network.hwaddr";
2720 char *lstart
= conf
->unexpanded_config
, *lend
, *p
, *p2
;
2722 if (!conf
->unexpanded_config
)
2725 char newhwaddr
[18], oldhwaddr
[17];
2726 lend
= strchr(lstart
, '\n');
2728 lend
= lstart
+ strlen(lstart
);
2731 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
2735 p
= strchr(lstart
+strlen(key
), '=');
2746 while (*p2
&& !isblank(*p2
) && *p2
!= '\n')
2749 WARN("Bad hwaddr entry");
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);
2767 static int config_ephemeral(const char *key
, const char *value
,
2768 struct lxc_conf
*lxc_conf
)
2770 int v
= atoi(value
);
2772 if (v
!= 0 && v
!= 1) {
2773 ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
2776 lxc_conf
->ephemeral
= v
;