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>
48 #include "confile_utils.h"
53 #include "lxcseccomp.h"
58 #include <../include/ifaddrs.h>
61 #if HAVE_SYS_PERSONALITY_H
62 #include <sys/personality.h>
65 lxc_log_define(lxc_confile
, lxc
);
67 static int set_config_personality(const char *, const char *, struct lxc_conf
*);
68 static int get_config_personality(const char *, char *, int, struct lxc_conf
*);
69 static int clr_config_personality(const char *, struct lxc_conf
*);
71 static int set_config_pts(const char *, const char *, struct lxc_conf
*);
72 static int get_config_pts(const char *, char *, int, struct lxc_conf
*);
73 static int clr_config_pts(const char *, struct lxc_conf
*);
75 static int set_config_tty(const char *, const char *, struct lxc_conf
*);
76 static int get_config_tty(const char *, char *, int, struct lxc_conf
*);
77 static int clr_config_tty(const char *, struct lxc_conf
*);
79 static int set_config_ttydir(const char *, const char *, struct lxc_conf
*);
80 static int get_config_ttydir(const char *, char *, int, struct lxc_conf
*);
81 static int clr_config_ttydir(const char *, struct lxc_conf
*);
83 static int set_config_kmsg(const char *, const char *, struct lxc_conf
*);
84 static int get_config_kmsg(const char *, char *, int, struct lxc_conf
*);
85 static int clr_config_kmsg(const char *, struct lxc_conf
*);
87 static int set_config_lsm_aa_profile(const char *, const char *, struct lxc_conf
*);
88 static int get_config_lsm_aa_profile(const char *, char *, int, struct lxc_conf
*);
89 static int clr_config_lsm_aa_profile(const char *, struct lxc_conf
*);
91 static int set_config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf
*);
92 static int get_config_lsm_aa_incomplete(const char *, char *, int, struct lxc_conf
*);
93 static int clr_config_lsm_aa_incomplete(const char *, struct lxc_conf
*);
95 static int set_config_lsm_se_context(const char *, const char *, struct lxc_conf
*);
96 static int get_config_lsm_se_context(const char *, char *, int, struct lxc_conf
*);
97 static int clr_config_lsm_se_context(const char *, struct lxc_conf
*);
99 static int set_config_cgroup(const char *, const char *, struct lxc_conf
*);
100 static int get_config_cgroup(const char *, char *, int, struct lxc_conf
*);
101 static int clr_config_cgroup(const char *, struct lxc_conf
*);
103 static int set_config_idmaps(const char *, const char *, struct lxc_conf
*);
104 static int get_config_idmaps(const char *, char *, int, struct lxc_conf
*);
105 static int clr_config_idmaps(const char *, struct lxc_conf
*);
107 static int set_config_loglevel(const char *, const char *, struct lxc_conf
*);
108 static int get_config_loglevel(const char *, char *, int, struct lxc_conf
*);
109 static int clr_config_loglevel(const char *, struct lxc_conf
*);
111 static int set_config_logfile(const char *, const char *, struct lxc_conf
*);
112 static int get_config_logfile(const char *, char *, int, struct lxc_conf
*);
113 static int clr_config_logfile(const char *, struct lxc_conf
*);
115 static int set_config_mount(const char *, const char *, struct lxc_conf
*);
116 static int get_config_mount(const char *, char *, int, struct lxc_conf
*);
117 static int clr_config_mount(const char *, struct lxc_conf
*);
119 static int set_config_mount_auto(const char *, const char *, struct lxc_conf
*);
120 static int get_config_mount_auto(const char *, char *, int, struct lxc_conf
*);
121 static int clr_config_mount_auto(const char *, struct lxc_conf
*);
123 static int set_config_fstab(const char *, const char *, struct lxc_conf
*);
124 static int get_config_fstab(const char *, char *, int, struct lxc_conf
*);
125 static int clr_config_fstab(const char *, struct lxc_conf
*);
127 static int set_config_rootfs_mount(const char *, const char *, struct lxc_conf
*);
128 static int get_config_rootfs_mount(const char *, char *, int, struct lxc_conf
*);
129 static int clr_config_rootfs_mount(const char *, struct lxc_conf
*);
131 static int set_config_rootfs_options(const char *, const char *, struct lxc_conf
*);
132 static int get_config_rootfs_options(const char *, char *, int, struct lxc_conf
*);
133 static int clr_config_rootfs_options(const char *, struct lxc_conf
*);
135 static int set_config_rootfs_backend(const char *, const char *, struct lxc_conf
*);
136 static int get_config_rootfs_backend(const char *, char *, int, struct lxc_conf
*);
137 static int clr_config_rootfs_backend(const char *, struct lxc_conf
*);
139 static int set_config_rootfs(const char *, const char *, struct lxc_conf
*);
140 static int get_config_rootfs(const char *, char *, int, struct lxc_conf
*);
141 static int clr_config_rootfs(const char *, struct lxc_conf
*);
143 static int set_config_pivotdir(const char *, const char *, struct lxc_conf
*);
144 static int get_config_pivotdir(const char *, char *, int, struct lxc_conf
*);
145 static int clr_config_pivotdir(const char *, struct lxc_conf
*);
147 static int set_config_utsname(const char *, const char *, struct lxc_conf
*);
148 static int get_config_utsname(const char *, char *, int, struct lxc_conf
*);
149 static int clr_config_utsname(const char *, struct lxc_conf
*);
151 static int set_config_hooks(const char *, const char *, struct lxc_conf
*lxc_conf
);
152 static int get_config_hooks(const char *, char *, int, struct lxc_conf
*);
153 static int clr_config_hooks(const char *, struct lxc_conf
*);
155 static int set_config_network_type(const char *, const char *, struct lxc_conf
*);
156 static int set_config_network_flags(const char *, const char *, struct lxc_conf
*);
157 static int set_config_network_link(const char *, const char *, struct lxc_conf
*);
158 static int set_config_network_name(const char *, const char *, struct lxc_conf
*);
159 static int set_config_network_veth_pair(const char *, const char *, struct lxc_conf
*);
160 static int set_config_network_macvlan_mode(const char *, const char *, struct lxc_conf
*);
161 static int set_config_network_hwaddr(const char *, const char *, struct lxc_conf
*);
162 static int set_config_network_vlan_id(const char *, const char *, struct lxc_conf
*);
163 static int set_config_network_mtu(const char *, const char *, struct lxc_conf
*);
164 static int set_config_network_ipv4(const char *, const char *, struct lxc_conf
*);
165 static int set_config_network_ipv4_gateway(const char *, const char *, struct lxc_conf
*);
166 static int set_config_network_script_up(const char *, const char *, struct lxc_conf
*);
167 static int set_config_network_script_down(const char *, const char *, struct lxc_conf
*);
168 static int set_config_network_ipv6(const char *, const char *, struct lxc_conf
*);
169 static int set_config_network_ipv6_gateway(const char *, const char *, struct lxc_conf
*);
170 static int set_config_network_nic(const char *, const char *, struct lxc_conf
*);
171 static int get_config_network_item(const char *, char *, int, struct lxc_conf
*);
172 static int clr_config_network_item(const char *, struct lxc_conf
*);
174 static int set_config_network(const char *, const char *, struct lxc_conf
*);
175 static int get_config_network(const char *, char *, int, struct lxc_conf
*);
176 static int clr_config_network(const char *, struct lxc_conf
*);
178 static int set_config_cap_drop(const char *, const char *, struct lxc_conf
*);
179 static int get_config_cap_drop(const char *, char *, int, struct lxc_conf
*);
180 static int clr_config_cap_drop(const char *, struct lxc_conf
*);
182 static int set_config_cap_keep(const char *, const char *, struct lxc_conf
*);
183 static int get_config_cap_keep(const char *, char *, int, struct lxc_conf
*);
184 static int clr_config_cap_keep(const char *, struct lxc_conf
*);
186 static int set_config_console_logfile(const char *, const char *, struct lxc_conf
*);
187 static int get_config_console_logfile(const char *, char *, int, struct lxc_conf
*);
188 static int clr_config_console_logfile(const char *, struct lxc_conf
*);
190 static int set_config_console(const char *, const char *, struct lxc_conf
*);
191 static int get_config_console(const char *, char *, int, struct lxc_conf
*);
192 static int clr_config_console(const char *, struct lxc_conf
*);
194 static int set_config_seccomp(const char *, const char *, struct lxc_conf
*);
195 static int get_config_seccomp(const char *, char *, int, struct lxc_conf
*);
196 static int clr_config_seccomp(const char *, struct lxc_conf
*);
198 static int set_config_includefiles(const char *, const char *, struct lxc_conf
*);
199 static int get_config_includefiles(const char *, char *, int, struct lxc_conf
*);
200 static int clr_config_includefiles(const char *, struct lxc_conf
*);
202 static int set_config_autodev(const char *, const char *, struct lxc_conf
*);
203 static int get_config_autodev(const char *, char *, int, struct lxc_conf
*);
204 static int clr_config_autodev(const char *, struct lxc_conf
*);
206 static int set_config_haltsignal(const char *, const char *, struct lxc_conf
*);
207 static int get_config_haltsignal(const char *, char *, int, struct lxc_conf
*);
208 static int clr_config_haltsignal(const char *, struct lxc_conf
*);
210 static int set_config_rebootsignal(const char *, const char *, struct lxc_conf
*);
211 static int get_config_rebootsignal(const char *, char *, int, struct lxc_conf
*);
212 static int clr_config_rebootsignal(const char *, struct lxc_conf
*);
214 static int set_config_stopsignal(const char *, const char *, struct lxc_conf
*);
215 static int get_config_stopsignal(const char *, char *, int, struct lxc_conf
*);
216 static int clr_config_stopsignal(const char *, struct lxc_conf
*);
218 static int set_config_start(const char *, const char *, struct lxc_conf
*);
219 static int get_config_start(const char *, char *, int, struct lxc_conf
*);
220 static int clr_config_start(const char *, struct lxc_conf
*);
222 static int set_config_monitor(const char *, const char *, struct lxc_conf
*);
223 static int get_config_monitor(const char *, char *, int, struct lxc_conf
*);
224 static int clr_config_monitor(const char *, struct lxc_conf
*);
226 static int set_config_group(const char *, const char *, struct lxc_conf
*);
227 static int get_config_group(const char *, char *, int, struct lxc_conf
*);
228 static int clr_config_group(const char *, struct lxc_conf
*);
230 static int set_config_environment(const char *, const char *, struct lxc_conf
*);
231 static int get_config_environment(const char *, char *, int, struct lxc_conf
*);
232 static int clr_config_environment(const char *, struct lxc_conf
*);
234 static int set_config_init_cmd(const char *, const char *, struct lxc_conf
*);
235 static int get_config_init_cmd(const char *, char *, int, struct lxc_conf
*);
236 static int clr_config_init_cmd(const char *, struct lxc_conf
*);
238 static int set_config_init_uid(const char *, const char *, struct lxc_conf
*);
239 static int get_config_init_uid(const char *, char *, int, struct lxc_conf
*);
240 static int clr_config_init_uid(const char *, struct lxc_conf
*);
242 static int set_config_init_gid(const char *, const char *, struct lxc_conf
*);
243 static int get_config_init_gid(const char *, char *, int, struct lxc_conf
*);
244 static int clr_config_init_gid(const char *, struct lxc_conf
*);
246 static int set_config_ephemeral(const char *, const char *, struct lxc_conf
*);
247 static int get_config_ephemeral(const char *, char *, int, struct lxc_conf
*);
248 static int clr_config_ephemeral(const char *, struct lxc_conf
*);
250 static int set_config_syslog(const char *, const char *, struct lxc_conf
*);
251 static int get_config_syslog(const char *, char *, int, struct lxc_conf
*);
252 static int clr_config_syslog(const char *, struct lxc_conf
*);
254 static int set_config_no_new_privs(const char *, const char *, struct lxc_conf
*);
255 static int get_config_no_new_privs(const char *, char *, int, struct lxc_conf
*);
256 static int clr_config_no_new_privs(const char *, struct lxc_conf
*);
258 static int set_config_limit(const char *, const char *, struct lxc_conf
*);
259 static int get_config_limit(const char *, char *, int, struct lxc_conf
*);
260 static int clr_config_limit(const char *, struct lxc_conf
*);
262 static struct lxc_config_t config
[] = {
263 { "lxc.arch", set_config_personality
, get_config_personality
, clr_config_personality
, },
264 { "lxc.pts", set_config_pts
, get_config_pts
, clr_config_pts
, },
265 { "lxc.tty", set_config_tty
, get_config_tty
, clr_config_tty
, },
266 { "lxc.devttydir", set_config_ttydir
, get_config_ttydir
, clr_config_ttydir
, },
267 { "lxc.kmsg", set_config_kmsg
, get_config_kmsg
, clr_config_kmsg
, },
268 { "lxc.aa_profile", set_config_lsm_aa_profile
, get_config_lsm_aa_profile
, clr_config_lsm_aa_profile
, },
269 { "lxc.aa_allow_incomplete", set_config_lsm_aa_incomplete
, get_config_lsm_aa_incomplete
, clr_config_lsm_aa_incomplete
, },
270 { "lxc.se_context", set_config_lsm_se_context
, get_config_lsm_se_context
, clr_config_lsm_se_context
, },
271 { "lxc.cgroup", set_config_cgroup
, get_config_cgroup
, clr_config_cgroup
, },
272 { "lxc.id_map", set_config_idmaps
, get_config_idmaps
, clr_config_idmaps
, },
273 { "lxc.loglevel", set_config_loglevel
, get_config_loglevel
, clr_config_loglevel
, },
274 { "lxc.logfile", set_config_logfile
, get_config_logfile
, clr_config_logfile
, },
275 { "lxc.mount.entry", set_config_mount
, get_config_mount
, clr_config_mount
, },
276 { "lxc.mount.auto", set_config_mount_auto
, get_config_mount_auto
, clr_config_mount_auto
, },
277 { "lxc.mount", set_config_fstab
, get_config_fstab
, clr_config_fstab
, },
278 { "lxc.rootfs.mount", set_config_rootfs_mount
, get_config_rootfs_mount
, clr_config_rootfs_mount
, },
279 { "lxc.rootfs.options", set_config_rootfs_options
, get_config_rootfs_options
, clr_config_rootfs_options
, },
280 { "lxc.rootfs.backend", set_config_rootfs_backend
, get_config_rootfs_backend
, clr_config_rootfs_backend
, },
281 { "lxc.rootfs", set_config_rootfs
, get_config_rootfs
, clr_config_rootfs
, },
282 { "lxc.pivotdir", set_config_pivotdir
, get_config_pivotdir
, clr_config_pivotdir
, },
283 { "lxc.utsname", set_config_utsname
, get_config_utsname
, clr_config_utsname
, },
284 { "lxc.hook.pre-start", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
285 { "lxc.hook.pre-mount", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
286 { "lxc.hook.mount", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
287 { "lxc.hook.autodev", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
288 { "lxc.hook.start", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
289 { "lxc.hook.stop", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
290 { "lxc.hook.post-stop", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
291 { "lxc.hook.clone", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
292 { "lxc.hook.destroy", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
293 { "lxc.hook", set_config_hooks
, get_config_hooks
, clr_config_hooks
, },
294 { "lxc.network.type", set_config_network_type
, get_config_network_item
, clr_config_network_item
, },
295 { "lxc.network.flags", set_config_network_flags
, get_config_network_item
, clr_config_network_item
, },
296 { "lxc.network.link", set_config_network_link
, get_config_network_item
, clr_config_network_item
, },
297 { "lxc.network.name", set_config_network_name
, get_config_network_item
, clr_config_network_item
, },
298 { "lxc.network.macvlan.mode", set_config_network_macvlan_mode
, get_config_network_item
, clr_config_network_item
, },
299 { "lxc.network.veth.pair", set_config_network_veth_pair
, get_config_network_item
, clr_config_network_item
, },
300 { "lxc.network.script.up", set_config_network_script_up
, get_config_network_item
, clr_config_network_item
, },
301 { "lxc.network.script.down", set_config_network_script_down
, get_config_network_item
, clr_config_network_item
, },
302 { "lxc.network.hwaddr", set_config_network_hwaddr
, get_config_network_item
, clr_config_network_item
, },
303 { "lxc.network.mtu", set_config_network_mtu
, get_config_network_item
, clr_config_network_item
, },
304 { "lxc.network.vlan.id", set_config_network_vlan_id
, get_config_network_item
, clr_config_network_item
, },
305 { "lxc.network.ipv4.gateway", set_config_network_ipv4_gateway
, get_config_network_item
, clr_config_network_item
, },
306 { "lxc.network.ipv4", set_config_network_ipv4
, get_config_network_item
, clr_config_network_item
, },
307 { "lxc.network.ipv6.gateway", set_config_network_ipv6_gateway
, get_config_network_item
, clr_config_network_item
, },
308 { "lxc.network.ipv6", set_config_network_ipv6
, get_config_network_item
, clr_config_network_item
, },
309 { "lxc.network.", set_config_network_nic
, get_config_network_item
, clr_config_network_item
, },
310 { "lxc.network", set_config_network
, get_config_network
, clr_config_network
, },
311 { "lxc.cap.drop", set_config_cap_drop
, get_config_cap_drop
, clr_config_cap_drop
, },
312 { "lxc.cap.keep", set_config_cap_keep
, get_config_cap_keep
, clr_config_cap_keep
, },
313 { "lxc.console.logfile", set_config_console_logfile
, get_config_console_logfile
, clr_config_console_logfile
, },
314 { "lxc.console", set_config_console
, get_config_console
, clr_config_console
, },
315 { "lxc.seccomp", set_config_seccomp
, get_config_seccomp
, clr_config_seccomp
, },
316 { "lxc.include", set_config_includefiles
, get_config_includefiles
, clr_config_includefiles
, },
317 { "lxc.autodev", set_config_autodev
, get_config_autodev
, clr_config_autodev
, },
318 { "lxc.haltsignal", set_config_haltsignal
, get_config_haltsignal
, clr_config_haltsignal
, },
319 { "lxc.rebootsignal", set_config_rebootsignal
, get_config_rebootsignal
, clr_config_rebootsignal
, },
320 { "lxc.stopsignal", set_config_stopsignal
, get_config_stopsignal
, clr_config_stopsignal
, },
321 { "lxc.start.auto", set_config_start
, get_config_start
, clr_config_start
, },
322 { "lxc.start.delay", set_config_start
, get_config_start
, clr_config_start
, },
323 { "lxc.start.order", set_config_start
, get_config_start
, clr_config_start
, },
324 { "lxc.monitor.unshare", set_config_monitor
, get_config_monitor
, clr_config_monitor
, },
325 { "lxc.group", set_config_group
, get_config_group
, clr_config_group
, },
326 { "lxc.environment", set_config_environment
, get_config_environment
, clr_config_environment
, },
327 { "lxc.init_cmd", set_config_init_cmd
, get_config_init_cmd
, clr_config_init_cmd
, },
328 { "lxc.init_uid", set_config_init_uid
, get_config_init_uid
, clr_config_init_uid
, },
329 { "lxc.init_gid", set_config_init_gid
, get_config_init_gid
, clr_config_init_gid
, },
330 { "lxc.ephemeral", set_config_ephemeral
, get_config_ephemeral
, clr_config_ephemeral
, },
331 { "lxc.syslog", set_config_syslog
, get_config_syslog
, clr_config_syslog
, },
332 { "lxc.no_new_privs", set_config_no_new_privs
, get_config_no_new_privs
, clr_config_no_new_privs
, },
333 { "lxc.limit", set_config_limit
, get_config_limit
, clr_config_limit
, },
341 static const struct signame signames
[] = {
374 { SIGSTKFLT
, "STKFLT" },
389 { SIGVTALRM
, "VTALRM" },
395 { SIGWINCH
, "WINCH" },
413 { SIGUNUSED
, "UNUSED" },
420 static const size_t config_size
= sizeof(config
) / sizeof(struct lxc_config_t
);
422 extern struct lxc_config_t
*lxc_getconfig(const char *key
)
426 for (i
= 0; i
< config_size
; i
++)
427 if (!strncmp(config
[i
].name
, key
, strlen(config
[i
].name
)))
432 #define strprint(str, inlen, ...) \
434 len = snprintf(str, inlen, ##__VA_ARGS__); \
436 SYSERROR("failed to create string"); \
449 int lxc_listconfigs(char *retv
, int inlen
)
458 memset(retv
, 0, inlen
);
460 for (i
= 0; i
< config_size
; i
++) {
461 char *s
= config
[i
].name
;
462 if (s
[strlen(s
) - 1] == '.')
464 strprint(retv
, inlen
, "%s\n", s
);
470 static inline bool config_value_empty(const char *value
)
472 if (value
&& strlen(value
) > 0)
478 static int set_config_string_item(char **conf_item
, const char *value
)
482 if (config_value_empty(value
)) {
488 new_value
= strdup(value
);
490 SYSERROR("failed to duplicate string \"%s\"", value
);
495 *conf_item
= new_value
;
499 static int set_config_string_item_max(char **conf_item
, const char *value
,
502 if (strlen(value
) >= max
) {
503 ERROR("%s is too long (>= %lu)", value
, (unsigned long)max
);
507 return set_config_string_item(conf_item
, value
);
510 static int set_config_path_item(char **conf_item
, const char *value
)
512 return set_config_string_item_max(conf_item
, value
, PATH_MAX
);
516 * Config entry is something like "lxc.network.0.ipv4" the key 'lxc.network.'
517 * was found. So we make sure next comes an integer, find the right callback
518 * (by rewriting the key), and call it.
520 static int set_config_network_nic(const char *key
, const char *value
,
521 struct lxc_conf
*lxc_conf
)
523 char *copy
= strdup(key
), *p
;
525 struct lxc_config_t
*config
;
528 SYSERROR("failed to allocate memory");
532 * Ok we know that to get here we've got "lxc.network."
533 * and it isn't any of the other network entries. So
534 * after the second . Should come an integer (# of defined
535 * nic) followed by a valid entry.
537 if (*(key
+ 12) < '0' || *(key
+ 12) > '9')
540 p
= strchr(key
+ 12, '.');
544 strcpy(copy
+ 12, p
+ 1);
545 config
= lxc_getconfig(copy
);
547 ERROR("unknown key %s", key
);
550 ret
= config
->set(key
, value
, lxc_conf
);
557 static int set_config_network(const char *key
, const char *value
,
558 struct lxc_conf
*lxc_conf
)
560 if (!config_value_empty(value
)) {
561 ERROR("lxc.network must not have a value");
565 return lxc_clear_config_network(lxc_conf
);
568 static int macvlan_mode(int *valuep
, const char *value
);
570 static int set_config_network_type(const char *key
, const char *value
,
571 struct lxc_conf
*lxc_conf
)
573 struct lxc_list
*network
= &lxc_conf
->network
;
574 struct lxc_netdev
*netdev
;
575 struct lxc_list
*list
;
577 if (config_value_empty(value
))
578 return lxc_clear_config_network(lxc_conf
);
580 netdev
= malloc(sizeof(*netdev
));
582 SYSERROR("failed to allocate memory");
586 memset(netdev
, 0, sizeof(*netdev
));
587 lxc_list_init(&netdev
->ipv4
);
588 lxc_list_init(&netdev
->ipv6
);
590 list
= malloc(sizeof(*list
));
592 SYSERROR("failed to allocate memory");
600 lxc_list_add_tail(network
, list
);
602 if (!strcmp(value
, "veth"))
603 netdev
->type
= LXC_NET_VETH
;
604 else if (!strcmp(value
, "macvlan")) {
605 netdev
->type
= LXC_NET_MACVLAN
;
606 macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, "private");
607 } else if (!strcmp(value
, "vlan"))
608 netdev
->type
= LXC_NET_VLAN
;
609 else if (!strcmp(value
, "phys"))
610 netdev
->type
= LXC_NET_PHYS
;
611 else if (!strcmp(value
, "empty"))
612 netdev
->type
= LXC_NET_EMPTY
;
613 else if (!strcmp(value
, "none"))
614 netdev
->type
= LXC_NET_NONE
;
616 ERROR("invalid network type %s", value
);
622 static int config_ip_prefix(struct in_addr
*addr
)
624 if (IN_CLASSA(addr
->s_addr
))
625 return 32 - IN_CLASSA_NSHIFT
;
626 if (IN_CLASSB(addr
->s_addr
))
627 return 32 - IN_CLASSB_NSHIFT
;
628 if (IN_CLASSC(addr
->s_addr
))
629 return 32 - IN_CLASSC_NSHIFT
;
635 * If you have p="lxc.network.0.link", pass it p+12
636 * to get back '0' (the index of the nic).
638 static int get_network_netdev_idx(const char *key
)
642 if (*key
< '0' || *key
> '9')
645 ret
= sscanf(key
, "%d", &idx
);
653 * If you have p="lxc.network.0", pass this p+12 and it will return
654 * the netdev of the first configured nic.
656 static struct lxc_netdev
*get_netdev_from_key(const char *key
,
657 struct lxc_list
*network
)
662 struct lxc_netdev
*netdev
= NULL
;
664 idx
= get_network_netdev_idx(key
);
668 lxc_list_for_each(it
, network
) {
678 extern int lxc_list_nicconfigs(struct lxc_conf
*c
, const char *key
, char *retv
,
681 struct lxc_netdev
*netdev
;
685 netdev
= get_netdev_from_key(key
+ 12, &c
->network
);
692 memset(retv
, 0, inlen
);
694 strprint(retv
, inlen
, "type\n");
695 strprint(retv
, inlen
, "script.up\n");
696 strprint(retv
, inlen
, "script.down\n");
697 if (netdev
->type
!= LXC_NET_EMPTY
) {
698 strprint(retv
, inlen
, "flags\n");
699 strprint(retv
, inlen
, "link\n");
700 strprint(retv
, inlen
, "name\n");
701 strprint(retv
, inlen
, "hwaddr\n");
702 strprint(retv
, inlen
, "mtu\n");
703 strprint(retv
, inlen
, "ipv6\n");
704 strprint(retv
, inlen
, "ipv6.gateway\n");
705 strprint(retv
, inlen
, "ipv4\n");
706 strprint(retv
, inlen
, "ipv4.gateway\n");
709 switch (netdev
->type
) {
711 strprint(retv
, inlen
, "veth.pair\n");
713 case LXC_NET_MACVLAN
:
714 strprint(retv
, inlen
, "macvlan.mode\n");
717 strprint(retv
, inlen
, "vlan.id\n");
726 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
727 struct lxc_list
*network
)
729 struct lxc_netdev
*netdev
= NULL
;
731 if (lxc_list_empty(network
)) {
732 ERROR("network is not created for '%s' = '%s' option", key
,
737 if (get_network_netdev_idx(key
+ 12) == -1)
738 netdev
= lxc_list_last_elem(network
);
740 netdev
= get_netdev_from_key(key
+ 12, network
);
743 ERROR("no network device defined for '%s' = '%s' option", key
,
751 static int network_ifname(char **valuep
, const char *value
)
753 return set_config_string_item_max(valuep
, value
, IFNAMSIZ
);
756 #ifndef MACVLAN_MODE_PRIVATE
757 #define MACVLAN_MODE_PRIVATE 1
760 #ifndef MACVLAN_MODE_VEPA
761 #define MACVLAN_MODE_VEPA 2
764 #ifndef MACVLAN_MODE_BRIDGE
765 #define MACVLAN_MODE_BRIDGE 4
768 #ifndef MACVLAN_MODE_PASSTHRU
769 #define MACVLAN_MODE_PASSTHRU 8
772 static int macvlan_mode(int *valuep
, const char *value
)
778 { "private", MACVLAN_MODE_PRIVATE
},
779 { "vepa", MACVLAN_MODE_VEPA
},
780 { "bridge", MACVLAN_MODE_BRIDGE
},
781 { "passthru", MACVLAN_MODE_PASSTHRU
},
786 for (i
= 0; i
< sizeof(m
) / sizeof(m
[0]); i
++) {
787 if (strcmp(m
[i
].name
, value
))
797 static int rand_complete_hwaddr(char *hwaddr
)
799 const char hex
[] = "0123456789abcdef";
807 seed
= randseed(false);
809 while (*curs
!= '\0' && *curs
!= '\n') {
810 if (*curs
== 'x' || *curs
== 'X') {
811 if (curs
- hwaddr
== 1) {
812 /* ensure address is unicast */
814 *curs
= hex
[rand_r(&seed
) & 0x0E];
816 *curs
= hex
[rand_r(&seed
) & 0x0F];
818 *curs
= hex
[rand() & 0x0E];
820 *curs
= hex
[rand() & 0x0F];
829 static int set_config_network_flags(const char *key
, const char *value
,
830 struct lxc_conf
*lxc_conf
)
832 struct lxc_netdev
*netdev
;
834 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
838 netdev
->flags
|= IFF_UP
;
843 static int set_network_link(const char *key
, const char *value
,
844 struct lxc_conf
*lxc_conf
)
846 struct lxc_netdev
*netdev
;
848 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
852 return network_ifname(&netdev
->link
, value
);
855 static int create_matched_ifnames(const char *value
, struct lxc_conf
*lxc_conf
)
857 struct ifaddrs
*ifaddr
, *ifa
;
860 const char *type_key
= "lxc.network.type";
861 const char *link_key
= "lxc.network.link";
862 const char *tmpvalue
= "phys";
864 if (getifaddrs(&ifaddr
) == -1) {
865 SYSERROR("Get network interfaces failed");
869 for (ifa
= ifaddr
, n
= 0; ifa
!= NULL
; ifa
= ifa
->ifa_next
, n
++) {
872 if (ifa
->ifa_addr
->sa_family
!= AF_PACKET
)
875 if (!strncmp(value
, ifa
->ifa_name
, strlen(value
) - 1)) {
876 ret
= set_config_network_type(type_key
, tmpvalue
,
879 ret
= set_network_link(link_key
, ifa
->ifa_name
,
882 ERROR("failed to create matched ifnames");
886 ERROR("failed to create matched ifnames");
898 static int set_config_network_link(const char *key
, const char *value
,
899 struct lxc_conf
*lxc_conf
)
901 struct lxc_netdev
*netdev
;
905 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
909 if (value
[strlen(value
) - 1] == '+' && netdev
->type
== LXC_NET_PHYS
) {
910 /* Get the last network list and remove it. */
911 it
= lxc_conf
->network
.prev
;
912 if (((struct lxc_netdev
*)(it
->elem
))->type
!= LXC_NET_PHYS
) {
913 ERROR("lxc config cannot support string pattern "
914 "matching for this link type");
920 ret
= create_matched_ifnames(value
, lxc_conf
);
922 ret
= network_ifname(&netdev
->link
, value
);
928 static int set_config_network_name(const char *key
, const char *value
,
929 struct lxc_conf
*lxc_conf
)
931 struct lxc_netdev
*netdev
;
933 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
937 return network_ifname(&netdev
->name
, value
);
940 static int set_config_network_veth_pair(const char *key
, const char *value
,
941 struct lxc_conf
*lxc_conf
)
943 struct lxc_netdev
*netdev
;
945 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
949 if (netdev
->type
!= LXC_NET_VETH
) {
950 ERROR("Invalid veth pair for a non-veth netdev");
954 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
957 static int set_config_network_macvlan_mode(const char *key
, const char *value
,
958 struct lxc_conf
*lxc_conf
)
960 struct lxc_netdev
*netdev
;
962 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
966 if (netdev
->type
!= LXC_NET_MACVLAN
) {
967 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
971 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
974 static int set_config_network_hwaddr(const char *key
, const char *value
,
975 struct lxc_conf
*lxc_conf
)
977 struct lxc_netdev
*netdev
;
980 new_value
= strdup(value
);
982 SYSERROR("failed to strdup \"%s\"", value
);
985 rand_complete_hwaddr(new_value
);
987 netdev
= network_netdev(key
, new_value
, &lxc_conf
->network
);
993 if (config_value_empty(new_value
)) {
995 netdev
->hwaddr
= NULL
;
999 netdev
->hwaddr
= new_value
;
1003 static int set_config_network_vlan_id(const char *key
, const char *value
,
1004 struct lxc_conf
*lxc_conf
)
1006 struct lxc_netdev
*netdev
;
1008 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1012 if (netdev
->type
!= LXC_NET_VLAN
) {
1013 ERROR("Invalid vlan.id for a non-macvlan netdev");
1017 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
1023 static int set_config_network_mtu(const char *key
, const char *value
,
1024 struct lxc_conf
*lxc_conf
)
1026 struct lxc_netdev
*netdev
;
1028 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1032 return set_config_string_item(&netdev
->mtu
, value
);
1035 static int set_config_network_ipv4(const char *key
, const char *value
,
1036 struct lxc_conf
*lxc_conf
)
1038 struct lxc_netdev
*netdev
;
1039 struct lxc_inetdev
*inetdev
;
1040 struct lxc_list
*list
;
1041 char *cursor
, *slash
;
1042 char *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
1044 if (config_value_empty(value
))
1045 return clr_config_network_item(key
, lxc_conf
);
1047 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1051 inetdev
= malloc(sizeof(*inetdev
));
1053 SYSERROR("failed to allocate ipv4 address");
1056 memset(inetdev
, 0, sizeof(*inetdev
));
1058 list
= malloc(sizeof(*list
));
1060 SYSERROR("failed to allocate memory");
1065 lxc_list_init(list
);
1066 list
->elem
= inetdev
;
1068 addr
= strdup(value
);
1070 ERROR("no address specified");
1076 cursor
= strstr(addr
, " ");
1082 slash
= strstr(addr
, "/");
1088 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
1089 SYSERROR("invalid ipv4 address: %s", value
);
1096 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
1097 SYSERROR("invalid ipv4 broadcast address: %s", value
);
1104 /* No prefix specified, determine it from the network class. */
1106 if (lxc_safe_uint(prefix
, &inetdev
->prefix
) < 0)
1109 inetdev
->prefix
= config_ip_prefix(&inetdev
->addr
);
1112 /* If no broadcast address, let compute one from the
1113 * prefix and address.
1116 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
1117 inetdev
->bcast
.s_addr
|=
1118 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
1121 lxc_list_add_tail(&netdev
->ipv4
, list
);
1127 static int set_config_network_ipv4_gateway(const char *key
, const char *value
,
1128 struct lxc_conf
*lxc_conf
)
1130 struct lxc_netdev
*netdev
;
1132 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1136 free(netdev
->ipv4_gateway
);
1138 if (config_value_empty(value
)) {
1139 netdev
->ipv4_gateway
= NULL
;
1140 } else if (!strcmp(value
, "auto")) {
1141 netdev
->ipv4_gateway
= NULL
;
1142 netdev
->ipv4_gateway_auto
= true;
1146 gw
= malloc(sizeof(*gw
));
1148 SYSERROR("failed to allocate ipv4 gateway address");
1152 if (!inet_pton(AF_INET
, value
, gw
)) {
1153 SYSERROR("invalid ipv4 gateway address: %s", value
);
1158 netdev
->ipv4_gateway
= gw
;
1159 netdev
->ipv4_gateway_auto
= false;
1165 static int set_config_network_ipv6(const char *key
, const char *value
,
1166 struct lxc_conf
*lxc_conf
)
1168 struct lxc_netdev
*netdev
;
1169 struct lxc_inet6dev
*inet6dev
;
1170 struct lxc_list
*list
;
1171 char *slash
, *valdup
, *netmask
;
1173 if (config_value_empty(value
))
1174 return clr_config_network_item(key
, lxc_conf
);
1176 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1180 inet6dev
= malloc(sizeof(*inet6dev
));
1182 SYSERROR("failed to allocate ipv6 address");
1185 memset(inet6dev
, 0, sizeof(*inet6dev
));
1187 list
= malloc(sizeof(*list
));
1189 SYSERROR("failed to allocate memory");
1194 lxc_list_init(list
);
1195 list
->elem
= inet6dev
;
1197 valdup
= strdup(value
);
1199 ERROR("no address specified");
1205 inet6dev
->prefix
= 64;
1206 slash
= strstr(valdup
, "/");
1209 netmask
= slash
+ 1;
1210 if (lxc_safe_uint(netmask
, &inet6dev
->prefix
) < 0)
1214 if (!inet_pton(AF_INET6
, valdup
, &inet6dev
->addr
)) {
1215 SYSERROR("invalid ipv6 address: %s", valdup
);
1222 lxc_list_add_tail(&netdev
->ipv6
, list
);
1228 static int set_config_network_ipv6_gateway(const char *key
, const char *value
,
1229 struct lxc_conf
*lxc_conf
)
1231 struct lxc_netdev
*netdev
;
1233 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1237 free(netdev
->ipv6_gateway
);
1239 if (config_value_empty(value
)) {
1240 netdev
->ipv6_gateway
= NULL
;
1241 } else if (!strcmp(value
, "auto")) {
1242 netdev
->ipv6_gateway
= NULL
;
1243 netdev
->ipv6_gateway_auto
= true;
1245 struct in6_addr
*gw
;
1247 gw
= malloc(sizeof(*gw
));
1249 SYSERROR("failed to allocate ipv6 gateway address");
1253 if (!inet_pton(AF_INET6
, value
, gw
)) {
1254 SYSERROR("invalid ipv6 gateway address: %s", value
);
1259 netdev
->ipv6_gateway
= gw
;
1260 netdev
->ipv6_gateway_auto
= false;
1266 static int set_config_network_script_up(const char *key
, const char *value
,
1267 struct lxc_conf
*lxc_conf
)
1269 struct lxc_netdev
*netdev
;
1271 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1275 return set_config_string_item(&netdev
->upscript
, value
);
1278 static int set_config_network_script_down(const char *key
, const char *value
,
1279 struct lxc_conf
*lxc_conf
)
1281 struct lxc_netdev
*netdev
;
1283 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
1287 return set_config_string_item(&netdev
->downscript
, value
);
1290 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
1292 struct lxc_list
*hooklist
;
1294 hooklist
= malloc(sizeof(*hooklist
));
1300 hooklist
->elem
= hook
;
1301 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
1305 static int set_config_seccomp(const char *key
, const char *value
,
1306 struct lxc_conf
*lxc_conf
)
1308 return set_config_path_item(&lxc_conf
->seccomp
, value
);
1311 static int set_config_init_cmd(const char *key
, const char *value
,
1312 struct lxc_conf
*lxc_conf
)
1314 return set_config_path_item(&lxc_conf
->init_cmd
, value
);
1317 static int set_config_init_uid(const char *key
, const char *value
,
1318 struct lxc_conf
*lxc_conf
)
1320 unsigned int init_uid
;
1322 /* Set config value to default. */
1323 if (config_value_empty(value
)) {
1324 lxc_conf
->init_uid
= 0;
1328 /* Parse new config value. */
1329 if (lxc_safe_uint(value
, &init_uid
) < 0)
1331 lxc_conf
->init_uid
= init_uid
;
1336 static int set_config_init_gid(const char *key
, const char *value
,
1337 struct lxc_conf
*lxc_conf
)
1339 unsigned int init_gid
;
1341 /* Set config value to default. */
1342 if (config_value_empty(value
)) {
1343 lxc_conf
->init_gid
= 0;
1347 /* Parse new config value. */
1348 if (lxc_safe_uint(value
, &init_gid
) < 0)
1350 lxc_conf
->init_gid
= init_gid
;
1355 static int set_config_hooks(const char *key
, const char *value
,
1356 struct lxc_conf
*lxc_conf
)
1360 if (config_value_empty(value
))
1361 return lxc_clear_hooks(lxc_conf
, key
);
1363 if (strcmp(key
+ 4, "hook") == 0) {
1364 ERROR("lxc.hook cannot take a value");
1367 copy
= strdup(value
);
1369 SYSERROR("failed to dup string '%s'", value
);
1373 if (strcmp(key
+ 9, "pre-start") == 0)
1374 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
1375 else if (strcmp(key
+ 9, "pre-mount") == 0)
1376 return add_hook(lxc_conf
, LXCHOOK_PREMOUNT
, copy
);
1377 else if (strcmp(key
+ 9, "autodev") == 0)
1378 return add_hook(lxc_conf
, LXCHOOK_AUTODEV
, copy
);
1379 else if (strcmp(key
+ 9, "mount") == 0)
1380 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
1381 else if (strcmp(key
+ 9, "start") == 0)
1382 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
1383 else if (strcmp(key
+ 9, "stop") == 0)
1384 return add_hook(lxc_conf
, LXCHOOK_STOP
, copy
);
1385 else if (strcmp(key
+ 9, "post-stop") == 0)
1386 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
1387 else if (strcmp(key
+ 9, "clone") == 0)
1388 return add_hook(lxc_conf
, LXCHOOK_CLONE
, copy
);
1389 else if (strcmp(key
+ 9, "destroy") == 0)
1390 return add_hook(lxc_conf
, LXCHOOK_DESTROY
, copy
);
1392 SYSERROR("Unknown key: %s", key
);
1397 static int set_config_personality(const char *key
, const char *value
,
1398 struct lxc_conf
*lxc_conf
)
1400 signed long personality
= lxc_config_parse_arch(value
);
1402 if (personality
>= 0)
1403 lxc_conf
->personality
= personality
;
1405 WARN("unsupported personality '%s'", value
);
1410 static int set_config_pts(const char *key
, const char *value
,
1411 struct lxc_conf
*lxc_conf
)
1413 /* Set config value to default. */
1414 if (config_value_empty(value
)) {
1419 /* Parse new config value. */
1420 if (lxc_safe_uint(value
, &lxc_conf
->pts
) < 0)
1426 /* We only need to check whether the first byte of the key after the lxc.start.
1427 * prefix matches our expectations since they fortunately all start with a
1428 * different letter. If anything was wrong with the key we would have already
1429 * noticed when the callback was called.
1431 static int set_config_start(const char *key
, const char *value
,
1432 struct lxc_conf
*lxc_conf
)
1436 is_empty
= config_value_empty(value
);
1438 if (*(key
+ 10) == 'a') { /* lxc.start.auto */
1439 /* Set config value to default. */
1441 lxc_conf
->start_auto
= 0;
1445 /* Parse new config value. */
1446 if (lxc_safe_uint(value
, &lxc_conf
->start_auto
) < 0)
1449 if (lxc_conf
->start_auto
> 1)
1453 } else if (*(key
+ 10) == 'd') { /* lxc.start.delay */
1454 /* Set config value to default. */
1456 lxc_conf
->start_delay
= 0;
1460 /* Parse new config value. */
1461 return lxc_safe_uint(value
, &lxc_conf
->start_delay
);
1462 } else if (*(key
+ 10) == 'o') { /* lxc.start.order */
1463 /* Set config value to default. */
1465 lxc_conf
->start_order
= 0;
1469 /* Parse new config value. */
1470 return lxc_safe_int(value
, &lxc_conf
->start_order
);
1473 SYSERROR("Unknown key: %s", key
);
1477 static int set_config_monitor(const char *key
, const char *value
,
1478 struct lxc_conf
*lxc_conf
)
1480 /* Set config value to default. */
1481 if (config_value_empty(value
)) {
1482 lxc_conf
->monitor_unshare
= 0;
1486 /* Parse new config value. */
1487 if (strcmp(key
+ 12, "unshare") == 0)
1488 return lxc_safe_uint(value
, &lxc_conf
->monitor_unshare
);
1490 SYSERROR("Unknown key: %s", key
);
1494 static int set_config_group(const char *key
, const char *value
,
1495 struct lxc_conf
*lxc_conf
)
1497 char *groups
, *groupptr
, *sptr
, *token
;
1498 struct lxc_list
*grouplist
;
1501 if (config_value_empty(value
))
1502 return lxc_clear_groups(lxc_conf
);
1504 groups
= strdup(value
);
1506 SYSERROR("failed to dup '%s'", value
);
1510 /* In case several groups are specified in a single line
1511 * split these groups in a single element for the list.
1513 for (groupptr
= groups
;; groupptr
= NULL
) {
1514 token
= strtok_r(groupptr
, " \t", &sptr
);
1520 grouplist
= malloc(sizeof(*grouplist
));
1522 SYSERROR("failed to allocate groups list");
1526 grouplist
->elem
= strdup(token
);
1527 if (!grouplist
->elem
) {
1528 SYSERROR("failed to dup '%s'", token
);
1533 lxc_list_add_tail(&lxc_conf
->groups
, grouplist
);
1540 static int set_config_environment(const char *key
, const char *value
,
1541 struct lxc_conf
*lxc_conf
)
1543 struct lxc_list
*list_item
= NULL
;
1545 if (config_value_empty(value
))
1546 return lxc_clear_environment(lxc_conf
);
1548 list_item
= malloc(sizeof(*list_item
));
1552 list_item
->elem
= strdup(value
);
1554 if (!list_item
->elem
)
1557 lxc_list_add_tail(&lxc_conf
->environment
, list_item
);
1566 static int set_config_tty(const char *key
, const char *value
,
1567 struct lxc_conf
*lxc_conf
)
1569 /* Set config value to default. */
1570 if (config_value_empty(value
)) {
1575 /* Parse new config value. */
1576 return lxc_safe_uint(value
, &lxc_conf
->tty
);
1579 static int set_config_ttydir(const char *key
, const char *value
,
1580 struct lxc_conf
*lxc_conf
)
1582 return set_config_string_item_max(&lxc_conf
->ttydir
, value
,
1586 static int set_config_kmsg(const char *key
, const char *value
,
1587 struct lxc_conf
*lxc_conf
)
1589 /* Set config value to default. */
1590 if (config_value_empty(value
)) {
1595 /* Parse new config value. */
1596 if (lxc_safe_uint(value
, &lxc_conf
->kmsg
) < 0)
1599 if (lxc_conf
->kmsg
> 1)
1605 static int set_config_lsm_aa_profile(const char *key
, const char *value
,
1606 struct lxc_conf
*lxc_conf
)
1608 return set_config_string_item(&lxc_conf
->lsm_aa_profile
, value
);
1611 static int set_config_lsm_aa_incomplete(const char *key
, const char *value
,
1612 struct lxc_conf
*lxc_conf
)
1614 /* Set config value to default. */
1615 if (config_value_empty(value
)) {
1616 lxc_conf
->lsm_aa_allow_incomplete
= 0;
1620 /* Parse new config value. */
1621 if (lxc_safe_uint(value
, &lxc_conf
->lsm_aa_allow_incomplete
) < 0)
1624 if (lxc_conf
->lsm_aa_allow_incomplete
> 1) {
1625 ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only "
1626 "be set to 0 or 1");
1633 static int set_config_lsm_se_context(const char *key
, const char *value
,
1634 struct lxc_conf
*lxc_conf
)
1636 return set_config_string_item(&lxc_conf
->lsm_se_context
, value
);
1639 static int set_config_logfile(const char *key
, const char *value
,
1644 if (config_value_empty(value
)) {
1650 /* Store these values in the lxc_conf, and then try to set for actual
1653 ret
= set_config_path_item(&c
->logfile
, value
);
1655 ret
= lxc_log_set_file(&c
->logfd
, c
->logfile
);
1659 static int set_config_loglevel(const char *key
, const char *value
,
1660 struct lxc_conf
*lxc_conf
)
1664 /* Set config value to default. */
1665 if (config_value_empty(value
)) {
1666 lxc_conf
->loglevel
= LXC_LOG_PRIORITY_NOTSET
;
1670 /* Parse new config value. */
1671 if (value
[0] >= '0' && value
[0] <= '9') {
1672 if (lxc_safe_int(value
, &newlevel
) < 0)
1675 newlevel
= lxc_log_priority_to_int(value
);
1678 /* Store these values in the lxc_conf, and then try to set for actual
1681 lxc_conf
->loglevel
= newlevel
;
1682 return lxc_log_set_level(&lxc_conf
->loglevel
, newlevel
);
1685 static int set_config_autodev(const char *key
, const char *value
,
1686 struct lxc_conf
*lxc_conf
)
1688 /* Set config value to default. */
1689 if (config_value_empty(value
)) {
1690 lxc_conf
->autodev
= 0;
1694 /* Parse new config value. */
1695 if (lxc_safe_uint(value
, &lxc_conf
->autodev
) < 0)
1698 if (lxc_conf
->autodev
> 1) {
1699 ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1");
1706 static int sig_num(const char *sig
)
1708 unsigned int signum
;
1710 if (lxc_safe_uint(sig
, &signum
) < 0)
1716 static int rt_sig_num(const char *signame
)
1718 int rtmax
= 0, sig_n
= 0;
1720 if (strncasecmp(signame
, "max-", 4) == 0) {
1725 if (!isdigit(*signame
))
1728 sig_n
= sig_num(signame
);
1729 sig_n
= rtmax
? SIGRTMAX
- sig_n
: SIGRTMIN
+ sig_n
;
1730 if (sig_n
> SIGRTMAX
|| sig_n
< SIGRTMIN
)
1736 static int sig_parse(const char *signame
)
1740 if (isdigit(*signame
)) {
1741 return sig_num(signame
);
1742 } else if (strncasecmp(signame
, "sig", 3) == 0) {
1744 if (strncasecmp(signame
, "rt", 2) == 0)
1745 return rt_sig_num(signame
+ 2);
1746 for (n
= 0; n
< sizeof(signames
) / sizeof((signames
)[0]); n
++) {
1747 if (strcasecmp(signames
[n
].name
, signame
) == 0)
1748 return signames
[n
].num
;
1755 static int set_config_haltsignal(const char *key
, const char *value
,
1756 struct lxc_conf
*lxc_conf
)
1760 /* Set config value to default. */
1761 if (config_value_empty(value
)) {
1762 lxc_conf
->haltsignal
= 0;
1766 /* Parse new config value. */
1767 sig_n
= sig_parse(value
);
1771 lxc_conf
->haltsignal
= sig_n
;
1776 static int set_config_rebootsignal(const char *key
, const char *value
,
1777 struct lxc_conf
*lxc_conf
)
1781 /* Set config value to default. */
1782 if (config_value_empty(value
)) {
1783 lxc_conf
->rebootsignal
= 0;
1787 /* Parse new config value. */
1788 sig_n
= sig_parse(value
);
1791 lxc_conf
->rebootsignal
= sig_n
;
1796 static int set_config_stopsignal(const char *key
, const char *value
,
1797 struct lxc_conf
*lxc_conf
)
1801 /* Set config value to default. */
1802 if (config_value_empty(value
)) {
1803 lxc_conf
->stopsignal
= 0;
1807 /* Parse new config value. */
1808 sig_n
= sig_parse(value
);
1811 lxc_conf
->stopsignal
= sig_n
;
1816 static int set_config_cgroup(const char *key
, const char *value
,
1817 struct lxc_conf
*lxc_conf
)
1820 char *token
= "lxc.cgroup.";
1821 struct lxc_list
*cglist
= NULL
;
1822 struct lxc_cgroup
*cgelem
= NULL
;
1824 if (config_value_empty(value
))
1825 return lxc_clear_cgroups(lxc_conf
, key
);
1827 subkey
= strstr(key
, token
);
1831 if (!strlen(subkey
))
1834 if (strlen(subkey
) == strlen(token
))
1837 subkey
+= strlen(token
);
1839 cglist
= malloc(sizeof(*cglist
));
1843 cgelem
= malloc(sizeof(*cgelem
));
1846 memset(cgelem
, 0, sizeof(*cgelem
));
1848 cgelem
->subsystem
= strdup(subkey
);
1849 cgelem
->value
= strdup(value
);
1851 if (!cgelem
->subsystem
|| !cgelem
->value
)
1854 cglist
->elem
= cgelem
;
1856 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
1864 free(cgelem
->subsystem
);
1866 free(cgelem
->value
);
1874 static bool parse_limit_value(const char **value
, unsigned long *res
)
1876 char *endptr
= NULL
;
1878 if (strncmp(*value
, "unlimited", sizeof("unlimited") - 1) == 0) {
1879 *res
= RLIM_INFINITY
;
1880 *value
+= sizeof("unlimited") - 1;
1885 *res
= strtoul(*value
, &endptr
, 10);
1886 if (errno
|| !endptr
)
1893 static int set_config_limit(const char *key
, const char *value
,
1894 struct lxc_conf
*lxc_conf
)
1896 struct lxc_list
*iter
;
1897 struct rlimit limit
;
1898 unsigned long limit_value
;
1899 struct lxc_list
*limlist
= NULL
;
1900 struct lxc_limit
*limelem
= NULL
;
1902 if (config_value_empty(value
))
1903 return lxc_clear_limits(lxc_conf
, key
);
1905 if (strncmp(key
, "lxc.limit.", sizeof("lxc.limit.") - 1) != 0)
1908 key
+= sizeof("lxc.limit.") - 1;
1910 /* soft limit comes first in the value */
1911 if (!parse_limit_value(&value
, &limit_value
))
1913 limit
.rlim_cur
= limit_value
;
1915 /* skip spaces and a colon */
1916 while (isspace(*value
))
1921 else if (*value
) /* any other character is an error here */
1924 while (isspace(*value
))
1927 /* optional hard limit */
1929 if (!parse_limit_value(&value
, &limit_value
))
1931 limit
.rlim_max
= limit_value
;
1933 /* check for trailing garbage */
1934 while (isspace(*value
))
1940 /* a single value sets both hard and soft limit */
1941 limit
.rlim_max
= limit
.rlim_cur
;
1944 /* find existing list element */
1945 lxc_list_for_each(iter
, &lxc_conf
->limits
)
1947 limelem
= iter
->elem
;
1948 if (!strcmp(key
, limelem
->resource
)) {
1949 limelem
->limit
= limit
;
1954 /* allocate list element */
1955 limlist
= malloc(sizeof(*limlist
));
1959 limelem
= malloc(sizeof(*limelem
));
1962 memset(limelem
, 0, sizeof(*limelem
));
1964 limelem
->resource
= strdup(key
);
1965 if (!limelem
->resource
)
1967 limelem
->limit
= limit
;
1969 limlist
->elem
= limelem
;
1971 lxc_list_add_tail(&lxc_conf
->limits
, limlist
);
1978 free(limelem
->resource
);
1984 static int set_config_idmaps(const char *key
, const char *value
,
1985 struct lxc_conf
*lxc_conf
)
1987 unsigned long hostid
, nsid
, range
;
1990 struct lxc_list
*idmaplist
= NULL
;
1991 struct id_map
*idmap
= NULL
;
1993 if (config_value_empty(value
))
1994 return lxc_clear_idmaps(lxc_conf
);
1996 idmaplist
= malloc(sizeof(*idmaplist
));
2000 idmap
= malloc(sizeof(*idmap
));
2003 memset(idmap
, 0, sizeof(*idmap
));
2005 ret
= parse_idmaps(value
, &type
, &nsid
, &hostid
, &range
);
2009 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type
, nsid
, hostid
, range
);
2011 idmap
->idtype
= ID_TYPE_UID
;
2012 else if (type
== 'g')
2013 idmap
->idtype
= ID_TYPE_GID
;
2017 idmap
->hostid
= hostid
;
2019 idmap
->range
= range
;
2020 idmaplist
->elem
= idmap
;
2021 lxc_list_add_tail(&lxc_conf
->id_map
, idmaplist
);
2033 static int set_config_fstab(const char *key
, const char *value
,
2034 struct lxc_conf
*lxc_conf
)
2036 if (config_value_empty(value
)) {
2037 clr_config_fstab(key
, lxc_conf
);
2041 return set_config_path_item(&lxc_conf
->fstab
, value
);
2044 static int set_config_mount_auto(const char *key
, const char *value
,
2045 struct lxc_conf
*lxc_conf
)
2047 char *autos
, *autoptr
, *sptr
, *token
;
2054 } allowed_auto_mounts
[] = {
2055 { "proc", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
2056 { "proc:mixed", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_MIXED
},
2057 { "proc:rw", LXC_AUTO_PROC_MASK
, LXC_AUTO_PROC_RW
},
2058 { "sys", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_MIXED
},
2059 { "sys:ro", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RO
},
2060 { "sys:mixed", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_MIXED
},
2061 { "sys:rw", LXC_AUTO_SYS_MASK
, LXC_AUTO_SYS_RW
},
2062 { "cgroup", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_NOSPEC
},
2063 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_MIXED
},
2064 { "cgroup:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RO
},
2065 { "cgroup:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_RW
},
2066 { "cgroup-full", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_NOSPEC
},
2067 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_MIXED
},
2068 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RO
},
2069 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK
, LXC_AUTO_CGROUP_FULL_RW
},
2070 /* NB: For adding anything that is just a single on/off, but has
2071 * no options: keep mask and flag identical and just define the
2072 * enum value as an unused bit so far
2077 if (config_value_empty(value
)) {
2078 lxc_conf
->auto_mounts
= 0;
2082 autos
= strdup(value
);
2084 SYSERROR("failed to dup '%s'", value
);
2088 for (autoptr
= autos
;; autoptr
= NULL
) {
2089 token
= strtok_r(autoptr
, " \t", &sptr
);
2095 for (i
= 0; allowed_auto_mounts
[i
].token
; i
++) {
2096 if (!strcmp(allowed_auto_mounts
[i
].token
, token
))
2100 if (!allowed_auto_mounts
[i
].token
) {
2101 ERROR("Invalid filesystem to automount: %s", token
);
2105 lxc_conf
->auto_mounts
&= ~allowed_auto_mounts
[i
].mask
;
2106 lxc_conf
->auto_mounts
|= allowed_auto_mounts
[i
].flag
;
2113 static int set_config_mount(const char *key
, const char *value
,
2114 struct lxc_conf
*lxc_conf
)
2117 struct lxc_list
*mntlist
;
2119 if (config_value_empty(value
))
2120 return lxc_clear_mount_entries(lxc_conf
);
2122 mntlist
= malloc(sizeof(*mntlist
));
2126 mntelem
= strdup(value
);
2131 mntlist
->elem
= mntelem
;
2133 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
2138 static int set_config_cap_keep(const char *key
, const char *value
,
2139 struct lxc_conf
*lxc_conf
)
2141 char *keepcaps
, *keepptr
, *sptr
, *token
;
2142 struct lxc_list
*keeplist
;
2145 if (config_value_empty(value
))
2146 return lxc_clear_config_keepcaps(lxc_conf
);
2148 keepcaps
= strdup(value
);
2150 SYSERROR("failed to dup '%s'", value
);
2154 /* In case several capability keep is specified in a single line
2155 * split these caps in a single element for the list.
2157 for (keepptr
= keepcaps
;; keepptr
= NULL
) {
2158 token
= strtok_r(keepptr
, " \t", &sptr
);
2164 if (!strcmp(token
, "none"))
2165 lxc_clear_config_keepcaps(lxc_conf
);
2167 keeplist
= malloc(sizeof(*keeplist
));
2169 SYSERROR("failed to allocate keepcap list");
2173 keeplist
->elem
= strdup(token
);
2174 if (!keeplist
->elem
) {
2175 SYSERROR("failed to dup '%s'", token
);
2180 lxc_list_add_tail(&lxc_conf
->keepcaps
, keeplist
);
2188 static int set_config_cap_drop(const char *key
, const char *value
,
2189 struct lxc_conf
*lxc_conf
)
2191 char *dropcaps
, *dropptr
, *sptr
, *token
;
2192 struct lxc_list
*droplist
;
2195 if (config_value_empty(value
))
2196 return lxc_clear_config_caps(lxc_conf
);
2198 dropcaps
= strdup(value
);
2200 SYSERROR("failed to dup '%s'", value
);
2204 /* In case several capability drop is specified in a single line
2205 * split these caps in a single element for the list.
2207 for (dropptr
= dropcaps
;; dropptr
= NULL
) {
2208 token
= strtok_r(dropptr
, " \t", &sptr
);
2214 droplist
= malloc(sizeof(*droplist
));
2216 SYSERROR("failed to allocate drop list");
2220 droplist
->elem
= strdup(token
);
2221 if (!droplist
->elem
) {
2222 SYSERROR("failed to dup '%s'", token
);
2227 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
2235 static int set_config_console(const char *key
, const char *value
,
2236 struct lxc_conf
*lxc_conf
)
2238 return set_config_path_item(&lxc_conf
->console
.path
, value
);
2241 static int set_config_console_logfile(const char *key
, const char *value
,
2242 struct lxc_conf
*lxc_conf
)
2244 return set_config_path_item(&lxc_conf
->console
.log_path
, value
);
2248 * If we find a lxc.network.hwaddr in the original config file, we expand it in
2249 * the unexpanded_config, so that after a save_config we store the hwaddr for
2251 * This is only called when reading the config file, not when executing a
2253 * 'x' and 'X' are substituted in-place.
2255 static void update_hwaddr(const char *line
)
2259 line
+= lxc_char_left_gc(line
, strlen(line
));
2263 if (strncmp(line
, "lxc.network.hwaddr", 18) != 0)
2266 /* Let config_network_hwaddr raise the error. */
2267 p
= strchr(line
, '=');
2278 rand_complete_hwaddr(p
);
2281 int append_unexp_config_line(const char *line
, struct lxc_conf
*conf
)
2283 size_t len
= conf
->unexpanded_len
, linelen
= strlen(line
);
2285 update_hwaddr(line
);
2287 while (conf
->unexpanded_alloced
<= len
+ linelen
+ 2) {
2288 char *tmp
= realloc(conf
->unexpanded_config
,
2289 conf
->unexpanded_alloced
+ 1024);
2293 if (!conf
->unexpanded_config
)
2295 conf
->unexpanded_config
= tmp
;
2296 conf
->unexpanded_alloced
+= 1024;
2298 strcat(conf
->unexpanded_config
, line
);
2299 conf
->unexpanded_len
+= linelen
;
2300 if (line
[linelen
- 1] != '\n') {
2301 strcat(conf
->unexpanded_config
, "\n");
2302 conf
->unexpanded_len
++;
2307 static int do_includedir(const char *dirp
, struct lxc_conf
*lxc_conf
)
2309 struct dirent
*direntp
;
2311 char path
[MAXPATHLEN
];
2315 dir
= opendir(dirp
);
2317 SYSERROR("failed to open '%s'", dirp
);
2321 while ((direntp
= readdir(dir
))) {
2326 fnam
= direntp
->d_name
;
2327 if (!strcmp(fnam
, "."))
2330 if (!strcmp(fnam
, ".."))
2334 if (len
< 6 || strncmp(fnam
+ len
- 5, ".conf", 5) != 0)
2336 len
= snprintf(path
, MAXPATHLEN
, "%s/%s", dirp
, fnam
);
2337 if (len
< 0 || len
>= MAXPATHLEN
) {
2338 ERROR("lxc.include filename too long under '%s'", dirp
);
2343 ret
= lxc_config_read(path
, lxc_conf
, true);
2351 WARN("lxc.include dir: failed to close directory");
2356 static int set_config_includefiles(const char *key
, const char *value
,
2357 struct lxc_conf
*lxc_conf
)
2359 /* Set config value to default. */
2360 if (config_value_empty(value
)) {
2361 clr_config_includefiles(key
, lxc_conf
);
2365 /* Parse new config value. */
2367 return do_includedir(value
, lxc_conf
);
2369 return lxc_config_read(value
, lxc_conf
, true);
2372 static int set_config_rootfs(const char *key
, const char *value
,
2373 struct lxc_conf
*lxc_conf
)
2375 return set_config_path_item(&lxc_conf
->rootfs
.path
, value
);
2378 static int set_config_rootfs_mount(const char *key
, const char *value
,
2379 struct lxc_conf
*lxc_conf
)
2381 return set_config_path_item(&lxc_conf
->rootfs
.mount
, value
);
2384 static int set_config_rootfs_options(const char *key
, const char *value
,
2385 struct lxc_conf
*lxc_conf
)
2387 return set_config_string_item(&lxc_conf
->rootfs
.options
, value
);
2390 static int set_config_rootfs_backend(const char *key
, const char *value
,
2391 struct lxc_conf
*lxc_conf
)
2393 if (config_value_empty(value
)) {
2394 free(lxc_conf
->rootfs
.bdev_type
);
2395 lxc_conf
->rootfs
.bdev_type
= NULL
;
2399 if (!is_valid_bdev_type(value
)) {
2400 ERROR("Bad rootfs.backend: '%s'", value
);
2404 return set_config_string_item(&lxc_conf
->rootfs
.bdev_type
, value
);
2407 static int set_config_pivotdir(const char *key
, const char *value
,
2408 struct lxc_conf
*lxc_conf
)
2410 WARN("lxc.pivotdir is ignored. It will soon become an error.");
2414 static int set_config_utsname(const char *key
, const char *value
,
2415 struct lxc_conf
*lxc_conf
)
2417 struct utsname
*utsname
;
2419 if (config_value_empty(value
)) {
2420 clr_config_utsname(key
, lxc_conf
);
2424 utsname
= malloc(sizeof(*utsname
));
2426 SYSERROR("failed to allocate memory");
2430 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
2431 ERROR("node name '%s' is too long", value
);
2436 strcpy(utsname
->nodename
, value
);
2437 free(lxc_conf
->utsname
);
2438 lxc_conf
->utsname
= utsname
;
2443 struct parse_line_conf
{
2444 struct lxc_conf
*conf
;
2448 static int parse_line(char *buffer
, void *data
)
2450 struct lxc_config_t
*config
;
2451 char *dot
, *key
, *line
, *linep
, *value
;
2452 struct parse_line_conf
*plc
= data
;
2455 if (lxc_is_line_empty(buffer
))
2458 /* we have to dup the buffer otherwise, at the re-exec for
2459 * reboot we modified the original string on the stack by
2460 * replacing '=' by '\0' below
2462 linep
= line
= strdup(buffer
);
2464 SYSERROR("failed to allocate memory for '%s'", buffer
);
2468 if (!plc
->from_include
)
2469 if ((ret
= append_unexp_config_line(line
, plc
->conf
)))
2472 line
+= lxc_char_left_gc(line
, strlen(line
));
2474 /* ignore comments */
2478 /* martian option - don't add it to the config itself */
2479 if (strncmp(line
, "lxc.", 4))
2484 dot
= strstr(line
, "=");
2486 ERROR("invalid configuration line: %s", line
);
2494 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
2496 value
+= lxc_char_left_gc(value
, strlen(value
));
2497 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
2499 if (*value
== '\'' || *value
== '\"') {
2500 size_t len
= strlen(value
);
2501 if (len
> 1 && value
[len
- 1] == *value
) {
2502 value
[len
- 1] = '\0';
2507 config
= lxc_getconfig(key
);
2509 ERROR("unknown key %s", key
);
2513 ret
= config
->set(key
, value
, plc
->conf
);
2520 static int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
2522 struct parse_line_conf c
;
2525 c
.from_include
= false;
2527 return parse_line(buffer
, &c
);
2530 int lxc_config_read(const char *file
, struct lxc_conf
*conf
, bool from_include
)
2532 struct parse_line_conf c
;
2535 c
.from_include
= from_include
;
2537 if (access(file
, R_OK
) == -1) {
2541 /* Catch only the top level config file name in the structure */
2543 conf
->rcfile
= strdup(file
);
2545 return lxc_file_for_each_line(file
, parse_line
, &c
);
2548 int lxc_config_define_add(struct lxc_list
*defines
, char *arg
)
2550 struct lxc_list
*dent
;
2552 dent
= malloc(sizeof(struct lxc_list
));
2557 lxc_list_add_tail(defines
, dent
);
2561 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
2563 struct lxc_list
*it
, *next
;
2566 lxc_list_for_each(it
, defines
) {
2567 ret
= lxc_config_readline(it
->elem
, conf
);
2572 lxc_list_for_each_safe(it
, defines
, next
) {
2580 signed long lxc_config_parse_arch(const char *arch
)
2582 #if HAVE_SYS_PERSONALITY_H
2588 { "x86", PER_LINUX32
},
2589 { "linux32", PER_LINUX32
},
2590 { "i386", PER_LINUX32
},
2591 { "i486", PER_LINUX32
},
2592 { "i586", PER_LINUX32
},
2593 { "i686", PER_LINUX32
},
2594 { "athlon", PER_LINUX32
},
2595 { "mips", PER_LINUX32
},
2596 { "mipsel", PER_LINUX32
},
2597 { "ppc", PER_LINUX32
},
2598 { "arm", PER_LINUX32
},
2599 { "armv7l", PER_LINUX32
},
2600 { "armhf", PER_LINUX32
},
2601 { "armel", PER_LINUX32
},
2602 { "powerpc", PER_LINUX32
},
2603 { "linux64", PER_LINUX
},
2604 { "x86_64", PER_LINUX
},
2605 { "amd64", PER_LINUX
},
2606 { "mips64", PER_LINUX
},
2607 { "mips64el", PER_LINUX
},
2608 { "ppc64", PER_LINUX
},
2609 { "ppc64le", PER_LINUX
},
2610 { "ppc64el", PER_LINUX
},
2611 { "powerpc64", PER_LINUX
},
2612 { "s390x", PER_LINUX
},
2613 { "aarch64", PER_LINUX
},
2614 { "arm64", PER_LINUX
},
2616 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
2618 for (i
= 0; i
< len
; i
++) {
2619 if (!strcmp(pername
[i
].name
, arch
))
2620 return pername
[i
].per
;
2627 int lxc_fill_elevated_privileges(char *flaglist
, int *flags
)
2629 char *token
, *saveptr
= NULL
;
2635 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP
},
2636 { "CAP", LXC_ATTACH_DROP_CAPABILITIES
},
2637 { "LSM", LXC_ATTACH_LSM_EXEC
},
2642 /* For the sake of backward compatibility, drop all privileges
2643 * if none is specified.
2645 for (i
= 0; all_privs
[i
].token
; i
++) {
2646 *flags
|= all_privs
[i
].flag
;
2651 token
= strtok_r(flaglist
, "|", &saveptr
);
2654 for (i
= 0; all_privs
[i
].token
; i
++) {
2655 if (!strcmp(all_privs
[i
].token
, token
))
2656 aflag
= all_privs
[i
].flag
;
2663 token
= strtok_r(NULL
, "|", &saveptr
);
2669 static inline int lxc_get_conf_int(struct lxc_conf
*c
, char *retv
, int inlen
,
2675 memset(retv
, 0, inlen
);
2677 return snprintf(retv
, inlen
, "%d", v
);
2680 /* Write out a configuration file. */
2681 void write_config(FILE *fout
, struct lxc_conf
*c
)
2684 size_t len
= c
->unexpanded_len
;
2689 ret
= fwrite(c
->unexpanded_config
, 1, len
, fout
);
2691 SYSERROR("Error writing configuration file");
2694 bool do_append_unexp_config_line(struct lxc_conf
*conf
, const char *key
,
2701 len
= strlen(key
) + strlen(v
) + 4;
2704 if (config_value_empty(v
))
2705 ret
= snprintf(tmp
, len
, "%s =", key
);
2707 ret
= snprintf(tmp
, len
, "%s = %s", key
, v
);
2708 if (ret
< 0 || ret
>= len
)
2711 /* Save the line verbatim into unexpanded_conf */
2712 if (append_unexp_config_line(tmp
, conf
))
2718 void clear_unexp_config_line(struct lxc_conf
*conf
, const char *key
,
2722 char *lstart
= conf
->unexpanded_config
;
2724 if (!conf
->unexpanded_config
)
2728 lend
= strchr(lstart
, '\n');
2731 lend
= lstart
+ strlen(lstart
);
2734 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
2739 v
= lstart
[strlen(key
)];
2740 if (!isspace(v
) && v
!= '=') {
2745 conf
->unexpanded_len
-= (lend
- lstart
);
2746 if (*lend
== '\0') {
2750 memmove(lstart
, lend
, strlen(lend
) + 1);
2754 bool clone_update_unexp_ovl_paths(struct lxc_conf
*conf
, const char *oldpath
,
2755 const char *newpath
, const char *oldname
,
2756 const char *newname
, const char *ovldir
)
2759 char *lend
, *newdir
, *olddir
, *p
, *q
;
2760 size_t newdirlen
, olddirlen
;
2761 char *lstart
= conf
->unexpanded_config
;
2762 const char *key
= "lxc.mount.entry";
2764 olddirlen
= strlen(ovldir
) + strlen(oldpath
) + strlen(oldname
) + 2;
2765 olddir
= alloca(olddirlen
+ 1);
2766 ret
= snprintf(olddir
, olddirlen
+ 1, "%s=%s/%s", ovldir
, oldpath
,
2768 if (ret
< 0 || ret
>= olddirlen
+ 1) {
2769 ERROR("failed to create string");
2773 newdirlen
= strlen(ovldir
) + strlen(newpath
) + strlen(newname
) + 2;
2774 newdir
= alloca(newdirlen
+ 1);
2775 ret
= snprintf(newdir
, newdirlen
+ 1, "%s=%s/%s", ovldir
, newpath
,
2777 if (ret
< 0 || ret
>= newdirlen
+ 1) {
2778 ERROR("failed to create string");
2782 if (!conf
->unexpanded_config
)
2786 lend
= strchr(lstart
, '\n');
2788 lend
= lstart
+ strlen(lstart
);
2792 if (strncmp(lstart
, key
, strlen(key
)) != 0)
2795 p
= strchr(lstart
+ strlen(key
), '=');
2806 /* Whenever an lxc.mount.entry entry is found in a line we check
2807 * if the substring " overlay" or the substring " aufs" is
2808 * present before doing any further work. We check for "
2809 * overlay" and " aufs" since both substrings need to have at
2810 * least one space before them in a valid overlay
2811 * lxc.mount.entry (/A B overlay). When the space before is
2812 * missing it is very likely that these substrings are part of a
2813 * path or something else. (Checking q >= lend ensures that we
2814 * only count matches in the current line.) */
2815 if ((!(q
= strstr(p
, " overlay")) || q
>= lend
) &&
2816 (!(q
= strstr(p
, " aufs")) || q
>= lend
))
2819 if (!(q
= strstr(p
, olddir
)) || (q
>= lend
))
2822 /* replace the olddir with newdir */
2823 if (olddirlen
>= newdirlen
) {
2824 size_t diff
= olddirlen
- newdirlen
;
2825 memcpy(q
, newdir
, newdirlen
);
2826 if (olddirlen
!= newdirlen
) {
2827 memmove(q
+ newdirlen
, q
+ newdirlen
+ diff
,
2828 strlen(q
) - newdirlen
- diff
+ 1);
2830 conf
->unexpanded_len
-= diff
;
2834 size_t diff
= newdirlen
- olddirlen
;
2835 size_t oldlen
= conf
->unexpanded_len
;
2836 size_t newlen
= oldlen
+ diff
;
2837 size_t poffset
= q
- conf
->unexpanded_config
;
2839 new = realloc(conf
->unexpanded_config
, newlen
+ 1);
2841 ERROR("Out of memory");
2844 conf
->unexpanded_len
= newlen
;
2845 conf
->unexpanded_alloced
= newlen
+ 1;
2846 new[newlen
- 1] = '\0';
2847 lend
= new + (lend
- conf
->unexpanded_config
);
2848 /* move over the remainder to make room for the newdir
2850 memmove(new + poffset
+ newdirlen
,
2851 new + poffset
+ olddirlen
,
2852 oldlen
- poffset
- olddirlen
+ 1);
2853 conf
->unexpanded_config
= new;
2854 memcpy(new + poffset
, newdir
, newdirlen
);
2864 bool clone_update_unexp_hooks(struct lxc_conf
*conf
, const char *oldpath
,
2865 const char *newpath
, const char *oldname
,
2866 const char *newname
)
2869 char *lend
, *newdir
, *olddir
, *p
;
2870 char *lstart
= conf
->unexpanded_config
;
2871 size_t newdirlen
, olddirlen
;
2872 const char *key
= "lxc.hook";
2874 olddirlen
= strlen(oldpath
) + strlen(oldname
) + 1;
2875 olddir
= alloca(olddirlen
+ 1);
2876 ret
= snprintf(olddir
, olddirlen
+ 1, "%s/%s", oldpath
, oldname
);
2877 if (ret
< 0 || ret
>= olddirlen
+ 1) {
2878 ERROR("failed to create string");
2882 newdirlen
= strlen(newpath
) + strlen(newname
) + 1;
2883 newdir
= alloca(newdirlen
+ 1);
2884 ret
= snprintf(newdir
, newdirlen
+ 1, "%s/%s", newpath
, newname
);
2885 if (ret
< 0 || ret
>= newdirlen
+ 1) {
2886 ERROR("failed to create string");
2889 if (!conf
->unexpanded_config
)
2892 lend
= strchr(lstart
, '\n');
2894 lend
= lstart
+ strlen(lstart
);
2898 if (strncmp(lstart
, key
, strlen(key
)) != 0)
2901 p
= strchr(lstart
+ strlen(key
), '=');
2912 if (strncmp(p
, olddir
, strlen(olddir
)) != 0)
2915 /* replace the olddir with newdir */
2916 if (olddirlen
>= newdirlen
) {
2917 size_t diff
= olddirlen
- newdirlen
;
2918 memcpy(p
, newdir
, newdirlen
);
2919 if (olddirlen
!= newdirlen
) {
2920 memmove(p
+ newdirlen
, p
+ newdirlen
+ diff
,
2921 strlen(p
) - newdirlen
- diff
+ 1);
2923 conf
->unexpanded_len
-= diff
;
2927 size_t diff
= newdirlen
- olddirlen
;
2928 size_t oldlen
= conf
->unexpanded_len
;
2929 size_t newlen
= oldlen
+ diff
;
2930 size_t poffset
= p
- conf
->unexpanded_config
;
2932 new = realloc(conf
->unexpanded_config
, newlen
+ 1);
2934 ERROR("failed to allocate memory");
2937 conf
->unexpanded_len
= newlen
;
2938 conf
->unexpanded_alloced
= newlen
+ 1;
2939 new[newlen
- 1] = '\0';
2940 lend
= new + (lend
- conf
->unexpanded_config
);
2941 /* move over the remainder to make room for the newdir
2943 memmove(new + poffset
+ newdirlen
,
2944 new + poffset
+ olddirlen
,
2945 oldlen
- poffset
- olddirlen
+ 1);
2946 conf
->unexpanded_config
= new;
2947 memcpy(new + poffset
, newdir
, newdirlen
);
2960 ERROR("Error writing to new config"); \
2965 static bool new_hwaddr(char *hwaddr
)
2969 (void)randseed(true);
2971 ret
= snprintf(hwaddr
, 18, "00:16:3e:%02x:%02x:%02x", rand() % 255,
2972 rand() % 255, rand() % 255);
2973 if (ret
< 0 || ret
>= 18) {
2974 SYSERROR("Failed to call snprintf().");
2982 * This is called only from clone. We wish to update all hwaddrs in the
2983 * unexpanded config file. We can't/don't want to update any which come from
2984 * lxc.includes (there shouldn't be any).
2985 * We can't just walk the c->lxc-conf->network list because that includes netifs
2986 * from the include files. So we update the ones which we find in the unexp
2987 * config file, then find the original macaddr in the conf->network, and update
2988 * that to the same value.
2990 bool network_new_hwaddrs(struct lxc_conf
*conf
)
2992 char *lend
, *p
, *p2
;
2993 struct lxc_list
*it
;
2994 const char *key
= "lxc.network.hwaddr";
2995 char *lstart
= conf
->unexpanded_config
;
2997 if (!conf
->unexpanded_config
)
3001 char newhwaddr
[18], oldhwaddr
[17];
3003 lend
= strchr(lstart
, '\n');
3005 lend
= lstart
+ strlen(lstart
);
3009 if (strncmp(lstart
, key
, strlen(key
)) != 0) {
3014 p
= strchr(lstart
+ strlen(key
), '=');
3027 while (*p2
&& !isblank(*p2
) && *p2
!= '\n')
3030 if ((p2
- p
) != 17) {
3031 WARN("Bad hwaddr entry");
3036 memcpy(oldhwaddr
, p
, 17);
3038 if (!new_hwaddr(newhwaddr
))
3041 memcpy(p
, newhwaddr
, 17);
3042 lxc_list_for_each(it
, &conf
->network
)
3044 struct lxc_netdev
*n
= it
->elem
;
3045 if (n
->hwaddr
&& memcmp(oldhwaddr
, n
->hwaddr
, 17) == 0)
3046 memcpy(n
->hwaddr
, newhwaddr
, 17);
3055 static int set_config_ephemeral(const char *key
, const char *value
,
3056 struct lxc_conf
*lxc_conf
)
3058 /* Set config value to default. */
3059 if (config_value_empty(value
)) {
3060 lxc_conf
->ephemeral
= 0;
3064 /* Parse new config value. */
3065 if (lxc_safe_uint(value
, &lxc_conf
->ephemeral
) < 0)
3068 if (lxc_conf
->ephemeral
> 1) {
3070 "Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
3077 static int set_config_syslog(const char *key
, const char *value
,
3078 struct lxc_conf
*lxc_conf
)
3082 /* Clear any previously set value. */
3083 if (lxc_conf
->syslog
) {
3084 free(lxc_conf
->syslog
);
3085 lxc_conf
->syslog
= NULL
;
3088 /* Check if value is empty. */
3089 if (config_value_empty(value
))
3093 facility
= lxc_syslog_priority_to_int(value
);
3094 if (facility
== -EINVAL
) {
3095 ERROR("Wrong value for lxc.syslog.");
3099 lxc_log_syslog(facility
);
3100 return set_config_string_item(&lxc_conf
->syslog
, value
);
3103 static int set_config_no_new_privs(const char *key
, const char *value
,
3104 struct lxc_conf
*lxc_conf
)
3108 /* Set config value to default. */
3109 if (config_value_empty(value
)) {
3110 lxc_conf
->no_new_privs
= false;
3114 /* Parse new config value. */
3115 if (lxc_safe_uint(value
, &v
) < 0)
3119 ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 "
3124 lxc_conf
->no_new_privs
= v
? true : false;
3129 /* Callbacks to get configuration items. */
3130 static int get_config_personality(const char *key
, char *retv
, int inlen
,
3138 memset(retv
, 0, inlen
);
3140 #if HAVE_SYS_PERSONALITY_H
3143 switch (c
->personality
) {
3145 strprint(retv
, inlen
, "i686");
3148 strprint(retv
, inlen
, "x86_64");
3158 static int get_config_pts(const char *key
, char *retv
, int inlen
,
3161 return lxc_get_conf_int(c
, retv
, inlen
, c
->pts
);
3164 static int get_config_tty(const char *key
, char *retv
, int inlen
,
3167 return lxc_get_conf_int(c
, retv
, inlen
, c
->tty
);
3170 static inline int lxc_get_conf_str(char *retv
, int inlen
, const char *value
)
3174 if (retv
&& inlen
>= strlen(value
) + 1)
3175 strncpy(retv
, value
, strlen(value
) + 1);
3177 return strlen(value
);
3180 static int get_config_ttydir(const char *key
, char *retv
, int inlen
,
3183 return lxc_get_conf_str(retv
, inlen
, c
->ttydir
);
3186 static int get_config_kmsg(const char *key
, char *retv
, int inlen
,
3189 return lxc_get_conf_int(c
, retv
, inlen
, c
->kmsg
);
3192 static int get_config_lsm_aa_profile(const char *key
, char *retv
, int inlen
,
3195 return lxc_get_conf_str(retv
, inlen
, c
->lsm_aa_profile
);
3198 static int get_config_lsm_aa_incomplete(const char *key
, char *retv
, int inlen
,
3201 return lxc_get_conf_int(c
, retv
, inlen
,
3202 c
->lsm_aa_allow_incomplete
);
3205 static int get_config_lsm_se_context(const char *key
, char *retv
, int inlen
,
3208 return lxc_get_conf_str(retv
, inlen
, c
->lsm_se_context
);
3212 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
3213 * then just the value(s) will be printed. Since there still could be
3214 * more than one, it is newline-separated.
3215 * (Maybe that's ambigous, since some values, i.e. devices.list, will
3216 * already have newlines?)
3217 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
3218 * in 'lxc.cgroup.subsystem.key = value' format.
3220 static int get_config_cgroup(const char *key
, char *retv
, int inlen
,
3223 struct lxc_list
*it
;
3226 bool get_all
= false;
3231 memset(retv
, 0, inlen
);
3233 if (!strcmp(key
, "lxc.cgroup"))
3235 else if (!strncmp(key
, "lxc.cgroup.", 11))
3240 lxc_list_for_each(it
, &c
->cgroup
) {
3241 struct lxc_cgroup
*cg
= it
->elem
;
3243 strprint(retv
, inlen
, "lxc.cgroup.%s = %s\n", cg
->subsystem
, cg
->value
);
3244 } else if (!strcmp(cg
->subsystem
, key
)) {
3245 strprint(retv
, inlen
, "%s\n", cg
->value
);
3252 static int get_config_idmaps(const char *key
, char *retv
, int inlen
,
3255 struct lxc_list
*it
;
3256 int len
, listlen
, ret
;
3258 /* "u 1000 1000000 65536"
3260 * let's render this as
3278 #define __LXC_IDMAP_STR_BUF (3 * LXC_NUMSTRLEN64 + 3 + 1 + 1)
3279 char buf
[__LXC_IDMAP_STR_BUF
];
3284 memset(retv
, 0, inlen
);
3286 listlen
= lxc_list_len(&c
->id_map
);
3287 lxc_list_for_each(it
, &c
->id_map
)
3289 struct id_map
*map
= it
->elem
;
3290 ret
= snprintf(buf
, __LXC_IDMAP_STR_BUF
, "%c %lu %lu %lu",
3291 (map
->idtype
== ID_TYPE_UID
) ? 'u' : 'g',
3292 map
->nsid
, map
->hostid
, map
->range
);
3293 if (ret
< 0 || ret
>= __LXC_IDMAP_STR_BUF
)
3296 strprint(retv
, inlen
, "%s%s", buf
, (listlen
-- > 1) ? "\n" : "");
3301 static int get_config_loglevel(const char *key
, char *retv
, int inlen
,
3305 v
= lxc_log_priority_to_string(c
->loglevel
);
3306 return lxc_get_conf_str(retv
, inlen
, v
);
3309 static int get_config_logfile(const char *key
, char *retv
, int inlen
,
3312 return lxc_get_conf_str(retv
, inlen
, c
->logfile
);
3315 static int get_config_fstab(const char *key
, char *retv
, int inlen
,
3318 return lxc_get_conf_str(retv
, inlen
, c
->fstab
);
3321 static int get_config_mount_auto(const char *key
, char *retv
, int inlen
,
3324 int len
, fulllen
= 0;
3325 const char *sep
= "";
3330 memset(retv
, 0, inlen
);
3332 if (!(c
->auto_mounts
& LXC_AUTO_ALL_MASK
))
3335 switch (c
->auto_mounts
& LXC_AUTO_PROC_MASK
) {
3336 case LXC_AUTO_PROC_MIXED
:
3337 strprint(retv
, inlen
, "%sproc:mixed", sep
);
3340 case LXC_AUTO_PROC_RW
:
3341 strprint(retv
, inlen
, "%sproc:rw", sep
);
3348 switch (c
->auto_mounts
& LXC_AUTO_SYS_MASK
) {
3349 case LXC_AUTO_SYS_RO
:
3350 strprint(retv
, inlen
, "%ssys:ro", sep
);
3353 case LXC_AUTO_SYS_RW
:
3354 strprint(retv
, inlen
, "%ssys:rw", sep
);
3357 case LXC_AUTO_SYS_MIXED
:
3358 strprint(retv
, inlen
, "%ssys:mixed", sep
);
3365 switch (c
->auto_mounts
& LXC_AUTO_CGROUP_MASK
) {
3366 case LXC_AUTO_CGROUP_NOSPEC
:
3367 strprint(retv
, inlen
, "%scgroup", sep
);
3370 case LXC_AUTO_CGROUP_MIXED
:
3371 strprint(retv
, inlen
, "%scgroup:mixed", sep
);
3374 case LXC_AUTO_CGROUP_RO
:
3375 strprint(retv
, inlen
, "%scgroup:ro", sep
);
3378 case LXC_AUTO_CGROUP_RW
:
3379 strprint(retv
, inlen
, "%scgroup:rw", sep
);
3382 case LXC_AUTO_CGROUP_FULL_NOSPEC
:
3383 strprint(retv
, inlen
, "%scgroup-full", sep
);
3386 case LXC_AUTO_CGROUP_FULL_MIXED
:
3387 strprint(retv
, inlen
, "%scgroup-full:mixed", sep
);
3390 case LXC_AUTO_CGROUP_FULL_RO
:
3391 strprint(retv
, inlen
, "%scgroup-full:ro", sep
);
3394 case LXC_AUTO_CGROUP_FULL_RW
:
3395 strprint(retv
, inlen
, "%scgroup-full:rw", sep
);
3405 static int get_config_mount(const char *key
, char *retv
, int inlen
,
3408 int len
, fulllen
= 0;
3409 struct lxc_list
*it
;
3414 memset(retv
, 0, inlen
);
3416 lxc_list_for_each(it
, &c
->mount_list
)
3418 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3424 static int get_config_rootfs(const char *key
, char *retv
, int inlen
,
3427 return lxc_get_conf_str(retv
, inlen
, c
->rootfs
.path
);
3430 static int get_config_rootfs_mount(const char *key
, char *retv
, int inlen
,
3433 return lxc_get_conf_str(retv
, inlen
, c
->rootfs
.mount
);
3436 static int get_config_rootfs_options(const char *key
, char *retv
, int inlen
,
3439 return lxc_get_conf_str(retv
, inlen
, c
->rootfs
.options
);
3442 static int get_config_rootfs_backend(const char *key
, char *retv
, int inlen
,
3445 return lxc_get_conf_str(retv
, inlen
, c
->rootfs
.bdev_type
);
3448 static int get_config_pivotdir(const char *key
, char *retv
, int inlen
,
3454 static int get_config_utsname(const char *key
, char *retv
, int inlen
,
3457 return lxc_get_conf_str(
3459 c
->utsname
? c
->utsname
->nodename
: NULL
);
3462 static int get_config_hooks(const char *key
, char *retv
, int inlen
,
3466 int len
, fulllen
= 0, found
= -1;
3467 struct lxc_list
*it
;
3470 /* "lxc.hook.mount" */
3471 subkey
= strchr(key
, '.');
3473 subkey
= strchr(subkey
+ 1, '.');
3479 for (i
= 0; i
< NUM_LXC_HOOKS
; i
++) {
3480 if (strcmp(lxchook_names
[i
], subkey
) == 0) {
3491 memset(retv
, 0, inlen
);
3493 lxc_list_for_each(it
, &c
->hooks
[found
]) {
3494 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3499 static int get_config_network(const char *key
, char *retv
, int inlen
,
3502 int len
, fulllen
= 0;
3503 struct lxc_list
*it
;
3508 memset(retv
, 0, inlen
);
3510 lxc_list_for_each(it
, &c
->network
) {
3511 struct lxc_netdev
*n
= it
->elem
;
3512 const char *t
= lxc_net_type_to_str(n
->type
);
3513 strprint(retv
, inlen
, "%s\n", t
? t
: "(invalid)");
3520 * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
3521 * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
3522 * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
3523 * of an address. ipv4 and ipv6 return lists (newline-separated).
3524 * things like veth.pair return '' if invalid (i.e. if called for vlan
3527 static int get_config_network_item(const char *key
, char *retv
, int inlen
,
3531 int len
, fulllen
= 0;
3532 struct lxc_netdev
*netdev
;
3537 memset(retv
, 0, inlen
);
3539 if (!strncmp(key
, "lxc.network.", 12))
3544 p1
= strchr(key
, '.');
3545 if (!p1
|| *(p1
+ 1) == '\0')
3549 netdev
= get_netdev_from_key(key
, &c
->network
);
3552 if (strcmp(p1
, "name") == 0) {
3554 strprint(retv
, inlen
, "%s", netdev
->name
);
3555 } else if (strcmp(p1
, "type") == 0) {
3556 strprint(retv
, inlen
, "%s", lxc_net_type_to_str(netdev
->type
));
3557 } else if (strcmp(p1
, "link") == 0) {
3559 strprint(retv
, inlen
, "%s", netdev
->link
);
3560 } else if (strcmp(p1
, "flags") == 0) {
3561 if (netdev
->flags
& IFF_UP
)
3562 strprint(retv
, inlen
, "up");
3563 } else if (strcmp(p1
, "script.up") == 0) {
3564 if (netdev
->upscript
)
3565 strprint(retv
, inlen
, "%s", netdev
->upscript
);
3566 } else if (strcmp(p1
, "script.down") == 0) {
3567 if (netdev
->downscript
)
3568 strprint(retv
, inlen
, "%s", netdev
->downscript
);
3569 } else if (strcmp(p1
, "hwaddr") == 0) {
3571 strprint(retv
, inlen
, "%s", netdev
->hwaddr
);
3572 } else if (strcmp(p1
, "mtu") == 0) {
3574 strprint(retv
, inlen
, "%s", netdev
->mtu
);
3575 } else if (strcmp(p1
, "macvlan.mode") == 0) {
3576 if (netdev
->type
== LXC_NET_MACVLAN
) {
3578 switch (netdev
->priv
.macvlan_attr
.mode
) {
3579 case MACVLAN_MODE_PRIVATE
:
3582 case MACVLAN_MODE_VEPA
:
3585 case MACVLAN_MODE_BRIDGE
:
3588 case MACVLAN_MODE_PASSTHRU
:
3595 strprint(retv
, inlen
, "%s", mode
);
3597 } else if (strcmp(p1
, "veth.pair") == 0) {
3598 if (netdev
->type
== LXC_NET_VETH
) {
3599 strprint(retv
, inlen
, "%s",
3600 netdev
->priv
.veth_attr
.pair
3601 ? netdev
->priv
.veth_attr
.pair
3602 : netdev
->priv
.veth_attr
.veth1
);
3604 } else if (strcmp(p1
, "vlan") == 0) {
3605 if (netdev
->type
== LXC_NET_VLAN
) {
3606 strprint(retv
, inlen
, "%d", netdev
->priv
.vlan_attr
.vid
);
3608 } else if (strcmp(p1
, "ipv4.gateway") == 0) {
3609 if (netdev
->ipv4_gateway_auto
) {
3610 strprint(retv
, inlen
, "auto");
3611 } else if (netdev
->ipv4_gateway
) {
3612 char buf
[INET_ADDRSTRLEN
];
3613 inet_ntop(AF_INET
, netdev
->ipv4_gateway
, buf
,
3615 strprint(retv
, inlen
, "%s", buf
);
3617 } else if (strcmp(p1
, "ipv4") == 0) {
3618 struct lxc_list
*it2
;
3619 lxc_list_for_each(it2
, &netdev
->ipv4
) {
3620 struct lxc_inetdev
*i
= it2
->elem
;
3621 char buf
[INET_ADDRSTRLEN
];
3622 inet_ntop(AF_INET
, &i
->addr
, buf
, sizeof(buf
));
3623 strprint(retv
, inlen
, "%s/%d\n", buf
, i
->prefix
);
3625 } else if (strcmp(p1
, "ipv6.gateway") == 0) {
3626 if (netdev
->ipv6_gateway_auto
) {
3627 strprint(retv
, inlen
, "auto");
3628 } else if (netdev
->ipv6_gateway
) {
3629 char buf
[INET6_ADDRSTRLEN
];
3630 inet_ntop(AF_INET6
, netdev
->ipv6_gateway
, buf
,
3632 strprint(retv
, inlen
, "%s", buf
);
3634 } else if (strcmp(p1
, "ipv6") == 0) {
3635 struct lxc_list
*it2
;
3636 lxc_list_for_each(it2
, &netdev
->ipv6
) {
3637 struct lxc_inet6dev
*i
= it2
->elem
;
3638 char buf
[INET6_ADDRSTRLEN
];
3639 inet_ntop(AF_INET6
, &i
->addr
, buf
, sizeof(buf
));
3640 strprint(retv
, inlen
, "%s/%d\n", buf
, i
->prefix
);
3646 static int get_config_cap_drop(const char *key
, char *retv
, int inlen
,
3649 int len
, fulllen
= 0;
3650 struct lxc_list
*it
;
3655 memset(retv
, 0, inlen
);
3657 lxc_list_for_each(it
, &c
->caps
) {
3658 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3663 static int get_config_cap_keep(const char *key
, char *retv
, int inlen
,
3666 int len
, fulllen
= 0;
3667 struct lxc_list
*it
;
3672 memset(retv
, 0, inlen
);
3674 lxc_list_for_each(it
, &c
->keepcaps
) {
3675 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3680 static int get_config_console(const char *key
, char *retv
, int inlen
,
3683 return lxc_get_conf_str(retv
, inlen
, c
->console
.path
);
3686 static int get_config_console_logfile(const char *key
, char *retv
, int inlen
,
3689 return lxc_get_conf_str(retv
, inlen
, c
->console
.log_path
);
3692 static int get_config_seccomp(const char *key
, char *retv
, int inlen
,
3695 return lxc_get_conf_str(retv
, inlen
, c
->seccomp
);
3698 static int get_config_autodev(const char *key
, char *retv
, int inlen
,
3701 return lxc_get_conf_int(c
, retv
, inlen
, c
->autodev
);
3704 static int get_config_haltsignal(const char *key
, char *retv
, int inlen
,
3707 return lxc_get_conf_int(c
, retv
, inlen
, c
->haltsignal
);
3710 static int get_config_rebootsignal(const char *key
, char *retv
, int inlen
,
3713 return lxc_get_conf_int(c
, retv
, inlen
, c
->rebootsignal
);
3716 static int get_config_stopsignal(const char *key
, char *retv
, int inlen
,
3719 return lxc_get_conf_int(c
, retv
, inlen
, c
->stopsignal
);
3722 static int get_config_start(const char *key
, char *retv
, int inlen
,
3725 if (strcmp(key
+ 10, "auto") == 0)
3726 return lxc_get_conf_int(c
, retv
, inlen
, c
->start_auto
);
3727 else if (strcmp(key
+ 10, "delay") == 0)
3728 return lxc_get_conf_int(c
, retv
, inlen
, c
->start_delay
);
3729 else if (strcmp(key
+ 10, "order") == 0)
3730 return lxc_get_conf_int(c
, retv
, inlen
, c
->start_order
);
3735 static int get_config_syslog(const char *key
, char *retv
, int inlen
,
3738 return lxc_get_conf_str(retv
, inlen
, c
->syslog
);
3741 static int get_config_monitor(const char *key
, char *retv
, int inlen
,
3744 return lxc_get_conf_int(c
, retv
, inlen
, c
->monitor_unshare
);
3747 static int get_config_group(const char *key
, char *retv
, int inlen
,
3750 int len
, fulllen
= 0;
3751 struct lxc_list
*it
;
3756 memset(retv
, 0, inlen
);
3758 lxc_list_for_each(it
, &c
->groups
) {
3759 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3764 static int get_config_environment(const char *key
, char *retv
, int inlen
,
3767 int len
, fulllen
= 0;
3768 struct lxc_list
*it
;
3773 memset(retv
, 0, inlen
);
3775 lxc_list_for_each(it
, &c
->environment
) {
3776 strprint(retv
, inlen
, "%s\n", (char *)it
->elem
);
3781 static int get_config_init_cmd(const char *key
, char *retv
, int inlen
,
3784 return lxc_get_conf_str(retv
, inlen
, c
->init_cmd
);
3787 static int get_config_init_uid(const char *key
, char *retv
, int inlen
,
3790 return lxc_get_conf_int(c
, retv
, inlen
, c
->init_uid
);
3793 static int get_config_init_gid(const char *key
, char *retv
, int inlen
,
3796 return lxc_get_conf_int(c
, retv
, inlen
, c
->init_gid
);
3799 static int get_config_ephemeral(const char *key
, char *retv
, int inlen
,
3802 return lxc_get_conf_int(c
, retv
, inlen
, c
->ephemeral
);
3805 static int get_config_no_new_privs(const char *key
, char *retv
, int inlen
,
3808 return lxc_get_conf_int(c
, retv
, inlen
, c
->no_new_privs
);
3812 * If you ask for a specific value, i.e. lxc.limit.nofile, then just the value
3813 * will be printed. If you ask for 'lxc.limit', then all limit entries will be
3814 * printed, in 'lxc.limit.resource = value' format.
3816 static int get_config_limit(const char *key
, char *retv
, int inlen
,
3819 int fulllen
= 0, len
;
3820 bool get_all
= false;
3821 struct lxc_list
*it
;
3826 memset(retv
, 0, inlen
);
3828 if (!strcmp(key
, "lxc.limit"))
3830 else if (strncmp(key
, "lxc.limit.", 10) == 0)
3835 lxc_list_for_each(it
, &c
->limits
) {
3836 char buf
[LXC_NUMSTRLEN64
* 2 + 2]; /* 2 colon separated 64 bit
3837 integers or the word
3840 struct lxc_limit
*lim
= it
->elem
;
3842 if (lim
->limit
.rlim_cur
== RLIM_INFINITY
) {
3843 memcpy(buf
, "unlimited", sizeof("unlimited"));
3844 partlen
= sizeof("unlimited") - 1;
3846 partlen
= sprintf(buf
, "%" PRIu64
,
3847 (uint64_t)lim
->limit
.rlim_cur
);
3849 if (lim
->limit
.rlim_cur
!= lim
->limit
.rlim_max
) {
3850 if (lim
->limit
.rlim_max
== RLIM_INFINITY
) {
3851 memcpy(buf
+ partlen
, ":unlimited",
3852 sizeof(":unlimited"));
3854 sprintf(buf
+ partlen
, ":%" PRIu64
,
3855 (uint64_t)lim
->limit
.rlim_max
);
3860 strprint(retv
, inlen
, "lxc.limit.%s = %s\n",
3861 lim
->resource
, buf
);
3862 } else if (strcmp(lim
->resource
, key
) == 0) {
3863 strprint(retv
, inlen
, "%s", buf
);
3870 /* Callbacks to clear config items. */
3871 static inline int clr_config_personality(const char *key
, struct lxc_conf
*c
)
3873 c
->personality
= -1;
3877 static inline int clr_config_pts(const char *key
, struct lxc_conf
*c
)
3883 static inline int clr_config_tty(const char *key
, struct lxc_conf
*c
)
3889 static inline int clr_config_ttydir(const char *key
, struct lxc_conf
*c
)
3896 static inline int clr_config_kmsg(const char *key
, struct lxc_conf
*c
)
3902 static inline int clr_config_lsm_aa_profile(const char *key
, struct lxc_conf
*c
)
3904 free(c
->lsm_aa_profile
);
3905 c
->lsm_aa_profile
= NULL
;
3909 static inline int clr_config_lsm_aa_incomplete(const char *key
,
3912 c
->lsm_aa_allow_incomplete
= 0;
3916 static inline int clr_config_lsm_se_context(const char *key
, struct lxc_conf
*c
)
3918 free(c
->lsm_se_context
);
3919 c
->lsm_se_context
= NULL
;
3923 static inline int clr_config_cgroup(const char *key
, struct lxc_conf
*c
)
3925 return lxc_clear_cgroups(c
, key
);
3928 static inline int clr_config_idmaps(const char *key
, struct lxc_conf
*c
)
3930 return lxc_clear_idmaps(c
);
3933 static inline int clr_config_loglevel(const char *key
, struct lxc_conf
*c
)
3935 c
->loglevel
= LXC_LOG_PRIORITY_NOTSET
;
3939 static inline int clr_config_logfile(const char *key
, struct lxc_conf
*c
)
3946 static inline int clr_config_mount(const char *key
, struct lxc_conf
*c
)
3948 return lxc_clear_mount_entries(c
);
3951 static inline int clr_config_mount_auto(const char *key
, struct lxc_conf
*c
)
3953 return lxc_clear_automounts(c
);
3956 static inline int clr_config_fstab(const char *key
, struct lxc_conf
*c
)
3963 static inline int clr_config_rootfs(const char *key
, struct lxc_conf
*c
)
3965 free(c
->rootfs
.path
);
3966 c
->rootfs
.path
= NULL
;
3970 static inline int clr_config_rootfs_mount(const char *key
, struct lxc_conf
*c
)
3972 free(c
->rootfs
.mount
);
3973 c
->rootfs
.mount
= NULL
;
3977 static inline int clr_config_rootfs_options(const char *key
, struct lxc_conf
*c
)
3979 free(c
->rootfs
.options
);
3980 c
->rootfs
.options
= NULL
;
3984 static inline int clr_config_rootfs_backend(const char *key
, struct lxc_conf
*c
)
3986 free(c
->rootfs
.bdev_type
);
3987 c
->rootfs
.bdev_type
= NULL
;
3991 static inline int clr_config_pivotdir(const char *key
, struct lxc_conf
*c
)
3996 static inline int clr_config_utsname(const char *key
, struct lxc_conf
*c
)
4003 static inline int clr_config_hooks(const char *key
, struct lxc_conf
*c
)
4005 return lxc_clear_hooks(c
, key
);
4008 static inline int clr_config_network_item(const char *key
, struct lxc_conf
*c
)
4010 return lxc_clear_nic(c
, key
+ 12);
4013 static inline int clr_config_network(const char *key
, struct lxc_conf
*c
)
4015 return lxc_clear_config_network(c
);
4018 static inline int clr_config_cap_drop(const char *key
, struct lxc_conf
*c
)
4020 return lxc_clear_config_caps(c
);
4023 static inline int clr_config_cap_keep(const char *key
, struct lxc_conf
*c
)
4025 return lxc_clear_config_keepcaps(c
);
4028 static inline int clr_config_console(const char *key
, struct lxc_conf
*c
)
4030 free(c
->console
.path
);
4031 c
->console
.path
= NULL
;
4035 static inline int clr_config_console_logfile(const char *key
,
4038 free(c
->console
.log_path
);
4039 c
->console
.log_path
= NULL
;
4043 static inline int clr_config_seccomp(const char *key
, struct lxc_conf
*c
)
4050 static inline int clr_config_autodev(const char *key
, struct lxc_conf
*c
)
4056 static inline int clr_config_haltsignal(const char *key
, struct lxc_conf
*c
)
4062 static inline int clr_config_rebootsignal(const char *key
, struct lxc_conf
*c
)
4064 c
->rebootsignal
= 0;
4068 static inline int clr_config_stopsignal(const char *key
, struct lxc_conf
*c
)
4074 static inline int clr_config_start(const char *key
, struct lxc_conf
*c
)
4076 if (strcmp(key
+ 10, "auto") == 0)
4078 else if (strcmp(key
+ 10, "delay") == 0)
4080 else if (strcmp(key
+ 10, "order") == 0)
4086 static inline int clr_config_syslog(const char *key
, struct lxc_conf
*c
)
4093 static inline int clr_config_monitor(const char *key
, struct lxc_conf
*c
)
4095 c
->monitor_unshare
= 0;
4099 static inline int clr_config_group(const char *key
, struct lxc_conf
*c
)
4101 return lxc_clear_groups(c
);
4104 static inline int clr_config_environment(const char *key
, struct lxc_conf
*c
)
4106 return lxc_clear_environment(c
);
4109 static inline int clr_config_init_cmd(const char *key
, struct lxc_conf
*c
)
4116 static inline int clr_config_init_uid(const char *key
, struct lxc_conf
*c
)
4122 static inline int clr_config_init_gid(const char *key
, struct lxc_conf
*c
)
4128 static inline int clr_config_ephemeral(const char *key
, struct lxc_conf
*c
)
4134 static inline int clr_config_no_new_privs(const char *key
, struct lxc_conf
*c
)
4136 c
->no_new_privs
= false;
4140 static inline int clr_config_limit(const char *key
, struct lxc_conf
*c
)
4142 return lxc_clear_limits(c
, key
);
4145 static inline int clr_config_includefiles(const char *key
, struct lxc_conf
*c
)
4147 lxc_clear_includes(c
);
4151 static int get_config_includefiles(const char *key
, char *retv
, int inlen
,