2 * lxc: linux Container library
3 * (C) Copyright IBM Corp. 2007, 2008
6 * Daniel Lezcano <daniel.lezcano at free.fr>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
31 #include <inttypes.h> /* Required for PRIu64 to work. */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/utsname.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
52 #include "lxcseccomp.h"
57 #include <../include/ifaddrs.h>
60 #if HAVE_SYS_PERSONALITY_H
61 #include <sys/personality.h>
64 lxc_log_define(lxc_confile
, lxc
);
66 static int set_config_personality(const char *, const char *, struct lxc_conf
*);
67 static int get_config_personality(struct lxc_container
*, const char *, char *, int);
69 static int set_config_pts(const char *, const char *, struct lxc_conf
*);
70 static int get_config_pts(struct lxc_container
*, const char *, char *, int);
72 static int set_config_tty(const char *, const char *, struct lxc_conf
*);
73 static int get_config_tty(struct lxc_container
*, const char *, char *, int);
75 static int set_config_ttydir(const char *, const char *, struct lxc_conf
*);
76 static int get_config_ttydir(struct lxc_container
*, const char *, char *, int);
78 static int set_config_kmsg(const char *, const char *, struct lxc_conf
*);
79 static int get_config_kmsg(struct lxc_container
*, const char *, char *, int);
81 static int set_config_lsm_aa_profile(const char *, const char *, struct lxc_conf
*);
82 static int get_config_lsm_aa_profile(struct lxc_container
*, const char *, char *, int);
84 static int set_config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf
*);
85 static int get_config_lsm_aa_incomplete(struct lxc_container
*, const char *, char *, int);
87 static int set_config_lsm_se_context(const char *, const char *, struct lxc_conf
*);
88 static int get_config_lsm_se_context(struct lxc_container
*, const char *, char *, int);
90 static int set_config_cgroup(const char *, const char *, struct lxc_conf
*);
91 static int get_config_cgroup(struct lxc_container
*, const char *, char *, int);
93 static int set_config_idmaps(const char *, const char *, struct lxc_conf
*);
94 static int get_config_idmaps(struct lxc_container
*, const char *, char *, int);
96 static int set_config_loglevel(const char *, const char *, struct lxc_conf
*);
97 static int get_config_loglevel(struct lxc_container
*, const char *, char *, int);
99 static int set_config_logfile(const char *, const char *, struct lxc_conf
*);
100 static int get_config_logfile(struct lxc_container
*, const char *, char *, int);
102 static int set_config_mount(const char *, const char *, struct lxc_conf
*);
103 static int get_config_mount(struct lxc_container
*, const char *, char *, int);
105 static int set_config_mount_auto(const char *, const char *, struct lxc_conf
*);
106 static int get_config_mount_auto(struct lxc_container
*, const char *, char *, int);
108 static int set_config_fstab(const char *, const char *, struct lxc_conf
*);
109 static int get_config_fstab(struct lxc_container
*, const char *, char *, int);
111 static int set_config_rootfs(const char *, const char *, struct lxc_conf
*);
112 static int get_config_rootfs(struct lxc_container
*, const char *, char *, int);
114 static int set_config_rootfs_mount(const char *, const char *, struct lxc_conf
*);
115 static int get_config_rootfs_mount(struct lxc_container
*, const char *, char *, int);
117 static int set_config_rootfs_options(const char *, const char *, struct lxc_conf
*);
118 static int get_config_rootfs_options(struct lxc_container
*, const char *, char *, int);
120 static int set_config_rootfs_backend(const char *, const char *, struct lxc_conf
*);
121 static int set_config_pivotdir(const char *, const char *, struct lxc_conf
*);
122 static int set_config_utsname(const char *, const char *, struct lxc_conf
*);
123 static int set_config_hook(const char *, const char *, struct lxc_conf
*lxc_conf
);
124 static int set_config_network(const char *, const char *, struct lxc_conf
*);
125 static int set_config_network_type(const char *, const char *, struct lxc_conf
*);
126 static int set_config_network_flags(const char *, const char *, struct lxc_conf
*);
127 static int set_config_network_link(const char *, const char *, struct lxc_conf
*);
128 static int set_config_network_name(const char *, const char *, struct lxc_conf
*);
129 static int set_config_network_veth_pair(const char *, const char *, struct lxc_conf
*);
130 static int set_config_network_macvlan_mode(const char *, const char *, struct lxc_conf
*);
131 static int set_config_network_hwaddr(const char *, const char *, struct lxc_conf
*);
132 static int set_config_network_vlan_id(const char *, const char *, struct lxc_conf
*);
133 static int set_config_network_mtu(const char *, const char *, struct lxc_conf
*);
134 static int set_config_network_ipv4(const char *, const char *, struct lxc_conf
*);
135 static int set_config_network_ipv4_gateway(const char *, const char *, struct lxc_conf
*);
136 static int set_config_network_script_up(const char *, const char *, struct lxc_conf
*);
137 static int set_config_network_script_down(const char *, const char *, struct lxc_conf
*);
138 static int set_config_network_ipv6(const char *, const char *, struct lxc_conf
*);
139 static int set_config_network_ipv6_gateway(const char *, const char *, struct lxc_conf
*);
140 static int set_config_cap_drop(const char *, const char *, struct lxc_conf
*);
141 static int set_config_cap_keep(const char *, const char *, struct lxc_conf
*);
142 static int set_config_console(const char *, const char *, struct lxc_conf
*);
143 static int set_config_console_logfile(const char *, const char *, struct lxc_conf
*);
144 static int set_config_seccomp(const char *, const char *, struct lxc_conf
*);
145 static int set_config_includefile(const char *, const char *, struct lxc_conf
*);
146 static int set_config_network_nic(const char *, const char *, struct lxc_conf
*);
147 static int set_config_autodev(const char *, const char *, struct lxc_conf
*);
148 static int set_config_haltsignal(const char *, const char *, struct lxc_conf
*);
149 static int set_config_rebootsignal(const char *, const char *, struct lxc_conf
*);
150 static int set_config_stopsignal(const char *, const char *, struct lxc_conf
*);
151 static int set_config_start(const char *, const char *, struct lxc_conf
*);
152 static int set_config_syslog(const char *, const char *, struct lxc_conf
*);
153 static int set_config_monitor(const char *, const char *, struct lxc_conf
*);
154 static int set_config_group(const char *, const char *, struct lxc_conf
*);
155 static int set_config_environment(const char *, const char *, struct lxc_conf
*);
156 static int set_config_init_cmd(const char *, const char *, struct lxc_conf
*);
157 static int set_config_init_uid(const char *, const char *, struct lxc_conf
*);
158 static int set_config_init_gid(const char *, const char *, struct lxc_conf
*);
159 static int set_config_ephemeral(const char *, const char *, struct lxc_conf
*);
160 static int set_config_no_new_privs(const char *, const char *, struct lxc_conf
*);
161 static int set_config_limit(const char *, const char *, struct lxc_conf
*);
163 static struct lxc_config_t config
[] = {
164 { "lxc.arch", set_config_personality
, get_config_personality
, NULL
},
165 { "lxc.pts", set_config_pts
, get_config_pts
, NULL
},
166 { "lxc.tty", set_config_tty
, get_config_tty
, NULL
},
167 { "lxc.devttydir", set_config_ttydir
, get_config_ttydir
, NULL
},
168 { "lxc.kmsg", set_config_kmsg
, get_config_kmsg
, NULL
},
169 { "lxc.aa_profile", set_config_lsm_aa_profile
, get_config_lsm_aa_profile
, NULL
},
170 { "lxc.aa_allow_incomplete", set_config_lsm_aa_incomplete
, get_config_lsm_aa_incomplete
, NULL
},
171 { "lxc.se_context", set_config_lsm_se_context
, get_config_lsm_se_context
, NULL
},
172 { "lxc.cgroup", set_config_cgroup
, get_config_cgroup
, NULL
},
173 { "lxc.id_map", set_config_idmaps
, get_config_idmaps
, NULL
},
174 { "lxc.loglevel", set_config_loglevel
, get_config_loglevel
, NULL
},
175 { "lxc.logfile", set_config_logfile
, get_config_logfile
, NULL
},
176 { "lxc.mount.entry", set_config_mount
, get_config_mount
, NULL
},
177 { "lxc.mount.auto", set_config_mount_auto
, get_config_mount_auto
, NULL
},
178 { "lxc.mount", set_config_fstab
, get_config_fstab
, NULL
},
179 { "lxc.rootfs.mount", set_config_rootfs_mount
, get_config_rootfs_mount
, NULL
},
180 { "lxc.rootfs.options", set_config_rootfs_options
, get_config_rootfs_options
, NULL
},
181 { "lxc.rootfs.backend", set_config_rootfs_backend
, NULL
, NULL
},
182 { "lxc.rootfs", set_config_rootfs
, get_config_rootfs
, NULL
},
183 { "lxc.pivotdir", set_config_pivotdir
, NULL
, NULL
},
184 { "lxc.utsname", set_config_utsname
, NULL
, NULL
},
185 { "lxc.hook.pre-start", set_config_hook
, NULL
, NULL
},
186 { "lxc.hook.pre-mount", set_config_hook
, NULL
, NULL
},
187 { "lxc.hook.mount", set_config_hook
, NULL
, NULL
},
188 { "lxc.hook.autodev", set_config_hook
, NULL
, NULL
},
189 { "lxc.hook.start", set_config_hook
, NULL
, NULL
},
190 { "lxc.hook.stop", set_config_hook
, NULL
, NULL
},
191 { "lxc.hook.post-stop", set_config_hook
, NULL
, NULL
},
192 { "lxc.hook.clone", set_config_hook
, NULL
, NULL
},
193 { "lxc.hook.destroy", set_config_hook
, NULL
, NULL
},
194 { "lxc.hook", set_config_hook
, NULL
, NULL
},
195 { "lxc.network.type", set_config_network_type
, NULL
, NULL
},
196 { "lxc.network.flags", set_config_network_flags
, NULL
, NULL
},
197 { "lxc.network.link", set_config_network_link
, NULL
, NULL
},
198 { "lxc.network.name", set_config_network_name
, NULL
, NULL
},
199 { "lxc.network.macvlan.mode", set_config_network_macvlan_mode
, NULL
, NULL
},
200 { "lxc.network.veth.pair", set_config_network_veth_pair
, NULL
, NULL
},
201 { "lxc.network.script.up", set_config_network_script_up
, NULL
, NULL
},
202 { "lxc.network.script.down", set_config_network_script_down
, NULL
, NULL
},
203 { "lxc.network.hwaddr", set_config_network_hwaddr
, NULL
, NULL
},
204 { "lxc.network.mtu", set_config_network_mtu
, NULL
, NULL
},
205 { "lxc.network.vlan.id", set_config_network_vlan_id
, NULL
, NULL
},
206 { "lxc.network.ipv4.gateway", set_config_network_ipv4_gateway
, NULL
, NULL
},
207 { "lxc.network.ipv4", set_config_network_ipv4
, NULL
, NULL
},
208 { "lxc.network.ipv6.gateway", set_config_network_ipv6_gateway
, NULL
, NULL
},
209 { "lxc.network.ipv6", set_config_network_ipv6
, NULL
, NULL
},
210 { "lxc.network.", set_config_network_nic
, NULL
, NULL
},
211 { "lxc.network", set_config_network
, NULL
, NULL
},
212 { "lxc.cap.drop", set_config_cap_drop
, NULL
, NULL
},
213 { "lxc.cap.keep", set_config_cap_keep
, NULL
, NULL
},
214 { "lxc.console.logfile", set_config_console_logfile
, NULL
, NULL
},
215 { "lxc.console", set_config_console
, NULL
, NULL
},
216 { "lxc.seccomp", set_config_seccomp
, NULL
, NULL
},
217 { "lxc.include", set_config_includefile
, NULL
, NULL
},
218 { "lxc.autodev", set_config_autodev
, NULL
, NULL
},
219 { "lxc.haltsignal", set_config_haltsignal
, NULL
, NULL
},
220 { "lxc.rebootsignal", set_config_rebootsignal
, NULL
, NULL
},
221 { "lxc.stopsignal", set_config_stopsignal
, NULL
, NULL
},
222 { "lxc.start.auto", set_config_start
, NULL
, NULL
},
223 { "lxc.start.delay", set_config_start
, NULL
, NULL
},
224 { "lxc.start.order", set_config_start
, NULL
, NULL
},
225 { "lxc.monitor.unshare", set_config_monitor
, NULL
, NULL
},
226 { "lxc.group", set_config_group
, NULL
, NULL
},
227 { "lxc.environment", set_config_environment
, NULL
, NULL
},
228 { "lxc.init_cmd", set_config_init_cmd
, NULL
, NULL
},
229 { "lxc.init_uid", set_config_init_uid
, NULL
, NULL
},
230 { "lxc.init_gid", set_config_init_gid
, NULL
, NULL
},
231 { "lxc.ephemeral", set_config_ephemeral
, NULL
, NULL
},
232 { "lxc.syslog", set_config_syslog
, NULL
, NULL
},
233 { "lxc.no_new_privs", set_config_no_new_privs
, NULL
, NULL
},
234 { "lxc.limit", set_config_limit
, NULL
, NULL
},
242 static const struct signame signames
[] = {
275 { SIGSTKFLT
, "STKFLT" },
290 { SIGVTALRM
, "VTALRM" },
296 { SIGWINCH
, "WINCH" },
314 { SIGUNUSED
, "UNUSED" },
321 static const size_t config_size
= sizeof(config
)/sizeof(struct lxc_config_t
);
323 extern struct lxc_config_t
*lxc_getconfig(const char *key
)
327 for (i
= 0; i
< config_size
; i
++)
328 if (!strncmp(config
[i
].name
, key
,
329 strlen(config
[i
].name
)))
334 #define strprint(str, inlen, ...) \
336 len = snprintf(str, inlen, ##__VA_ARGS__); \
337 if (len < 0) { SYSERROR("snprintf"); return -1; }; \
340 if (str) str += len; \
342 if (inlen < 0) inlen = 0; \
346 int lxc_listconfigs(char *retv
, int inlen
)
349 int fulllen
= 0, len
;
354 memset(retv
, 0, inlen
);
355 for (i
= 0; i
< config_size
; i
++) {
356 char *s
= config
[i
].name
;
357 if (s
[strlen(s
)-1] == '.')
359 strprint(retv
, inlen
, "%s\n", s
);
364 static inline bool config_value_empty(const char *value
)
366 if (value
&& strlen(value
) > 0)
372 static int set_config_string_item(char **conf_item
, const char *value
)
376 if (config_value_empty(value
)) {
382 new_value
= strdup(value
);
384 SYSERROR("failed to duplicate string \"%s\"", value
);
389 *conf_item
= new_value
;
393 static int set_config_string_item_max(char **conf_item
, const char *value
,
396 if (strlen(value
) >= max
) {
397 ERROR("%s is too long (>= %lu)", value
, (unsigned long)max
);
401 return set_config_string_item(conf_item
, value
);
404 static int set_config_path_item(char **conf_item
, const char *value
)
406 return set_config_string_item_max(conf_item
, value
, PATH_MAX
);
410 * config entry is something like "lxc.network.0.ipv4"
411 * the key 'lxc.network.' was found. So we make sure next
412 * comes an integer, find the right callback (by rewriting
413 * the key), and call it.
415 static int set_config_network_nic(const char *key
, const char *value
,
416 struct lxc_conf
*lxc_conf
)
418 char *copy
= strdup(key
), *p
;
420 struct lxc_config_t
*config
;
423 SYSERROR("failed to allocate memory");
427 * ok we know that to get here we've got "lxc.network."
428 * and it isn't any of the other network entries. So
429 * after the second . should come an integer (# of defined
430 * nic) followed by a valid entry.
432 if (*(key
+12) < '0' || *(key
+12) > '9')
434 p
= strchr(key
+12, '.');
437 strcpy(copy
+12, p
+1);
438 config
= lxc_getconfig(copy
);
440 ERROR("unknown key %s", key
);
443 ret
= config
->set(key
, value
, lxc_conf
);
450 static int set_config_network(const char *key
, const char *value
,
451 struct lxc_conf
*lxc_conf
)
453 if (!config_value_empty(value
)) {
454 ERROR("lxc.network must not have a value");
458 return lxc_clear_config_network(lxc_conf
);
461 static int macvlan_mode(int *valuep
, const char *value
);
463 static int set_config_network_type(const char *key
, const char *value
,
464 struct lxc_conf
*lxc_conf
)
466 struct lxc_list
*network
= &lxc_conf
->network
;
467 struct lxc_netdev
*netdev
;
468 struct lxc_list
*list
;
470 if (config_value_empty(value
))
471 return lxc_clear_config_network(lxc_conf
);
473 netdev
= malloc(sizeof(*netdev
));
475 SYSERROR("failed to allocate memory");
479 memset(netdev
, 0, sizeof(*netdev
));
480 lxc_list_init(&netdev
->ipv4
);
481 lxc_list_init(&netdev
->ipv6
);
483 list
= malloc(sizeof(*list
));
485 SYSERROR("failed to allocate memory");
493 lxc_list_add_tail(network
, list
);
495 if (!strcmp(value
, "veth"))
496 netdev
->type
= LXC_NET_VETH
;
497 else if (!strcmp(value
, "macvlan")) {
498 netdev
->type
= LXC_NET_MACVLAN
;
499 macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, "private");
501 else if (!strcmp(value
, "vlan"))
502 netdev
->type
= LXC_NET_VLAN
;
503 else if (!strcmp(value
, "phys"))
504 netdev
->type
= LXC_NET_PHYS
;
505 else if (!strcmp(value
, "empty"))
506 netdev
->type
= LXC_NET_EMPTY
;
507 else if (!strcmp(value
, "none"))
508 netdev
->type
= LXC_NET_NONE
;
510 ERROR("invalid network type %s", value
);
516 static int config_ip_prefix(struct in_addr
*addr
)
518 if (IN_CLASSA(addr
->s_addr
))
519 return 32 - IN_CLASSA_NSHIFT
;
520 if (IN_CLASSB(addr
->s_addr
))
521 return 32 - IN_CLASSB_NSHIFT
;
522 if (IN_CLASSC(addr
->s_addr
))
523 return 32 - IN_CLASSC_NSHIFT
;
529 * if you have p="lxc.network.0.link", pass it p+12
530 * to get back '0' (the index of the nic)
532 static int get_network_netdev_idx(const char *key
)
536 if (*key
< '0' || *key
> '9')
538 ret
= sscanf(key
, "%d", &idx
);
545 * if you have p="lxc.network.0", pass this p+12 and it will return
546 * the netdev of the first configured nic
548 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
549 struct lxc_list
*network
)
551 int i
= 0, idx
= get_network_netdev_idx(key
);
552 struct lxc_netdev
*netdev
= NULL
;
556 lxc_list_for_each(it
, network
) {
565 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, const char *key
,
566 char *retv
, int inlen
)
568 struct lxc_netdev
*netdev
;
569 int fulllen
= 0, len
;
571 netdev
= get_netdev_from_key(key
+12, &c
->network
);
578 memset(retv
, 0, inlen
);
580 strprint(retv
, inlen
, "type\n");
581 strprint(retv
, inlen
, "script.up\n");
582 strprint(retv
, inlen
, "script.down\n");
583 if (netdev
->type
!= LXC_NET_EMPTY
) {
584 strprint(retv
, inlen
, "flags\n");
585 strprint(retv
, inlen
, "link\n");
586 strprint(retv
, inlen
, "name\n");
587 strprint(retv
, inlen
, "hwaddr\n");
588 strprint(retv
, inlen
, "mtu\n");
589 strprint(retv
, inlen
, "ipv6\n");
590 strprint(retv
, inlen
, "ipv6.gateway\n");
591 strprint(retv
, inlen
, "ipv4\n");
592 strprint(retv
, inlen
, "ipv4.gateway\n");
594 switch(netdev
->type
) {
596 strprint(retv
, inlen
, "veth.pair\n");
598 case LXC_NET_MACVLAN
:
599 strprint(retv
, inlen
, "macvlan.mode\n");
602 strprint(retv
, inlen
, "vlan.id\n");
610 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
611 struct lxc_list
*network
)
613 struct lxc_netdev
*netdev
= NULL
;
615 if (lxc_list_empty(network
)) {
616 ERROR("network is not created for '%s' = '%s' option",
621 if (get_network_netdev_idx(key
+12) == -1)
622 netdev
= lxc_list_last_elem(network
);
624 netdev
= get_netdev_from_key(key
+12, network
);
627 ERROR("no network device defined for '%s' = '%s' option",
635 static int network_ifname(char **valuep
, const char *value
)
637 return set_config_string_item_max(valuep
, value
, IFNAMSIZ
);
640 #ifndef MACVLAN_MODE_PRIVATE
641 # define MACVLAN_MODE_PRIVATE 1
644 #ifndef MACVLAN_MODE_VEPA
645 # define MACVLAN_MODE_VEPA 2
648 #ifndef MACVLAN_MODE_BRIDGE
649 # define MACVLAN_MODE_BRIDGE 4
652 #ifndef MACVLAN_MODE_PASSTHRU
653 # define MACVLAN_MODE_PASSTHRU 8
656 static int macvlan_mode(int *valuep
, const char *value
)
662 { "private", MACVLAN_MODE_PRIVATE
},
663 { "vepa", MACVLAN_MODE_VEPA
},
664 { "bridge", MACVLAN_MODE_BRIDGE
},
665 { "passthru", MACVLAN_MODE_PASSTHRU
},
670 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
671 if (strcmp(m
[i
].name
, value
))
681 static int rand_complete_hwaddr(char *hwaddr
)
683 const char hex
[] = "0123456789abcdef";
689 unsigned int seed
=randseed(false);
691 while (*curs
!= '\0' && *curs
!= '\n')
693 if ( *curs
== 'x' || *curs
== 'X' ) {
694 if (curs
- hwaddr
== 1) {
695 //ensure address is unicast
697 *curs
= hex
[rand_r(&seed
) & 0x0E];
699 *curs
= hex
[rand_r(&seed
) & 0x0F];
701 *curs
= hex
[rand() & 0x0E];
703 *curs
= hex
[rand() & 0x0F];
712 static int set_config_network_flags(const char *key
, const char *value
,
713 struct lxc_conf
*lxc_conf
)
715 struct lxc_netdev
*netdev
;
717 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
721 netdev
->flags
|= IFF_UP
;
726 static int set_network_link(const char *key
, const char *value
, struct lxc_conf
*lxc_conf
)
728 struct lxc_netdev
*netdev
;
730 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
734 return network_ifname(&netdev
->link
, value
);
737 static int create_matched_ifnames(const char *value
, struct lxc_conf
*lxc_conf
)
739 struct ifaddrs
*ifaddr
, *ifa
;
740 const char *type_key
= "lxc.network.type";
741 const char *link_key
= "lxc.network.link";
742 const char *tmpvalue
= "phys";
745 if (getifaddrs(&ifaddr
) == -1) {
746 SYSERROR("Get network interfaces failed");
750 for (ifa
= ifaddr
, n
= 0; ifa
!= NULL
; ifa
= ifa
->ifa_next
, n
++) {
753 if (ifa
->ifa_addr
->sa_family
!= AF_PACKET
)
756 if (!strncmp(value
, ifa
->ifa_name
, strlen(value
)-1)) {
757 ret
= set_config_network_type(type_key
, tmpvalue
, lxc_conf
);
759 ret
= set_network_link(link_key
, ifa
->ifa_name
, lxc_conf
);
761 ERROR("failed to create matched ifnames");
765 ERROR("failed to create matched ifnames");
771 freeifaddrs(ifaddr
); /* free the dynamic memory */
772 ifaddr
= NULL
; /* prevent use after free */
777 static int set_config_network_link(const char *key
, const char *value
,
778 struct lxc_conf
*lxc_conf
)
780 struct lxc_netdev
*netdev
;
781 struct lxc_list
* it
;
784 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
788 if (value
[strlen(value
) - 1] == '+' && netdev
->type
== LXC_NET_PHYS
) {
789 //get the last network list and remove it.
790 it
= lxc_conf
->network
.prev
;
791 if (((struct lxc_netdev
*)(it
->elem
))->type
!= LXC_NET_PHYS
) {
792 ERROR("lxc config cannot support string pattern matching for this link type");
798 ret
= create_matched_ifnames(value
, lxc_conf
);
801 ret
= network_ifname(&netdev
->link
, value
);
807 static int set_config_network_name(const char *key
, const char *value
,
808 struct lxc_conf
*lxc_conf
)
810 struct lxc_netdev
*netdev
;
812 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
816 return network_ifname(&netdev
->name
, value
);
819 static int set_config_network_veth_pair(const char *key
, const char *value
,
820 struct lxc_conf
*lxc_conf
)
822 struct lxc_netdev
*netdev
;
824 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
828 if (netdev
->type
!= LXC_NET_VETH
) {
829 ERROR("Invalid veth pair for a non-veth netdev");
832 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
835 static int set_config_network_macvlan_mode(const char *key
, const char *value
,
836 struct lxc_conf
*lxc_conf
)
838 struct lxc_netdev
*netdev
;
840 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
844 if (netdev
->type
!= LXC_NET_MACVLAN
) {
845 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
848 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
851 static int set_config_network_hwaddr(const char *key
, const char *value
,
852 struct lxc_conf
*lxc_conf
)
854 struct lxc_netdev
*netdev
;
856 char *new_value
= strdup(value
);
858 SYSERROR("failed to strdup '%s': %m", value
);
861 rand_complete_hwaddr(new_value
);
863 netdev
= network_netdev(key
, new_value
, &lxc_conf
->network
);
869 if (config_value_empty(new_value
)) {
871 netdev
->hwaddr
= NULL
;
875 netdev
->hwaddr
= new_value
;
879 static int set_config_network_vlan_id(const char *key
, const char *value
,
880 struct lxc_conf
*lxc_conf
)
882 struct lxc_netdev
*netdev
;
884 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
888 if (netdev
->type
!= LXC_NET_VLAN
) {
889 ERROR("Invalid vlan.id for a non-macvlan netdev");
892 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
898 static int set_config_network_mtu(const char *key
, const char *value
,
899 struct lxc_conf
*lxc_conf
)
901 struct lxc_netdev
*netdev
;
903 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
907 return set_config_string_item(&netdev
->mtu
, value
);
910 static int set_config_network_ipv4(const char *key
, const char *value
,
911 struct lxc_conf
*lxc_conf
)
913 struct lxc_netdev
*netdev
;
914 struct lxc_inetdev
*inetdev
;
915 struct lxc_list
*list
;
916 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
918 if (config_value_empty(value
))
919 return lxc_clear_config_item(lxc_conf
, key
);
921 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
925 inetdev
= malloc(sizeof(*inetdev
));
927 SYSERROR("failed to allocate ipv4 address");
930 memset(inetdev
, 0, sizeof(*inetdev
));
932 list
= malloc(sizeof(*list
));
934 SYSERROR("failed to allocate memory");
940 list
->elem
= inetdev
;
942 addr
= strdup(value
);
944 ERROR("no address specified");
950 cursor
= strstr(addr
, " ");
956 slash
= strstr(addr
, "/");
962 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
963 SYSERROR("invalid ipv4 address: %s", value
);
970 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
971 SYSERROR("invalid ipv4 broadcast address: %s", value
);
978 /* no prefix specified, determine it from the network class */
980 if (lxc_safe_uint(prefix
, &inetdev
->prefix
) < 0)
983 inetdev
->prefix
= config_ip_prefix(&inetdev
->addr
);
986 /* if no broadcast address, let compute one from the
990 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
991 inetdev
->bcast
.s_addr
|=
992 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
995 lxc_list_add_tail(&netdev
->ipv4
, list
);
1001 static int set_config_network_ipv4_gateway(const char *key
, const char *value
,
1002 struct lxc_conf
*lxc_conf
)
1004 struct lxc_netdev
*netdev
;
1006 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1010 free(netdev
->ipv4_gateway
);
1012 if (config_value_empty(value
)) {
1013 netdev
->ipv4_gateway
= NULL
;
1014 } else if (!strcmp(value
, "auto")) {
1015 netdev
->ipv4_gateway
= NULL
;
1016 netdev
->ipv4_gateway_auto
= true;
1020 gw
= malloc(sizeof(*gw
));
1022 SYSERROR("failed to allocate ipv4 gateway address");
1026 if (!inet_pton(AF_INET
, value
, gw
)) {
1027 SYSERROR("invalid ipv4 gateway address: %s", value
);
1032 netdev
->ipv4_gateway
= gw
;
1033 netdev
->ipv4_gateway_auto
= false;
1039 static int set_config_network_ipv6(const char *key
, const char *value
,
1040 struct lxc_conf
*lxc_conf
)
1042 struct lxc_netdev
*netdev
;
1043 struct lxc_inet6dev
*inet6dev
;
1044 struct lxc_list
*list
;
1045 char *slash
,*valdup
;
1048 if (config_value_empty(value
))
1049 return lxc_clear_config_item(lxc_conf
, key
);
1051 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1055 inet6dev
= malloc(sizeof(*inet6dev
));
1057 SYSERROR("failed to allocate ipv6 address");
1060 memset(inet6dev
, 0, sizeof(*inet6dev
));
1062 list
= malloc(sizeof(*list
));
1064 SYSERROR("failed to allocate memory");
1069 lxc_list_init(list
);
1070 list
->elem
= inet6dev
;
1072 valdup
= strdup(value
);
1074 ERROR("no address specified");
1080 inet6dev
->prefix
= 64;
1081 slash
= strstr(valdup
, "/");
1084 netmask
= slash
+ 1;
1085 if (lxc_safe_uint(netmask
, &inet6dev
->prefix
) < 0)
1089 if (!inet_pton(AF_INET6
, valdup
, &inet6dev
->addr
)) {
1090 SYSERROR("invalid ipv6 address: %s", valdup
);
1097 lxc_list_add_tail(&netdev
->ipv6
, list
);
1103 static int set_config_network_ipv6_gateway(const char *key
, const char *value
,
1104 struct lxc_conf
*lxc_conf
)
1106 struct lxc_netdev
*netdev
;
1108 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1112 free(netdev
->ipv6_gateway
);
1114 if (config_value_empty(value
)) {
1115 netdev
->ipv6_gateway
= NULL
;
1116 } else if (!strcmp(value
, "auto")) {
1117 netdev
->ipv6_gateway
= NULL
;
1118 netdev
->ipv6_gateway_auto
= true;
1120 struct in6_addr
*gw
;
1122 gw
= malloc(sizeof(*gw
));
1124 SYSERROR("failed to allocate ipv6 gateway address");
1128 if (!inet_pton(AF_INET6
, value
, gw
)) {
1129 SYSERROR("invalid ipv6 gateway address: %s", value
);
1134 netdev
->ipv6_gateway
= gw
;
1135 netdev
->ipv6_gateway_auto
= false;
1141 static int set_config_network_script_up(const char *key
, const char *value
,
1142 struct lxc_conf
*lxc_conf
)
1144 struct lxc_netdev
*netdev
;
1146 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1150 return set_config_string_item(&netdev
->upscript
, value
);
1153 static int set_config_network_script_down(const char *key
, const char *value
,
1154 struct lxc_conf
*lxc_conf
)
1156 struct lxc_netdev
*netdev
;
1158 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1162 return set_config_string_item(&netdev
->downscript
, value
);
1165 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
1167 struct lxc_list
*hooklist
;
1169 hooklist
= malloc(sizeof(*hooklist
));
1174 hooklist
->elem
= hook
;
1175 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
1179 static int set_config_seccomp(const char *key
, const char *value
,
1180 struct lxc_conf
*lxc_conf
)
1182 return set_config_path_item(&lxc_conf
->seccomp
, value
);
1185 static int set_config_init_cmd(const char *key
, const char *value
,
1186 struct lxc_conf
*lxc_conf
)
1188 return set_config_path_item(&lxc_conf
->init_cmd
, value
);
1191 static int set_config_init_uid(const char *key
, const char *value
,
1192 struct lxc_conf
*lxc_conf
)
1194 unsigned int init_uid
;
1196 /* Set config value to default. */
1197 if (config_value_empty(value
)) {
1198 lxc_conf
->init_uid
= 0;
1202 /* Parse new config value. */
1203 if (lxc_safe_uint(value
, &init_uid
) < 0)
1205 lxc_conf
->init_uid
= init_uid
;
1210 static int set_config_init_gid(const char *key
, const char *value
,
1211 struct lxc_conf
*lxc_conf
)
1213 unsigned int init_gid
;
1215 /* Set config value to default. */
1216 if (config_value_empty(value
)) {
1217 lxc_conf
->init_gid
= 0;
1221 /* Parse new config value. */
1222 if (lxc_safe_uint(value
, &init_gid
) < 0)
1224 lxc_conf
->init_gid
= init_gid
;
1229 static int set_config_hook(const char *key
, const char *value
,
1230 struct lxc_conf
*lxc_conf
)
1234 if (config_value_empty(value
))
1235 return lxc_clear_hooks(lxc_conf
, key
);
1237 if (strcmp(key
, "lxc.hook") == 0) {
1238 ERROR("lxc.hook cannot take a value");
1241 copy
= strdup(value
);
1243 SYSERROR("failed to dup string '%s'", value
);
1246 if (strcmp(key
, "lxc.hook.pre-start") == 0)
1247 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
1248 else if (strcmp(key
, "lxc.hook.pre-mount") == 0)
1249 return add_hook(lxc_conf
, LXCHOOK_PREMOUNT
, copy
);
1250 else if (strcmp(key
, "lxc.hook.autodev") == 0)
1251 return add_hook(lxc_conf
, LXCHOOK_AUTODEV
, copy
);
1252 else if (strcmp(key
, "lxc.hook.mount") == 0)
1253 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
1254 else if (strcmp(key
, "lxc.hook.start") == 0)
1255 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
1256 else if (strcmp(key
, "lxc.hook.stop") == 0)
1257 return add_hook(lxc_conf
, LXCHOOK_STOP
, copy
);
1258 else if (strcmp(key
, "lxc.hook.post-stop") == 0)
1259 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
1260 else if (strcmp(key
, "lxc.hook.clone") == 0)
1261 return add_hook(lxc_conf
, LXCHOOK_CLONE
, copy
);
1262 else if (strcmp(key
, "lxc.hook.destroy") == 0)
1263 return add_hook(lxc_conf
, LXCHOOK_DESTROY
, copy
);
1264 SYSERROR("Unknown key: %s", key
);
1269 static int set_config_personality(const char *key
, const char *value
,
1270 struct lxc_conf
*lxc_conf
)
1272 signed long personality
= lxc_config_parse_arch(value
);
1274 if (personality
>= 0)
1275 lxc_conf
->personality
= personality
;
1277 WARN("unsupported personality '%s'", value
);
1282 static int set_config_pts(const char *key
, const char *value
,
1283 struct lxc_conf
*lxc_conf
)
1285 /* Set config value to default. */
1286 if (config_value_empty(value
)) {
1291 /* Parse new config value. */
1292 if (lxc_safe_uint(value
, &lxc_conf
->pts
) < 0)
1298 static int set_config_start(const char *key
, const char *value
,
1299 struct lxc_conf
*lxc_conf
)
1303 is_empty
= config_value_empty(value
);
1305 if (strcmp(key
, "lxc.start.auto") == 0) {
1306 /* Set config value to default. */
1308 lxc_conf
->start_auto
= 0;
1312 /* Parse new config value. */
1313 if (lxc_safe_uint(value
, &lxc_conf
->start_auto
) < 0)
1316 if (lxc_conf
->start_auto
> 1)
1320 } else if (strcmp(key
, "lxc.start.delay") == 0) {
1321 /* Set config value to default. */
1323 lxc_conf
->start_delay
= 0;
1327 /* Parse new config value. */
1328 return lxc_safe_uint(value
, &lxc_conf
->start_delay
);
1329 } else if (strcmp(key
, "lxc.start.order") == 0) {
1330 /* Set config value to default. */
1332 lxc_conf
->start_order
= 0;
1336 /* Parse new config value. */
1337 return lxc_safe_int(value
, &lxc_conf
->start_order
);
1340 SYSERROR("Unknown key: %s", key
);
1344 static int set_config_monitor(const char *key
, const char *value
,
1345 struct lxc_conf
*lxc_conf
)
1347 /* Set config value to default. */
1348 if (config_value_empty(value
)) {
1349 lxc_conf
->monitor_unshare
= 0;
1353 /* Parse new config value. */
1354 if (strcmp(key
, "lxc.monitor.unshare") == 0)
1355 return lxc_safe_uint(value
, &lxc_conf
->monitor_unshare
);
1357 SYSERROR("Unknown key: %s", key
);
1361 static int set_config_group(const char *key
, const char *value
,
1362 struct lxc_conf
*lxc_conf
)
1364 char *groups
, *groupptr
, *sptr
, *token
;
1365 struct lxc_list
*grouplist
;
1368 if (config_value_empty(value
))
1369 return lxc_clear_groups(lxc_conf
);
1371 groups
= strdup(value
);
1373 SYSERROR("failed to dup '%s'", value
);
1377 /* in case several groups are specified in a single line
1378 * split these groups in a single element for the list */
1379 for (groupptr
= groups
;;groupptr
= NULL
) {
1380 token
= strtok_r(groupptr
, " \t", &sptr
);
1386 grouplist
= malloc(sizeof(*grouplist
));
1388 SYSERROR("failed to allocate groups list");
1392 grouplist
->elem
= strdup(token
);
1393 if (!grouplist
->elem
) {
1394 SYSERROR("failed to dup '%s'", token
);
1399 lxc_list_add_tail(&lxc_conf
->groups
, grouplist
);
1407 static int set_config_environment(const char *key
, const char *value
,
1408 struct lxc_conf
*lxc_conf
)
1410 struct lxc_list
*list_item
= NULL
;
1412 if (config_value_empty(value
))
1413 return lxc_clear_environment(lxc_conf
);
1415 list_item
= malloc(sizeof(*list_item
));
1419 list_item
->elem
= strdup(value
);
1421 if (!list_item
->elem
)
1424 lxc_list_add_tail(&lxc_conf
->environment
, list_item
);
1434 static int set_config_tty(const char *key
, const char *value
,
1435 struct lxc_conf
*lxc_conf
)
1437 /* Set config value to default. */
1438 if (config_value_empty(value
)) {
1443 /* Parse new config value. */
1444 return lxc_safe_uint(value
, &lxc_conf
->tty
);
1447 static int set_config_ttydir(const char *key
, const char *value
,
1448 struct lxc_conf
*lxc_conf
)
1450 return set_config_string_item_max(&lxc_conf
->ttydir
, value
, NAME_MAX
+1);
1453 static int set_config_kmsg(const char *key
, const char *value
,
1454 struct lxc_conf
*lxc_conf
)
1456 /* Set config value to default. */
1457 if (config_value_empty(value
)) {
1462 /* Parse new config value. */
1463 if (lxc_safe_uint(value
, &lxc_conf
->kmsg
) < 0)
1466 if (lxc_conf
->kmsg
> 1)
1472 static int set_config_lsm_aa_profile(const char *key
, const char *value
,
1473 struct lxc_conf
*lxc_conf
)
1475 return set_config_string_item(&lxc_conf
->lsm_aa_profile
, value
);
1478 static int set_config_lsm_aa_incomplete(const char *key
, const char *value
,
1479 struct lxc_conf
*lxc_conf
)
1481 /* Set config value to default. */
1482 if (config_value_empty(value
)) {
1483 lxc_conf
->lsm_aa_allow_incomplete
= 0;
1487 /* Parse new config value. */
1488 if (lxc_safe_uint(value
, &lxc_conf
->lsm_aa_allow_incomplete
) < 0)
1491 if (lxc_conf
->lsm_aa_allow_incomplete
> 1) {
1492 ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only "
1493 "be set to 0 or 1");
1500 static int set_config_lsm_se_context(const char *key
, const char *value
,
1501 struct lxc_conf
*lxc_conf
)
1503 return set_config_string_item(&lxc_conf
->lsm_se_context
, value
);
1506 static int set_config_logfile(const char *key
, const char *value
,
1511 if (config_value_empty(value
)) {
1517 /* Store these values in the lxc_conf, and then try to set for actual
1518 * current logging. */
1519 ret
= set_config_path_item(&c
->logfile
, value
);
1521 ret
= lxc_log_set_file(&c
->logfd
, c
->logfile
);
1525 static int set_config_loglevel(const char *key
, const char *value
,
1526 struct lxc_conf
*lxc_conf
)
1530 /* Set config value to default. */
1531 if (config_value_empty(value
)) {
1532 lxc_conf
->loglevel
= LXC_LOG_PRIORITY_NOTSET
;
1536 /* Parse new config value. */
1537 if (value
[0] >= '0' && value
[0] <= '9') {
1538 if (lxc_safe_int(value
, &newlevel
) < 0)
1541 newlevel
= lxc_log_priority_to_int(value
);
1544 /* store these values in the lxc_conf, and then try to set for actual
1547 lxc_conf
->loglevel
= newlevel
;
1548 return lxc_log_set_level(&lxc_conf
->loglevel
, newlevel
);
1551 static int set_config_autodev(const char *key
, const char *value
,
1552 struct lxc_conf
*lxc_conf
)
1554 /* Set config value to default. */
1555 if (config_value_empty(value
)) {
1556 lxc_conf
->autodev
= 0;
1560 /* Parse new config value. */
1561 if (lxc_safe_uint(value
, &lxc_conf
->autodev
) < 0)
1564 if (lxc_conf
->autodev
> 1) {
1565 ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1");
1572 static int sig_num(const char *sig
)
1574 unsigned int signum
;
1576 if (lxc_safe_uint(sig
, &signum
) < 0)
1582 static int rt_sig_num(const char *signame
)
1587 if (strncasecmp(signame
, "max-", 4) == 0) {
1591 if (!isdigit(*signame
))
1593 sig_n
= sig_num(signame
);
1594 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1595 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1600 static int sig_parse(const char *signame
) {
1603 if (isdigit(*signame
)) {
1604 return sig_num(signame
);
1605 } else if (strncasecmp(signame
, "sig", 3) == 0) {
1607 if (strncasecmp(signame
, "rt", 2) == 0)
1608 return rt_sig_num(signame
+ 2);
1609 for (n
= 0; n
< sizeof(signames
) / sizeof((signames
)[0]); n
++) {
1610 if (strcasecmp (signames
[n
].name
, signame
) == 0)
1611 return signames
[n
].num
;
1617 static int set_config_haltsignal(const char *key
, const char *value
,
1618 struct lxc_conf
*lxc_conf
)
1622 /* Set config value to default. */
1623 if (config_value_empty(value
)) {
1624 lxc_conf
->haltsignal
= 0;
1628 /* Parse new config value. */
1629 sig_n
= sig_parse(value
);
1633 lxc_conf
->haltsignal
= sig_n
;
1638 static int set_config_rebootsignal(const char *key
, const char *value
,
1639 struct lxc_conf
*lxc_conf
)
1643 /* Set config value to default. */
1644 if (config_value_empty(value
)) {
1645 lxc_conf
->rebootsignal
= 0;
1649 /* Parse new config value. */
1650 sig_n
= sig_parse(value
);
1653 lxc_conf
->rebootsignal
= sig_n
;
1658 static int set_config_stopsignal(const char *key
, const char *value
,
1659 struct lxc_conf
*lxc_conf
)
1663 /* Set config value to default. */
1664 if (config_value_empty(value
)) {
1665 lxc_conf
->stopsignal
= 0;
1669 /* Parse new config value. */
1670 sig_n
= sig_parse(value
);
1673 lxc_conf
->stopsignal
= sig_n
;
1678 static int set_config_cgroup(const char *key
, const char *value
,
1679 struct lxc_conf
*lxc_conf
)
1681 char *token
= "lxc.cgroup.";
1683 struct lxc_list
*cglist
= NULL
;
1684 struct lxc_cgroup
*cgelem
= NULL
;
1686 if (config_value_empty(value
))
1687 return lxc_clear_cgroups(lxc_conf
, key
);
1689 subkey
= strstr(key
, token
);
1694 if (!strlen(subkey
))
1697 if (strlen(subkey
) == strlen(token
))
1700 subkey
+= strlen(token
);
1702 cglist
= malloc(sizeof(*cglist
));
1706 cgelem
= malloc(sizeof(*cgelem
));
1709 memset(cgelem
, 0, sizeof(*cgelem
));
1711 cgelem
->subsystem
= strdup(subkey
);
1712 cgelem
->value
= strdup(value
);
1714 if (!cgelem
->subsystem
|| !cgelem
->value
)
1717 cglist
->elem
= cgelem
;
1719 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1727 free(cgelem
->subsystem
);
1729 free(cgelem
->value
);
1737 static bool parse_limit_value(const char **value
, unsigned long *res
) {
1738 char *endptr
= NULL
;
1740 if (strncmp(*value
, "unlimited", sizeof("unlimited")-1) == 0) {
1741 *res
= RLIM_INFINITY
;
1742 *value
+= sizeof("unlimited")-1;
1747 *res
= strtoul(*value
, &endptr
, 10);
1748 if (errno
|| !endptr
)
1755 static int set_config_limit(const char *key
, const char *value
,
1756 struct lxc_conf
*lxc_conf
)
1758 struct lxc_list
*limlist
= NULL
;
1759 struct lxc_limit
*limelem
= NULL
;
1760 struct lxc_list
*iter
;
1761 struct rlimit limit
;
1762 unsigned long limit_value
;
1764 if (config_value_empty(value
))
1765 return lxc_clear_limits(lxc_conf
, key
);
1767 if (strncmp(key
, "lxc.limit.", sizeof("lxc.limit.")-1) != 0)
1770 key
+= sizeof("lxc.limit.")-1;
1772 /* soft limit comes first in the value */
1773 if (!parse_limit_value(&value
, &limit_value
))
1775 limit
.rlim_cur
= limit_value
;
1777 /* skip spaces and a colon */
1778 while (isspace(*value
))
1782 else if (*value
) /* any other character is an error here */
1784 while (isspace(*value
))
1787 /* optional hard limit */
1789 if (!parse_limit_value(&value
, &limit_value
))
1791 limit
.rlim_max
= limit_value
;
1792 /* check for trailing garbage */
1793 while (isspace(*value
))
1798 /* a single value sets both hard and soft limit */
1799 limit
.rlim_max
= limit
.rlim_cur
;
1802 /* find existing list element */
1803 lxc_list_for_each(iter
, &lxc_conf
->limits
) {
1804 limelem
= iter
->elem
;
1805 if (!strcmp(key
, limelem
->resource
)) {
1806 limelem
->limit
= limit
;
1811 /* allocate list element */
1812 limlist
= malloc(sizeof(*limlist
));
1816 limelem
= malloc(sizeof(*limelem
));
1819 memset(limelem
, 0, sizeof(*limelem
));
1821 limelem
->resource
= strdup(key
);
1822 if (!limelem
->resource
)
1824 limelem
->limit
= limit
;
1826 limlist
->elem
= limelem
;
1828 lxc_list_add_tail(&lxc_conf
->limits
, limlist
);
1835 free(limelem
->resource
);
1841 static int set_config_idmaps(const char *key
, const char *value
,
1842 struct lxc_conf
*lxc_conf
)
1844 unsigned long hostid
, nsid
, range
;
1846 char *window
, *slide
;
1848 struct lxc_list
*idmaplist
= NULL
;
1849 struct id_map
*idmap
= NULL
;
1851 if (config_value_empty(value
))
1852 return lxc_clear_idmaps(lxc_conf
);
1854 idmaplist
= malloc(sizeof(*idmaplist
));
1858 idmap
= malloc(sizeof(*idmap
));
1861 memset(idmap
, 0, sizeof(*idmap
));
1863 /* Duplicate string. */
1864 dup
= strdup(value
);
1868 /* A prototypical idmap entry would be: "0 1000 1000000 65536" */
1871 slide
= window
= dup
;
1872 /* skip whitespace */
1873 slide
+= strspn(slide
, " \t\r");
1874 if (slide
!= window
&& *slide
== '\0')
1877 /* Validate type. */
1878 if (*slide
!= 'u' && *slide
!= 'g')
1883 /* move beyond type */
1887 /* Validate that only whitespace follows. */
1888 slide
+= strspn(slide
, " \t\r");
1889 /* There must be whitespace. */
1890 if (slide
== window
)
1893 /* Mark beginning of nsuid. */
1895 /* Validate that non-whitespace follows. */
1896 slide
+= strcspn(slide
, " \t\r");
1897 /* There must be non-whitespace. */
1898 if (slide
== window
|| *slide
== '\0')
1900 /* Mark end of nsuid. */
1904 if (lxc_safe_ulong(window
, &nsid
) < 0)
1907 /* Move beyond \0. */
1911 /* Validate that only whitespace follows. */
1912 slide
+= strspn(slide
, " \t\r");
1913 /* If there was only one whitespace then we whiped it with our \0 above.
1914 * So only ensure that we're not at the end of the string.
1919 /* Mark beginning of hostid. */
1921 /* Validate that non-whitespace follows. */
1922 slide
+= strcspn(slide
, " \t\r");
1923 /* There must be non-whitespace. */
1924 if (slide
== window
|| *slide
== '\0')
1926 /* Mark end of nsuid. */
1930 if (lxc_safe_ulong(window
, &hostid
) < 0)
1933 /* Move beyond \0. */
1937 /* Validate that only whitespace follows. */
1938 slide
+= strspn(slide
, " \t\r");
1939 /* If there was only one whitespace then we whiped it with our \0 above.
1940 * So only ensure that we're not at the end of the string.
1945 /* Mark beginning of range. */
1947 /* Validate that non-whitespace follows. */
1948 slide
+= strcspn(slide
, " \t\r");
1949 /* There must be non-whitespace. */
1950 if (slide
== window
)
1953 /* The range is the last valid entry we expect. So make sure that there
1954 * is not trailing garbage and if there is, error out.
1956 if (*(slide
+ strspn(slide
, " \t\r\n")) != '\0')
1958 /* Mark end of range. */
1962 if (lxc_safe_ulong(window
, &range
) < 0)
1965 /* Yay, we survived. */
1966 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
1968 idmap
->idtype
= ID_TYPE_UID
;
1969 else if (type
== 'g')
1970 idmap
->idtype
= ID_TYPE_GID
;
1974 idmap
->hostid
= hostid
;
1976 idmap
->range
= range
;
1977 idmaplist
->elem
= idmap
;
1978 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
1991 static int set_config_fstab(const char *key
, const char *value
,
1992 struct lxc_conf
*lxc_conf
)
1994 if (config_value_empty(value
)) {
1995 lxc_clear_config_item(lxc_conf
, key
);
1999 return set_config_path_item(&lxc_conf
->fstab
, value
);
2002 static int set_config_mount_auto(const char *key
, const char *value
,
2003 struct lxc_conf
*lxc_conf
)
2005 char *autos
, *autoptr
, *sptr
, *token
;
2006 static struct { const char *token
; int mask
; int flag
; } allowed_auto_mounts
[] = {
2007 { "proc", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
2008 { "proc:mixed", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
2009 { "proc:rw", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_RW
},
2010 { "sys", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_MIXED
},
2011 { "sys:ro", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RO
},
2012 { "sys:mixed", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_MIXED
},
2013 { "sys:rw", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RW
},
2014 { "cgroup", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_NOSPEC
},
2015 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_MIXED
},
2016 { "cgroup:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RO
},
2017 { "cgroup:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RW
},
2018 { "cgroup-full", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_NOSPEC
},
2019 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_MIXED
},
2020 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RO
},
2021 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RW
},
2022 /* NB: For adding anything that is just a single on/off, but has
2023 * no options: keep mask and flag identical and just define the
2024 * enum value as an unused bit so far
2031 if (config_value_empty(value
)) {
2032 lxc_conf
->auto_mounts
= 0;
2036 autos
= strdup(value
);
2038 SYSERROR("failed to dup '%s'", value
);
2042 for (autoptr
= autos
; ; autoptr
= NULL
) {
2043 token
= strtok_r(autoptr
, " \t", &sptr
);
2049 for (i
= 0; allowed_auto_mounts
[i
].token
; i
++) {
2050 if (!strcmp(allowed_auto_mounts
[i
].token
, token
))
2054 if (!allowed_auto_mounts
[i
].token
) {
2055 ERROR("Invalid filesystem to automount: %s", token
);
2059 lxc_conf
->auto_mounts
&= ~allowed_auto_mounts
[i
].mask
;
2060 lxc_conf
->auto_mounts
|= allowed_auto_mounts
[i
].flag
;
2068 static int set_config_mount(const char *key
, const char *value
,
2069 struct lxc_conf
*lxc_conf
)
2072 struct lxc_list
*mntlist
;
2074 if (config_value_empty(value
))
2075 return lxc_clear_mount_entries(lxc_conf
);
2077 mntlist
= malloc(sizeof(*mntlist
));
2081 mntelem
= strdup(value
);
2086 mntlist
->elem
= mntelem
;
2088 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
2093 static int set_config_cap_keep(const char *key
, const char *value
,
2094 struct lxc_conf
*lxc_conf
)
2096 char *keepcaps
, *keepptr
, *sptr
, *token
;
2097 struct lxc_list
*keeplist
;
2100 if (config_value_empty(value
))
2101 return lxc_clear_config_keepcaps(lxc_conf
);
2103 keepcaps
= strdup(value
);
2105 SYSERROR("failed to dup '%s'", value
);
2109 /* in case several capability keep is specified in a single line
2110 * split these caps in a single element for the list */
2111 for (keepptr
= keepcaps
;;keepptr
= NULL
) {
2112 token
= strtok_r(keepptr
, " \t", &sptr
);
2118 if (!strcmp(token
, "none"))
2119 lxc_clear_config_keepcaps(lxc_conf
);
2121 keeplist
= malloc(sizeof(*keeplist
));
2123 SYSERROR("failed to allocate keepcap list");
2127 keeplist
->elem
= strdup(token
);
2128 if (!keeplist
->elem
) {
2129 SYSERROR("failed to dup '%s'", token
);
2134 lxc_list_add_tail(&lxc_conf
->keepcaps
, keeplist
);
2142 static int set_config_cap_drop(const char *key
, const char *value
,
2143 struct lxc_conf
*lxc_conf
)
2145 char *dropcaps
, *dropptr
, *sptr
, *token
;
2146 struct lxc_list
*droplist
;
2149 if (config_value_empty(value
))
2150 return lxc_clear_config_caps(lxc_conf
);
2152 dropcaps
= strdup(value
);
2154 SYSERROR("failed to dup '%s'", value
);
2158 /* in case several capability drop is specified in a single line
2159 * split these caps in a single element for the list */
2160 for (dropptr
= dropcaps
;;dropptr
= NULL
) {
2161 token
= strtok_r(dropptr
, " \t", &sptr
);
2167 droplist
= malloc(sizeof(*droplist
));
2169 SYSERROR("failed to allocate drop list");
2173 droplist
->elem
= strdup(token
);
2174 if (!droplist
->elem
) {
2175 SYSERROR("failed to dup '%s'", token
);
2180 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
2188 static int set_config_console(const char *key
, const char *value
,
2189 struct lxc_conf
*lxc_conf
)
2191 return set_config_path_item(&lxc_conf
->console
.path
, value
);
2194 static int set_config_console_logfile(const char *key
, const char *value
,
2195 struct lxc_conf
*lxc_conf
)
2197 return set_config_path_item(&lxc_conf
->console
.log_path
, value
);
2201 * If we find a lxc.network.hwaddr in the original config file,
2202 * we expand it in the unexpanded_config, so that after a save_config
2203 * we store the hwaddr for re-use.
2204 * This is only called when reading the config file, not when executing
2206 * 'x' and 'X' are substituted in-place.
2208 static void update_hwaddr(const char *line
)
2212 line
+= lxc_char_left_gc(line
, strlen(line
));
2215 if (strncmp(line
, "lxc.network.hwaddr", 18) != 0)
2217 p
= strchr(line
, '=');
2219 return; // let config_network_hwaddr raise the error
2226 rand_complete_hwaddr(p
);
2229 int append_unexp_config_line(const char *line
, struct lxc_conf
*conf
)
2231 size_t len
= conf
->unexpanded_len
, linelen
= strlen(line
);
2233 update_hwaddr(line
);
2235 while (conf
->unexpanded_alloced
<= len
+ linelen
+ 2) {
2236 char *tmp
= realloc(conf
->unexpanded_config
, conf
->unexpanded_alloced
+ 1024);
2239 if (!conf
->unexpanded_config
)
2241 conf
->unexpanded_config
= tmp
;
2242 conf
->unexpanded_alloced
+= 1024;
2244 strcat(conf
->unexpanded_config
, line
);
2245 conf
->unexpanded_len
+= linelen
;
2246 if (line
[linelen
-1] != '\n') {
2247 strcat(conf
->unexpanded_config
, "\n");
2248 conf
->unexpanded_len
++;
2253 static int do_includedir(const char *dirp
, struct lxc_conf
*lxc_conf
)
2255 struct dirent
*direntp
;
2257 char path
[MAXPATHLEN
];
2260 dir
= opendir(dirp
);
2262 SYSERROR("failed to open '%s'", dirp
);
2266 while ((direntp
= readdir(dir
))) {
2271 fnam
= direntp
->d_name
;
2272 if (!strcmp(fnam
, "."))
2275 if (!strcmp(fnam
, ".."))
2279 if (len
< 6 || strncmp(fnam
+len
-5, ".conf", 5) != 0)
2281 len
= snprintf(path
, MAXPATHLEN
, "%s/%s", dirp
, fnam
);
2282 if (len
< 0 || len
>= MAXPATHLEN
) {
2283 ERROR("lxc.include filename too long under '%s'", dirp
);
2288 ret
= lxc_config_read(path
, lxc_conf
, true);
2296 WARN("lxc.include dir: failed to close directory");
2301 static int set_config_includefile(const char *key
, const char *value
,
2302 struct lxc_conf
*lxc_conf
)
2304 /* Set config value to default. */
2305 if (config_value_empty(value
)) {
2306 lxc_clear_config_item(lxc_conf
, key
);
2310 /* Parse new config value. */
2312 return do_includedir(value
, lxc_conf
);
2314 return lxc_config_read(value
, lxc_conf
, true);
2317 static int set_config_rootfs(const char *key
, const char *value
,
2318 struct lxc_conf
*lxc_conf
)
2320 return set_config_path_item(&lxc_conf
->rootfs
.path
, value
);
2323 static int set_config_rootfs_mount(const char *key
, const char *value
,
2324 struct lxc_conf
*lxc_conf
)
2326 return set_config_path_item(&lxc_conf
->rootfs
.mount
, value
);
2329 static int set_config_rootfs_options(const char *key
, const char *value
,
2330 struct lxc_conf
*lxc_conf
)
2332 return set_config_string_item(&lxc_conf
->rootfs
.options
, value
);
2335 static int set_config_rootfs_backend(const char *key
, const char *value
,
2336 struct lxc_conf
*lxc_conf
)
2338 if (config_value_empty(value
)) {
2339 free(lxc_conf
->rootfs
.bdev_type
);
2340 lxc_conf
->rootfs
.bdev_type
= NULL
;
2344 if (!is_valid_bdev_type(value
)) {
2345 ERROR("Bad rootfs.backend: '%s'", value
);
2349 return set_config_string_item(&lxc_conf
->rootfs
.bdev_type
, value
);
2352 static int set_config_pivotdir(const char *key
, const char *value
,
2353 struct lxc_conf
*lxc_conf
)
2355 WARN("lxc.pivotdir is ignored. It will soon become an error.");
2359 static int set_config_utsname(const char *key
, const char *value
,
2360 struct lxc_conf
*lxc_conf
)
2362 struct utsname
*utsname
;
2364 if (config_value_empty(value
)) {
2365 lxc_clear_config_item(lxc_conf
, key
);
2369 utsname
= malloc(sizeof(*utsname
));
2371 SYSERROR("failed to allocate memory");
2375 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
2376 ERROR("node name '%s' is too long", value
);
2381 strcpy(utsname
->nodename
, value
);
2382 free(lxc_conf
->utsname
);
2383 lxc_conf
->utsname
= utsname
;
2388 struct parse_line_conf
{
2389 struct lxc_conf
*conf
;
2393 static int parse_line(char *buffer
, void *data
)
2395 struct lxc_config_t
*config
;
2401 struct parse_line_conf
*plc
= data
;
2403 if (lxc_is_line_empty(buffer
))
2406 /* we have to dup the buffer otherwise, at the re-exec for
2407 * reboot we modified the original string on the stack by
2408 * replacing '=' by '\0' below
2410 linep
= line
= strdup(buffer
);
2412 SYSERROR("failed to allocate memory for '%s'", buffer
);
2416 if (!plc
->from_include
)
2417 if ((ret
= append_unexp_config_line(line
, plc
->conf
)))
2420 line
+= lxc_char_left_gc(line
, strlen(line
));
2422 /* ignore comments */
2426 /* martian option - don't add it to the config itself */
2427 if (strncmp(line
, "lxc.", 4))
2432 dot
= strstr(line
, "=");
2434 ERROR("invalid configuration line: %s", line
);
2442 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
2444 value
+= lxc_char_left_gc(value
, strlen(value
));
2445 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
2447 if (*value
== '\'' || *value
== '\"') {
2448 size_t len
= strlen(value
);
2449 if (len
> 1 && value
[len
-1] == *value
) {
2450 value
[len
-1] = '\0';
2455 config
= lxc_getconfig(key
);
2457 ERROR("unknown key %s", key
);
2461 ret
= config
->set(key
, value
, plc
->conf
);
2468 static int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
2470 struct parse_line_conf c
;
2473 c
.from_include
= false;
2475 return parse_line(buffer
, &c
);
2478 int lxc_config_read(const char *file
, struct lxc_conf
*conf
, bool from_include
)
2480 struct parse_line_conf c
;
2483 c
.from_include
= from_include
;
2485 if( access(file
, R_OK
) == -1 ) {
2489 /* Catch only the top level config file name in the structure */
2491 conf
->rcfile
= strdup(file
);
2493 return lxc_file_for_each_line(file
, parse_line
, &c
);
2496 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
2498 struct lxc_list
*dent
;
2500 dent
= malloc(sizeof(struct lxc_list
));
2505 lxc_list_add_tail(defines
, dent
);
2509 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
2511 struct lxc_list
*it
,*next
;
2514 lxc_list_for_each(it
, defines
) {
2515 ret
= lxc_config_readline(it
->elem
, conf
);
2520 lxc_list_for_each_safe(it
, defines
, next
) {
2528 signed long lxc_config_parse_arch(const char *arch
)
2530 #if HAVE_SYS_PERSONALITY_H
2535 { "x86", PER_LINUX32
},
2536 { "linux32", PER_LINUX32
},
2537 { "i386", PER_LINUX32
},
2538 { "i486", PER_LINUX32
},
2539 { "i586", PER_LINUX32
},
2540 { "i686", PER_LINUX32
},
2541 { "athlon", PER_LINUX32
},
2542 { "mips", PER_LINUX32
},
2543 { "mipsel", PER_LINUX32
},
2544 { "ppc", PER_LINUX32
},
2545 { "arm", PER_LINUX32
},
2546 { "armv7l", PER_LINUX32
},
2547 { "armhf", PER_LINUX32
},
2548 { "armel", PER_LINUX32
},
2549 { "powerpc", PER_LINUX32
},
2550 { "linux64", PER_LINUX
},
2551 { "x86_64", PER_LINUX
},
2552 { "amd64", PER_LINUX
},
2553 { "mips64", PER_LINUX
},
2554 { "mips64el", PER_LINUX
},
2555 { "ppc64", PER_LINUX
},
2556 { "ppc64le", PER_LINUX
},
2557 { "ppc64el", PER_LINUX
},
2558 { "powerpc64", PER_LINUX
},
2559 { "s390x", PER_LINUX
},
2560 { "aarch64", PER_LINUX
},
2561 { "arm64", PER_LINUX
},
2563 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
2567 for (i
= 0; i
< len
; i
++) {
2568 if (!strcmp(pername
[i
].name
, arch
))
2569 return pername
[i
].per
;
2576 int lxc_fill_elevated_privileges(char *flaglist
, int *flags
)
2578 char *token
, *saveptr
= NULL
;
2580 struct { const char *token
; int flag
; } all_privs
[] = {
2581 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP
},
2582 { "CAP", LXC_ATTACH_DROP_CAPABILITIES
},
2583 { "LSM", LXC_ATTACH_LSM_EXEC
},
2588 /* for the sake of backward compatibility, drop all privileges
2589 if none is specified */
2590 for (i
= 0; all_privs
[i
].token
; i
++) {
2591 *flags
|= all_privs
[i
].flag
;
2596 token
= strtok_r(flaglist
, "|", &saveptr
);
2599 for (i
= 0; all_privs
[i
].token
; i
++) {
2600 if (!strcmp(all_privs
[i
].token
, token
))
2601 aflag
= all_privs
[i
].flag
;
2608 token
= strtok_r(NULL
, "|", &saveptr
);
2613 static inline int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
,
2619 memset(retv
, 0, inlen
);
2621 return snprintf(retv
, inlen
, "%d", v
);
2625 * If you ask for a specific value, i.e. lxc.limit.nofile, then just the value
2626 * will be printed. If you ask for 'lxc.limit', then all limit entries will be
2627 * printed, in 'lxc.limit.resource = value' format.
2629 static int lxc_get_limit_entry(struct lxc_conf
*c
, char *retv
, int inlen
,
2632 int fulllen
= 0, len
;
2634 struct lxc_list
*it
;
2639 memset(retv
, 0, inlen
);
2641 if (strcmp(key
, "all") == 0)
2644 lxc_list_for_each(it
, &c
->limits
) {
2645 char buf
[LXC_NUMSTRLEN64
*2+2]; /* 2 colon separated 64 bit integers or the word 'unlimited' */
2647 struct lxc_limit
*lim
= it
->elem
;
2649 if (lim
->limit
.rlim_cur
== RLIM_INFINITY
) {
2650 memcpy(buf
, "unlimited", sizeof("unlimited"));
2651 partlen
= sizeof("unlimited")-1;
2653 partlen
= sprintf(buf
, "%"PRIu64
, (uint64_t)lim
->limit
.rlim_cur
);
2655 if (lim
->limit
.rlim_cur
!= lim
->limit
.rlim_max
) {
2656 if (lim
->limit
.rlim_max
== RLIM_INFINITY
) {
2657 memcpy(buf
+partlen
, ":unlimited", sizeof(":unlimited"));
2659 sprintf(buf
+partlen
, ":%"PRIu64
, (uint64_t)lim
->limit
.rlim_max
);
2664 strprint(retv
, inlen
, "lxc.limit.%s = %s\n", lim
->resource
, buf
);
2665 } else if (strcmp(lim
->resource
, key
) == 0) {
2666 strprint(retv
, inlen
, "%s", buf
);
2673 static int lxc_get_item_hooks(struct lxc_conf
*c
, char *retv
, int inlen
,
2677 int len
, fulllen
= 0, found
= -1;
2678 struct lxc_list
*it
;
2681 /* "lxc.hook.mount" */
2682 subkey
= strchr(key
, '.');
2683 if (subkey
) subkey
= strchr(subkey
+1, '.');
2689 for (i
=0; i
<NUM_LXC_HOOKS
; i
++) {
2690 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
2701 memset(retv
, 0, inlen
);
2703 lxc_list_for_each(it
, &c
->hooks
[found
]) {
2704 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2709 static int lxc_get_item_groups(struct lxc_conf
*c
, char *retv
, int inlen
)
2711 int len
, fulllen
= 0;
2712 struct lxc_list
*it
;
2717 memset(retv
, 0, inlen
);
2719 lxc_list_for_each(it
, &c
->groups
) {
2720 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2725 static int lxc_get_item_environment(struct lxc_conf
*c
, char *retv
, int inlen
)
2727 int len
, fulllen
= 0;
2728 struct lxc_list
*it
;
2733 memset(retv
, 0, inlen
);
2735 lxc_list_for_each(it
, &c
->environment
) {
2736 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2741 static int lxc_get_item_cap_drop(struct lxc_conf
*c
, char *retv
, int inlen
)
2743 int len
, fulllen
= 0;
2744 struct lxc_list
*it
;
2749 memset(retv
, 0, inlen
);
2751 lxc_list_for_each(it
, &c
->caps
) {
2752 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2757 static int lxc_get_item_cap_keep(struct lxc_conf
*c
, char *retv
, int inlen
)
2759 int len
, fulllen
= 0;
2760 struct lxc_list
*it
;
2765 memset(retv
, 0, inlen
);
2767 lxc_list_for_each(it
, &c
->keepcaps
) {
2768 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
2774 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
2775 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
2776 * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
2777 * of an address. ipv4 and ipv6 return lists (newline-separated).
2778 * things like veth.pair return '' if invalid (i.e. if called for vlan
2781 static int lxc_get_item_nic(struct lxc_conf
*c
, char *retv
, int inlen
,
2785 int len
, fulllen
= 0;
2786 struct lxc_netdev
*netdev
;
2791 memset(retv
, 0, inlen
);
2793 p1
= strchr(key
, '.');
2794 if (!p1
|| *(p1
+1) == '\0') return -1;
2797 netdev
= get_netdev_from_key(key
, &c
->network
);
2800 if (strcmp(p1
, "name") == 0) {
2802 strprint(retv
, inlen
, "%s", netdev
->name
);
2803 } else if (strcmp(p1
, "type") == 0) {
2804 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
2805 } else if (strcmp(p1
, "link") == 0) {
2807 strprint(retv
, inlen
, "%s", netdev
->link
);
2808 } else if (strcmp(p1
, "flags") == 0) {
2809 if (netdev
->flags
& IFF_UP
)
2810 strprint(retv
, inlen
, "up");
2811 } else if (strcmp(p1
, "script.up") == 0) {
2812 if (netdev
->upscript
)
2813 strprint(retv
, inlen
, "%s", netdev
->upscript
);
2814 } else if (strcmp(p1
, "script.down") == 0) {
2815 if (netdev
->downscript
)
2816 strprint(retv
, inlen
, "%s", netdev
->downscript
);
2817 } else if (strcmp(p1
, "hwaddr") == 0) {
2819 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
2820 } else if (strcmp(p1
, "mtu") == 0) {
2822 strprint(retv
, inlen
, "%s", netdev
->mtu
);
2823 } else if (strcmp(p1
, "macvlan.mode") == 0) {
2824 if (netdev
->type
== LXC_NET_MACVLAN
) {
2826 switch (netdev
->priv
.macvlan_attr
.mode
) {
2827 case MACVLAN_MODE_PRIVATE
: mode
= "private"; break;
2828 case MACVLAN_MODE_VEPA
: mode
= "vepa"; break;
2829 case MACVLAN_MODE_BRIDGE
: mode
= "bridge"; break;
2830 case MACVLAN_MODE_PASSTHRU
: mode
= "passthru"; break;
2831 default: mode
= "(invalid)"; break;
2833 strprint(retv
, inlen
, "%s", mode
);
2835 } else if (strcmp(p1
, "veth.pair") == 0) {
2836 if (netdev
->type
== LXC_NET_VETH
) {
2837 strprint(retv
, inlen
, "%s",
2838 netdev
->priv
.veth_attr
.pair
?
2839 netdev
->priv
.veth_attr
.pair
:
2840 netdev
->priv
.veth_attr
.veth1
);
2842 } else if (strcmp(p1
, "vlan") == 0) {
2843 if (netdev
->type
== LXC_NET_VLAN
) {
2844 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
2846 } else if (strcmp(p1
, "ipv4.gateway") == 0) {
2847 if (netdev
->ipv4_gateway_auto
) {
2848 strprint(retv
, inlen
, "auto");
2849 } else if (netdev
->ipv4_gateway
) {
2850 char buf
[INET_ADDRSTRLEN
];
2851 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
, sizeof(buf
));
2852 strprint(retv
, inlen
, "%s", buf
);
2854 } else if (strcmp(p1
, "ipv4") == 0) {
2855 struct lxc_list
*it2
;
2856 lxc_list_for_each(it2
, &netdev
->ipv4
) {
2857 struct lxc_inetdev
*i
= it2
->elem
;
2858 char buf
[INET_ADDRSTRLEN
];
2859 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
2860 strprint(retv
, inlen
, "%s/%d\n", buf
, i
->prefix
);
2862 } else if (strcmp(p1
, "ipv6.gateway") == 0) {
2863 if (netdev
->ipv6_gateway_auto
) {
2864 strprint(retv
, inlen
, "auto");
2865 } else if (netdev
->ipv6_gateway
) {
2866 char buf
[INET6_ADDRSTRLEN
];
2867 inet_ntop(AF_INET6
, netdev
->ipv6_gateway
, buf
, sizeof(buf
));
2868 strprint(retv
, inlen
, "%s", buf
);
2870 } else if (strcmp(p1
, "ipv6") == 0) {
2871 struct lxc_list
*it2
;
2872 lxc_list_for_each(it2
, &netdev
->ipv6
) {
2873 struct lxc_inet6dev
*i
= it2
->elem
;
2874 char buf
[INET6_ADDRSTRLEN
];
2875 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
2876 strprint(retv
, inlen
, "%s/%d\n", buf
, i
->prefix
);
2882 static int lxc_get_item_network(struct lxc_conf
*c
, char *retv
, int inlen
)
2884 int len
, fulllen
= 0;
2885 struct lxc_list
*it
;
2890 memset(retv
, 0, inlen
);
2892 lxc_list_for_each(it
, &c
->network
) {
2893 struct lxc_netdev
*n
= it
->elem
;
2894 const char *t
= lxc_net_type_to_str(n
->type
);
2895 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
2900 int lxc_get_config_item(struct lxc_conf
*c
, const char *key
, char *retv
,
2903 const char *v
= NULL
;
2905 if (strcmp(key
, "lxc.utsname") == 0)
2906 v
= c
->utsname
? c
->utsname
->nodename
: NULL
;
2907 else if (strcmp(key
, "lxc.console.logfile") == 0)
2908 v
= c
->console
.log_path
;
2909 else if (strcmp(key
, "lxc.console") == 0)
2910 v
= c
->console
.path
;
2911 else if (strcmp(key
, "lxc.rootfs.backend") == 0)
2912 v
= c
->rootfs
.bdev_type
;
2913 else if (strcmp(key
, "lxc.cap.drop") == 0)
2914 return lxc_get_item_cap_drop(c
, retv
, inlen
);
2915 else if (strcmp(key
, "lxc.cap.keep") == 0)
2916 return lxc_get_item_cap_keep(c
, retv
, inlen
);
2917 else if (strncmp(key
, "lxc.hook", 8) == 0)
2918 return lxc_get_item_hooks(c
, retv
, inlen
, key
);
2919 else if (strcmp(key
, "lxc.network") == 0)
2920 return lxc_get_item_network(c
, retv
, inlen
);
2921 else if (strncmp(key
, "lxc.network.", 12) == 0)
2922 return lxc_get_item_nic(c
, retv
, inlen
, key
+ 12);
2923 else if (strcmp(key
, "lxc.start.auto") == 0)
2924 return lxc_get_conf_int(c
, retv
, inlen
, c
->start_auto
);
2925 else if (strcmp(key
, "lxc.start.delay") == 0)
2926 return lxc_get_conf_int(c
, retv
, inlen
, c
->start_delay
);
2927 else if (strcmp(key
, "lxc.start.order") == 0)
2928 return lxc_get_conf_int(c
, retv
, inlen
, c
->start_order
);
2929 else if (strcmp(key
, "lxc.monitor.unshare") == 0)
2930 return lxc_get_conf_int(c
, retv
, inlen
, c
->monitor_unshare
);
2931 else if (strcmp(key
, "lxc.group") == 0)
2932 return lxc_get_item_groups(c
, retv
, inlen
);
2933 else if (strcmp(key
, "lxc.seccomp") == 0)
2935 else if (strcmp(key
, "lxc.environment") == 0)
2936 return lxc_get_item_environment(c
, retv
, inlen
);
2937 else if (strcmp(key
, "lxc.init_cmd") == 0)
2939 else if (strcmp(key
, "lxc.init_uid") == 0)
2940 return lxc_get_conf_int(c
, retv
, inlen
, c
->init_uid
);
2941 else if (strcmp(key
, "lxc.init_gid") == 0)
2942 return lxc_get_conf_int(c
, retv
, inlen
, c
->init_gid
);
2943 else if (strcmp(key
, "lxc.ephemeral") == 0)
2944 return lxc_get_conf_int(c
, retv
, inlen
, c
->ephemeral
);
2945 else if (strcmp(key
, "lxc.syslog") == 0)
2947 else if (strcmp(key
, "lxc.no_new_privs") == 0)
2948 return lxc_get_conf_int(c
, retv
, inlen
, c
->no_new_privs
);
2949 else if (strcmp(key
, "lxc.limit") == 0) // all limits
2950 return lxc_get_limit_entry(c
, retv
, inlen
, "all");
2951 else if (strncmp(key
, "lxc.limit.", 10) == 0) // specific limit
2952 return lxc_get_limit_entry(c
, retv
, inlen
, key
+ 10);
2953 else if (strcmp(key
, "lxc.haltsignal") == 0)
2954 return lxc_get_conf_int(c
, retv
, inlen
, c
->haltsignal
);
2955 else if (strcmp(key
, "lxc.rebootsignal") == 0)
2956 return lxc_get_conf_int(c
, retv
, inlen
, c
->rebootsignal
);
2957 else if (strcmp(key
, "lxc.stopsignal") == 0)
2958 return lxc_get_conf_int(c
, retv
, inlen
, c
->stopsignal
);
2959 else if (strcmp(key
, "lxc.autodev") == 0)
2960 return lxc_get_conf_int(c
, retv
, inlen
, c
->autodev
);
2965 if (retv
&& inlen
>= strlen(v
) + 1)
2966 strncpy(retv
, v
, strlen(v
)+1);
2970 int lxc_clear_config_item(struct lxc_conf
*c
, const char *key
)
2974 if (strcmp(key
, "lxc.network") == 0) {
2975 ret
= lxc_clear_config_network(c
);
2977 } else if (strncmp(key
, "lxc.network.", 12) == 0) {
2978 ret
= lxc_clear_nic(c
, key
+ 12);
2980 } else if (strcmp(key
, "lxc.cap.drop") == 0) {
2981 ret
= lxc_clear_config_caps(c
);
2983 } else if (strcmp(key
, "lxc.cap.keep") == 0) {
2984 ret
= lxc_clear_config_keepcaps(c
);
2986 } else if (strncmp(key
, "lxc.cgroup", 10) == 0) {
2987 ret
= lxc_clear_cgroups(c
, key
);
2989 } else if (strcmp(key
, "lxc.mount.entry") == 0) {
2990 ret
= lxc_clear_mount_entries(c
);
2992 } else if (strcmp(key
, "lxc.mount.auto") == 0) {
2993 ret
= lxc_clear_automounts(c
);
2995 } else if (strncmp(key
, "lxc.hook", 8) == 0) {
2996 ret
= lxc_clear_hooks(c
, key
);
2998 } else if (strncmp(key
, "lxc.group", 9) == 0) {
2999 ret
= lxc_clear_groups(c
);
3001 } else if (strncmp(key
, "lxc.environment", 15) == 0) {
3002 ret
= lxc_clear_environment(c
);
3004 } else if (strncmp(key
, "lxc.id_map", 10) == 0) {
3005 ret
= lxc_clear_idmaps(c
);
3007 } else if (strncmp(key
, "lxc.limit", 9) == 0) {
3008 ret
= lxc_clear_limits(c
, key
);
3010 } else if (strcmp(key
, "lxc.utsname") == 0) {
3014 } else if (strcmp(key
, "lxc.arch") == 0) {
3015 c
->personality
= -1;
3017 } else if (strcmp(key
, "lxc.haltsignal") == 0) {
3020 } else if (strcmp(key
, "lxc.rebootsignal") == 0) {
3021 c
->rebootsignal
= 0;
3023 } else if (strcmp(key
, "lxc.stopsignal") == 0) {
3026 } else if (strcmp(key
, "lxc.init_cmd") == 0) {
3030 } else if (strcmp(key
, "lxc.init_uid") == 0) {
3033 } else if (strcmp(key
, "lxc.init_gid") == 0) {
3036 } else if (strcmp(key
, "lxc.ephemeral") == 0) {
3039 } else if (strcmp(key
, "lxc.console.logfile") == 0) {
3040 free(c
->console
.log_path
);
3041 c
->console
.log_path
= NULL
;
3043 } else if (strcmp(key
, "lxc.console") == 0) {
3044 free(c
->console
.path
);
3045 c
->console
.path
= NULL
;
3047 } else if (strcmp(key
, "lxc.tty") == 0) {
3050 } else if (strcmp(key
, "lxc.devttydir") == 0) {
3054 } else if (strcmp(key
, "lxc.autodev") == 0) {
3057 } else if (strcmp(key
, "lxc.kmsg") == 0) {
3060 } else if (strcmp(key
, "lxc.mount") == 0) {
3064 } else if (strcmp(key
, "lxc.rootfs") == 0) {
3065 free(c
->rootfs
.path
);
3066 c
->rootfs
.path
= NULL
;
3068 } else if (strcmp(key
, "lxc.rootfs.mount") == 0) {
3069 free(c
->rootfs
.mount
);
3070 c
->rootfs
.mount
= NULL
;
3072 } else if (strcmp(key
, "lxc.rootfs.options") == 0) {
3073 free(c
->rootfs
.options
);
3074 c
->rootfs
.options
= NULL
;
3076 } else if (strcmp(key
, "lxc.rootfs.backend") == 0) {
3077 free(c
->rootfs
.bdev_type
);
3078 c
->rootfs
.bdev_type
= NULL
;
3080 } else if (strcmp(key
, "lxc.aa_profile") == 0) {
3081 free(c
->lsm_aa_profile
);
3082 c
->lsm_aa_profile
= NULL
;
3084 } else if (strcmp(key
, "lxc.aa_allow_incomplete") == 0) {
3085 c
->lsm_aa_allow_incomplete
= 0;
3087 } else if (strcmp(key
, "lxc.se_context") == 0) {
3088 free(c
->lsm_se_context
);
3089 c
->lsm_se_context
= NULL
;
3091 } else if (strcmp(key
, "lxc.seccomp") == 0) {
3095 } else if (strcmp(key
, "lxc.loglevel") == 0) {
3096 c
->loglevel
= LXC_LOG_PRIORITY_NOTSET
;
3098 } else if (strcmp(key
, "lxc.logfile") == 0) {
3102 } else if (strcmp(key
, "lxc.monitor.unshare") == 0) {
3103 c
->monitor_unshare
= 0;
3105 } else if (strcmp(key
, "lxc.pts") == 0) {
3108 } else if (strcmp(key
, "lxc.include") == 0) {
3109 lxc_clear_includes(c
);
3111 } else if (strcmp(key
, "lxc.syslog") == 0) {
3122 * writing out a confile.
3124 void write_config(FILE *fout
, struct lxc_conf
*c
)
3126 size_t len
= c
->unexpanded_len
;
3131 ret
= fwrite(c
->unexpanded_config
, 1, len
, fout
);
3133 SYSERROR("Error writing configuration file");
3136 bool do_append_unexp_config_line(struct lxc_conf
*conf
, const char *key
, const char *v
)
3142 len
= strlen(key
) + strlen(v
) + 4;
3145 if (config_value_empty(v
))
3146 ret
= snprintf(tmp
, len
, "%s =", key
);
3148 ret
= snprintf(tmp
, len
, "%s = %s", key
, v
);
3149 if (ret
< 0 || ret
>= len
)
3152 /* Save the line verbatim into unexpanded_conf */
3153 if (append_unexp_config_line(tmp
, conf
))
3159 void clear_unexp_config_line(struct lxc_conf
*conf
, const char *key
, bool rm_subkeys
)
3161 char *lstart
= conf
->unexpanded_config
, *lend
;
3163 if (!conf
->unexpanded_config
)
3166 lend
= strchr(lstart
, '\n');
3169 lend
= lstart
+ strlen(lstart
);
3172 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
3177 v
= lstart
[strlen(key
)];
3178 if (!isspace(v
) && v
!= '=') {
3183 conf
->unexpanded_len
-= (lend
- lstart
);
3184 if (*lend
== '\0') {
3188 memmove(lstart
, lend
, strlen(lend
)+1);
3192 bool clone_update_unexp_ovl_paths(struct lxc_conf
*conf
, const char *oldpath
,
3193 const char *newpath
, const char *oldname
,
3194 const char *newname
, const char *ovldir
)
3196 const char *key
= "lxc.mount.entry";
3198 char *lstart
= conf
->unexpanded_config
;
3202 size_t newdirlen
= strlen(ovldir
) + strlen(newpath
) + strlen(newname
) + 2;
3203 size_t olddirlen
= strlen(ovldir
) + strlen(oldpath
) + strlen(oldname
) + 2;
3204 char *olddir
= alloca(olddirlen
+ 1);
3205 char *newdir
= alloca(newdirlen
+ 1);
3207 ret
= snprintf(olddir
, olddirlen
+ 1, "%s=%s/%s", ovldir
, oldpath
, oldname
);
3208 if (ret
< 0 || ret
>= olddirlen
+ 1) {
3209 ERROR("Bug in %s", __func__
);
3212 ret
= snprintf(newdir
, newdirlen
+ 1, "%s=%s/%s", ovldir
, newpath
, newname
);
3213 if (ret
< 0 || ret
>= newdirlen
+ 1) {
3214 ERROR("Bug in %s", __func__
);
3217 if (!conf
->unexpanded_config
)
3220 lend
= strchr(lstart
, '\n');
3222 lend
= lstart
+ strlen(lstart
);
3225 if (strncmp(lstart
, key
, strlen(key
)) != 0)
3227 p
= strchr(lstart
+ strlen(key
), '=');
3235 /* Whenever an lxc.mount.entry entry is found in a line we check
3236 * if the substring " overlay" or the substring " aufs" is
3237 * present before doing any further work. We check for "
3238 * overlay" and " aufs" since both substrings need to have at
3239 * least one space before them in a valid overlay
3240 * lxc.mount.entry (/A B overlay). When the space before is
3241 * missing it is very likely that these substrings are part of a
3242 * path or something else. (Checking q >= lend ensures that we
3243 * only count matches in the current line.) */
3244 if ((!(q
= strstr(p
, " overlay")) || q
>= lend
) && (!(q
= strstr(p
, " aufs")) || q
>= lend
))
3246 if (!(q
= strstr(p
, olddir
)) || (q
>= lend
))
3249 /* replace the olddir with newdir */
3250 if (olddirlen
>= newdirlen
) {
3251 size_t diff
= olddirlen
- newdirlen
;
3252 memcpy(q
, newdir
, newdirlen
);
3253 if (olddirlen
!= newdirlen
) {
3254 memmove(q
+ newdirlen
, q
+ newdirlen
+ diff
,
3255 strlen(q
) - newdirlen
- diff
+ 1);
3257 conf
->unexpanded_len
-= diff
;
3261 size_t diff
= newdirlen
- olddirlen
;
3262 size_t oldlen
= conf
->unexpanded_len
;
3263 size_t newlen
= oldlen
+ diff
;
3264 size_t poffset
= q
- conf
->unexpanded_config
;
3265 new = realloc(conf
->unexpanded_config
, newlen
+ 1);
3267 ERROR("Out of memory");
3270 conf
->unexpanded_len
= newlen
;
3271 conf
->unexpanded_alloced
= newlen
+ 1;
3272 new[newlen
- 1] = '\0';
3273 lend
= new + (lend
- conf
->unexpanded_config
);
3274 /* move over the remainder to make room for the newdir */
3275 memmove(new + poffset
+ newdirlen
,
3276 new + poffset
+ olddirlen
,
3277 oldlen
- poffset
- olddirlen
+ 1);
3278 conf
->unexpanded_config
= new;
3279 memcpy(new + poffset
, newdir
, newdirlen
);
3288 bool clone_update_unexp_hooks(struct lxc_conf
*conf
, const char *oldpath
,
3289 const char *newpath
, const char *oldname
,
3290 const char *newname
)
3292 const char *key
= "lxc.hook";
3294 char *lstart
= conf
->unexpanded_config
, *lend
, *p
;
3295 size_t newdirlen
= strlen(newpath
) + strlen(newname
) + 1;
3296 size_t olddirlen
= strlen(oldpath
) + strlen(oldname
) + 1;
3297 char *olddir
= alloca(olddirlen
+ 1);
3298 char *newdir
= alloca(newdirlen
+ 1);
3300 ret
= snprintf(olddir
, olddirlen
+ 1, "%s/%s", oldpath
, oldname
);
3301 if (ret
< 0 || ret
>= olddirlen
+ 1) {
3302 ERROR("Bug in %s", __func__
);
3305 ret
= snprintf(newdir
, newdirlen
+ 1, "%s/%s", newpath
, newname
);
3306 if (ret
< 0 || ret
>= newdirlen
+ 1) {
3307 ERROR("Bug in %s", __func__
);
3310 if (!conf
->unexpanded_config
)
3313 lend
= strchr(lstart
, '\n');
3315 lend
= lstart
+ strlen(lstart
);
3318 if (strncmp(lstart
, key
, strlen(key
)) != 0)
3320 p
= strchr(lstart
+ strlen(key
), '=');
3328 if (strncmp(p
, olddir
, strlen(olddir
)) != 0)
3330 /* replace the olddir with newdir */
3331 if (olddirlen
>= newdirlen
) {
3332 size_t diff
= olddirlen
- newdirlen
;
3333 memcpy(p
, newdir
, newdirlen
);
3334 if (olddirlen
!= newdirlen
) {
3335 memmove(p
+ newdirlen
, p
+ newdirlen
+ diff
,
3336 strlen(p
) - newdirlen
- diff
+ 1);
3338 conf
->unexpanded_len
-= diff
;
3342 size_t diff
= newdirlen
- olddirlen
;
3343 size_t oldlen
= conf
->unexpanded_len
;
3344 size_t newlen
= oldlen
+ diff
;
3345 size_t poffset
= p
- conf
->unexpanded_config
;
3346 new = realloc(conf
->unexpanded_config
, newlen
+ 1);
3348 ERROR("Out of memory");
3351 conf
->unexpanded_len
= newlen
;
3352 conf
->unexpanded_alloced
= newlen
+ 1;
3353 new[newlen
- 1] = '\0';
3354 lend
= new + (lend
- conf
->unexpanded_config
);
3355 /* move over the remainder to make room for the newdir */
3356 memmove(new + poffset
+ newdirlen
,
3357 new + poffset
+ olddirlen
,
3358 oldlen
- poffset
- olddirlen
+ 1);
3359 conf
->unexpanded_config
= new;
3360 memcpy(new + poffset
, newdir
, newdirlen
);
3371 ERROR("Error writing to new config"); \
3376 static bool new_hwaddr(char *hwaddr
)
3380 (void)randseed(true);
3382 ret
= snprintf(hwaddr
, 18, "00:16:3e:%02x:%02x:%02x", rand() % 255,
3383 rand() % 255, rand() % 255);
3384 if (ret
< 0 || ret
>= 18) {
3385 SYSERROR("Failed to call snprintf().");
3393 * This is called only from clone.
3394 * We wish to update all hwaddrs in the unexpanded config file. We
3395 * can't/don't want to update any which come from lxc.includes (there
3396 * shouldn't be any).
3397 * We can't just walk the c->lxc-conf->network list because that includes
3398 * netifs from the include files. So we update the ones which we find in
3399 * the unexp config file, then find the original macaddr in the
3400 * conf->network, and update that to the same value.
3402 bool network_new_hwaddrs(struct lxc_conf
*conf
)
3404 struct lxc_list
*it
;
3406 const char *key
= "lxc.network.hwaddr";
3407 char *lstart
= conf
->unexpanded_config
, *lend
, *p
, *p2
;
3409 if (!conf
->unexpanded_config
)
3413 char newhwaddr
[18], oldhwaddr
[17];
3415 lend
= strchr(lstart
, '\n');
3417 lend
= lstart
+ strlen(lstart
);
3421 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
3426 p
= strchr(lstart
+strlen(key
), '=');
3439 while (*p2
&& !isblank(*p2
) && *p2
!= '\n')
3442 WARN("Bad hwaddr entry");
3447 memcpy(oldhwaddr
, p
, 17);
3449 if (!new_hwaddr(newhwaddr
))
3452 memcpy(p
, newhwaddr
, 17);
3453 lxc_list_for_each(it
, &conf
->network
) {
3454 struct lxc_netdev
*n
= it
->elem
;
3455 if (n
->hwaddr
&& memcmp(oldhwaddr
, n
->hwaddr
, 17) == 0)
3456 memcpy(n
->hwaddr
, newhwaddr
, 17);
3465 static int set_config_ephemeral(const char *key
, const char *value
,
3466 struct lxc_conf
*lxc_conf
)
3468 /* Set config value to default. */
3469 if (config_value_empty(value
)) {
3470 lxc_conf
->ephemeral
= 0;
3474 /* Parse new config value. */
3475 if (lxc_safe_uint(value
, &lxc_conf
->ephemeral
) < 0)
3478 if (lxc_conf
->ephemeral
> 1) {
3479 ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
3486 static int set_config_syslog(const char *key
, const char *value
,
3487 struct lxc_conf
*lxc_conf
)
3491 /* Clear any previously set value. */
3492 if (lxc_conf
->syslog
) {
3493 free(lxc_conf
->syslog
);
3494 lxc_conf
->syslog
= NULL
;
3497 /* Check if value is empty. */
3498 if (config_value_empty(value
))
3502 facility
= lxc_syslog_priority_to_int(value
);
3503 if (facility
== -EINVAL
) {
3504 ERROR("Wrong value for lxc.syslog.");
3508 lxc_log_syslog(facility
);
3509 return set_config_string_item(&lxc_conf
->syslog
, value
);
3512 static int set_config_no_new_privs(const char *key
, const char *value
,
3513 struct lxc_conf
*lxc_conf
)
3517 /* Set config value to default. */
3518 if (config_value_empty(value
)) {
3519 lxc_conf
->no_new_privs
= false;
3523 /* Parse new config value. */
3524 if (lxc_safe_uint(value
, &v
) < 0)
3528 ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 or 1");
3532 lxc_conf
->no_new_privs
= v
? true : false;
3537 /* Callbacks to get configuration items. */
3538 static int get_config_personality(struct lxc_container
*c
, const char *key
,
3539 char *retv
, int inlen
)
3546 memset(retv
, 0, inlen
);
3548 #if HAVE_SYS_PERSONALITY_H
3551 switch (c
->lxc_conf
->personality
) {
3553 strprint(retv
, inlen
, "i686");
3556 strprint(retv
, inlen
, "x86_64");
3566 static int get_config_pts(struct lxc_container
*c
, const char *key
, char *retv
,
3569 return lxc_get_conf_int(c
->lxc_conf
, retv
, inlen
, c
->lxc_conf
->pts
);
3572 static int get_config_tty(struct lxc_container
*c
, const char *key
, char *retv
,
3575 return lxc_get_conf_int(c
->lxc_conf
, retv
, inlen
, c
->lxc_conf
->tty
);
3578 static inline int lxc_get_conf_str(char *retv
, int inlen
, const char *value
)
3582 if (retv
&& inlen
>= strlen(value
) + 1)
3583 strncpy(retv
, value
, strlen(value
) + 1);
3585 return strlen(value
);
3588 static int get_config_ttydir(struct lxc_container
*c
, const char *key
,
3589 char *retv
, int inlen
)
3591 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->ttydir
);
3594 static int get_config_kmsg(struct lxc_container
*c
, const char *key
, char *retv
,
3597 return lxc_get_conf_int(c
->lxc_conf
, retv
, inlen
, c
->lxc_conf
->kmsg
);
3600 static int get_config_lsm_aa_profile(struct lxc_container
*c
, const char *key
,
3601 char *retv
, int inlen
)
3603 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->lsm_aa_profile
);
3606 static int get_config_lsm_aa_incomplete(struct lxc_container
*c
,
3607 const char *key
, char *retv
, int inlen
)
3609 return lxc_get_conf_int(c
->lxc_conf
, retv
, inlen
,
3610 c
->lxc_conf
->lsm_aa_allow_incomplete
);
3613 static int get_config_lsm_se_context(struct lxc_container
*c
, const char *key
,
3614 char *retv
, int inlen
)
3616 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->lsm_se_context
);
3620 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
3621 * then just the value(s) will be printed. Since there still could be
3622 * more than one, it is newline-separated.
3623 * (Maybe that's ambigous, since some values, i.e. devices.list, will
3624 * already have newlines?)
3625 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
3626 * in 'lxc.cgroup.subsystem.key = value' format.
3628 static int get_config_cgroup(struct lxc_container
*c
, const char *key
,
3629 char *retv
, int inlen
)
3631 struct lxc_list
*it
;
3634 bool get_all
= false;
3639 memset(retv
, 0, inlen
);
3641 if (!strcmp(key
, "lxc.cgroup"))
3643 else if (!strncmp(key
, "lxc.cgroup.", 11))
3648 lxc_list_for_each(it
, &c
->lxc_conf
->cgroup
) {
3649 struct lxc_cgroup
*cg
= it
->elem
;
3651 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
3652 } else if (!strcmp(cg
->subsystem
, key
)) {
3653 strprint(retv
, inlen
, "%s\n", cg
->value
);
3660 static int get_config_idmaps(struct lxc_container
*c
, const char *key
,
3661 char *retv
, int inlen
)
3663 struct lxc_list
*it
;
3664 int len
, listlen
, ret
;
3666 /* "u 1000 1000000 65536"
3668 * let's render this as
3686 #define __LXC_IDMAP_STR_BUF (3 * LXC_NUMSTRLEN64 + 3 + 1 + 1)
3687 char buf
[__LXC_IDMAP_STR_BUF
];
3692 memset(retv
, 0, inlen
);
3694 listlen
= lxc_list_len(&c
->lxc_conf
->id_map
);
3695 lxc_list_for_each(it
, &c
->lxc_conf
->id_map
)
3697 struct id_map
*map
= it
->elem
;
3698 ret
= snprintf(buf
, __LXC_IDMAP_STR_BUF
, "%c %lu %lu %lu",
3699 (map
->idtype
== ID_TYPE_UID
) ? 'u' : 'g',
3700 map
->nsid
, map
->hostid
, map
->range
);
3701 if (ret
< 0 || ret
>= __LXC_IDMAP_STR_BUF
)
3704 strprint(retv
, inlen
, "%s%s", buf
, (listlen
-- > 1) ? "\n" : "");
3709 static int get_config_loglevel(struct lxc_container
*c
, const char *key
,
3710 char *retv
, int inlen
)
3713 v
= lxc_log_priority_to_string(c
->lxc_conf
->loglevel
);
3714 return lxc_get_conf_str(retv
, inlen
, v
);
3717 static int get_config_logfile(struct lxc_container
*c
, const char *key
,
3718 char *retv
, int inlen
)
3720 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->logfile
);
3723 static int get_config_fstab(struct lxc_container
*c
, const char *key
,
3724 char *retv
, int inlen
)
3726 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->fstab
);
3729 static int get_config_mount_auto(struct lxc_container
*c
, const char *key
,
3730 char *retv
, int inlen
)
3732 int len
, fulllen
= 0;
3733 const char *sep
= "";
3738 memset(retv
, 0, inlen
);
3740 if (!(c
->lxc_conf
->auto_mounts
& LXC_AUTO_ALL_MASK
))
3743 switch (c
->lxc_conf
->auto_mounts
& LXC_AUTO_PROC_MASK
) {
3744 case LXC_AUTO_PROC_MIXED
:
3745 strprint(retv
, inlen
, "%sproc:mixed", sep
);
3748 case LXC_AUTO_PROC_RW
:
3749 strprint(retv
, inlen
, "%sproc:rw", sep
);
3756 switch (c
->lxc_conf
->auto_mounts
& LXC_AUTO_SYS_MASK
) {
3757 case LXC_AUTO_SYS_RO
:
3758 strprint(retv
, inlen
, "%ssys:ro", sep
);
3761 case LXC_AUTO_SYS_RW
:
3762 strprint(retv
, inlen
, "%ssys:rw", sep
);
3765 case LXC_AUTO_SYS_MIXED
:
3766 strprint(retv
, inlen
, "%ssys:mixed", sep
);
3773 switch (c
->lxc_conf
->auto_mounts
& LXC_AUTO_CGROUP_MASK
) {
3774 case LXC_AUTO_CGROUP_NOSPEC
:
3775 strprint(retv
, inlen
, "%scgroup", sep
);
3778 case LXC_AUTO_CGROUP_MIXED
:
3779 strprint(retv
, inlen
, "%scgroup:mixed", sep
);
3782 case LXC_AUTO_CGROUP_RO
:
3783 strprint(retv
, inlen
, "%scgroup:ro", sep
);
3786 case LXC_AUTO_CGROUP_RW
:
3787 strprint(retv
, inlen
, "%scgroup:rw", sep
);
3790 case LXC_AUTO_CGROUP_FULL_NOSPEC
:
3791 strprint(retv
, inlen
, "%scgroup-full", sep
);
3794 case LXC_AUTO_CGROUP_FULL_MIXED
:
3795 strprint(retv
, inlen
, "%scgroup-full:mixed", sep
);
3798 case LXC_AUTO_CGROUP_FULL_RO
:
3799 strprint(retv
, inlen
, "%scgroup-full:ro", sep
);
3802 case LXC_AUTO_CGROUP_FULL_RW
:
3803 strprint(retv
, inlen
, "%scgroup-full:rw", sep
);
3813 static int get_config_mount(struct lxc_container
*c
, const char *key
,
3814 char *retv
, int inlen
)
3816 int len
, fulllen
= 0;
3817 struct lxc_list
*it
;
3822 memset(retv
, 0, inlen
);
3824 lxc_list_for_each(it
, &c
->lxc_conf
->mount_list
)
3826 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3832 static int get_config_rootfs(struct lxc_container
*c
, const char *key
,
3833 char *retv
, int inlen
)
3835 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->rootfs
.path
);
3838 static int get_config_rootfs_mount(struct lxc_container
*c
, const char *key
,
3839 char *retv
, int inlen
)
3841 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->rootfs
.mount
);
3844 static int get_config_rootfs_options(struct lxc_container
*c
, const char *key
,
3845 char *retv
, int inlen
)
3847 return lxc_get_conf_str(retv
, inlen
, c
->lxc_conf
->rootfs
.options
);