]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
Merge pull request #1611 from brauner/2017-06-02/enforce_config_item_method_implement...
[mirror_lxc.git] / src / lxc / confile.c
1 /*
2 * lxc: linux Container library
3 * (C) Copyright IBM Corp. 2007, 2008
4 *
5 * Authors:
6 * Daniel Lezcano <daniel.lezcano at free.fr>
7 *
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.
12 *
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.
17 *
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
21 */
22 #define _GNU_SOURCE
23 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <inttypes.h> /* Required for PRIu64 to work. */
32 #include <signal.h>
33 #include <sys/stat.h>
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>
39 #include <net/if.h>
40 #include <time.h>
41 #include <dirent.h>
42 #include <syslog.h>
43
44 #include "bdev.h"
45 #include "parse.h"
46 #include "config.h"
47 #include "confile.h"
48 #include "confile_utils.h"
49 #include "utils.h"
50 #include "log.h"
51 #include "conf.h"
52 #include "network.h"
53 #include "lxcseccomp.h"
54
55 #if HAVE_IFADDRS_H
56 #include <ifaddrs.h>
57 #else
58 #include <../include/ifaddrs.h>
59 #endif
60
61 #if HAVE_SYS_PERSONALITY_H
62 #include <sys/personality.h>
63 #endif
64
65 lxc_log_define(lxc_confile, lxc);
66
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 *);
70
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 *);
74
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 *);
78
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 *);
82
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 *);
86
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 *);
90
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 *);
94
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 *);
98
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 *);
102
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 *);
106
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 *);
110
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 *);
114
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 *);
118
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 *);
122
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 *);
126
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 *);
130
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 *);
134
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 *);
138
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 *);
142
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 *);
146
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 *);
150
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 *);
154
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 *);
173
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 *);
177
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 *);
181
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 *);
185
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 *);
189
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 *);
193
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 *);
197
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 *);
201
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 *);
205
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 *);
209
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 *);
213
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 *);
217
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 *);
221
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 *);
225
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 *);
229
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 *);
233
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 *);
237
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 *);
241
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 *);
245
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 *);
249
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 *);
253
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 *);
257
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 *);
261
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, },
334 };
335
336 struct signame {
337 int num;
338 const char *name;
339 };
340
341 static const struct signame signames[] = {
342 { SIGHUP, "HUP" },
343 { SIGINT, "INT" },
344 { SIGQUIT, "QUIT" },
345 { SIGILL, "ILL" },
346 { SIGABRT, "ABRT" },
347 { SIGFPE, "FPE" },
348 { SIGKILL, "KILL" },
349 { SIGSEGV, "SEGV" },
350 { SIGPIPE, "PIPE" },
351 { SIGALRM, "ALRM" },
352 { SIGTERM, "TERM" },
353 { SIGUSR1, "USR1" },
354 { SIGUSR2, "USR2" },
355 { SIGCHLD, "CHLD" },
356 { SIGCONT, "CONT" },
357 { SIGSTOP, "STOP" },
358 { SIGTSTP, "TSTP" },
359 { SIGTTIN, "TTIN" },
360 { SIGTTOU, "TTOU" },
361 #ifdef SIGTRAP
362 { SIGTRAP, "TRAP" },
363 #endif
364 #ifdef SIGIOT
365 { SIGIOT, "IOT" },
366 #endif
367 #ifdef SIGEMT
368 { SIGEMT, "EMT" },
369 #endif
370 #ifdef SIGBUS
371 { SIGBUS, "BUS" },
372 #endif
373 #ifdef SIGSTKFLT
374 { SIGSTKFLT, "STKFLT" },
375 #endif
376 #ifdef SIGCLD
377 { SIGCLD, "CLD" },
378 #endif
379 #ifdef SIGURG
380 { SIGURG, "URG" },
381 #endif
382 #ifdef SIGXCPU
383 { SIGXCPU, "XCPU" },
384 #endif
385 #ifdef SIGXFSZ
386 { SIGXFSZ, "XFSZ" },
387 #endif
388 #ifdef SIGVTALRM
389 { SIGVTALRM, "VTALRM" },
390 #endif
391 #ifdef SIGPROF
392 { SIGPROF, "PROF" },
393 #endif
394 #ifdef SIGWINCH
395 { SIGWINCH, "WINCH" },
396 #endif
397 #ifdef SIGIO
398 { SIGIO, "IO" },
399 #endif
400 #ifdef SIGPOLL
401 { SIGPOLL, "POLL" },
402 #endif
403 #ifdef SIGINFO
404 { SIGINFO, "INFO" },
405 #endif
406 #ifdef SIGLOST
407 { SIGLOST, "LOST" },
408 #endif
409 #ifdef SIGPWR
410 { SIGPWR, "PWR" },
411 #endif
412 #ifdef SIGUNUSED
413 { SIGUNUSED, "UNUSED" },
414 #endif
415 #ifdef SIGSYS
416 { SIGSYS, "SYS" },
417 #endif
418 };
419
420 static const size_t config_size = sizeof(config) / sizeof(struct lxc_config_t);
421
422 extern struct lxc_config_t *lxc_getconfig(const char *key)
423 {
424 size_t i;
425
426 for (i = 0; i < config_size; i++)
427 if (!strncmp(config[i].name, key, strlen(config[i].name)))
428 return &config[i];
429 return NULL;
430 }
431
432 #define strprint(str, inlen, ...) \
433 do { \
434 len = snprintf(str, inlen, ##__VA_ARGS__); \
435 if (len < 0) { \
436 SYSERROR("failed to create string"); \
437 return -1; \
438 }; \
439 fulllen += len; \
440 if (inlen > 0) { \
441 if (str) \
442 str += len; \
443 inlen -= len; \
444 if (inlen < 0) \
445 inlen = 0; \
446 } \
447 } while (0);
448
449 int lxc_listconfigs(char *retv, int inlen)
450 {
451 size_t i;
452 int len;
453 int fulllen = 0;
454
455 if (!retv)
456 inlen = 0;
457 else
458 memset(retv, 0, inlen);
459
460 for (i = 0; i < config_size; i++) {
461 char *s = config[i].name;
462 if (s[strlen(s) - 1] == '.')
463 continue;
464 strprint(retv, inlen, "%s\n", s);
465 }
466
467 return fulllen;
468 }
469
470 static inline bool config_value_empty(const char *value)
471 {
472 if (value && strlen(value) > 0)
473 return false;
474
475 return true;
476 }
477
478 static int set_config_string_item(char **conf_item, const char *value)
479 {
480 char *new_value;
481
482 if (config_value_empty(value)) {
483 free(*conf_item);
484 *conf_item = NULL;
485 return 0;
486 }
487
488 new_value = strdup(value);
489 if (!new_value) {
490 SYSERROR("failed to duplicate string \"%s\"", value);
491 return -1;
492 }
493
494 free(*conf_item);
495 *conf_item = new_value;
496 return 0;
497 }
498
499 static int set_config_string_item_max(char **conf_item, const char *value,
500 size_t max)
501 {
502 if (strlen(value) >= max) {
503 ERROR("%s is too long (>= %lu)", value, (unsigned long)max);
504 return -1;
505 }
506
507 return set_config_string_item(conf_item, value);
508 }
509
510 static int set_config_path_item(char **conf_item, const char *value)
511 {
512 return set_config_string_item_max(conf_item, value, PATH_MAX);
513 }
514
515 /*
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.
519 */
520 static int set_config_network_nic(const char *key, const char *value,
521 struct lxc_conf *lxc_conf)
522 {
523 char *copy = strdup(key), *p;
524 int ret = -1;
525 struct lxc_config_t *config;
526
527 if (!copy) {
528 SYSERROR("failed to allocate memory");
529 return -1;
530 }
531 /*
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.
536 */
537 if (*(key + 12) < '0' || *(key + 12) > '9')
538 goto out;
539
540 p = strchr(key + 12, '.');
541 if (!p)
542 goto out;
543
544 strcpy(copy + 12, p + 1);
545 config = lxc_getconfig(copy);
546 if (!config) {
547 ERROR("unknown key %s", key);
548 goto out;
549 }
550 ret = config->set(key, value, lxc_conf);
551
552 out:
553 free(copy);
554 return ret;
555 }
556
557 static int set_config_network(const char *key, const char *value,
558 struct lxc_conf *lxc_conf)
559 {
560 if (!config_value_empty(value)) {
561 ERROR("lxc.network must not have a value");
562 return -1;
563 }
564
565 return lxc_clear_config_network(lxc_conf);
566 }
567
568 static int macvlan_mode(int *valuep, const char *value);
569
570 static int set_config_network_type(const char *key, const char *value,
571 struct lxc_conf *lxc_conf)
572 {
573 struct lxc_list *network = &lxc_conf->network;
574 struct lxc_netdev *netdev;
575 struct lxc_list *list;
576
577 if (config_value_empty(value))
578 return lxc_clear_config_network(lxc_conf);
579
580 netdev = malloc(sizeof(*netdev));
581 if (!netdev) {
582 SYSERROR("failed to allocate memory");
583 return -1;
584 }
585
586 memset(netdev, 0, sizeof(*netdev));
587 lxc_list_init(&netdev->ipv4);
588 lxc_list_init(&netdev->ipv6);
589
590 list = malloc(sizeof(*list));
591 if (!list) {
592 SYSERROR("failed to allocate memory");
593 free(netdev);
594 return -1;
595 }
596
597 lxc_list_init(list);
598 list->elem = netdev;
599
600 lxc_list_add_tail(network, list);
601
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;
615 else {
616 ERROR("invalid network type %s", value);
617 return -1;
618 }
619 return 0;
620 }
621
622 static int config_ip_prefix(struct in_addr *addr)
623 {
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;
630
631 return 0;
632 }
633
634 /*
635 * If you have p="lxc.network.0.link", pass it p+12
636 * to get back '0' (the index of the nic).
637 */
638 static int get_network_netdev_idx(const char *key)
639 {
640 int ret, idx;
641
642 if (*key < '0' || *key > '9')
643 return -1;
644
645 ret = sscanf(key, "%d", &idx);
646 if (ret != 1)
647 return -1;
648
649 return idx;
650 }
651
652 /*
653 * If you have p="lxc.network.0", pass this p+12 and it will return
654 * the netdev of the first configured nic.
655 */
656 static struct lxc_netdev *get_netdev_from_key(const char *key,
657 struct lxc_list *network)
658 {
659 int idx;
660 struct lxc_list *it;
661 int i = 0;
662 struct lxc_netdev *netdev = NULL;
663
664 idx = get_network_netdev_idx(key);
665 if (idx == -1)
666 return NULL;
667
668 lxc_list_for_each(it, network) {
669 if (idx == i++) {
670 netdev = it->elem;
671 break;
672 }
673 }
674
675 return netdev;
676 }
677
678 extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv,
679 int inlen)
680 {
681 struct lxc_netdev *netdev;
682 int len;
683 int fulllen = 0;
684
685 netdev = get_netdev_from_key(key + 12, &c->network);
686 if (!netdev)
687 return -1;
688
689 if (!retv)
690 inlen = 0;
691 else
692 memset(retv, 0, inlen);
693
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");
707 }
708
709 switch (netdev->type) {
710 case LXC_NET_VETH:
711 strprint(retv, inlen, "veth.pair\n");
712 break;
713 case LXC_NET_MACVLAN:
714 strprint(retv, inlen, "macvlan.mode\n");
715 break;
716 case LXC_NET_VLAN:
717 strprint(retv, inlen, "vlan.id\n");
718 break;
719 case LXC_NET_PHYS:
720 break;
721 }
722
723 return fulllen;
724 }
725
726 static struct lxc_netdev *network_netdev(const char *key, const char *value,
727 struct lxc_list *network)
728 {
729 struct lxc_netdev *netdev = NULL;
730
731 if (lxc_list_empty(network)) {
732 ERROR("network is not created for '%s' = '%s' option", key,
733 value);
734 return NULL;
735 }
736
737 if (get_network_netdev_idx(key + 12) == -1)
738 netdev = lxc_list_last_elem(network);
739 else
740 netdev = get_netdev_from_key(key + 12, network);
741
742 if (!netdev) {
743 ERROR("no network device defined for '%s' = '%s' option", key,
744 value);
745 return NULL;
746 }
747
748 return netdev;
749 }
750
751 static int network_ifname(char **valuep, const char *value)
752 {
753 return set_config_string_item_max(valuep, value, IFNAMSIZ);
754 }
755
756 #ifndef MACVLAN_MODE_PRIVATE
757 #define MACVLAN_MODE_PRIVATE 1
758 #endif
759
760 #ifndef MACVLAN_MODE_VEPA
761 #define MACVLAN_MODE_VEPA 2
762 #endif
763
764 #ifndef MACVLAN_MODE_BRIDGE
765 #define MACVLAN_MODE_BRIDGE 4
766 #endif
767
768 #ifndef MACVLAN_MODE_PASSTHRU
769 #define MACVLAN_MODE_PASSTHRU 8
770 #endif
771
772 static int macvlan_mode(int *valuep, const char *value)
773 {
774 struct mc_mode {
775 char *name;
776 int mode;
777 } m[] = {
778 { "private", MACVLAN_MODE_PRIVATE },
779 { "vepa", MACVLAN_MODE_VEPA },
780 { "bridge", MACVLAN_MODE_BRIDGE },
781 { "passthru", MACVLAN_MODE_PASSTHRU },
782 };
783
784 size_t i;
785
786 for (i = 0; i < sizeof(m) / sizeof(m[0]); i++) {
787 if (strcmp(m[i].name, value))
788 continue;
789
790 *valuep = m[i].mode;
791 return 0;
792 }
793
794 return -1;
795 }
796
797 static int rand_complete_hwaddr(char *hwaddr)
798 {
799 const char hex[] = "0123456789abcdef";
800 char *curs = hwaddr;
801
802 #ifndef HAVE_RAND_R
803 randseed(true);
804 #else
805 unsigned int seed;
806
807 seed = randseed(false);
808 #endif
809 while (*curs != '\0' && *curs != '\n') {
810 if (*curs == 'x' || *curs == 'X') {
811 if (curs - hwaddr == 1) {
812 /* ensure address is unicast */
813 #ifdef HAVE_RAND_R
814 *curs = hex[rand_r(&seed) & 0x0E];
815 } else {
816 *curs = hex[rand_r(&seed) & 0x0F];
817 #else
818 *curs = hex[rand() & 0x0E];
819 } else {
820 *curs = hex[rand() & 0x0F];
821 #endif
822 }
823 }
824 curs++;
825 }
826 return 0;
827 }
828
829 static int set_config_network_flags(const char *key, const char *value,
830 struct lxc_conf *lxc_conf)
831 {
832 struct lxc_netdev *netdev;
833
834 netdev = network_netdev(key, value, &lxc_conf->network);
835 if (!netdev)
836 return -1;
837
838 netdev->flags |= IFF_UP;
839
840 return 0;
841 }
842
843 static int set_network_link(const char *key, const char *value,
844 struct lxc_conf *lxc_conf)
845 {
846 struct lxc_netdev *netdev;
847
848 netdev = network_netdev(key, value, &lxc_conf->network);
849 if (!netdev)
850 return -1;
851
852 return network_ifname(&netdev->link, value);
853 }
854
855 static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf)
856 {
857 struct ifaddrs *ifaddr, *ifa;
858 int n;
859 int ret = 0;
860 const char *type_key = "lxc.network.type";
861 const char *link_key = "lxc.network.link";
862 const char *tmpvalue = "phys";
863
864 if (getifaddrs(&ifaddr) == -1) {
865 SYSERROR("Get network interfaces failed");
866 return -1;
867 }
868
869 for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
870 if (!ifa->ifa_addr)
871 continue;
872 if (ifa->ifa_addr->sa_family != AF_PACKET)
873 continue;
874
875 if (!strncmp(value, ifa->ifa_name, strlen(value) - 1)) {
876 ret = set_config_network_type(type_key, tmpvalue,
877 lxc_conf);
878 if (!ret) {
879 ret = set_network_link(link_key, ifa->ifa_name,
880 lxc_conf);
881 if (ret) {
882 ERROR("failed to create matched ifnames");
883 break;
884 }
885 } else {
886 ERROR("failed to create matched ifnames");
887 break;
888 }
889 }
890 }
891
892 freeifaddrs(ifaddr);
893 ifaddr = NULL;
894
895 return ret;
896 }
897
898 static int set_config_network_link(const char *key, const char *value,
899 struct lxc_conf *lxc_conf)
900 {
901 struct lxc_netdev *netdev;
902 struct lxc_list *it;
903 int ret = 0;
904
905 netdev = network_netdev(key, value, &lxc_conf->network);
906 if (!netdev)
907 return -1;
908
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");
915 return -1;
916 }
917
918 lxc_list_del(it);
919 free(it);
920 ret = create_matched_ifnames(value, lxc_conf);
921 } else {
922 ret = network_ifname(&netdev->link, value);
923 }
924
925 return ret;
926 }
927
928 static int set_config_network_name(const char *key, const char *value,
929 struct lxc_conf *lxc_conf)
930 {
931 struct lxc_netdev *netdev;
932
933 netdev = network_netdev(key, value, &lxc_conf->network);
934 if (!netdev)
935 return -1;
936
937 return network_ifname(&netdev->name, value);
938 }
939
940 static int set_config_network_veth_pair(const char *key, const char *value,
941 struct lxc_conf *lxc_conf)
942 {
943 struct lxc_netdev *netdev;
944
945 netdev = network_netdev(key, value, &lxc_conf->network);
946 if (!netdev)
947 return -1;
948
949 if (netdev->type != LXC_NET_VETH) {
950 ERROR("Invalid veth pair for a non-veth netdev");
951 return -1;
952 }
953
954 return network_ifname(&netdev->priv.veth_attr.pair, value);
955 }
956
957 static int set_config_network_macvlan_mode(const char *key, const char *value,
958 struct lxc_conf *lxc_conf)
959 {
960 struct lxc_netdev *netdev;
961
962 netdev = network_netdev(key, value, &lxc_conf->network);
963 if (!netdev)
964 return -1;
965
966 if (netdev->type != LXC_NET_MACVLAN) {
967 ERROR("Invalid macvlan.mode for a non-macvlan netdev");
968 return -1;
969 }
970
971 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
972 }
973
974 static int set_config_network_hwaddr(const char *key, const char *value,
975 struct lxc_conf *lxc_conf)
976 {
977 struct lxc_netdev *netdev;
978 char *new_value;
979
980 new_value = strdup(value);
981 if (!new_value) {
982 SYSERROR("failed to strdup \"%s\"", value);
983 return -1;
984 }
985 rand_complete_hwaddr(new_value);
986
987 netdev = network_netdev(key, new_value, &lxc_conf->network);
988 if (!netdev) {
989 free(new_value);
990 return -1;
991 };
992
993 if (config_value_empty(new_value)) {
994 free(new_value);
995 netdev->hwaddr = NULL;
996 return 0;
997 }
998
999 netdev->hwaddr = new_value;
1000 return 0;
1001 }
1002
1003 static int set_config_network_vlan_id(const char *key, const char *value,
1004 struct lxc_conf *lxc_conf)
1005 {
1006 struct lxc_netdev *netdev;
1007
1008 netdev = network_netdev(key, value, &lxc_conf->network);
1009 if (!netdev)
1010 return -1;
1011
1012 if (netdev->type != LXC_NET_VLAN) {
1013 ERROR("Invalid vlan.id for a non-macvlan netdev");
1014 return -1;
1015 }
1016
1017 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
1018 return -1;
1019
1020 return 0;
1021 }
1022
1023 static int set_config_network_mtu(const char *key, const char *value,
1024 struct lxc_conf *lxc_conf)
1025 {
1026 struct lxc_netdev *netdev;
1027
1028 netdev = network_netdev(key, value, &lxc_conf->network);
1029 if (!netdev)
1030 return -1;
1031
1032 return set_config_string_item(&netdev->mtu, value);
1033 }
1034
1035 static int set_config_network_ipv4(const char *key, const char *value,
1036 struct lxc_conf *lxc_conf)
1037 {
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;
1043
1044 if (config_value_empty(value))
1045 return clr_config_network_item(key, lxc_conf);
1046
1047 netdev = network_netdev(key, value, &lxc_conf->network);
1048 if (!netdev)
1049 return -1;
1050
1051 inetdev = malloc(sizeof(*inetdev));
1052 if (!inetdev) {
1053 SYSERROR("failed to allocate ipv4 address");
1054 return -1;
1055 }
1056 memset(inetdev, 0, sizeof(*inetdev));
1057
1058 list = malloc(sizeof(*list));
1059 if (!list) {
1060 SYSERROR("failed to allocate memory");
1061 free(inetdev);
1062 return -1;
1063 }
1064
1065 lxc_list_init(list);
1066 list->elem = inetdev;
1067
1068 addr = strdup(value);
1069 if (!addr) {
1070 ERROR("no address specified");
1071 free(inetdev);
1072 free(list);
1073 return -1;
1074 }
1075
1076 cursor = strstr(addr, " ");
1077 if (cursor) {
1078 *cursor = '\0';
1079 bcast = cursor + 1;
1080 }
1081
1082 slash = strstr(addr, "/");
1083 if (slash) {
1084 *slash = '\0';
1085 prefix = slash + 1;
1086 }
1087
1088 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
1089 SYSERROR("invalid ipv4 address: %s", value);
1090 free(inetdev);
1091 free(addr);
1092 free(list);
1093 return -1;
1094 }
1095
1096 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
1097 SYSERROR("invalid ipv4 broadcast address: %s", value);
1098 free(inetdev);
1099 free(list);
1100 free(addr);
1101 return -1;
1102 }
1103
1104 /* No prefix specified, determine it from the network class. */
1105 if (prefix) {
1106 if (lxc_safe_uint(prefix, &inetdev->prefix) < 0)
1107 return -1;
1108 } else {
1109 inetdev->prefix = config_ip_prefix(&inetdev->addr);
1110 }
1111
1112 /* If no broadcast address, let compute one from the
1113 * prefix and address.
1114 */
1115 if (!bcast) {
1116 inetdev->bcast.s_addr = inetdev->addr.s_addr;
1117 inetdev->bcast.s_addr |=
1118 htonl(INADDR_BROADCAST >> inetdev->prefix);
1119 }
1120
1121 lxc_list_add_tail(&netdev->ipv4, list);
1122
1123 free(addr);
1124 return 0;
1125 }
1126
1127 static int set_config_network_ipv4_gateway(const char *key, const char *value,
1128 struct lxc_conf *lxc_conf)
1129 {
1130 struct lxc_netdev *netdev;
1131
1132 netdev = network_netdev(key, value, &lxc_conf->network);
1133 if (!netdev)
1134 return -1;
1135
1136 free(netdev->ipv4_gateway);
1137
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;
1143 } else {
1144 struct in_addr *gw;
1145
1146 gw = malloc(sizeof(*gw));
1147 if (!gw) {
1148 SYSERROR("failed to allocate ipv4 gateway address");
1149 return -1;
1150 }
1151
1152 if (!inet_pton(AF_INET, value, gw)) {
1153 SYSERROR("invalid ipv4 gateway address: %s", value);
1154 free(gw);
1155 return -1;
1156 }
1157
1158 netdev->ipv4_gateway = gw;
1159 netdev->ipv4_gateway_auto = false;
1160 }
1161
1162 return 0;
1163 }
1164
1165 static int set_config_network_ipv6(const char *key, const char *value,
1166 struct lxc_conf *lxc_conf)
1167 {
1168 struct lxc_netdev *netdev;
1169 struct lxc_inet6dev *inet6dev;
1170 struct lxc_list *list;
1171 char *slash, *valdup, *netmask;
1172
1173 if (config_value_empty(value))
1174 return clr_config_network_item(key, lxc_conf);
1175
1176 netdev = network_netdev(key, value, &lxc_conf->network);
1177 if (!netdev)
1178 return -1;
1179
1180 inet6dev = malloc(sizeof(*inet6dev));
1181 if (!inet6dev) {
1182 SYSERROR("failed to allocate ipv6 address");
1183 return -1;
1184 }
1185 memset(inet6dev, 0, sizeof(*inet6dev));
1186
1187 list = malloc(sizeof(*list));
1188 if (!list) {
1189 SYSERROR("failed to allocate memory");
1190 free(inet6dev);
1191 return -1;
1192 }
1193
1194 lxc_list_init(list);
1195 list->elem = inet6dev;
1196
1197 valdup = strdup(value);
1198 if (!valdup) {
1199 ERROR("no address specified");
1200 free(list);
1201 free(inet6dev);
1202 return -1;
1203 }
1204
1205 inet6dev->prefix = 64;
1206 slash = strstr(valdup, "/");
1207 if (slash) {
1208 *slash = '\0';
1209 netmask = slash + 1;
1210 if (lxc_safe_uint(netmask, &inet6dev->prefix) < 0)
1211 return -1;
1212 }
1213
1214 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
1215 SYSERROR("invalid ipv6 address: %s", valdup);
1216 free(list);
1217 free(inet6dev);
1218 free(valdup);
1219 return -1;
1220 }
1221
1222 lxc_list_add_tail(&netdev->ipv6, list);
1223
1224 free(valdup);
1225 return 0;
1226 }
1227
1228 static int set_config_network_ipv6_gateway(const char *key, const char *value,
1229 struct lxc_conf *lxc_conf)
1230 {
1231 struct lxc_netdev *netdev;
1232
1233 netdev = network_netdev(key, value, &lxc_conf->network);
1234 if (!netdev)
1235 return -1;
1236
1237 free(netdev->ipv6_gateway);
1238
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;
1244 } else {
1245 struct in6_addr *gw;
1246
1247 gw = malloc(sizeof(*gw));
1248 if (!gw) {
1249 SYSERROR("failed to allocate ipv6 gateway address");
1250 return -1;
1251 }
1252
1253 if (!inet_pton(AF_INET6, value, gw)) {
1254 SYSERROR("invalid ipv6 gateway address: %s", value);
1255 free(gw);
1256 return -1;
1257 }
1258
1259 netdev->ipv6_gateway = gw;
1260 netdev->ipv6_gateway_auto = false;
1261 }
1262
1263 return 0;
1264 }
1265
1266 static int set_config_network_script_up(const char *key, const char *value,
1267 struct lxc_conf *lxc_conf)
1268 {
1269 struct lxc_netdev *netdev;
1270
1271 netdev = network_netdev(key, value, &lxc_conf->network);
1272 if (!netdev)
1273 return -1;
1274
1275 return set_config_string_item(&netdev->upscript, value);
1276 }
1277
1278 static int set_config_network_script_down(const char *key, const char *value,
1279 struct lxc_conf *lxc_conf)
1280 {
1281 struct lxc_netdev *netdev;
1282
1283 netdev = network_netdev(key, value, &lxc_conf->network);
1284 if (!netdev)
1285 return -1;
1286
1287 return set_config_string_item(&netdev->downscript, value);
1288 }
1289
1290 static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
1291 {
1292 struct lxc_list *hooklist;
1293
1294 hooklist = malloc(sizeof(*hooklist));
1295 if (!hooklist) {
1296 free(hook);
1297 return -1;
1298 }
1299
1300 hooklist->elem = hook;
1301 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
1302 return 0;
1303 }
1304
1305 static int set_config_seccomp(const char *key, const char *value,
1306 struct lxc_conf *lxc_conf)
1307 {
1308 return set_config_path_item(&lxc_conf->seccomp, value);
1309 }
1310
1311 static int set_config_init_cmd(const char *key, const char *value,
1312 struct lxc_conf *lxc_conf)
1313 {
1314 return set_config_path_item(&lxc_conf->init_cmd, value);
1315 }
1316
1317 static int set_config_init_uid(const char *key, const char *value,
1318 struct lxc_conf *lxc_conf)
1319 {
1320 unsigned int init_uid;
1321
1322 /* Set config value to default. */
1323 if (config_value_empty(value)) {
1324 lxc_conf->init_uid = 0;
1325 return 0;
1326 }
1327
1328 /* Parse new config value. */
1329 if (lxc_safe_uint(value, &init_uid) < 0)
1330 return -1;
1331 lxc_conf->init_uid = init_uid;
1332
1333 return 0;
1334 }
1335
1336 static int set_config_init_gid(const char *key, const char *value,
1337 struct lxc_conf *lxc_conf)
1338 {
1339 unsigned int init_gid;
1340
1341 /* Set config value to default. */
1342 if (config_value_empty(value)) {
1343 lxc_conf->init_gid = 0;
1344 return 0;
1345 }
1346
1347 /* Parse new config value. */
1348 if (lxc_safe_uint(value, &init_gid) < 0)
1349 return -1;
1350 lxc_conf->init_gid = init_gid;
1351
1352 return 0;
1353 }
1354
1355 static int set_config_hooks(const char *key, const char *value,
1356 struct lxc_conf *lxc_conf)
1357 {
1358 char *copy;
1359
1360 if (config_value_empty(value))
1361 return lxc_clear_hooks(lxc_conf, key);
1362
1363 if (strcmp(key + 4, "hook") == 0) {
1364 ERROR("lxc.hook cannot take a value");
1365 return -1;
1366 }
1367 copy = strdup(value);
1368 if (!copy) {
1369 SYSERROR("failed to dup string '%s'", value);
1370 return -1;
1371 }
1372
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);
1391
1392 SYSERROR("Unknown key: %s", key);
1393 free(copy);
1394 return -1;
1395 }
1396
1397 static int set_config_personality(const char *key, const char *value,
1398 struct lxc_conf *lxc_conf)
1399 {
1400 signed long personality = lxc_config_parse_arch(value);
1401
1402 if (personality >= 0)
1403 lxc_conf->personality = personality;
1404 else
1405 WARN("unsupported personality '%s'", value);
1406
1407 return 0;
1408 }
1409
1410 static int set_config_pts(const char *key, const char *value,
1411 struct lxc_conf *lxc_conf)
1412 {
1413 /* Set config value to default. */
1414 if (config_value_empty(value)) {
1415 lxc_conf->pts = 0;
1416 return 0;
1417 }
1418
1419 /* Parse new config value. */
1420 if (lxc_safe_uint(value, &lxc_conf->pts) < 0)
1421 return -1;
1422
1423 return 0;
1424 }
1425
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.
1430 */
1431 static int set_config_start(const char *key, const char *value,
1432 struct lxc_conf *lxc_conf)
1433 {
1434 bool is_empty;
1435
1436 is_empty = config_value_empty(value);
1437
1438 if (*(key + 10) == 'a') { /* lxc.start.auto */
1439 /* Set config value to default. */
1440 if (is_empty) {
1441 lxc_conf->start_auto = 0;
1442 return 0;
1443 }
1444
1445 /* Parse new config value. */
1446 if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0)
1447 return -1;
1448
1449 if (lxc_conf->start_auto > 1)
1450 return -1;
1451
1452 return 0;
1453 } else if (*(key + 10) == 'd') { /* lxc.start.delay */
1454 /* Set config value to default. */
1455 if (is_empty) {
1456 lxc_conf->start_delay = 0;
1457 return 0;
1458 }
1459
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. */
1464 if (is_empty) {
1465 lxc_conf->start_order = 0;
1466 return 0;
1467 }
1468
1469 /* Parse new config value. */
1470 return lxc_safe_int(value, &lxc_conf->start_order);
1471 }
1472
1473 SYSERROR("Unknown key: %s", key);
1474 return -1;
1475 }
1476
1477 static int set_config_monitor(const char *key, const char *value,
1478 struct lxc_conf *lxc_conf)
1479 {
1480 /* Set config value to default. */
1481 if (config_value_empty(value)) {
1482 lxc_conf->monitor_unshare = 0;
1483 return 0;
1484 }
1485
1486 /* Parse new config value. */
1487 if (strcmp(key + 12, "unshare") == 0)
1488 return lxc_safe_uint(value, &lxc_conf->monitor_unshare);
1489
1490 SYSERROR("Unknown key: %s", key);
1491 return -1;
1492 }
1493
1494 static int set_config_group(const char *key, const char *value,
1495 struct lxc_conf *lxc_conf)
1496 {
1497 char *groups, *groupptr, *sptr, *token;
1498 struct lxc_list *grouplist;
1499 int ret = -1;
1500
1501 if (config_value_empty(value))
1502 return lxc_clear_groups(lxc_conf);
1503
1504 groups = strdup(value);
1505 if (!groups) {
1506 SYSERROR("failed to dup '%s'", value);
1507 return -1;
1508 }
1509
1510 /* In case several groups are specified in a single line
1511 * split these groups in a single element for the list.
1512 */
1513 for (groupptr = groups;; groupptr = NULL) {
1514 token = strtok_r(groupptr, " \t", &sptr);
1515 if (!token) {
1516 ret = 0;
1517 break;
1518 }
1519
1520 grouplist = malloc(sizeof(*grouplist));
1521 if (!grouplist) {
1522 SYSERROR("failed to allocate groups list");
1523 break;
1524 }
1525
1526 grouplist->elem = strdup(token);
1527 if (!grouplist->elem) {
1528 SYSERROR("failed to dup '%s'", token);
1529 free(grouplist);
1530 break;
1531 }
1532
1533 lxc_list_add_tail(&lxc_conf->groups, grouplist);
1534 }
1535
1536 free(groups);
1537 return ret;
1538 }
1539
1540 static int set_config_environment(const char *key, const char *value,
1541 struct lxc_conf *lxc_conf)
1542 {
1543 struct lxc_list *list_item = NULL;
1544
1545 if (config_value_empty(value))
1546 return lxc_clear_environment(lxc_conf);
1547
1548 list_item = malloc(sizeof(*list_item));
1549 if (!list_item)
1550 goto on_error;
1551
1552 list_item->elem = strdup(value);
1553
1554 if (!list_item->elem)
1555 goto on_error;
1556
1557 lxc_list_add_tail(&lxc_conf->environment, list_item);
1558
1559 return 0;
1560
1561 on_error:
1562 free(list_item);
1563 return -1;
1564 }
1565
1566 static int set_config_tty(const char *key, const char *value,
1567 struct lxc_conf *lxc_conf)
1568 {
1569 /* Set config value to default. */
1570 if (config_value_empty(value)) {
1571 lxc_conf->tty = 0;
1572 return 0;
1573 }
1574
1575 /* Parse new config value. */
1576 return lxc_safe_uint(value, &lxc_conf->tty);
1577 }
1578
1579 static int set_config_ttydir(const char *key, const char *value,
1580 struct lxc_conf *lxc_conf)
1581 {
1582 return set_config_string_item_max(&lxc_conf->ttydir, value,
1583 NAME_MAX + 1);
1584 }
1585
1586 static int set_config_kmsg(const char *key, const char *value,
1587 struct lxc_conf *lxc_conf)
1588 {
1589 /* Set config value to default. */
1590 if (config_value_empty(value)) {
1591 lxc_conf->kmsg = 0;
1592 return 0;
1593 }
1594
1595 /* Parse new config value. */
1596 if (lxc_safe_uint(value, &lxc_conf->kmsg) < 0)
1597 return -1;
1598
1599 if (lxc_conf->kmsg > 1)
1600 return -1;
1601
1602 return 0;
1603 }
1604
1605 static int set_config_lsm_aa_profile(const char *key, const char *value,
1606 struct lxc_conf *lxc_conf)
1607 {
1608 return set_config_string_item(&lxc_conf->lsm_aa_profile, value);
1609 }
1610
1611 static int set_config_lsm_aa_incomplete(const char *key, const char *value,
1612 struct lxc_conf *lxc_conf)
1613 {
1614 /* Set config value to default. */
1615 if (config_value_empty(value)) {
1616 lxc_conf->lsm_aa_allow_incomplete = 0;
1617 return 0;
1618 }
1619
1620 /* Parse new config value. */
1621 if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0)
1622 return -1;
1623
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");
1627 return -1;
1628 }
1629
1630 return 0;
1631 }
1632
1633 static int set_config_lsm_se_context(const char *key, const char *value,
1634 struct lxc_conf *lxc_conf)
1635 {
1636 return set_config_string_item(&lxc_conf->lsm_se_context, value);
1637 }
1638
1639 static int set_config_logfile(const char *key, const char *value,
1640 struct lxc_conf *c)
1641 {
1642 int ret;
1643
1644 if (config_value_empty(value)) {
1645 free(c->logfile);
1646 c->logfile = NULL;
1647 return 0;
1648 }
1649
1650 /* Store these values in the lxc_conf, and then try to set for actual
1651 * current logging.
1652 */
1653 ret = set_config_path_item(&c->logfile, value);
1654 if (ret == 0)
1655 ret = lxc_log_set_file(&c->logfd, c->logfile);
1656 return ret;
1657 }
1658
1659 static int set_config_loglevel(const char *key, const char *value,
1660 struct lxc_conf *lxc_conf)
1661 {
1662 int newlevel;
1663
1664 /* Set config value to default. */
1665 if (config_value_empty(value)) {
1666 lxc_conf->loglevel = LXC_LOG_PRIORITY_NOTSET;
1667 return 0;
1668 }
1669
1670 /* Parse new config value. */
1671 if (value[0] >= '0' && value[0] <= '9') {
1672 if (lxc_safe_int(value, &newlevel) < 0)
1673 return -1;
1674 } else {
1675 newlevel = lxc_log_priority_to_int(value);
1676 }
1677
1678 /* Store these values in the lxc_conf, and then try to set for actual
1679 * current logging.
1680 */
1681 lxc_conf->loglevel = newlevel;
1682 return lxc_log_set_level(&lxc_conf->loglevel, newlevel);
1683 }
1684
1685 static int set_config_autodev(const char *key, const char *value,
1686 struct lxc_conf *lxc_conf)
1687 {
1688 /* Set config value to default. */
1689 if (config_value_empty(value)) {
1690 lxc_conf->autodev = 0;
1691 return 0;
1692 }
1693
1694 /* Parse new config value. */
1695 if (lxc_safe_uint(value, &lxc_conf->autodev) < 0)
1696 return -1;
1697
1698 if (lxc_conf->autodev > 1) {
1699 ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1");
1700 return -1;
1701 }
1702
1703 return 0;
1704 }
1705
1706 static int sig_num(const char *sig)
1707 {
1708 unsigned int signum;
1709
1710 if (lxc_safe_uint(sig, &signum) < 0)
1711 return -1;
1712
1713 return signum;
1714 }
1715
1716 static int rt_sig_num(const char *signame)
1717 {
1718 int rtmax = 0, sig_n = 0;
1719
1720 if (strncasecmp(signame, "max-", 4) == 0) {
1721 rtmax = 1;
1722 }
1723
1724 signame += 4;
1725 if (!isdigit(*signame))
1726 return -1;
1727
1728 sig_n = sig_num(signame);
1729 sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
1730 if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
1731 return -1;
1732
1733 return sig_n;
1734 }
1735
1736 static int sig_parse(const char *signame)
1737 {
1738 size_t n;
1739
1740 if (isdigit(*signame)) {
1741 return sig_num(signame);
1742 } else if (strncasecmp(signame, "sig", 3) == 0) {
1743 signame += 3;
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;
1749 }
1750 }
1751
1752 return -1;
1753 }
1754
1755 static int set_config_haltsignal(const char *key, const char *value,
1756 struct lxc_conf *lxc_conf)
1757 {
1758 int sig_n;
1759
1760 /* Set config value to default. */
1761 if (config_value_empty(value)) {
1762 lxc_conf->haltsignal = 0;
1763 return 0;
1764 }
1765
1766 /* Parse new config value. */
1767 sig_n = sig_parse(value);
1768
1769 if (sig_n < 0)
1770 return -1;
1771 lxc_conf->haltsignal = sig_n;
1772
1773 return 0;
1774 }
1775
1776 static int set_config_rebootsignal(const char *key, const char *value,
1777 struct lxc_conf *lxc_conf)
1778 {
1779 int sig_n;
1780
1781 /* Set config value to default. */
1782 if (config_value_empty(value)) {
1783 lxc_conf->rebootsignal = 0;
1784 return 0;
1785 }
1786
1787 /* Parse new config value. */
1788 sig_n = sig_parse(value);
1789 if (sig_n < 0)
1790 return -1;
1791 lxc_conf->rebootsignal = sig_n;
1792
1793 return 0;
1794 }
1795
1796 static int set_config_stopsignal(const char *key, const char *value,
1797 struct lxc_conf *lxc_conf)
1798 {
1799 int sig_n;
1800
1801 /* Set config value to default. */
1802 if (config_value_empty(value)) {
1803 lxc_conf->stopsignal = 0;
1804 return 0;
1805 }
1806
1807 /* Parse new config value. */
1808 sig_n = sig_parse(value);
1809 if (sig_n < 0)
1810 return -1;
1811 lxc_conf->stopsignal = sig_n;
1812
1813 return 0;
1814 }
1815
1816 static int set_config_cgroup(const char *key, const char *value,
1817 struct lxc_conf *lxc_conf)
1818 {
1819 char *subkey;
1820 char *token = "lxc.cgroup.";
1821 struct lxc_list *cglist = NULL;
1822 struct lxc_cgroup *cgelem = NULL;
1823
1824 if (config_value_empty(value))
1825 return lxc_clear_cgroups(lxc_conf, key);
1826
1827 subkey = strstr(key, token);
1828 if (!subkey)
1829 return -1;
1830
1831 if (!strlen(subkey))
1832 return -1;
1833
1834 if (strlen(subkey) == strlen(token))
1835 return -1;
1836
1837 subkey += strlen(token);
1838
1839 cglist = malloc(sizeof(*cglist));
1840 if (!cglist)
1841 goto out;
1842
1843 cgelem = malloc(sizeof(*cgelem));
1844 if (!cgelem)
1845 goto out;
1846 memset(cgelem, 0, sizeof(*cgelem));
1847
1848 cgelem->subsystem = strdup(subkey);
1849 cgelem->value = strdup(value);
1850
1851 if (!cgelem->subsystem || !cgelem->value)
1852 goto out;
1853
1854 cglist->elem = cgelem;
1855
1856 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
1857
1858 return 0;
1859
1860 out:
1861 free(cglist);
1862
1863 if (cgelem) {
1864 free(cgelem->subsystem);
1865
1866 free(cgelem->value);
1867
1868 free(cgelem);
1869 }
1870
1871 return -1;
1872 }
1873
1874 static bool parse_limit_value(const char **value, unsigned long *res)
1875 {
1876 char *endptr = NULL;
1877
1878 if (strncmp(*value, "unlimited", sizeof("unlimited") - 1) == 0) {
1879 *res = RLIM_INFINITY;
1880 *value += sizeof("unlimited") - 1;
1881 return true;
1882 }
1883
1884 errno = 0;
1885 *res = strtoul(*value, &endptr, 10);
1886 if (errno || !endptr)
1887 return false;
1888 *value = endptr;
1889
1890 return true;
1891 }
1892
1893 static int set_config_limit(const char *key, const char *value,
1894 struct lxc_conf *lxc_conf)
1895 {
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;
1901
1902 if (config_value_empty(value))
1903 return lxc_clear_limits(lxc_conf, key);
1904
1905 if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.") - 1) != 0)
1906 return -1;
1907
1908 key += sizeof("lxc.limit.") - 1;
1909
1910 /* soft limit comes first in the value */
1911 if (!parse_limit_value(&value, &limit_value))
1912 return -1;
1913 limit.rlim_cur = limit_value;
1914
1915 /* skip spaces and a colon */
1916 while (isspace(*value))
1917 ++value;
1918
1919 if (*value == ':')
1920 ++value;
1921 else if (*value) /* any other character is an error here */
1922 return -1;
1923
1924 while (isspace(*value))
1925 ++value;
1926
1927 /* optional hard limit */
1928 if (*value) {
1929 if (!parse_limit_value(&value, &limit_value))
1930 return -1;
1931 limit.rlim_max = limit_value;
1932
1933 /* check for trailing garbage */
1934 while (isspace(*value))
1935 ++value;
1936
1937 if (*value)
1938 return -1;
1939 } else {
1940 /* a single value sets both hard and soft limit */
1941 limit.rlim_max = limit.rlim_cur;
1942 }
1943
1944 /* find existing list element */
1945 lxc_list_for_each(iter, &lxc_conf->limits)
1946 {
1947 limelem = iter->elem;
1948 if (!strcmp(key, limelem->resource)) {
1949 limelem->limit = limit;
1950 return 0;
1951 }
1952 }
1953
1954 /* allocate list element */
1955 limlist = malloc(sizeof(*limlist));
1956 if (!limlist)
1957 goto out;
1958
1959 limelem = malloc(sizeof(*limelem));
1960 if (!limelem)
1961 goto out;
1962 memset(limelem, 0, sizeof(*limelem));
1963
1964 limelem->resource = strdup(key);
1965 if (!limelem->resource)
1966 goto out;
1967 limelem->limit = limit;
1968
1969 limlist->elem = limelem;
1970
1971 lxc_list_add_tail(&lxc_conf->limits, limlist);
1972
1973 return 0;
1974
1975 out:
1976 free(limlist);
1977 if (limelem) {
1978 free(limelem->resource);
1979 free(limelem);
1980 }
1981 return -1;
1982 }
1983
1984 static int set_config_idmaps(const char *key, const char *value,
1985 struct lxc_conf *lxc_conf)
1986 {
1987 unsigned long hostid, nsid, range;
1988 char type;
1989 int ret;
1990 struct lxc_list *idmaplist = NULL;
1991 struct id_map *idmap = NULL;
1992
1993 if (config_value_empty(value))
1994 return lxc_clear_idmaps(lxc_conf);
1995
1996 idmaplist = malloc(sizeof(*idmaplist));
1997 if (!idmaplist)
1998 goto on_error;
1999
2000 idmap = malloc(sizeof(*idmap));
2001 if (!idmap)
2002 goto on_error;
2003 memset(idmap, 0, sizeof(*idmap));
2004
2005 ret = parse_idmaps(value, &type, &nsid, &hostid, &range);
2006 if (ret < 0)
2007 goto on_error;
2008
2009 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
2010 if (type == 'u')
2011 idmap->idtype = ID_TYPE_UID;
2012 else if (type == 'g')
2013 idmap->idtype = ID_TYPE_GID;
2014 else
2015 goto on_error;
2016
2017 idmap->hostid = hostid;
2018 idmap->nsid = nsid;
2019 idmap->range = range;
2020 idmaplist->elem = idmap;
2021 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
2022 idmap = NULL;
2023
2024 return 0;
2025
2026 on_error:
2027 free(idmaplist);
2028 free(idmap);
2029
2030 return -1;
2031 }
2032
2033 static int set_config_fstab(const char *key, const char *value,
2034 struct lxc_conf *lxc_conf)
2035 {
2036 if (config_value_empty(value)) {
2037 clr_config_fstab(key, lxc_conf);
2038 return -1;
2039 }
2040
2041 return set_config_path_item(&lxc_conf->fstab, value);
2042 }
2043
2044 static int set_config_mount_auto(const char *key, const char *value,
2045 struct lxc_conf *lxc_conf)
2046 {
2047 char *autos, *autoptr, *sptr, *token;
2048 int i;
2049 int ret = -1;
2050 static struct {
2051 const char *token;
2052 int mask;
2053 int flag;
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
2073 */
2074 { NULL, 0, 0 }
2075 };
2076
2077 if (config_value_empty(value)) {
2078 lxc_conf->auto_mounts = 0;
2079 return 0;
2080 }
2081
2082 autos = strdup(value);
2083 if (!autos) {
2084 SYSERROR("failed to dup '%s'", value);
2085 return -1;
2086 }
2087
2088 for (autoptr = autos;; autoptr = NULL) {
2089 token = strtok_r(autoptr, " \t", &sptr);
2090 if (!token) {
2091 ret = 0;
2092 break;
2093 }
2094
2095 for (i = 0; allowed_auto_mounts[i].token; i++) {
2096 if (!strcmp(allowed_auto_mounts[i].token, token))
2097 break;
2098 }
2099
2100 if (!allowed_auto_mounts[i].token) {
2101 ERROR("Invalid filesystem to automount: %s", token);
2102 break;
2103 }
2104
2105 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
2106 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
2107 }
2108
2109 free(autos);
2110 return ret;
2111 }
2112
2113 static int set_config_mount(const char *key, const char *value,
2114 struct lxc_conf *lxc_conf)
2115 {
2116 char *mntelem;
2117 struct lxc_list *mntlist;
2118
2119 if (config_value_empty(value))
2120 return lxc_clear_mount_entries(lxc_conf);
2121
2122 mntlist = malloc(sizeof(*mntlist));
2123 if (!mntlist)
2124 return -1;
2125
2126 mntelem = strdup(value);
2127 if (!mntelem) {
2128 free(mntlist);
2129 return -1;
2130 }
2131 mntlist->elem = mntelem;
2132
2133 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
2134
2135 return 0;
2136 }
2137
2138 static int set_config_cap_keep(const char *key, const char *value,
2139 struct lxc_conf *lxc_conf)
2140 {
2141 char *keepcaps, *keepptr, *sptr, *token;
2142 struct lxc_list *keeplist;
2143 int ret = -1;
2144
2145 if (config_value_empty(value))
2146 return lxc_clear_config_keepcaps(lxc_conf);
2147
2148 keepcaps = strdup(value);
2149 if (!keepcaps) {
2150 SYSERROR("failed to dup '%s'", value);
2151 return -1;
2152 }
2153
2154 /* In case several capability keep is specified in a single line
2155 * split these caps in a single element for the list.
2156 */
2157 for (keepptr = keepcaps;; keepptr = NULL) {
2158 token = strtok_r(keepptr, " \t", &sptr);
2159 if (!token) {
2160 ret = 0;
2161 break;
2162 }
2163
2164 if (!strcmp(token, "none"))
2165 lxc_clear_config_keepcaps(lxc_conf);
2166
2167 keeplist = malloc(sizeof(*keeplist));
2168 if (!keeplist) {
2169 SYSERROR("failed to allocate keepcap list");
2170 break;
2171 }
2172
2173 keeplist->elem = strdup(token);
2174 if (!keeplist->elem) {
2175 SYSERROR("failed to dup '%s'", token);
2176 free(keeplist);
2177 break;
2178 }
2179
2180 lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
2181 }
2182
2183 free(keepcaps);
2184
2185 return ret;
2186 }
2187
2188 static int set_config_cap_drop(const char *key, const char *value,
2189 struct lxc_conf *lxc_conf)
2190 {
2191 char *dropcaps, *dropptr, *sptr, *token;
2192 struct lxc_list *droplist;
2193 int ret = -1;
2194
2195 if (config_value_empty(value))
2196 return lxc_clear_config_caps(lxc_conf);
2197
2198 dropcaps = strdup(value);
2199 if (!dropcaps) {
2200 SYSERROR("failed to dup '%s'", value);
2201 return -1;
2202 }
2203
2204 /* In case several capability drop is specified in a single line
2205 * split these caps in a single element for the list.
2206 */
2207 for (dropptr = dropcaps;; dropptr = NULL) {
2208 token = strtok_r(dropptr, " \t", &sptr);
2209 if (!token) {
2210 ret = 0;
2211 break;
2212 }
2213
2214 droplist = malloc(sizeof(*droplist));
2215 if (!droplist) {
2216 SYSERROR("failed to allocate drop list");
2217 break;
2218 }
2219
2220 droplist->elem = strdup(token);
2221 if (!droplist->elem) {
2222 SYSERROR("failed to dup '%s'", token);
2223 free(droplist);
2224 break;
2225 }
2226
2227 lxc_list_add_tail(&lxc_conf->caps, droplist);
2228 }
2229
2230 free(dropcaps);
2231
2232 return ret;
2233 }
2234
2235 static int set_config_console(const char *key, const char *value,
2236 struct lxc_conf *lxc_conf)
2237 {
2238 return set_config_path_item(&lxc_conf->console.path, value);
2239 }
2240
2241 static int set_config_console_logfile(const char *key, const char *value,
2242 struct lxc_conf *lxc_conf)
2243 {
2244 return set_config_path_item(&lxc_conf->console.log_path, value);
2245 }
2246
2247 /*
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
2250 * re-use.
2251 * This is only called when reading the config file, not when executing a
2252 * lxc.include.
2253 * 'x' and 'X' are substituted in-place.
2254 */
2255 static void update_hwaddr(const char *line)
2256 {
2257 char *p;
2258
2259 line += lxc_char_left_gc(line, strlen(line));
2260 if (line[0] == '#')
2261 return;
2262
2263 if (strncmp(line, "lxc.network.hwaddr", 18) != 0)
2264 return;
2265
2266 /* Let config_network_hwaddr raise the error. */
2267 p = strchr(line, '=');
2268 if (!p)
2269 return;
2270 p++;
2271
2272 while (isblank(*p))
2273 p++;
2274
2275 if (!*p)
2276 return;
2277
2278 rand_complete_hwaddr(p);
2279 }
2280
2281 int append_unexp_config_line(const char *line, struct lxc_conf *conf)
2282 {
2283 size_t len = conf->unexpanded_len, linelen = strlen(line);
2284
2285 update_hwaddr(line);
2286
2287 while (conf->unexpanded_alloced <= len + linelen + 2) {
2288 char *tmp = realloc(conf->unexpanded_config,
2289 conf->unexpanded_alloced + 1024);
2290 if (!tmp)
2291 return -1;
2292
2293 if (!conf->unexpanded_config)
2294 *tmp = '\0';
2295 conf->unexpanded_config = tmp;
2296 conf->unexpanded_alloced += 1024;
2297 }
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++;
2303 }
2304 return 0;
2305 }
2306
2307 static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
2308 {
2309 struct dirent *direntp;
2310 DIR *dir;
2311 char path[MAXPATHLEN];
2312 int len;
2313 int ret = -1;
2314
2315 dir = opendir(dirp);
2316 if (!dir) {
2317 SYSERROR("failed to open '%s'", dirp);
2318 return -1;
2319 }
2320
2321 while ((direntp = readdir(dir))) {
2322 const char *fnam;
2323 if (!direntp)
2324 break;
2325
2326 fnam = direntp->d_name;
2327 if (!strcmp(fnam, "."))
2328 continue;
2329
2330 if (!strcmp(fnam, ".."))
2331 continue;
2332
2333 len = strlen(fnam);
2334 if (len < 6 || strncmp(fnam + len - 5, ".conf", 5) != 0)
2335 continue;
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);
2339 ret = -1;
2340 goto out;
2341 }
2342
2343 ret = lxc_config_read(path, lxc_conf, true);
2344 if (ret < 0)
2345 goto out;
2346 }
2347 ret = 0;
2348
2349 out:
2350 if (closedir(dir))
2351 WARN("lxc.include dir: failed to close directory");
2352
2353 return ret;
2354 }
2355
2356 static int set_config_includefiles(const char *key, const char *value,
2357 struct lxc_conf *lxc_conf)
2358 {
2359 /* Set config value to default. */
2360 if (config_value_empty(value)) {
2361 clr_config_includefiles(key, lxc_conf);
2362 return 0;
2363 }
2364
2365 /* Parse new config value. */
2366 if (is_dir(value))
2367 return do_includedir(value, lxc_conf);
2368
2369 return lxc_config_read(value, lxc_conf, true);
2370 }
2371
2372 static int set_config_rootfs(const char *key, const char *value,
2373 struct lxc_conf *lxc_conf)
2374 {
2375 return set_config_path_item(&lxc_conf->rootfs.path, value);
2376 }
2377
2378 static int set_config_rootfs_mount(const char *key, const char *value,
2379 struct lxc_conf *lxc_conf)
2380 {
2381 return set_config_path_item(&lxc_conf->rootfs.mount, value);
2382 }
2383
2384 static int set_config_rootfs_options(const char *key, const char *value,
2385 struct lxc_conf *lxc_conf)
2386 {
2387 return set_config_string_item(&lxc_conf->rootfs.options, value);
2388 }
2389
2390 static int set_config_rootfs_backend(const char *key, const char *value,
2391 struct lxc_conf *lxc_conf)
2392 {
2393 if (config_value_empty(value)) {
2394 free(lxc_conf->rootfs.bdev_type);
2395 lxc_conf->rootfs.bdev_type = NULL;
2396 return 0;
2397 }
2398
2399 if (!is_valid_bdev_type(value)) {
2400 ERROR("Bad rootfs.backend: '%s'", value);
2401 return -1;
2402 }
2403
2404 return set_config_string_item(&lxc_conf->rootfs.bdev_type, value);
2405 }
2406
2407 static int set_config_pivotdir(const char *key, const char *value,
2408 struct lxc_conf *lxc_conf)
2409 {
2410 WARN("lxc.pivotdir is ignored. It will soon become an error.");
2411 return 0;
2412 }
2413
2414 static int set_config_utsname(const char *key, const char *value,
2415 struct lxc_conf *lxc_conf)
2416 {
2417 struct utsname *utsname;
2418
2419 if (config_value_empty(value)) {
2420 clr_config_utsname(key, lxc_conf);
2421 return 0;
2422 }
2423
2424 utsname = malloc(sizeof(*utsname));
2425 if (!utsname) {
2426 SYSERROR("failed to allocate memory");
2427 return -1;
2428 }
2429
2430 if (strlen(value) >= sizeof(utsname->nodename)) {
2431 ERROR("node name '%s' is too long", value);
2432 free(utsname);
2433 return -1;
2434 }
2435
2436 strcpy(utsname->nodename, value);
2437 free(lxc_conf->utsname);
2438 lxc_conf->utsname = utsname;
2439
2440 return 0;
2441 }
2442
2443 struct parse_line_conf {
2444 struct lxc_conf *conf;
2445 bool from_include;
2446 };
2447
2448 static int parse_line(char *buffer, void *data)
2449 {
2450 struct lxc_config_t *config;
2451 char *dot, *key, *line, *linep, *value;
2452 struct parse_line_conf *plc = data;
2453 int ret = 0;
2454
2455 if (lxc_is_line_empty(buffer))
2456 return 0;
2457
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
2461 */
2462 linep = line = strdup(buffer);
2463 if (!line) {
2464 SYSERROR("failed to allocate memory for '%s'", buffer);
2465 return -1;
2466 }
2467
2468 if (!plc->from_include)
2469 if ((ret = append_unexp_config_line(line, plc->conf)))
2470 goto out;
2471
2472 line += lxc_char_left_gc(line, strlen(line));
2473
2474 /* ignore comments */
2475 if (line[0] == '#')
2476 goto out;
2477
2478 /* martian option - don't add it to the config itself */
2479 if (strncmp(line, "lxc.", 4))
2480 goto out;
2481
2482 ret = -1;
2483
2484 dot = strstr(line, "=");
2485 if (!dot) {
2486 ERROR("invalid configuration line: %s", line);
2487 goto out;
2488 }
2489
2490 *dot = '\0';
2491 value = dot + 1;
2492
2493 key = line;
2494 key[lxc_char_right_gc(key, strlen(key))] = '\0';
2495
2496 value += lxc_char_left_gc(value, strlen(value));
2497 value[lxc_char_right_gc(value, strlen(value))] = '\0';
2498
2499 if (*value == '\'' || *value == '\"') {
2500 size_t len = strlen(value);
2501 if (len > 1 && value[len - 1] == *value) {
2502 value[len - 1] = '\0';
2503 value++;
2504 }
2505 }
2506
2507 config = lxc_getconfig(key);
2508 if (!config) {
2509 ERROR("unknown key %s", key);
2510 goto out;
2511 }
2512
2513 ret = config->set(key, value, plc->conf);
2514
2515 out:
2516 free(linep);
2517 return ret;
2518 }
2519
2520 static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
2521 {
2522 struct parse_line_conf c;
2523
2524 c.conf = conf;
2525 c.from_include = false;
2526
2527 return parse_line(buffer, &c);
2528 }
2529
2530 int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
2531 {
2532 struct parse_line_conf c;
2533
2534 c.conf = conf;
2535 c.from_include = from_include;
2536
2537 if (access(file, R_OK) == -1) {
2538 return -1;
2539 }
2540
2541 /* Catch only the top level config file name in the structure */
2542 if (!conf->rcfile)
2543 conf->rcfile = strdup(file);
2544
2545 return lxc_file_for_each_line(file, parse_line, &c);
2546 }
2547
2548 int lxc_config_define_add(struct lxc_list *defines, char *arg)
2549 {
2550 struct lxc_list *dent;
2551
2552 dent = malloc(sizeof(struct lxc_list));
2553 if (!dent)
2554 return -1;
2555
2556 dent->elem = arg;
2557 lxc_list_add_tail(defines, dent);
2558 return 0;
2559 }
2560
2561 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
2562 {
2563 struct lxc_list *it, *next;
2564 int ret = 0;
2565
2566 lxc_list_for_each(it, defines) {
2567 ret = lxc_config_readline(it->elem, conf);
2568 if (ret)
2569 break;
2570 }
2571
2572 lxc_list_for_each_safe(it, defines, next) {
2573 lxc_list_del(it);
2574 free(it);
2575 }
2576
2577 return ret;
2578 }
2579
2580 signed long lxc_config_parse_arch(const char *arch)
2581 {
2582 #if HAVE_SYS_PERSONALITY_H
2583 size_t i;
2584 struct per_name {
2585 char *name;
2586 unsigned long per;
2587 } pername[] = {
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 },
2615 };
2616 size_t len = sizeof(pername) / sizeof(pername[0]);
2617
2618 for (i = 0; i < len; i++) {
2619 if (!strcmp(pername[i].name, arch))
2620 return pername[i].per;
2621 }
2622 #endif
2623
2624 return -1;
2625 }
2626
2627 int lxc_fill_elevated_privileges(char *flaglist, int *flags)
2628 {
2629 char *token, *saveptr = NULL;
2630 int i, aflag;
2631 struct {
2632 const char *token;
2633 int flag;
2634 } all_privs[] = {
2635 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
2636 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
2637 { "LSM", LXC_ATTACH_LSM_EXEC },
2638 { NULL, 0 }
2639 };
2640
2641 if (!flaglist) {
2642 /* For the sake of backward compatibility, drop all privileges
2643 * if none is specified.
2644 */
2645 for (i = 0; all_privs[i].token; i++) {
2646 *flags |= all_privs[i].flag;
2647 }
2648 return 0;
2649 }
2650
2651 token = strtok_r(flaglist, "|", &saveptr);
2652 while (token) {
2653 aflag = -1;
2654 for (i = 0; all_privs[i].token; i++) {
2655 if (!strcmp(all_privs[i].token, token))
2656 aflag = all_privs[i].flag;
2657 }
2658 if (aflag < 0)
2659 return -1;
2660
2661 *flags |= aflag;
2662
2663 token = strtok_r(NULL, "|", &saveptr);
2664 }
2665
2666 return 0;
2667 }
2668
2669 static inline int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen,
2670 int v)
2671 {
2672 if (!retv)
2673 inlen = 0;
2674 else
2675 memset(retv, 0, inlen);
2676
2677 return snprintf(retv, inlen, "%d", v);
2678 }
2679
2680 /* Write out a configuration file. */
2681 void write_config(FILE *fout, struct lxc_conf *c)
2682 {
2683 int ret;
2684 size_t len = c->unexpanded_len;
2685
2686 if (!len)
2687 return;
2688
2689 ret = fwrite(c->unexpanded_config, 1, len, fout);
2690 if (ret != len)
2691 SYSERROR("Error writing configuration file");
2692 }
2693
2694 bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key,
2695 const char *v)
2696 {
2697 int ret;
2698 size_t len;
2699 char *tmp;
2700
2701 len = strlen(key) + strlen(v) + 4;
2702 tmp = alloca(len);
2703
2704 if (config_value_empty(v))
2705 ret = snprintf(tmp, len, "%s =", key);
2706 else
2707 ret = snprintf(tmp, len, "%s = %s", key, v);
2708 if (ret < 0 || ret >= len)
2709 return false;
2710
2711 /* Save the line verbatim into unexpanded_conf */
2712 if (append_unexp_config_line(tmp, conf))
2713 return false;
2714
2715 return true;
2716 }
2717
2718 void clear_unexp_config_line(struct lxc_conf *conf, const char *key,
2719 bool rm_subkeys)
2720 {
2721 char *lend;
2722 char *lstart = conf->unexpanded_config;
2723
2724 if (!conf->unexpanded_config)
2725 return;
2726
2727 while (*lstart) {
2728 lend = strchr(lstart, '\n');
2729 char v;
2730 if (!lend)
2731 lend = lstart + strlen(lstart);
2732 else
2733 lend++;
2734 if (strncmp(lstart, key, strlen(key)) != 0) {
2735 lstart = lend;
2736 continue;
2737 }
2738 if (!rm_subkeys) {
2739 v = lstart[strlen(key)];
2740 if (!isspace(v) && v != '=') {
2741 lstart = lend;
2742 continue;
2743 }
2744 }
2745 conf->unexpanded_len -= (lend - lstart);
2746 if (*lend == '\0') {
2747 *lstart = '\0';
2748 return;
2749 }
2750 memmove(lstart, lend, strlen(lend) + 1);
2751 }
2752 }
2753
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)
2757 {
2758 int ret;
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";
2763
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,
2767 oldname);
2768 if (ret < 0 || ret >= olddirlen + 1) {
2769 ERROR("failed to create string");
2770 return false;
2771 }
2772
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,
2776 newname);
2777 if (ret < 0 || ret >= newdirlen + 1) {
2778 ERROR("failed to create string");
2779 return false;
2780 }
2781
2782 if (!conf->unexpanded_config)
2783 return true;
2784
2785 while (*lstart) {
2786 lend = strchr(lstart, '\n');
2787 if (!lend)
2788 lend = lstart + strlen(lstart);
2789 else
2790 lend++;
2791
2792 if (strncmp(lstart, key, strlen(key)) != 0)
2793 goto next;
2794
2795 p = strchr(lstart + strlen(key), '=');
2796 if (!p)
2797 goto next;
2798 p++;
2799
2800 while (isblank(*p))
2801 p++;
2802
2803 if (p >= lend)
2804 goto next;
2805
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))
2817 goto next;
2818
2819 if (!(q = strstr(p, olddir)) || (q >= lend))
2820 goto next;
2821
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);
2829 lend -= diff;
2830 conf->unexpanded_len -= diff;
2831 }
2832 } else {
2833 char *new;
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;
2838
2839 new = realloc(conf->unexpanded_config, newlen + 1);
2840 if (!new) {
2841 ERROR("Out of memory");
2842 return false;
2843 }
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
2849 */
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);
2855 lend += diff;
2856 }
2857 next:
2858 lstart = lend;
2859 }
2860
2861 return true;
2862 }
2863
2864 bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
2865 const char *newpath, const char *oldname,
2866 const char *newname)
2867 {
2868 int ret;
2869 char *lend, *newdir, *olddir, *p;
2870 char *lstart = conf->unexpanded_config;
2871 size_t newdirlen, olddirlen;
2872 const char *key = "lxc.hook";
2873
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");
2879 return false;
2880 }
2881
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");
2887 return false;
2888 }
2889 if (!conf->unexpanded_config)
2890 return true;
2891 while (*lstart) {
2892 lend = strchr(lstart, '\n');
2893 if (!lend)
2894 lend = lstart + strlen(lstart);
2895 else
2896 lend++;
2897
2898 if (strncmp(lstart, key, strlen(key)) != 0)
2899 goto next;
2900
2901 p = strchr(lstart + strlen(key), '=');
2902 if (!p)
2903 goto next;
2904 p++;
2905
2906 while (isblank(*p))
2907 p++;
2908
2909 if (p >= lend)
2910 goto next;
2911
2912 if (strncmp(p, olddir, strlen(olddir)) != 0)
2913 goto next;
2914
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);
2922 lend -= diff;
2923 conf->unexpanded_len -= diff;
2924 }
2925 } else {
2926 char *new;
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;
2931
2932 new = realloc(conf->unexpanded_config, newlen + 1);
2933 if (!new) {
2934 ERROR("failed to allocate memory");
2935 return false;
2936 }
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
2942 */
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);
2948 lend += diff;
2949 }
2950 next:
2951 lstart = lend;
2952 }
2953
2954 return true;
2955 }
2956
2957 #define DO(cmd) \
2958 { \
2959 if (!(cmd)) { \
2960 ERROR("Error writing to new config"); \
2961 return false; \
2962 } \
2963 }
2964
2965 static bool new_hwaddr(char *hwaddr)
2966 {
2967 int ret;
2968
2969 (void)randseed(true);
2970
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().");
2975 return false;
2976 }
2977
2978 return true;
2979 }
2980
2981 /*
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.
2989 */
2990 bool network_new_hwaddrs(struct lxc_conf *conf)
2991 {
2992 char *lend, *p, *p2;
2993 struct lxc_list *it;
2994 const char *key = "lxc.network.hwaddr";
2995 char *lstart = conf->unexpanded_config;
2996
2997 if (!conf->unexpanded_config)
2998 return true;
2999
3000 while (*lstart) {
3001 char newhwaddr[18], oldhwaddr[17];
3002
3003 lend = strchr(lstart, '\n');
3004 if (!lend)
3005 lend = lstart + strlen(lstart);
3006 else
3007 lend++;
3008
3009 if (strncmp(lstart, key, strlen(key)) != 0) {
3010 lstart = lend;
3011 continue;
3012 }
3013
3014 p = strchr(lstart + strlen(key), '=');
3015 if (!p) {
3016 lstart = lend;
3017 continue;
3018 }
3019
3020 p++;
3021 while (isblank(*p))
3022 p++;
3023 if (!*p)
3024 return true;
3025
3026 p2 = p;
3027 while (*p2 && !isblank(*p2) && *p2 != '\n')
3028 p2++;
3029
3030 if ((p2 - p) != 17) {
3031 WARN("Bad hwaddr entry");
3032 lstart = lend;
3033 continue;
3034 }
3035
3036 memcpy(oldhwaddr, p, 17);
3037
3038 if (!new_hwaddr(newhwaddr))
3039 return false;
3040
3041 memcpy(p, newhwaddr, 17);
3042 lxc_list_for_each(it, &conf->network)
3043 {
3044 struct lxc_netdev *n = it->elem;
3045 if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0)
3046 memcpy(n->hwaddr, newhwaddr, 17);
3047 }
3048
3049 lstart = lend;
3050 }
3051
3052 return true;
3053 }
3054
3055 static int set_config_ephemeral(const char *key, const char *value,
3056 struct lxc_conf *lxc_conf)
3057 {
3058 /* Set config value to default. */
3059 if (config_value_empty(value)) {
3060 lxc_conf->ephemeral = 0;
3061 return 0;
3062 }
3063
3064 /* Parse new config value. */
3065 if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0)
3066 return -1;
3067
3068 if (lxc_conf->ephemeral > 1) {
3069 ERROR(
3070 "Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
3071 return -1;
3072 }
3073
3074 return 0;
3075 }
3076
3077 static int set_config_syslog(const char *key, const char *value,
3078 struct lxc_conf *lxc_conf)
3079 {
3080 int facility;
3081
3082 /* Clear any previously set value. */
3083 if (lxc_conf->syslog) {
3084 free(lxc_conf->syslog);
3085 lxc_conf->syslog = NULL;
3086 }
3087
3088 /* Check if value is empty. */
3089 if (config_value_empty(value))
3090 return 0;
3091
3092 /* Parse value. */
3093 facility = lxc_syslog_priority_to_int(value);
3094 if (facility == -EINVAL) {
3095 ERROR("Wrong value for lxc.syslog.");
3096 return -1;
3097 }
3098
3099 lxc_log_syslog(facility);
3100 return set_config_string_item(&lxc_conf->syslog, value);
3101 }
3102
3103 static int set_config_no_new_privs(const char *key, const char *value,
3104 struct lxc_conf *lxc_conf)
3105 {
3106 unsigned int v;
3107
3108 /* Set config value to default. */
3109 if (config_value_empty(value)) {
3110 lxc_conf->no_new_privs = false;
3111 return 0;
3112 }
3113
3114 /* Parse new config value. */
3115 if (lxc_safe_uint(value, &v) < 0)
3116 return -1;
3117
3118 if (v > 1) {
3119 ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 "
3120 "or 1");
3121 return -1;
3122 }
3123
3124 lxc_conf->no_new_privs = v ? true : false;
3125
3126 return 0;
3127 }
3128
3129 /* Callbacks to get configuration items. */
3130 static int get_config_personality(const char *key, char *retv, int inlen,
3131 struct lxc_conf *c)
3132 {
3133 int fulllen = 0;
3134
3135 if (!retv)
3136 inlen = 0;
3137 else
3138 memset(retv, 0, inlen);
3139
3140 #if HAVE_SYS_PERSONALITY_H
3141 int len = 0;
3142
3143 switch (c->personality) {
3144 case PER_LINUX32:
3145 strprint(retv, inlen, "i686");
3146 break;
3147 case PER_LINUX:
3148 strprint(retv, inlen, "x86_64");
3149 break;
3150 default:
3151 break;
3152 }
3153 #endif
3154
3155 return fulllen;
3156 }
3157
3158 static int get_config_pts(const char *key, char *retv, int inlen,
3159 struct lxc_conf *c)
3160 {
3161 return lxc_get_conf_int(c, retv, inlen, c->pts);
3162 }
3163
3164 static int get_config_tty(const char *key, char *retv, int inlen,
3165 struct lxc_conf *c)
3166 {
3167 return lxc_get_conf_int(c, retv, inlen, c->tty);
3168 }
3169
3170 static inline int lxc_get_conf_str(char *retv, int inlen, const char *value)
3171 {
3172 if (!value)
3173 return 0;
3174 if (retv && inlen >= strlen(value) + 1)
3175 strncpy(retv, value, strlen(value) + 1);
3176
3177 return strlen(value);
3178 }
3179
3180 static int get_config_ttydir(const char *key, char *retv, int inlen,
3181 struct lxc_conf *c)
3182 {
3183 return lxc_get_conf_str(retv, inlen, c->ttydir);
3184 }
3185
3186 static int get_config_kmsg(const char *key, char *retv, int inlen,
3187 struct lxc_conf *c)
3188 {
3189 return lxc_get_conf_int(c, retv, inlen, c->kmsg);
3190 }
3191
3192 static int get_config_lsm_aa_profile(const char *key, char *retv, int inlen,
3193 struct lxc_conf *c)
3194 {
3195 return lxc_get_conf_str(retv, inlen, c->lsm_aa_profile);
3196 }
3197
3198 static int get_config_lsm_aa_incomplete(const char *key, char *retv, int inlen,
3199 struct lxc_conf *c)
3200 {
3201 return lxc_get_conf_int(c, retv, inlen,
3202 c->lsm_aa_allow_incomplete);
3203 }
3204
3205 static int get_config_lsm_se_context(const char *key, char *retv, int inlen,
3206 struct lxc_conf *c)
3207 {
3208 return lxc_get_conf_str(retv, inlen, c->lsm_se_context);
3209 }
3210
3211 /*
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.
3219 */
3220 static int get_config_cgroup(const char *key, char *retv, int inlen,
3221 struct lxc_conf *c)
3222 {
3223 struct lxc_list *it;
3224 int len;
3225 int fulllen = 0;
3226 bool get_all = false;
3227
3228 if (!retv)
3229 inlen = 0;
3230 else
3231 memset(retv, 0, inlen);
3232
3233 if (!strcmp(key, "lxc.cgroup"))
3234 get_all = true;
3235 else if (!strncmp(key, "lxc.cgroup.", 11))
3236 key += 11;
3237 else
3238 return -1;
3239
3240 lxc_list_for_each(it, &c->cgroup) {
3241 struct lxc_cgroup *cg = it->elem;
3242 if (get_all) {
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);
3246 }
3247 }
3248
3249 return fulllen;
3250 }
3251
3252 static int get_config_idmaps(const char *key, char *retv, int inlen,
3253 struct lxc_conf *c)
3254 {
3255 struct lxc_list *it;
3256 int len, listlen, ret;
3257 int fulllen = 0;
3258 /* "u 1000 1000000 65536"
3259 *
3260 * let's render this as
3261 *
3262 * sizeof(char)
3263 * +
3264 * sizeof(" ")
3265 * +
3266 * sizeof(uint64_t)
3267 * +
3268 * sizeof(" ")
3269 * +
3270 * sizeof(uint64_t)
3271 * +
3272 * sizeof(" ")
3273 * +
3274 * sizeof(uint64_t)
3275 * +
3276 * \0
3277 */
3278 #define __LXC_IDMAP_STR_BUF (3 * LXC_NUMSTRLEN64 + 3 + 1 + 1)
3279 char buf[__LXC_IDMAP_STR_BUF];
3280
3281 if (!retv)
3282 inlen = 0;
3283 else
3284 memset(retv, 0, inlen);
3285
3286 listlen = lxc_list_len(&c->id_map);
3287 lxc_list_for_each(it, &c->id_map)
3288 {
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)
3294 return -1;
3295
3296 strprint(retv, inlen, "%s%s", buf, (listlen-- > 1) ? "\n" : "");
3297 }
3298 return fulllen;
3299 }
3300
3301 static int get_config_loglevel(const char *key, char *retv, int inlen,
3302 struct lxc_conf *c)
3303 {
3304 const char *v;
3305 v = lxc_log_priority_to_string(c->loglevel);
3306 return lxc_get_conf_str(retv, inlen, v);
3307 }
3308
3309 static int get_config_logfile(const char *key, char *retv, int inlen,
3310 struct lxc_conf *c)
3311 {
3312 return lxc_get_conf_str(retv, inlen, c->logfile);
3313 }
3314
3315 static int get_config_fstab(const char *key, char *retv, int inlen,
3316 struct lxc_conf *c)
3317 {
3318 return lxc_get_conf_str(retv, inlen, c->fstab);
3319 }
3320
3321 static int get_config_mount_auto(const char *key, char *retv, int inlen,
3322 struct lxc_conf *c)
3323 {
3324 int len, fulllen = 0;
3325 const char *sep = "";
3326
3327 if (!retv)
3328 inlen = 0;
3329 else
3330 memset(retv, 0, inlen);
3331
3332 if (!(c->auto_mounts & LXC_AUTO_ALL_MASK))
3333 return 0;
3334
3335 switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
3336 case LXC_AUTO_PROC_MIXED:
3337 strprint(retv, inlen, "%sproc:mixed", sep);
3338 sep = " ";
3339 break;
3340 case LXC_AUTO_PROC_RW:
3341 strprint(retv, inlen, "%sproc:rw", sep);
3342 sep = " ";
3343 break;
3344 default:
3345 break;
3346 }
3347
3348 switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
3349 case LXC_AUTO_SYS_RO:
3350 strprint(retv, inlen, "%ssys:ro", sep);
3351 sep = " ";
3352 break;
3353 case LXC_AUTO_SYS_RW:
3354 strprint(retv, inlen, "%ssys:rw", sep);
3355 sep = " ";
3356 break;
3357 case LXC_AUTO_SYS_MIXED:
3358 strprint(retv, inlen, "%ssys:mixed", sep);
3359 sep = " ";
3360 break;
3361 default:
3362 break;
3363 }
3364
3365 switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
3366 case LXC_AUTO_CGROUP_NOSPEC:
3367 strprint(retv, inlen, "%scgroup", sep);
3368 sep = " ";
3369 break;
3370 case LXC_AUTO_CGROUP_MIXED:
3371 strprint(retv, inlen, "%scgroup:mixed", sep);
3372 sep = " ";
3373 break;
3374 case LXC_AUTO_CGROUP_RO:
3375 strprint(retv, inlen, "%scgroup:ro", sep);
3376 sep = " ";
3377 break;
3378 case LXC_AUTO_CGROUP_RW:
3379 strprint(retv, inlen, "%scgroup:rw", sep);
3380 sep = " ";
3381 break;
3382 case LXC_AUTO_CGROUP_FULL_NOSPEC:
3383 strprint(retv, inlen, "%scgroup-full", sep);
3384 sep = " ";
3385 break;
3386 case LXC_AUTO_CGROUP_FULL_MIXED:
3387 strprint(retv, inlen, "%scgroup-full:mixed", sep);
3388 sep = " ";
3389 break;
3390 case LXC_AUTO_CGROUP_FULL_RO:
3391 strprint(retv, inlen, "%scgroup-full:ro", sep);
3392 sep = " ";
3393 break;
3394 case LXC_AUTO_CGROUP_FULL_RW:
3395 strprint(retv, inlen, "%scgroup-full:rw", sep);
3396 sep = " ";
3397 break;
3398 default:
3399 break;
3400 }
3401
3402 return fulllen;
3403 }
3404
3405 static int get_config_mount(const char *key, char *retv, int inlen,
3406 struct lxc_conf *c)
3407 {
3408 int len, fulllen = 0;
3409 struct lxc_list *it;
3410
3411 if (!retv)
3412 inlen = 0;
3413 else
3414 memset(retv, 0, inlen);
3415
3416 lxc_list_for_each(it, &c->mount_list)
3417 {
3418 strprint(retv, inlen, "%s\n", (char *)it->elem);
3419 }
3420
3421 return fulllen;
3422 }
3423
3424 static int get_config_rootfs(const char *key, char *retv, int inlen,
3425 struct lxc_conf *c)
3426 {
3427 return lxc_get_conf_str(retv, inlen, c->rootfs.path);
3428 }
3429
3430 static int get_config_rootfs_mount(const char *key, char *retv, int inlen,
3431 struct lxc_conf *c)
3432 {
3433 return lxc_get_conf_str(retv, inlen, c->rootfs.mount);
3434 }
3435
3436 static int get_config_rootfs_options(const char *key, char *retv, int inlen,
3437 struct lxc_conf *c)
3438 {
3439 return lxc_get_conf_str(retv, inlen, c->rootfs.options);
3440 }
3441
3442 static int get_config_rootfs_backend(const char *key, char *retv, int inlen,
3443 struct lxc_conf *c)
3444 {
3445 return lxc_get_conf_str(retv, inlen, c->rootfs.bdev_type);
3446 }
3447
3448 static int get_config_pivotdir(const char *key, char *retv, int inlen,
3449 struct lxc_conf *c)
3450 {
3451 return 0;
3452 }
3453
3454 static int get_config_utsname(const char *key, char *retv, int inlen,
3455 struct lxc_conf *c)
3456 {
3457 return lxc_get_conf_str(
3458 retv, inlen,
3459 c->utsname ? c->utsname->nodename : NULL);
3460 }
3461
3462 static int get_config_hooks(const char *key, char *retv, int inlen,
3463 struct lxc_conf *c)
3464 {
3465 char *subkey;
3466 int len, fulllen = 0, found = -1;
3467 struct lxc_list *it;
3468 int i;
3469
3470 /* "lxc.hook.mount" */
3471 subkey = strchr(key, '.');
3472 if (subkey)
3473 subkey = strchr(subkey + 1, '.');
3474 if (!subkey)
3475 return -1;
3476 subkey++;
3477 if (!*subkey)
3478 return -1;
3479 for (i = 0; i < NUM_LXC_HOOKS; i++) {
3480 if (strcmp(lxchook_names[i], subkey) == 0) {
3481 found = i;
3482 break;
3483 }
3484 }
3485 if (found == -1)
3486 return -1;
3487
3488 if (!retv)
3489 inlen = 0;
3490 else
3491 memset(retv, 0, inlen);
3492
3493 lxc_list_for_each(it, &c->hooks[found]) {
3494 strprint(retv, inlen, "%s\n", (char *)it->elem);
3495 }
3496 return fulllen;
3497 }
3498
3499 static int get_config_network(const char *key, char *retv, int inlen,
3500 struct lxc_conf *c)
3501 {
3502 int len, fulllen = 0;
3503 struct lxc_list *it;
3504
3505 if (!retv)
3506 inlen = 0;
3507 else
3508 memset(retv, 0, inlen);
3509
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)");
3514 }
3515
3516 return fulllen;
3517 }
3518
3519 /*
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
3525 * type).
3526 */
3527 static int get_config_network_item(const char *key, char *retv, int inlen,
3528 struct lxc_conf *c)
3529 {
3530 char *p1;
3531 int len, fulllen = 0;
3532 struct lxc_netdev *netdev;
3533
3534 if (!retv)
3535 inlen = 0;
3536 else
3537 memset(retv, 0, inlen);
3538
3539 if (!strncmp(key, "lxc.network.", 12))
3540 key += 12;
3541 else
3542 return -1;
3543
3544 p1 = strchr(key, '.');
3545 if (!p1 || *(p1 + 1) == '\0')
3546 return -1;
3547 p1++;
3548
3549 netdev = get_netdev_from_key(key, &c->network);
3550 if (!netdev)
3551 return -1;
3552 if (strcmp(p1, "name") == 0) {
3553 if (netdev->name)
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) {
3558 if (netdev->link)
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) {
3570 if (netdev->hwaddr)
3571 strprint(retv, inlen, "%s", netdev->hwaddr);
3572 } else if (strcmp(p1, "mtu") == 0) {
3573 if (netdev->mtu)
3574 strprint(retv, inlen, "%s", netdev->mtu);
3575 } else if (strcmp(p1, "macvlan.mode") == 0) {
3576 if (netdev->type == LXC_NET_MACVLAN) {
3577 const char *mode;
3578 switch (netdev->priv.macvlan_attr.mode) {
3579 case MACVLAN_MODE_PRIVATE:
3580 mode = "private";
3581 break;
3582 case MACVLAN_MODE_VEPA:
3583 mode = "vepa";
3584 break;
3585 case MACVLAN_MODE_BRIDGE:
3586 mode = "bridge";
3587 break;
3588 case MACVLAN_MODE_PASSTHRU:
3589 mode = "passthru";
3590 break;
3591 default:
3592 mode = "(invalid)";
3593 break;
3594 }
3595 strprint(retv, inlen, "%s", mode);
3596 }
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);
3603 }
3604 } else if (strcmp(p1, "vlan") == 0) {
3605 if (netdev->type == LXC_NET_VLAN) {
3606 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
3607 }
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,
3614 sizeof(buf));
3615 strprint(retv, inlen, "%s", buf);
3616 }
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);
3624 }
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,
3631 sizeof(buf));
3632 strprint(retv, inlen, "%s", buf);
3633 }
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);
3641 }
3642 }
3643 return fulllen;
3644 }
3645
3646 static int get_config_cap_drop(const char *key, char *retv, int inlen,
3647 struct lxc_conf *c)
3648 {
3649 int len, fulllen = 0;
3650 struct lxc_list *it;
3651
3652 if (!retv)
3653 inlen = 0;
3654 else
3655 memset(retv, 0, inlen);
3656
3657 lxc_list_for_each(it, &c->caps) {
3658 strprint(retv, inlen, "%s\n", (char *)it->elem);
3659 }
3660 return fulllen;
3661 }
3662
3663 static int get_config_cap_keep(const char *key, char *retv, int inlen,
3664 struct lxc_conf *c)
3665 {
3666 int len, fulllen = 0;
3667 struct lxc_list *it;
3668
3669 if (!retv)
3670 inlen = 0;
3671 else
3672 memset(retv, 0, inlen);
3673
3674 lxc_list_for_each(it, &c->keepcaps) {
3675 strprint(retv, inlen, "%s\n", (char *)it->elem);
3676 }
3677 return fulllen;
3678 }
3679
3680 static int get_config_console(const char *key, char *retv, int inlen,
3681 struct lxc_conf *c)
3682 {
3683 return lxc_get_conf_str(retv, inlen, c->console.path);
3684 }
3685
3686 static int get_config_console_logfile(const char *key, char *retv, int inlen,
3687 struct lxc_conf *c)
3688 {
3689 return lxc_get_conf_str(retv, inlen, c->console.log_path);
3690 }
3691
3692 static int get_config_seccomp(const char *key, char *retv, int inlen,
3693 struct lxc_conf *c)
3694 {
3695 return lxc_get_conf_str(retv, inlen, c->seccomp);
3696 }
3697
3698 static int get_config_autodev(const char *key, char *retv, int inlen,
3699 struct lxc_conf *c)
3700 {
3701 return lxc_get_conf_int(c, retv, inlen, c->autodev);
3702 }
3703
3704 static int get_config_haltsignal(const char *key, char *retv, int inlen,
3705 struct lxc_conf *c)
3706 {
3707 return lxc_get_conf_int(c, retv, inlen, c->haltsignal);
3708 }
3709
3710 static int get_config_rebootsignal(const char *key, char *retv, int inlen,
3711 struct lxc_conf *c)
3712 {
3713 return lxc_get_conf_int(c, retv, inlen, c->rebootsignal);
3714 }
3715
3716 static int get_config_stopsignal(const char *key, char *retv, int inlen,
3717 struct lxc_conf *c)
3718 {
3719 return lxc_get_conf_int(c, retv, inlen, c->stopsignal);
3720 }
3721
3722 static int get_config_start(const char *key, char *retv, int inlen,
3723 struct lxc_conf *c)
3724 {
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);
3731
3732 return -1;
3733 }
3734
3735 static int get_config_syslog(const char *key, char *retv, int inlen,
3736 struct lxc_conf *c)
3737 {
3738 return lxc_get_conf_str(retv, inlen, c->syslog);
3739 }
3740
3741 static int get_config_monitor(const char *key, char *retv, int inlen,
3742 struct lxc_conf *c)
3743 {
3744 return lxc_get_conf_int(c, retv, inlen, c->monitor_unshare);
3745 }
3746
3747 static int get_config_group(const char *key, char *retv, int inlen,
3748 struct lxc_conf *c)
3749 {
3750 int len, fulllen = 0;
3751 struct lxc_list *it;
3752
3753 if (!retv)
3754 inlen = 0;
3755 else
3756 memset(retv, 0, inlen);
3757
3758 lxc_list_for_each(it, &c->groups) {
3759 strprint(retv, inlen, "%s\n", (char *)it->elem);
3760 }
3761 return fulllen;
3762 }
3763
3764 static int get_config_environment(const char *key, char *retv, int inlen,
3765 struct lxc_conf *c)
3766 {
3767 int len, fulllen = 0;
3768 struct lxc_list *it;
3769
3770 if (!retv)
3771 inlen = 0;
3772 else
3773 memset(retv, 0, inlen);
3774
3775 lxc_list_for_each(it, &c->environment) {
3776 strprint(retv, inlen, "%s\n", (char *)it->elem);
3777 }
3778 return fulllen;
3779 }
3780
3781 static int get_config_init_cmd(const char *key, char *retv, int inlen,
3782 struct lxc_conf *c)
3783 {
3784 return lxc_get_conf_str(retv, inlen, c->init_cmd);
3785 }
3786
3787 static int get_config_init_uid(const char *key, char *retv, int inlen,
3788 struct lxc_conf *c)
3789 {
3790 return lxc_get_conf_int(c, retv, inlen, c->init_uid);
3791 }
3792
3793 static int get_config_init_gid(const char *key, char *retv, int inlen,
3794 struct lxc_conf *c)
3795 {
3796 return lxc_get_conf_int(c, retv, inlen, c->init_gid);
3797 }
3798
3799 static int get_config_ephemeral(const char *key, char *retv, int inlen,
3800 struct lxc_conf *c)
3801 {
3802 return lxc_get_conf_int(c, retv, inlen, c->ephemeral);
3803 }
3804
3805 static int get_config_no_new_privs(const char *key, char *retv, int inlen,
3806 struct lxc_conf *c)
3807 {
3808 return lxc_get_conf_int(c, retv, inlen, c->no_new_privs);
3809 }
3810
3811 /*
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.
3815 */
3816 static int get_config_limit(const char *key, char *retv, int inlen,
3817 struct lxc_conf *c)
3818 {
3819 int fulllen = 0, len;
3820 bool get_all = false;
3821 struct lxc_list *it;
3822
3823 if (!retv)
3824 inlen = 0;
3825 else
3826 memset(retv, 0, inlen);
3827
3828 if (!strcmp(key, "lxc.limit"))
3829 get_all = true;
3830 else if (strncmp(key, "lxc.limit.", 10) == 0)
3831 key += 10;
3832 else
3833 return -1;
3834
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
3838 'unlimited' */
3839 int partlen;
3840 struct lxc_limit *lim = it->elem;
3841
3842 if (lim->limit.rlim_cur == RLIM_INFINITY) {
3843 memcpy(buf, "unlimited", sizeof("unlimited"));
3844 partlen = sizeof("unlimited") - 1;
3845 } else {
3846 partlen = sprintf(buf, "%" PRIu64,
3847 (uint64_t)lim->limit.rlim_cur);
3848 }
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"));
3853 } else {
3854 sprintf(buf + partlen, ":%" PRIu64,
3855 (uint64_t)lim->limit.rlim_max);
3856 }
3857 }
3858
3859 if (get_all) {
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);
3864 }
3865 }
3866
3867 return fulllen;
3868 }
3869
3870 /* Callbacks to clear config items. */
3871 static inline int clr_config_personality(const char *key, struct lxc_conf *c)
3872 {
3873 c->personality = -1;
3874 return 0;
3875 }
3876
3877 static inline int clr_config_pts(const char *key, struct lxc_conf *c)
3878 {
3879 c->pts = 0;
3880 return 0;
3881 }
3882
3883 static inline int clr_config_tty(const char *key, struct lxc_conf *c)
3884 {
3885 c->tty = 0;
3886 return 0;
3887 }
3888
3889 static inline int clr_config_ttydir(const char *key, struct lxc_conf *c)
3890 {
3891 free(c->ttydir);
3892 c->ttydir = NULL;
3893 return 0;
3894 }
3895
3896 static inline int clr_config_kmsg(const char *key, struct lxc_conf *c)
3897 {
3898 c->kmsg = 0;
3899 return 0;
3900 }
3901
3902 static inline int clr_config_lsm_aa_profile(const char *key, struct lxc_conf *c)
3903 {
3904 free(c->lsm_aa_profile);
3905 c->lsm_aa_profile = NULL;
3906 return 0;
3907 }
3908
3909 static inline int clr_config_lsm_aa_incomplete(const char *key,
3910 struct lxc_conf *c)
3911 {
3912 c->lsm_aa_allow_incomplete = 0;
3913 return 0;
3914 }
3915
3916 static inline int clr_config_lsm_se_context(const char *key, struct lxc_conf *c)
3917 {
3918 free(c->lsm_se_context);
3919 c->lsm_se_context = NULL;
3920 return 0;
3921 }
3922
3923 static inline int clr_config_cgroup(const char *key, struct lxc_conf *c)
3924 {
3925 return lxc_clear_cgroups(c, key);
3926 }
3927
3928 static inline int clr_config_idmaps(const char *key, struct lxc_conf *c)
3929 {
3930 return lxc_clear_idmaps(c);
3931 }
3932
3933 static inline int clr_config_loglevel(const char *key, struct lxc_conf *c)
3934 {
3935 c->loglevel = LXC_LOG_PRIORITY_NOTSET;
3936 return 0;
3937 }
3938
3939 static inline int clr_config_logfile(const char *key, struct lxc_conf *c)
3940 {
3941 free(c->logfile);
3942 c->logfile = NULL;
3943 return 0;
3944 }
3945
3946 static inline int clr_config_mount(const char *key, struct lxc_conf *c)
3947 {
3948 return lxc_clear_mount_entries(c);
3949 }
3950
3951 static inline int clr_config_mount_auto(const char *key, struct lxc_conf *c)
3952 {
3953 return lxc_clear_automounts(c);
3954 }
3955
3956 static inline int clr_config_fstab(const char *key, struct lxc_conf *c)
3957 {
3958 free(c->fstab);
3959 c->fstab = NULL;
3960 return 0;
3961 }
3962
3963 static inline int clr_config_rootfs(const char *key, struct lxc_conf *c)
3964 {
3965 free(c->rootfs.path);
3966 c->rootfs.path = NULL;
3967 return 0;
3968 }
3969
3970 static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c)
3971 {
3972 free(c->rootfs.mount);
3973 c->rootfs.mount = NULL;
3974 return 0;
3975 }
3976
3977 static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c)
3978 {
3979 free(c->rootfs.options);
3980 c->rootfs.options = NULL;
3981 return 0;
3982 }
3983
3984 static inline int clr_config_rootfs_backend(const char *key, struct lxc_conf *c)
3985 {
3986 free(c->rootfs.bdev_type);
3987 c->rootfs.bdev_type = NULL;
3988 return 0;
3989 }
3990
3991 static inline int clr_config_pivotdir(const char *key, struct lxc_conf *c)
3992 {
3993 return 0;
3994 }
3995
3996 static inline int clr_config_utsname(const char *key, struct lxc_conf *c)
3997 {
3998 free(c->utsname);
3999 c->utsname = NULL;
4000 return 0;
4001 }
4002
4003 static inline int clr_config_hooks(const char *key, struct lxc_conf *c)
4004 {
4005 return lxc_clear_hooks(c, key);
4006 }
4007
4008 static inline int clr_config_network_item(const char *key, struct lxc_conf *c)
4009 {
4010 return lxc_clear_nic(c, key + 12);
4011 }
4012
4013 static inline int clr_config_network(const char *key, struct lxc_conf *c)
4014 {
4015 return lxc_clear_config_network(c);
4016 }
4017
4018 static inline int clr_config_cap_drop(const char *key, struct lxc_conf *c)
4019 {
4020 return lxc_clear_config_caps(c);
4021 }
4022
4023 static inline int clr_config_cap_keep(const char *key, struct lxc_conf *c)
4024 {
4025 return lxc_clear_config_keepcaps(c);
4026 }
4027
4028 static inline int clr_config_console(const char *key, struct lxc_conf *c)
4029 {
4030 free(c->console.path);
4031 c->console.path = NULL;
4032 return 0;
4033 }
4034
4035 static inline int clr_config_console_logfile(const char *key,
4036 struct lxc_conf *c)
4037 {
4038 free(c->console.log_path);
4039 c->console.log_path = NULL;
4040 return 0;
4041 }
4042
4043 static inline int clr_config_seccomp(const char *key, struct lxc_conf *c)
4044 {
4045 free(c->seccomp);
4046 c->seccomp = NULL;
4047 return 0;
4048 }
4049
4050 static inline int clr_config_autodev(const char *key, struct lxc_conf *c)
4051 {
4052 c->autodev = 1;
4053 return 0;
4054 }
4055
4056 static inline int clr_config_haltsignal(const char *key, struct lxc_conf *c)
4057 {
4058 c->haltsignal = 0;
4059 return 0;
4060 }
4061
4062 static inline int clr_config_rebootsignal(const char *key, struct lxc_conf *c)
4063 {
4064 c->rebootsignal = 0;
4065 return 0;
4066 }
4067
4068 static inline int clr_config_stopsignal(const char *key, struct lxc_conf *c)
4069 {
4070 c->stopsignal = 0;
4071 return 0;
4072 }
4073
4074 static inline int clr_config_start(const char *key, struct lxc_conf *c)
4075 {
4076 if (strcmp(key + 10, "auto") == 0)
4077 c->start_auto = 0;
4078 else if (strcmp(key + 10, "delay") == 0)
4079 c->start_delay = 0;
4080 else if (strcmp(key + 10, "order") == 0)
4081 c->start_order = 0;
4082
4083 return 0;
4084 }
4085
4086 static inline int clr_config_syslog(const char *key, struct lxc_conf *c)
4087 {
4088 free(c->syslog);
4089 c->syslog = NULL;
4090 return 0;
4091 }
4092
4093 static inline int clr_config_monitor(const char *key, struct lxc_conf *c)
4094 {
4095 c->monitor_unshare = 0;
4096 return 0;
4097 }
4098
4099 static inline int clr_config_group(const char *key, struct lxc_conf *c)
4100 {
4101 return lxc_clear_groups(c);
4102 }
4103
4104 static inline int clr_config_environment(const char *key, struct lxc_conf *c)
4105 {
4106 return lxc_clear_environment(c);
4107 }
4108
4109 static inline int clr_config_init_cmd(const char *key, struct lxc_conf *c)
4110 {
4111 free(c->init_cmd);
4112 c->init_cmd = NULL;
4113 return 0;
4114 }
4115
4116 static inline int clr_config_init_uid(const char *key, struct lxc_conf *c)
4117 {
4118 c->init_uid = 0;
4119 return 0;
4120 }
4121
4122 static inline int clr_config_init_gid(const char *key, struct lxc_conf *c)
4123 {
4124 c->init_gid = 0;
4125 return 0;
4126 }
4127
4128 static inline int clr_config_ephemeral(const char *key, struct lxc_conf *c)
4129 {
4130 c->ephemeral = 0;
4131 return 0;
4132 }
4133
4134 static inline int clr_config_no_new_privs(const char *key, struct lxc_conf *c)
4135 {
4136 c->no_new_privs = false;
4137 return 0;
4138 }
4139
4140 static inline int clr_config_limit(const char *key, struct lxc_conf *c)
4141 {
4142 return lxc_clear_limits(c, key);
4143 }
4144
4145 static inline int clr_config_includefiles(const char *key, struct lxc_conf *c)
4146 {
4147 lxc_clear_includes(c);
4148 return 0;
4149 }
4150
4151 static int get_config_includefiles(const char *key, char *retv, int inlen,
4152 struct lxc_conf *c)
4153 {
4154 return -ENOSYS;
4155 }