]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/confile.c
confile: rename lxc.limit to lxc.prlimit
[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_legacy.h"
49 #include "confile_utils.h"
50 #include "utils.h"
51 #include "log.h"
52 #include "conf.h"
53 #include "network.h"
54 #include "lxcseccomp.h"
55
56 #if HAVE_IFADDRS_H
57 #include <ifaddrs.h>
58 #else
59 #include <../include/ifaddrs.h>
60 #endif
61
62 #if HAVE_SYS_PERSONALITY_H
63 #include <sys/personality.h>
64 #endif
65
66 lxc_log_define(lxc_confile, lxc);
67
68 #define lxc_config_define(name) \
69 static int set_config_##name(const char *, const char *, \
70 struct lxc_conf *, void *); \
71 static int get_config_##name(const char *, char *, int, \
72 struct lxc_conf *, void *); \
73 static int clr_config_##name(const char *, struct lxc_conf *, \
74 void *);
75
76
77 lxc_config_define(personality);
78 lxc_config_define(pts);
79 lxc_config_define(tty);
80 lxc_config_define(ttydir);
81 lxc_config_define(apparmor_profile);
82 lxc_config_define(apparmor_allow_incomplete);
83 lxc_config_define(selinux_context);
84 lxc_config_define(cgroup);
85 lxc_config_define(idmaps);
86 lxc_config_define(loglevel);
87 lxc_config_define(logfile);
88 lxc_config_define(mount);
89 lxc_config_define(mount_auto);
90 lxc_config_define(fstab);
91 lxc_config_define(rootfs_mount);
92 lxc_config_define(rootfs_options);
93 lxc_config_define(rootfs_backend);
94 lxc_config_define(rootfs);
95 lxc_config_define(utsname);
96 lxc_config_define(hooks);
97 lxc_config_define(net_type);
98 lxc_config_define(net_flags);
99 lxc_config_define(net_link);
100 lxc_config_define(net_name);
101 lxc_config_define(net_veth_pair);
102 lxc_config_define(net_macvlan_mode);
103 lxc_config_define(net_hwaddr);
104 lxc_config_define(net_vlan_id);
105 lxc_config_define(net_mtu);
106 lxc_config_define(net_ipv4);
107 lxc_config_define(net_ipv4_gateway);
108 lxc_config_define(net_script_up);
109 lxc_config_define(net_script_down);
110 lxc_config_define(net_ipv6);
111 lxc_config_define(net_ipv6_gateway);
112 lxc_config_define(net_nic);
113 lxc_config_define(net);
114 lxc_config_define(cap_drop);
115 lxc_config_define(cap_keep);
116 lxc_config_define(console_logfile);
117 lxc_config_define(console);
118 lxc_config_define(seccomp);
119 lxc_config_define(includefiles);
120 lxc_config_define(autodev);
121 lxc_config_define(haltsignal);
122 lxc_config_define(rebootsignal);
123 lxc_config_define(stopsignal);
124 lxc_config_define(start);
125 lxc_config_define(monitor);
126 lxc_config_define(group);
127 lxc_config_define(environment);
128 lxc_config_define(init_cmd);
129 lxc_config_define(init_uid);
130 lxc_config_define(init_gid);
131 lxc_config_define(ephemeral);
132 lxc_config_define(syslog);
133 lxc_config_define(no_new_privs);
134 lxc_config_define(prlimit);
135
136 static struct lxc_config_t config[] = {
137 { "lxc.arch", set_config_personality, get_config_personality, clr_config_personality, },
138 { "lxc.pts", set_config_pts, get_config_pts, clr_config_pts, },
139 { "lxc.tty", set_config_tty, get_config_tty, clr_config_tty, },
140 { "lxc.devttydir", set_config_ttydir, get_config_ttydir, clr_config_ttydir, },
141 { "lxc.apparmor.profile", set_config_apparmor_profile, get_config_apparmor_profile, clr_config_apparmor_profile, },
142 { "lxc.apparmor.allow_incomplete", set_config_apparmor_allow_incomplete, get_config_apparmor_allow_incomplete, clr_config_apparmor_allow_incomplete, },
143 { "lxc.selinux.context", set_config_selinux_context, get_config_selinux_context, clr_config_selinux_context, },
144
145 /* REMOVE IN LXC 3.0
146 legacy security keys
147 */
148 { "lxc.aa_profile", set_config_lsm_aa_profile, get_config_lsm_aa_profile, clr_config_lsm_aa_profile, },
149 { "lxc.aa_allow_incomplete", set_config_lsm_aa_incomplete, get_config_lsm_aa_incomplete, clr_config_lsm_aa_incomplete, },
150 { "lxc.se_context", set_config_lsm_se_context, get_config_lsm_se_context, clr_config_lsm_se_context, },
151
152 { "lxc.cgroup", set_config_cgroup, get_config_cgroup, clr_config_cgroup, },
153 { "lxc.id_map", set_config_idmaps, get_config_idmaps, clr_config_idmaps, },
154 { "lxc.loglevel", set_config_loglevel, get_config_loglevel, clr_config_loglevel, },
155 { "lxc.logfile", set_config_logfile, get_config_logfile, clr_config_logfile, },
156 { "lxc.mount.entry", set_config_mount, get_config_mount, clr_config_mount, },
157 { "lxc.mount.auto", set_config_mount_auto, get_config_mount_auto, clr_config_mount_auto, },
158 { "lxc.mount", set_config_fstab, get_config_fstab, clr_config_fstab, },
159 { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, },
160 { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, },
161 { "lxc.rootfs.backend", set_config_rootfs_backend, get_config_rootfs_backend, clr_config_rootfs_backend, },
162 { "lxc.rootfs", set_config_rootfs, get_config_rootfs, clr_config_rootfs, },
163 { "lxc.utsname", set_config_utsname, get_config_utsname, clr_config_utsname, },
164 { "lxc.hook.pre-start", set_config_hooks, get_config_hooks, clr_config_hooks, },
165 { "lxc.hook.pre-mount", set_config_hooks, get_config_hooks, clr_config_hooks, },
166 { "lxc.hook.mount", set_config_hooks, get_config_hooks, clr_config_hooks, },
167 { "lxc.hook.autodev", set_config_hooks, get_config_hooks, clr_config_hooks, },
168 { "lxc.hook.start", set_config_hooks, get_config_hooks, clr_config_hooks, },
169 { "lxc.hook.stop", set_config_hooks, get_config_hooks, clr_config_hooks, },
170 { "lxc.hook.post-stop", set_config_hooks, get_config_hooks, clr_config_hooks, },
171 { "lxc.hook.clone", set_config_hooks, get_config_hooks, clr_config_hooks, },
172 { "lxc.hook.destroy", set_config_hooks, get_config_hooks, clr_config_hooks, },
173 { "lxc.hook", set_config_hooks, get_config_hooks, clr_config_hooks, },
174
175 /* REMOVE IN LXC 3.0
176 legacy security keys
177 */
178 { "lxc.network.type", set_config_network_legacy_type, get_config_network_legacy_item, clr_config_network_legacy_item, },
179 { "lxc.network.flags", set_config_network_legacy_flags, get_config_network_legacy_item, clr_config_network_legacy_item, },
180 { "lxc.network.link", set_config_network_legacy_link, get_config_network_legacy_item, clr_config_network_legacy_item, },
181 { "lxc.network.name", set_config_network_legacy_name, get_config_network_legacy_item, clr_config_network_legacy_item, },
182 { "lxc.network.macvlan.mode", set_config_network_legacy_macvlan_mode, get_config_network_legacy_item, clr_config_network_legacy_item, },
183 { "lxc.network.veth.pair", set_config_network_legacy_veth_pair, get_config_network_legacy_item, clr_config_network_legacy_item, },
184 { "lxc.network.script.up", set_config_network_legacy_script_up, get_config_network_legacy_item, clr_config_network_legacy_item, },
185 { "lxc.network.script.down", set_config_network_legacy_script_down, get_config_network_legacy_item, clr_config_network_legacy_item, },
186 { "lxc.network.hwaddr", set_config_network_legacy_hwaddr, get_config_network_legacy_item, clr_config_network_legacy_item, },
187 { "lxc.network.mtu", set_config_network_legacy_mtu, get_config_network_legacy_item, clr_config_network_legacy_item, },
188 { "lxc.network.vlan.id", set_config_network_legacy_vlan_id, get_config_network_legacy_item, clr_config_network_legacy_item, },
189 { "lxc.network.ipv4.gateway", set_config_network_legacy_ipv4_gateway, get_config_network_legacy_item, clr_config_network_legacy_item, },
190 { "lxc.network.ipv4", set_config_network_legacy_ipv4, get_config_network_legacy_item, clr_config_network_legacy_item, },
191 { "lxc.network.ipv6.gateway", set_config_network_legacy_ipv6_gateway, get_config_network_legacy_item, clr_config_network_legacy_item, },
192 { "lxc.network.ipv6", set_config_network_legacy_ipv6, get_config_network_legacy_item, clr_config_network_legacy_item, },
193 { "lxc.network.", set_config_network_legacy_nic, get_config_network_legacy_item, clr_config_network_legacy_item, },
194 { "lxc.network", set_config_network_legacy, get_config_network_legacy, clr_config_network_legacy, },
195
196 { "lxc.net.type", set_config_net_type, get_config_net_type, clr_config_net_type, },
197 { "lxc.net.flags", set_config_net_flags, get_config_net_flags, clr_config_net_flags, },
198 { "lxc.net.link", set_config_net_link, get_config_net_link, clr_config_net_link, },
199 { "lxc.net.name", set_config_net_name, get_config_net_name, clr_config_net_name, },
200 { "lxc.net.macvlan.mode", set_config_net_macvlan_mode, get_config_net_macvlan_mode, clr_config_net_macvlan_mode, },
201 { "lxc.net.veth.pair", set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, },
202 { "lxc.net.script.up", set_config_net_script_up, get_config_net_script_up, clr_config_net_script_up, },
203 { "lxc.net.script.down", set_config_net_script_down, get_config_net_script_down, clr_config_net_script_down, },
204 { "lxc.net.hwaddr", set_config_net_hwaddr, get_config_net_hwaddr, clr_config_net_hwaddr, },
205 { "lxc.net.mtu", set_config_net_mtu, get_config_net_mtu, clr_config_net_mtu, },
206 { "lxc.net.vlan.id", set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, },
207 { "lxc.net.ipv4.gateway", set_config_net_ipv4_gateway, get_config_net_ipv4_gateway, clr_config_net_ipv4_gateway, },
208 { "lxc.net.ipv4", set_config_net_ipv4, get_config_net_ipv4, clr_config_net_ipv4, },
209 { "lxc.net.ipv6.gateway", set_config_net_ipv6_gateway, get_config_net_ipv6_gateway, clr_config_net_ipv6_gateway, },
210 { "lxc.net.ipv6", set_config_net_ipv6, get_config_net_ipv6, clr_config_net_ipv6, },
211 { "lxc.net.", set_config_net_nic, get_config_net_nic, clr_config_net_nic, },
212 { "lxc.net", set_config_net, get_config_net, clr_config_net, },
213 { "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, },
214 { "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
215 { "lxc.console.logfile", set_config_console_logfile, get_config_console_logfile, clr_config_console_logfile, },
216 { "lxc.console", set_config_console, get_config_console, clr_config_console, },
217 { "lxc.seccomp", set_config_seccomp, get_config_seccomp, clr_config_seccomp, },
218 { "lxc.include", set_config_includefiles, get_config_includefiles, clr_config_includefiles, },
219 { "lxc.autodev", set_config_autodev, get_config_autodev, clr_config_autodev, },
220 { "lxc.haltsignal", set_config_haltsignal, get_config_haltsignal, clr_config_haltsignal, },
221 { "lxc.rebootsignal", set_config_rebootsignal, get_config_rebootsignal, clr_config_rebootsignal, },
222 { "lxc.stopsignal", set_config_stopsignal, get_config_stopsignal, clr_config_stopsignal, },
223 { "lxc.start.auto", set_config_start, get_config_start, clr_config_start, },
224 { "lxc.start.delay", set_config_start, get_config_start, clr_config_start, },
225 { "lxc.start.order", set_config_start, get_config_start, clr_config_start, },
226 { "lxc.monitor.unshare", set_config_monitor, get_config_monitor, clr_config_monitor, },
227 { "lxc.group", set_config_group, get_config_group, clr_config_group, },
228 { "lxc.environment", set_config_environment, get_config_environment, clr_config_environment, },
229 { "lxc.init_cmd", set_config_init_cmd, get_config_init_cmd, clr_config_init_cmd, },
230 { "lxc.init_uid", set_config_init_uid, get_config_init_uid, clr_config_init_uid, },
231 { "lxc.init_gid", set_config_init_gid, get_config_init_gid, clr_config_init_gid, },
232 { "lxc.ephemeral", set_config_ephemeral, get_config_ephemeral, clr_config_ephemeral, },
233 { "lxc.syslog", set_config_syslog, get_config_syslog, clr_config_syslog, },
234 { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
235
236 /* REMOVE IN LXC 3.0
237 legacy keys
238 */
239 { "lxc.limit", set_config_limit, get_config_limit, clr_config_limit, },
240
241 { "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, },
242 };
243
244 struct signame {
245 int num;
246 const char *name;
247 };
248
249 static const struct signame signames[] = {
250 { SIGHUP, "HUP" },
251 { SIGINT, "INT" },
252 { SIGQUIT, "QUIT" },
253 { SIGILL, "ILL" },
254 { SIGABRT, "ABRT" },
255 { SIGFPE, "FPE" },
256 { SIGKILL, "KILL" },
257 { SIGSEGV, "SEGV" },
258 { SIGPIPE, "PIPE" },
259 { SIGALRM, "ALRM" },
260 { SIGTERM, "TERM" },
261 { SIGUSR1, "USR1" },
262 { SIGUSR2, "USR2" },
263 { SIGCHLD, "CHLD" },
264 { SIGCONT, "CONT" },
265 { SIGSTOP, "STOP" },
266 { SIGTSTP, "TSTP" },
267 { SIGTTIN, "TTIN" },
268 { SIGTTOU, "TTOU" },
269 #ifdef SIGTRAP
270 { SIGTRAP, "TRAP" },
271 #endif
272 #ifdef SIGIOT
273 { SIGIOT, "IOT" },
274 #endif
275 #ifdef SIGEMT
276 { SIGEMT, "EMT" },
277 #endif
278 #ifdef SIGBUS
279 { SIGBUS, "BUS" },
280 #endif
281 #ifdef SIGSTKFLT
282 { SIGSTKFLT, "STKFLT" },
283 #endif
284 #ifdef SIGCLD
285 { SIGCLD, "CLD" },
286 #endif
287 #ifdef SIGURG
288 { SIGURG, "URG" },
289 #endif
290 #ifdef SIGXCPU
291 { SIGXCPU, "XCPU" },
292 #endif
293 #ifdef SIGXFSZ
294 { SIGXFSZ, "XFSZ" },
295 #endif
296 #ifdef SIGVTALRM
297 { SIGVTALRM, "VTALRM" },
298 #endif
299 #ifdef SIGPROF
300 { SIGPROF, "PROF" },
301 #endif
302 #ifdef SIGWINCH
303 { SIGWINCH, "WINCH" },
304 #endif
305 #ifdef SIGIO
306 { SIGIO, "IO" },
307 #endif
308 #ifdef SIGPOLL
309 { SIGPOLL, "POLL" },
310 #endif
311 #ifdef SIGINFO
312 { SIGINFO, "INFO" },
313 #endif
314 #ifdef SIGLOST
315 { SIGLOST, "LOST" },
316 #endif
317 #ifdef SIGPWR
318 { SIGPWR, "PWR" },
319 #endif
320 #ifdef SIGUNUSED
321 { SIGUNUSED, "UNUSED" },
322 #endif
323 #ifdef SIGSYS
324 { SIGSYS, "SYS" },
325 #endif
326 };
327
328 static const size_t config_size = sizeof(config) / sizeof(struct lxc_config_t);
329
330 extern struct lxc_config_t *lxc_getconfig(const char *key)
331 {
332 size_t i;
333
334 for (i = 0; i < config_size; i++)
335 if (!strncmp(config[i].name, key, strlen(config[i].name)))
336 return &config[i];
337 return NULL;
338 }
339
340 int lxc_listconfigs(char *retv, int inlen)
341 {
342 size_t i;
343 int len;
344 int fulllen = 0;
345
346 if (!retv)
347 inlen = 0;
348 else
349 memset(retv, 0, inlen);
350
351 for (i = 0; i < config_size; i++) {
352 char *s = config[i].name;
353 if (s[strlen(s) - 1] == '.')
354 continue;
355 strprint(retv, inlen, "%s\n", s);
356 }
357
358 return fulllen;
359 }
360
361 static int set_config_net(const char *key, const char *value,
362 struct lxc_conf *lxc_conf, void *data)
363 {
364 if (!lxc_config_value_empty(value)) {
365 ERROR("lxc.net must not have a value");
366 return -1;
367 }
368
369 return clr_config_net(key, lxc_conf, data);
370 }
371
372 static int set_config_net_type(const char *key, const char *value,
373 struct lxc_conf *lxc_conf, void *data)
374 {
375 struct lxc_netdev *netdev;
376
377 if (lxc_config_value_empty(value))
378 return clr_config_net_type(key, lxc_conf, data);
379
380 if (!data)
381 return -1;
382 else
383 netdev = data;
384 if (!netdev)
385 return -1;
386
387 if (!strcmp(value, "veth")) {
388 netdev->type = LXC_NET_VETH;
389 } else if (!strcmp(value, "macvlan")) {
390 netdev->type = LXC_NET_MACVLAN;
391 lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode,
392 "private");
393 } else if (!strcmp(value, "vlan")) {
394 netdev->type = LXC_NET_VLAN;
395 } else if (!strcmp(value, "phys")) {
396 netdev->type = LXC_NET_PHYS;
397 } else if (!strcmp(value, "empty")) {
398 netdev->type = LXC_NET_EMPTY;
399 } else if (!strcmp(value, "none")) {
400 netdev->type = LXC_NET_NONE;
401 } else {
402 ERROR("invalid network type %s", value);
403 return -1;
404 }
405
406 return 0;
407 }
408
409 /*
410 * If you have p="lxc.net.0.link", pass it p+8
411 * to get back '0' (the index of the nic).
412 */
413 static int get_network_netdev_idx(const char *key)
414 {
415 int ret, idx;
416
417 if (*key < '0' || *key > '9')
418 return -1;
419
420 ret = sscanf(key, "%d", &idx);
421 if (ret != 1)
422 return -1;
423
424 return idx;
425 }
426
427 /*
428 * If you have p="lxc.net.0", pass this p+8 and it will return
429 * the netdev of the first configured nic.
430 */
431 static struct lxc_netdev *get_netdev_from_key(const char *key,
432 struct lxc_list *network)
433 {
434 int idx;
435 struct lxc_list *it;
436 int i = 0;
437 struct lxc_netdev *netdev = NULL;
438
439 idx = get_network_netdev_idx(key);
440 if (idx == -1)
441 return NULL;
442
443 lxc_list_for_each(it, network) {
444 if (idx == i++) {
445 netdev = it->elem;
446 break;
447 }
448 }
449
450 return netdev;
451 }
452
453 extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv,
454 int inlen)
455 {
456 struct lxc_netdev *netdev;
457 int len;
458 int fulllen = 0;
459
460 netdev = get_netdev_from_key(key + 8, &c->network);
461 if (!netdev)
462 return -1;
463
464 if (!retv)
465 inlen = 0;
466 else
467 memset(retv, 0, inlen);
468
469 strprint(retv, inlen, "type\n");
470 strprint(retv, inlen, "script.up\n");
471 strprint(retv, inlen, "script.down\n");
472 if (netdev->type != LXC_NET_EMPTY) {
473 strprint(retv, inlen, "flags\n");
474 strprint(retv, inlen, "link\n");
475 strprint(retv, inlen, "name\n");
476 strprint(retv, inlen, "hwaddr\n");
477 strprint(retv, inlen, "mtu\n");
478 strprint(retv, inlen, "ipv6\n");
479 strprint(retv, inlen, "ipv6.gateway\n");
480 strprint(retv, inlen, "ipv4\n");
481 strprint(retv, inlen, "ipv4.gateway\n");
482 }
483
484 switch (netdev->type) {
485 case LXC_NET_VETH:
486 strprint(retv, inlen, "veth.pair\n");
487 break;
488 case LXC_NET_MACVLAN:
489 strprint(retv, inlen, "macvlan.mode\n");
490 break;
491 case LXC_NET_VLAN:
492 strprint(retv, inlen, "vlan.id\n");
493 break;
494 case LXC_NET_PHYS:
495 break;
496 }
497
498 return fulllen;
499 }
500
501 static int set_config_net_flags(const char *key, const char *value,
502 struct lxc_conf *lxc_conf, void *data)
503 {
504 struct lxc_netdev *netdev;
505
506 if (lxc_config_value_empty(value))
507 return clr_config_net_flags(key, lxc_conf, data);
508
509 if (!data)
510 return -1;
511 else
512 netdev = data;
513 if (!netdev)
514 return -1;
515
516 netdev->flags |= IFF_UP;
517
518 return 0;
519 }
520
521 static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf,
522 struct lxc_netdev *netdev)
523 {
524 struct ifaddrs *ifaddr, *ifa;
525 int n;
526 int ret = 0;
527 const char *type_key = "lxc.net.type";
528 const char *link_key = "lxc.net.link";
529 const char *tmpvalue = "phys";
530
531 if (getifaddrs(&ifaddr) == -1) {
532 SYSERROR("Get network interfaces failed");
533 return -1;
534 }
535
536 for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
537 if (!ifa->ifa_addr)
538 continue;
539 if (ifa->ifa_addr->sa_family != AF_PACKET)
540 continue;
541
542 if (!strncmp(value, ifa->ifa_name, strlen(value) - 1)) {
543 ret = set_config_net_type(type_key, tmpvalue, lxc_conf,
544 netdev);
545 if (!ret) {
546 ret = set_config_net_link(
547 link_key, ifa->ifa_name, lxc_conf, netdev);
548 if (ret) {
549 ERROR("failed to create matched ifnames");
550 break;
551 }
552 } else {
553 ERROR("failed to create matched ifnames");
554 break;
555 }
556 }
557 }
558
559 freeifaddrs(ifaddr);
560 ifaddr = NULL;
561
562 return ret;
563 }
564
565 static int set_config_net_link(const char *key, const char *value,
566 struct lxc_conf *lxc_conf, void *data)
567 {
568 struct lxc_netdev *netdev;
569 int ret = 0;
570
571 if (lxc_config_value_empty(value))
572 return clr_config_net_link(key, lxc_conf, data);
573
574 if (!data)
575 return -1;
576 else
577 netdev = data;
578 if (!netdev)
579 return -1;
580
581 if (value[strlen(value) - 1] == '+' && netdev->type == LXC_NET_PHYS)
582 ret = create_matched_ifnames(value, lxc_conf, netdev);
583 else
584 ret = network_ifname(&netdev->link, value);
585
586 return ret;
587 }
588
589 static int set_config_net_name(const char *key, const char *value,
590 struct lxc_conf *lxc_conf, void *data)
591 {
592 struct lxc_netdev *netdev;
593
594 if (lxc_config_value_empty(value))
595 return clr_config_net_name(key, lxc_conf, data);
596
597 if (!data)
598 return -1;
599 else
600 netdev = data;
601 if (!netdev)
602 return -1;
603
604 return network_ifname(&netdev->name, value);
605 }
606
607 static int set_config_net_veth_pair(const char *key, const char *value,
608 struct lxc_conf *lxc_conf, void *data)
609 {
610 struct lxc_netdev *netdev;
611
612 if (lxc_config_value_empty(value))
613 return clr_config_net_veth_pair(key, lxc_conf, data);
614
615 if (!data)
616 return -1;
617 else
618 netdev = data;
619 if (!netdev)
620 return -1;
621
622 return network_ifname(&netdev->priv.veth_attr.pair, value);
623 }
624
625 static int set_config_net_macvlan_mode(const char *key, const char *value,
626 struct lxc_conf *lxc_conf, void *data)
627 {
628 struct lxc_netdev *netdev;
629
630 if (lxc_config_value_empty(value))
631 return clr_config_net_macvlan_mode(key, lxc_conf, data);
632
633 if (!data)
634 return -1;
635 else
636 netdev = data;
637 if (!netdev)
638 return -1;
639
640 return lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, value);
641 }
642
643 static int set_config_net_hwaddr(const char *key, const char *value,
644 struct lxc_conf *lxc_conf, void *data)
645 {
646 struct lxc_netdev *netdev;
647 char *new_value;
648
649 if (lxc_config_value_empty(value))
650 return clr_config_net_hwaddr(key, lxc_conf, data);
651
652 if (!data)
653 return -1;
654 else
655 netdev = data;
656 if (!netdev)
657 return -1;
658
659 new_value = strdup(value);
660 if (!new_value) {
661 SYSERROR("failed to strdup \"%s\"", value);
662 return -1;
663 }
664 rand_complete_hwaddr(new_value);
665
666 if (lxc_config_value_empty(new_value)) {
667 free(new_value);
668 netdev->hwaddr = NULL;
669 return 0;
670 }
671
672 netdev->hwaddr = new_value;
673 return 0;
674 }
675
676 static int set_config_net_vlan_id(const char *key, const char *value,
677 struct lxc_conf *lxc_conf, void *data)
678 {
679 struct lxc_netdev *netdev;
680
681 if (lxc_config_value_empty(value))
682 return clr_config_net_vlan_id(key, lxc_conf, data);
683
684 if (!data)
685 return -1;
686 else
687 netdev = data;
688 if (!netdev)
689 return -1;
690
691 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
692 return -1;
693
694 return 0;
695 }
696
697 static int set_config_net_mtu(const char *key, const char *value,
698 struct lxc_conf *lxc_conf, void *data)
699 {
700 struct lxc_netdev *netdev;
701
702 if (lxc_config_value_empty(value))
703 return clr_config_net_mtu(key, lxc_conf, data);
704
705 if (!data)
706 return -1;
707 else
708 netdev = data;
709 if (!netdev)
710 return -1;
711
712 return set_config_string_item(&netdev->mtu, value);
713 }
714
715 static int set_config_net_ipv4(const char *key, const char *value,
716 struct lxc_conf *lxc_conf, void *data)
717 {
718 struct lxc_netdev *netdev;
719 struct lxc_inetdev *inetdev;
720 struct lxc_list *list;
721 char *cursor, *slash;
722 char *addr = NULL, *bcast = NULL, *prefix = NULL;
723
724 if (lxc_config_value_empty(value))
725 return clr_config_net_ipv4(key, lxc_conf, data);
726
727 if (!data)
728 return -1;
729 else
730 netdev = data;
731 if (!netdev)
732 return -1;
733
734 inetdev = malloc(sizeof(*inetdev));
735 if (!inetdev) {
736 SYSERROR("failed to allocate ipv4 address");
737 return -1;
738 }
739 memset(inetdev, 0, sizeof(*inetdev));
740
741 list = malloc(sizeof(*list));
742 if (!list) {
743 SYSERROR("failed to allocate memory");
744 free(inetdev);
745 return -1;
746 }
747
748 lxc_list_init(list);
749 list->elem = inetdev;
750
751 addr = strdup(value);
752 if (!addr) {
753 ERROR("no address specified");
754 free(inetdev);
755 free(list);
756 return -1;
757 }
758
759 cursor = strstr(addr, " ");
760 if (cursor) {
761 *cursor = '\0';
762 bcast = cursor + 1;
763 }
764
765 slash = strstr(addr, "/");
766 if (slash) {
767 *slash = '\0';
768 prefix = slash + 1;
769 }
770
771 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
772 SYSERROR("invalid ipv4 address: %s", value);
773 free(inetdev);
774 free(addr);
775 free(list);
776 return -1;
777 }
778
779 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
780 SYSERROR("invalid ipv4 broadcast address: %s", value);
781 free(inetdev);
782 free(list);
783 free(addr);
784 return -1;
785 }
786
787 /* No prefix specified, determine it from the network class. */
788 if (prefix) {
789 if (lxc_safe_uint(prefix, &inetdev->prefix) < 0)
790 return -1;
791 } else {
792 inetdev->prefix = config_ip_prefix(&inetdev->addr);
793 }
794
795 /* If no broadcast address, let compute one from the
796 * prefix and address.
797 */
798 if (!bcast) {
799 inetdev->bcast.s_addr = inetdev->addr.s_addr;
800 inetdev->bcast.s_addr |=
801 htonl(INADDR_BROADCAST >> inetdev->prefix);
802 }
803
804 lxc_list_add_tail(&netdev->ipv4, list);
805
806 free(addr);
807 return 0;
808 }
809
810 static int set_config_net_ipv4_gateway(const char *key, const char *value,
811 struct lxc_conf *lxc_conf, void *data)
812 {
813 struct lxc_netdev *netdev;
814
815 if (lxc_config_value_empty(value))
816 return clr_config_net_ipv4_gateway(key, lxc_conf, data);
817
818 if (!data)
819 return -1;
820 else
821 netdev = data;
822 if (!netdev)
823 return -1;
824
825 free(netdev->ipv4_gateway);
826
827 if (!strcmp(value, "auto")) {
828 netdev->ipv4_gateway = NULL;
829 netdev->ipv4_gateway_auto = true;
830 } else {
831 struct in_addr *gw;
832
833 gw = malloc(sizeof(*gw));
834 if (!gw) {
835 SYSERROR("failed to allocate ipv4 gateway address");
836 return -1;
837 }
838
839 if (!inet_pton(AF_INET, value, gw)) {
840 SYSERROR("invalid ipv4 gateway address: %s", value);
841 free(gw);
842 return -1;
843 }
844
845 netdev->ipv4_gateway = gw;
846 netdev->ipv4_gateway_auto = false;
847 }
848
849 return 0;
850 }
851
852 static int set_config_net_ipv6(const char *key, const char *value,
853 struct lxc_conf *lxc_conf, void *data)
854 {
855 struct lxc_netdev *netdev;
856 struct lxc_inet6dev *inet6dev;
857 struct lxc_list *list;
858 char *slash, *valdup, *netmask;
859
860 if (lxc_config_value_empty(value))
861 return clr_config_net_ipv6(key, lxc_conf, data);
862
863 if (!data)
864 return -1;
865 else
866 netdev = data;
867 if (!netdev)
868 return -1;
869
870 inet6dev = malloc(sizeof(*inet6dev));
871 if (!inet6dev) {
872 SYSERROR("failed to allocate ipv6 address");
873 return -1;
874 }
875 memset(inet6dev, 0, sizeof(*inet6dev));
876
877 list = malloc(sizeof(*list));
878 if (!list) {
879 SYSERROR("failed to allocate memory");
880 free(inet6dev);
881 return -1;
882 }
883
884 lxc_list_init(list);
885 list->elem = inet6dev;
886
887 valdup = strdup(value);
888 if (!valdup) {
889 ERROR("no address specified");
890 free(list);
891 free(inet6dev);
892 return -1;
893 }
894
895 inet6dev->prefix = 64;
896 slash = strstr(valdup, "/");
897 if (slash) {
898 *slash = '\0';
899 netmask = slash + 1;
900 if (lxc_safe_uint(netmask, &inet6dev->prefix) < 0)
901 return -1;
902 }
903
904 if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {
905 SYSERROR("invalid ipv6 address: %s", valdup);
906 free(list);
907 free(inet6dev);
908 free(valdup);
909 return -1;
910 }
911
912 lxc_list_add_tail(&netdev->ipv6, list);
913
914 free(valdup);
915 return 0;
916 }
917
918 static int set_config_net_ipv6_gateway(const char *key, const char *value,
919 struct lxc_conf *lxc_conf, void *data)
920 {
921 struct lxc_netdev *netdev;
922
923 if (lxc_config_value_empty(value))
924 return clr_config_net_ipv6_gateway(key, lxc_conf, data);
925
926 if (!data)
927 return -1;
928 else
929 netdev = data;
930 if (!netdev)
931 return -1;
932
933 free(netdev->ipv6_gateway);
934
935 if (!strcmp(value, "auto")) {
936 netdev->ipv6_gateway = NULL;
937 netdev->ipv6_gateway_auto = true;
938 } else {
939 struct in6_addr *gw;
940
941 gw = malloc(sizeof(*gw));
942 if (!gw) {
943 SYSERROR("failed to allocate ipv6 gateway address");
944 return -1;
945 }
946
947 if (!inet_pton(AF_INET6, value, gw)) {
948 SYSERROR("invalid ipv6 gateway address: %s", value);
949 free(gw);
950 return -1;
951 }
952
953 netdev->ipv6_gateway = gw;
954 netdev->ipv6_gateway_auto = false;
955 }
956
957 return 0;
958 }
959
960 static int set_config_net_script_up(const char *key, const char *value,
961 struct lxc_conf *lxc_conf, void *data)
962 {
963 struct lxc_netdev *netdev;
964
965 if (lxc_config_value_empty(value))
966 return clr_config_net_script_up(key, lxc_conf, data);
967
968 if (!data)
969 return -1;
970 else
971 netdev = data;
972 if (!netdev)
973 return -1;
974
975 return set_config_string_item(&netdev->upscript, value);
976 }
977
978 static int set_config_net_script_down(const char *key, const char *value,
979 struct lxc_conf *lxc_conf, void *data)
980 {
981 struct lxc_netdev *netdev;
982
983 if (lxc_config_value_empty(value))
984 return clr_config_net_script_down(key, lxc_conf, data);
985
986 if (!data)
987 return -1;
988 else
989 netdev = data;
990 if (!netdev)
991 return -1;
992
993 return set_config_string_item(&netdev->downscript, value);
994 }
995
996 static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
997 {
998 struct lxc_list *hooklist;
999
1000 hooklist = malloc(sizeof(*hooklist));
1001 if (!hooklist) {
1002 free(hook);
1003 return -1;
1004 }
1005
1006 hooklist->elem = hook;
1007 lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
1008 return 0;
1009 }
1010
1011 static int set_config_seccomp(const char *key, const char *value,
1012 struct lxc_conf *lxc_conf, void *data)
1013 {
1014 return set_config_path_item(&lxc_conf->seccomp, value);
1015 }
1016
1017 static int set_config_init_cmd(const char *key, const char *value,
1018 struct lxc_conf *lxc_conf, void *data)
1019 {
1020 return set_config_path_item(&lxc_conf->init_cmd, value);
1021 }
1022
1023 static int set_config_init_uid(const char *key, const char *value,
1024 struct lxc_conf *lxc_conf, void *data)
1025 {
1026 unsigned int init_uid;
1027
1028 /* Set config value to default. */
1029 if (lxc_config_value_empty(value)) {
1030 lxc_conf->init_uid = 0;
1031 return 0;
1032 }
1033
1034 /* Parse new config value. */
1035 if (lxc_safe_uint(value, &init_uid) < 0)
1036 return -1;
1037 lxc_conf->init_uid = init_uid;
1038
1039 return 0;
1040 }
1041
1042 static int set_config_init_gid(const char *key, const char *value,
1043 struct lxc_conf *lxc_conf, void *data)
1044 {
1045 unsigned int init_gid;
1046
1047 /* Set config value to default. */
1048 if (lxc_config_value_empty(value)) {
1049 lxc_conf->init_gid = 0;
1050 return 0;
1051 }
1052
1053 /* Parse new config value. */
1054 if (lxc_safe_uint(value, &init_gid) < 0)
1055 return -1;
1056 lxc_conf->init_gid = init_gid;
1057
1058 return 0;
1059 }
1060
1061 static int set_config_hooks(const char *key, const char *value,
1062 struct lxc_conf *lxc_conf, void *data)
1063 {
1064 char *copy;
1065
1066 if (lxc_config_value_empty(value))
1067 return lxc_clear_hooks(lxc_conf, key);
1068
1069 if (strcmp(key + 4, "hook") == 0) {
1070 ERROR("lxc.hook cannot take a value");
1071 return -1;
1072 }
1073 copy = strdup(value);
1074 if (!copy) {
1075 SYSERROR("failed to dup string '%s'", value);
1076 return -1;
1077 }
1078
1079 if (strcmp(key + 9, "pre-start") == 0)
1080 return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
1081 else if (strcmp(key + 9, "pre-mount") == 0)
1082 return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
1083 else if (strcmp(key + 9, "autodev") == 0)
1084 return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
1085 else if (strcmp(key + 9, "mount") == 0)
1086 return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
1087 else if (strcmp(key + 9, "start") == 0)
1088 return add_hook(lxc_conf, LXCHOOK_START, copy);
1089 else if (strcmp(key + 9, "stop") == 0)
1090 return add_hook(lxc_conf, LXCHOOK_STOP, copy);
1091 else if (strcmp(key + 9, "post-stop") == 0)
1092 return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
1093 else if (strcmp(key + 9, "clone") == 0)
1094 return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
1095 else if (strcmp(key + 9, "destroy") == 0)
1096 return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
1097
1098 SYSERROR("Unknown key: %s", key);
1099 free(copy);
1100 return -1;
1101 }
1102
1103 static int set_config_personality(const char *key, const char *value,
1104 struct lxc_conf *lxc_conf, void *data)
1105 {
1106 signed long personality = lxc_config_parse_arch(value);
1107
1108 if (personality >= 0)
1109 lxc_conf->personality = personality;
1110 else
1111 WARN("unsupported personality '%s'", value);
1112
1113 return 0;
1114 }
1115
1116 static int set_config_pts(const char *key, const char *value,
1117 struct lxc_conf *lxc_conf, void *data)
1118 {
1119 /* Set config value to default. */
1120 if (lxc_config_value_empty(value)) {
1121 lxc_conf->pts = 0;
1122 return 0;
1123 }
1124
1125 /* Parse new config value. */
1126 if (lxc_safe_uint(value, &lxc_conf->pts) < 0)
1127 return -1;
1128
1129 return 0;
1130 }
1131
1132 /* We only need to check whether the first byte of the key after the lxc.start.
1133 * prefix matches our expectations since they fortunately all start with a
1134 * different letter. If anything was wrong with the key we would have already
1135 * noticed when the callback was called.
1136 */
1137 static int set_config_start(const char *key, const char *value,
1138 struct lxc_conf *lxc_conf, void *data)
1139 {
1140 bool is_empty;
1141
1142 is_empty = lxc_config_value_empty(value);
1143
1144 if (*(key + 10) == 'a') { /* lxc.start.auto */
1145 /* Set config value to default. */
1146 if (is_empty) {
1147 lxc_conf->start_auto = 0;
1148 return 0;
1149 }
1150
1151 /* Parse new config value. */
1152 if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0)
1153 return -1;
1154
1155 if (lxc_conf->start_auto > 1)
1156 return -1;
1157
1158 return 0;
1159 } else if (*(key + 10) == 'd') { /* lxc.start.delay */
1160 /* Set config value to default. */
1161 if (is_empty) {
1162 lxc_conf->start_delay = 0;
1163 return 0;
1164 }
1165
1166 /* Parse new config value. */
1167 return lxc_safe_uint(value, &lxc_conf->start_delay);
1168 } else if (*(key + 10) == 'o') { /* lxc.start.order */
1169 /* Set config value to default. */
1170 if (is_empty) {
1171 lxc_conf->start_order = 0;
1172 return 0;
1173 }
1174
1175 /* Parse new config value. */
1176 return lxc_safe_int(value, &lxc_conf->start_order);
1177 }
1178
1179 SYSERROR("Unknown key: %s", key);
1180 return -1;
1181 }
1182
1183 static int set_config_monitor(const char *key, const char *value,
1184 struct lxc_conf *lxc_conf, void *data)
1185 {
1186 /* Set config value to default. */
1187 if (lxc_config_value_empty(value)) {
1188 lxc_conf->monitor_unshare = 0;
1189 return 0;
1190 }
1191
1192 /* Parse new config value. */
1193 if (strcmp(key + 12, "unshare") == 0)
1194 return lxc_safe_uint(value, &lxc_conf->monitor_unshare);
1195
1196 SYSERROR("Unknown key: %s", key);
1197 return -1;
1198 }
1199
1200 static int set_config_group(const char *key, const char *value,
1201 struct lxc_conf *lxc_conf, void *data)
1202 {
1203 char *groups, *groupptr, *sptr, *token;
1204 struct lxc_list *grouplist;
1205 int ret = -1;
1206
1207 if (lxc_config_value_empty(value))
1208 return lxc_clear_groups(lxc_conf);
1209
1210 groups = strdup(value);
1211 if (!groups) {
1212 SYSERROR("failed to dup '%s'", value);
1213 return -1;
1214 }
1215
1216 /* In case several groups are specified in a single line
1217 * split these groups in a single element for the list.
1218 */
1219 for (groupptr = groups;; groupptr = NULL) {
1220 token = strtok_r(groupptr, " \t", &sptr);
1221 if (!token) {
1222 ret = 0;
1223 break;
1224 }
1225
1226 grouplist = malloc(sizeof(*grouplist));
1227 if (!grouplist) {
1228 SYSERROR("failed to allocate groups list");
1229 break;
1230 }
1231
1232 grouplist->elem = strdup(token);
1233 if (!grouplist->elem) {
1234 SYSERROR("failed to dup '%s'", token);
1235 free(grouplist);
1236 break;
1237 }
1238
1239 lxc_list_add_tail(&lxc_conf->groups, grouplist);
1240 }
1241
1242 free(groups);
1243 return ret;
1244 }
1245
1246 static int set_config_environment(const char *key, const char *value,
1247 struct lxc_conf *lxc_conf, void *data)
1248 {
1249 struct lxc_list *list_item = NULL;
1250
1251 if (lxc_config_value_empty(value))
1252 return lxc_clear_environment(lxc_conf);
1253
1254 list_item = malloc(sizeof(*list_item));
1255 if (!list_item)
1256 goto on_error;
1257
1258 list_item->elem = strdup(value);
1259
1260 if (!list_item->elem)
1261 goto on_error;
1262
1263 lxc_list_add_tail(&lxc_conf->environment, list_item);
1264
1265 return 0;
1266
1267 on_error:
1268 free(list_item);
1269 return -1;
1270 }
1271
1272 static int set_config_tty(const char *key, const char *value,
1273 struct lxc_conf *lxc_conf, void *data)
1274 {
1275 /* Set config value to default. */
1276 if (lxc_config_value_empty(value)) {
1277 lxc_conf->tty = 0;
1278 return 0;
1279 }
1280
1281 /* Parse new config value. */
1282 return lxc_safe_uint(value, &lxc_conf->tty);
1283 }
1284
1285 static int set_config_ttydir(const char *key, const char *value,
1286 struct lxc_conf *lxc_conf, void *data)
1287 {
1288 return set_config_string_item_max(&lxc_conf->ttydir, value,
1289 NAME_MAX + 1);
1290 }
1291
1292 static int set_config_apparmor_profile(const char *key, const char *value,
1293 struct lxc_conf *lxc_conf, void *data)
1294 {
1295 return set_config_string_item(&lxc_conf->lsm_aa_profile, value);
1296 }
1297
1298 static int set_config_apparmor_allow_incomplete(const char *key,
1299 const char *value,
1300 struct lxc_conf *lxc_conf,
1301 void *data)
1302 {
1303 /* Set config value to default. */
1304 if (lxc_config_value_empty(value)) {
1305 lxc_conf->lsm_aa_allow_incomplete = 0;
1306 return 0;
1307 }
1308
1309 /* Parse new config value. */
1310 if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0)
1311 return -1;
1312
1313 if (lxc_conf->lsm_aa_allow_incomplete > 1) {
1314 ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only "
1315 "be set to 0 or 1");
1316 return -1;
1317 }
1318
1319 return 0;
1320 }
1321
1322 static int set_config_selinux_context(const char *key, const char *value,
1323 struct lxc_conf *lxc_conf, void *data)
1324 {
1325 return set_config_string_item(&lxc_conf->lsm_se_context, value);
1326 }
1327
1328 static int set_config_logfile(const char *key, const char *value,
1329 struct lxc_conf *c, void *data)
1330 {
1331 int ret;
1332
1333 if (lxc_config_value_empty(value)) {
1334 free(c->logfile);
1335 c->logfile = NULL;
1336 return 0;
1337 }
1338
1339 /* Store these values in the lxc_conf, and then try to set for actual
1340 * current logging.
1341 */
1342 ret = set_config_path_item(&c->logfile, value);
1343 if (ret == 0)
1344 ret = lxc_log_set_file(&c->logfd, c->logfile);
1345 return ret;
1346 }
1347
1348 static int set_config_loglevel(const char *key, const char *value,
1349 struct lxc_conf *lxc_conf, void *data)
1350 {
1351 int newlevel;
1352
1353 /* Set config value to default. */
1354 if (lxc_config_value_empty(value)) {
1355 lxc_conf->loglevel = LXC_LOG_LEVEL_NOTSET;
1356 return 0;
1357 }
1358
1359 /* Parse new config value. */
1360 if (value[0] >= '0' && value[0] <= '9') {
1361 if (lxc_safe_int(value, &newlevel) < 0)
1362 return -1;
1363 } else {
1364 newlevel = lxc_log_priority_to_int(value);
1365 }
1366
1367 /* Store these values in the lxc_conf, and then try to set for actual
1368 * current logging.
1369 */
1370 lxc_conf->loglevel = newlevel;
1371 return lxc_log_set_level(&lxc_conf->loglevel, newlevel);
1372 }
1373
1374 static int set_config_autodev(const char *key, const char *value,
1375 struct lxc_conf *lxc_conf, void *data)
1376 {
1377 /* Set config value to default. */
1378 if (lxc_config_value_empty(value)) {
1379 lxc_conf->autodev = 0;
1380 return 0;
1381 }
1382
1383 /* Parse new config value. */
1384 if (lxc_safe_uint(value, &lxc_conf->autodev) < 0)
1385 return -1;
1386
1387 if (lxc_conf->autodev > 1) {
1388 ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1");
1389 return -1;
1390 }
1391
1392 return 0;
1393 }
1394
1395 static int sig_num(const char *sig)
1396 {
1397 unsigned int signum;
1398
1399 if (lxc_safe_uint(sig, &signum) < 0)
1400 return -1;
1401
1402 return signum;
1403 }
1404
1405 static int rt_sig_num(const char *signame)
1406 {
1407 int rtmax = 0, sig_n = 0;
1408
1409 if (strncasecmp(signame, "max-", 4) == 0) {
1410 rtmax = 1;
1411 }
1412
1413 signame += 4;
1414 if (!isdigit(*signame))
1415 return -1;
1416
1417 sig_n = sig_num(signame);
1418 sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n;
1419 if (sig_n > SIGRTMAX || sig_n < SIGRTMIN)
1420 return -1;
1421
1422 return sig_n;
1423 }
1424
1425 static int sig_parse(const char *signame)
1426 {
1427 size_t n;
1428
1429 if (isdigit(*signame)) {
1430 return sig_num(signame);
1431 } else if (strncasecmp(signame, "sig", 3) == 0) {
1432 signame += 3;
1433 if (strncasecmp(signame, "rt", 2) == 0)
1434 return rt_sig_num(signame + 2);
1435 for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
1436 if (strcasecmp(signames[n].name, signame) == 0)
1437 return signames[n].num;
1438 }
1439 }
1440
1441 return -1;
1442 }
1443
1444 static int set_config_haltsignal(const char *key, const char *value,
1445 struct lxc_conf *lxc_conf, void *data)
1446 {
1447 int sig_n;
1448
1449 /* Set config value to default. */
1450 if (lxc_config_value_empty(value)) {
1451 lxc_conf->haltsignal = 0;
1452 return 0;
1453 }
1454
1455 /* Parse new config value. */
1456 sig_n = sig_parse(value);
1457
1458 if (sig_n < 0)
1459 return -1;
1460 lxc_conf->haltsignal = sig_n;
1461
1462 return 0;
1463 }
1464
1465 static int set_config_rebootsignal(const char *key, const char *value,
1466 struct lxc_conf *lxc_conf, void *data)
1467 {
1468 int sig_n;
1469
1470 /* Set config value to default. */
1471 if (lxc_config_value_empty(value)) {
1472 lxc_conf->rebootsignal = 0;
1473 return 0;
1474 }
1475
1476 /* Parse new config value. */
1477 sig_n = sig_parse(value);
1478 if (sig_n < 0)
1479 return -1;
1480 lxc_conf->rebootsignal = sig_n;
1481
1482 return 0;
1483 }
1484
1485 static int set_config_stopsignal(const char *key, const char *value,
1486 struct lxc_conf *lxc_conf, void *data)
1487 {
1488 int sig_n;
1489
1490 /* Set config value to default. */
1491 if (lxc_config_value_empty(value)) {
1492 lxc_conf->stopsignal = 0;
1493 return 0;
1494 }
1495
1496 /* Parse new config value. */
1497 sig_n = sig_parse(value);
1498 if (sig_n < 0)
1499 return -1;
1500 lxc_conf->stopsignal = sig_n;
1501
1502 return 0;
1503 }
1504
1505 static int set_config_cgroup(const char *key, const char *value,
1506 struct lxc_conf *lxc_conf, void *data)
1507 {
1508 char *subkey;
1509 char *token = "lxc.cgroup.";
1510 struct lxc_list *cglist = NULL;
1511 struct lxc_cgroup *cgelem = NULL;
1512
1513 if (lxc_config_value_empty(value))
1514 return lxc_clear_cgroups(lxc_conf, key);
1515
1516 subkey = strstr(key, token);
1517 if (!subkey)
1518 return -1;
1519
1520 if (!strlen(subkey))
1521 return -1;
1522
1523 if (strlen(subkey) == strlen(token))
1524 return -1;
1525
1526 subkey += strlen(token);
1527
1528 cglist = malloc(sizeof(*cglist));
1529 if (!cglist)
1530 goto out;
1531
1532 cgelem = malloc(sizeof(*cgelem));
1533 if (!cgelem)
1534 goto out;
1535 memset(cgelem, 0, sizeof(*cgelem));
1536
1537 cgelem->subsystem = strdup(subkey);
1538 cgelem->value = strdup(value);
1539
1540 if (!cgelem->subsystem || !cgelem->value)
1541 goto out;
1542
1543 cglist->elem = cgelem;
1544
1545 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
1546
1547 return 0;
1548
1549 out:
1550 free(cglist);
1551
1552 if (cgelem) {
1553 free(cgelem->subsystem);
1554
1555 free(cgelem->value);
1556
1557 free(cgelem);
1558 }
1559
1560 return -1;
1561 }
1562
1563 static int set_config_prlimit(const char *key, const char *value,
1564 struct lxc_conf *lxc_conf, void *data)
1565 {
1566 struct lxc_list *iter;
1567 struct rlimit limit;
1568 unsigned long limit_value;
1569 struct lxc_list *limlist = NULL;
1570 struct lxc_limit *limelem = NULL;
1571
1572 if (lxc_config_value_empty(value))
1573 return lxc_clear_limits(lxc_conf, key);
1574
1575 if (strncmp(key, "lxc.prlimit.", sizeof("lxc.prlimit.") - 1) != 0)
1576 return -1;
1577
1578 key += sizeof("lxc.prlimit.") - 1;
1579
1580 /* soft limit comes first in the value */
1581 if (!parse_limit_value(&value, &limit_value))
1582 return -1;
1583 limit.rlim_cur = limit_value;
1584
1585 /* skip spaces and a colon */
1586 while (isspace(*value))
1587 ++value;
1588
1589 if (*value == ':')
1590 ++value;
1591 else if (*value) /* any other character is an error here */
1592 return -1;
1593
1594 while (isspace(*value))
1595 ++value;
1596
1597 /* optional hard limit */
1598 if (*value) {
1599 if (!parse_limit_value(&value, &limit_value))
1600 return -1;
1601 limit.rlim_max = limit_value;
1602
1603 /* check for trailing garbage */
1604 while (isspace(*value))
1605 ++value;
1606
1607 if (*value)
1608 return -1;
1609 } else {
1610 /* a single value sets both hard and soft limit */
1611 limit.rlim_max = limit.rlim_cur;
1612 }
1613
1614 /* find existing list element */
1615 lxc_list_for_each(iter, &lxc_conf->limits)
1616 {
1617 limelem = iter->elem;
1618 if (!strcmp(key, limelem->resource)) {
1619 limelem->limit = limit;
1620 return 0;
1621 }
1622 }
1623
1624 /* allocate list element */
1625 limlist = malloc(sizeof(*limlist));
1626 if (!limlist)
1627 goto out;
1628
1629 limelem = malloc(sizeof(*limelem));
1630 if (!limelem)
1631 goto out;
1632 memset(limelem, 0, sizeof(*limelem));
1633
1634 limelem->resource = strdup(key);
1635 if (!limelem->resource)
1636 goto out;
1637 limelem->limit = limit;
1638
1639 limlist->elem = limelem;
1640
1641 lxc_list_add_tail(&lxc_conf->limits, limlist);
1642
1643 return 0;
1644
1645 out:
1646 free(limlist);
1647 if (limelem) {
1648 free(limelem->resource);
1649 free(limelem);
1650 }
1651 return -1;
1652 }
1653
1654 static int set_config_idmaps(const char *key, const char *value,
1655 struct lxc_conf *lxc_conf, void *data)
1656 {
1657 unsigned long hostid, nsid, range;
1658 char type;
1659 int ret;
1660 struct lxc_list *idmaplist = NULL;
1661 struct id_map *idmap = NULL;
1662
1663 if (lxc_config_value_empty(value))
1664 return lxc_clear_idmaps(lxc_conf);
1665
1666 idmaplist = malloc(sizeof(*idmaplist));
1667 if (!idmaplist)
1668 goto on_error;
1669
1670 idmap = malloc(sizeof(*idmap));
1671 if (!idmap)
1672 goto on_error;
1673 memset(idmap, 0, sizeof(*idmap));
1674
1675 ret = parse_idmaps(value, &type, &nsid, &hostid, &range);
1676 if (ret < 0)
1677 goto on_error;
1678
1679 INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
1680 if (type == 'u')
1681 idmap->idtype = ID_TYPE_UID;
1682 else if (type == 'g')
1683 idmap->idtype = ID_TYPE_GID;
1684 else
1685 goto on_error;
1686
1687 idmap->hostid = hostid;
1688 idmap->nsid = nsid;
1689 idmap->range = range;
1690 idmaplist->elem = idmap;
1691 lxc_list_add_tail(&lxc_conf->id_map, idmaplist);
1692 idmap = NULL;
1693
1694 return 0;
1695
1696 on_error:
1697 free(idmaplist);
1698 free(idmap);
1699
1700 return -1;
1701 }
1702
1703 static int set_config_fstab(const char *key, const char *value,
1704 struct lxc_conf *lxc_conf, void *data)
1705 {
1706 if (lxc_config_value_empty(value)) {
1707 clr_config_fstab(key, lxc_conf, NULL);
1708 return -1;
1709 }
1710
1711 return set_config_path_item(&lxc_conf->fstab, value);
1712 }
1713
1714 static int set_config_mount_auto(const char *key, const char *value,
1715 struct lxc_conf *lxc_conf, void *data)
1716 {
1717 char *autos, *autoptr, *sptr, *token;
1718 int i;
1719 int ret = -1;
1720 static struct {
1721 const char *token;
1722 int mask;
1723 int flag;
1724 } allowed_auto_mounts[] = {
1725 { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1726 { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
1727 { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
1728 { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
1729 { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
1730 { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
1731 { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
1732 { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
1733 { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
1734 { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
1735 { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
1736 { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
1737 { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
1738 { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
1739 { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
1740 /* NB: For adding anything that is just a single on/off, but has
1741 * no options: keep mask and flag identical and just define the
1742 * enum value as an unused bit so far
1743 */
1744 { NULL, 0, 0 }
1745 };
1746
1747 if (lxc_config_value_empty(value)) {
1748 lxc_conf->auto_mounts = 0;
1749 return 0;
1750 }
1751
1752 autos = strdup(value);
1753 if (!autos) {
1754 SYSERROR("failed to dup '%s'", value);
1755 return -1;
1756 }
1757
1758 for (autoptr = autos;; autoptr = NULL) {
1759 token = strtok_r(autoptr, " \t", &sptr);
1760 if (!token) {
1761 ret = 0;
1762 break;
1763 }
1764
1765 for (i = 0; allowed_auto_mounts[i].token; i++) {
1766 if (!strcmp(allowed_auto_mounts[i].token, token))
1767 break;
1768 }
1769
1770 if (!allowed_auto_mounts[i].token) {
1771 ERROR("Invalid filesystem to automount: %s", token);
1772 break;
1773 }
1774
1775 lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
1776 lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
1777 }
1778
1779 free(autos);
1780 return ret;
1781 }
1782
1783 static int set_config_mount(const char *key, const char *value,
1784 struct lxc_conf *lxc_conf, void *data)
1785 {
1786 char *mntelem;
1787 struct lxc_list *mntlist;
1788
1789 if (lxc_config_value_empty(value))
1790 return lxc_clear_mount_entries(lxc_conf);
1791
1792 mntlist = malloc(sizeof(*mntlist));
1793 if (!mntlist)
1794 return -1;
1795
1796 mntelem = strdup(value);
1797 if (!mntelem) {
1798 free(mntlist);
1799 return -1;
1800 }
1801 mntlist->elem = mntelem;
1802
1803 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
1804
1805 return 0;
1806 }
1807
1808 static int set_config_cap_keep(const char *key, const char *value,
1809 struct lxc_conf *lxc_conf, void *data)
1810 {
1811 char *keepcaps, *keepptr, *sptr, *token;
1812 struct lxc_list *keeplist;
1813 int ret = -1;
1814
1815 if (lxc_config_value_empty(value))
1816 return lxc_clear_config_keepcaps(lxc_conf);
1817
1818 keepcaps = strdup(value);
1819 if (!keepcaps) {
1820 SYSERROR("failed to dup '%s'", value);
1821 return -1;
1822 }
1823
1824 /* In case several capability keep is specified in a single line
1825 * split these caps in a single element for the list.
1826 */
1827 for (keepptr = keepcaps;; keepptr = NULL) {
1828 token = strtok_r(keepptr, " \t", &sptr);
1829 if (!token) {
1830 ret = 0;
1831 break;
1832 }
1833
1834 if (!strcmp(token, "none"))
1835 lxc_clear_config_keepcaps(lxc_conf);
1836
1837 keeplist = malloc(sizeof(*keeplist));
1838 if (!keeplist) {
1839 SYSERROR("failed to allocate keepcap list");
1840 break;
1841 }
1842
1843 keeplist->elem = strdup(token);
1844 if (!keeplist->elem) {
1845 SYSERROR("failed to dup '%s'", token);
1846 free(keeplist);
1847 break;
1848 }
1849
1850 lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
1851 }
1852
1853 free(keepcaps);
1854
1855 return ret;
1856 }
1857
1858 static int set_config_cap_drop(const char *key, const char *value,
1859 struct lxc_conf *lxc_conf, void *data)
1860 {
1861 char *dropcaps, *dropptr, *sptr, *token;
1862 struct lxc_list *droplist;
1863 int ret = -1;
1864
1865 if (lxc_config_value_empty(value))
1866 return lxc_clear_config_caps(lxc_conf);
1867
1868 dropcaps = strdup(value);
1869 if (!dropcaps) {
1870 SYSERROR("failed to dup '%s'", value);
1871 return -1;
1872 }
1873
1874 /* In case several capability drop is specified in a single line
1875 * split these caps in a single element for the list.
1876 */
1877 for (dropptr = dropcaps;; dropptr = NULL) {
1878 token = strtok_r(dropptr, " \t", &sptr);
1879 if (!token) {
1880 ret = 0;
1881 break;
1882 }
1883
1884 droplist = malloc(sizeof(*droplist));
1885 if (!droplist) {
1886 SYSERROR("failed to allocate drop list");
1887 break;
1888 }
1889
1890 droplist->elem = strdup(token);
1891 if (!droplist->elem) {
1892 SYSERROR("failed to dup '%s'", token);
1893 free(droplist);
1894 break;
1895 }
1896
1897 lxc_list_add_tail(&lxc_conf->caps, droplist);
1898 }
1899
1900 free(dropcaps);
1901
1902 return ret;
1903 }
1904
1905 static int set_config_console(const char *key, const char *value,
1906 struct lxc_conf *lxc_conf, void *data)
1907 {
1908 return set_config_path_item(&lxc_conf->console.path, value);
1909 }
1910
1911 static int set_config_console_logfile(const char *key, const char *value,
1912 struct lxc_conf *lxc_conf, void *data)
1913 {
1914 return set_config_path_item(&lxc_conf->console.log_path, value);
1915 }
1916
1917 int append_unexp_config_line(const char *line, struct lxc_conf *conf)
1918 {
1919 size_t len = conf->unexpanded_len, linelen = strlen(line);
1920
1921 update_hwaddr(line);
1922
1923 while (conf->unexpanded_alloced <= len + linelen + 2) {
1924 char *tmp = realloc(conf->unexpanded_config,
1925 conf->unexpanded_alloced + 1024);
1926 if (!tmp)
1927 return -1;
1928
1929 if (!conf->unexpanded_config)
1930 *tmp = '\0';
1931 conf->unexpanded_config = tmp;
1932 conf->unexpanded_alloced += 1024;
1933 }
1934 strcat(conf->unexpanded_config, line);
1935 conf->unexpanded_len += linelen;
1936 if (line[linelen - 1] != '\n') {
1937 strcat(conf->unexpanded_config, "\n");
1938 conf->unexpanded_len++;
1939 }
1940 return 0;
1941 }
1942
1943 static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
1944 {
1945 struct dirent *direntp;
1946 DIR *dir;
1947 char path[MAXPATHLEN];
1948 int len;
1949 int ret = -1;
1950
1951 dir = opendir(dirp);
1952 if (!dir) {
1953 SYSERROR("failed to open '%s'", dirp);
1954 return -1;
1955 }
1956
1957 while ((direntp = readdir(dir))) {
1958 const char *fnam;
1959 if (!direntp)
1960 break;
1961
1962 fnam = direntp->d_name;
1963 if (!strcmp(fnam, "."))
1964 continue;
1965
1966 if (!strcmp(fnam, ".."))
1967 continue;
1968
1969 len = strlen(fnam);
1970 if (len < 6 || strncmp(fnam + len - 5, ".conf", 5) != 0)
1971 continue;
1972 len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam);
1973 if (len < 0 || len >= MAXPATHLEN) {
1974 ERROR("lxc.include filename too long under '%s'", dirp);
1975 ret = -1;
1976 goto out;
1977 }
1978
1979 ret = lxc_config_read(path, lxc_conf, true);
1980 if (ret < 0)
1981 goto out;
1982 }
1983 ret = 0;
1984
1985 out:
1986 if (closedir(dir))
1987 WARN("lxc.include dir: failed to close directory");
1988
1989 return ret;
1990 }
1991
1992 static int set_config_includefiles(const char *key, const char *value,
1993 struct lxc_conf *lxc_conf, void *data)
1994 {
1995 /* Set config value to default. */
1996 if (lxc_config_value_empty(value)) {
1997 clr_config_includefiles(key, lxc_conf, NULL);
1998 return 0;
1999 }
2000
2001 /* Parse new config value. */
2002 if (is_dir(value))
2003 return do_includedir(value, lxc_conf);
2004
2005 return lxc_config_read(value, lxc_conf, true);
2006 }
2007
2008 static int set_config_rootfs(const char *key, const char *value,
2009 struct lxc_conf *lxc_conf, void *data)
2010 {
2011 return set_config_path_item(&lxc_conf->rootfs.path, value);
2012 }
2013
2014 static int set_config_rootfs_mount(const char *key, const char *value,
2015 struct lxc_conf *lxc_conf, void *data)
2016 {
2017 return set_config_path_item(&lxc_conf->rootfs.mount, value);
2018 }
2019
2020 static int set_config_rootfs_options(const char *key, const char *value,
2021 struct lxc_conf *lxc_conf, void *data)
2022 {
2023 return set_config_string_item(&lxc_conf->rootfs.options, value);
2024 }
2025
2026 static int set_config_rootfs_backend(const char *key, const char *value,
2027 struct lxc_conf *lxc_conf, void *data)
2028 {
2029 if (lxc_config_value_empty(value)) {
2030 free(lxc_conf->rootfs.bdev_type);
2031 lxc_conf->rootfs.bdev_type = NULL;
2032 return 0;
2033 }
2034
2035 if (!is_valid_bdev_type(value)) {
2036 ERROR("Bad rootfs.backend: '%s'", value);
2037 return -1;
2038 }
2039
2040 return set_config_string_item(&lxc_conf->rootfs.bdev_type, value);
2041 }
2042
2043 static int set_config_utsname(const char *key, const char *value,
2044 struct lxc_conf *lxc_conf, void *data)
2045 {
2046 struct utsname *utsname;
2047
2048 if (lxc_config_value_empty(value)) {
2049 clr_config_utsname(key, lxc_conf, NULL);
2050 return 0;
2051 }
2052
2053 utsname = malloc(sizeof(*utsname));
2054 if (!utsname) {
2055 SYSERROR("failed to allocate memory");
2056 return -1;
2057 }
2058
2059 if (strlen(value) >= sizeof(utsname->nodename)) {
2060 ERROR("node name '%s' is too long", value);
2061 free(utsname);
2062 return -1;
2063 }
2064
2065 strcpy(utsname->nodename, value);
2066 free(lxc_conf->utsname);
2067 lxc_conf->utsname = utsname;
2068
2069 return 0;
2070 }
2071
2072 struct parse_line_conf {
2073 struct lxc_conf *conf;
2074 bool from_include;
2075 };
2076
2077 static int parse_line(char *buffer, void *data)
2078 {
2079 struct lxc_config_t *config;
2080 char *dot, *key, *line, *linep, *value;
2081 struct parse_line_conf *plc = data;
2082 int ret = 0;
2083
2084 if (lxc_is_line_empty(buffer))
2085 return 0;
2086
2087 /* we have to dup the buffer otherwise, at the re-exec for
2088 * reboot we modified the original string on the stack by
2089 * replacing '=' by '\0' below
2090 */
2091 linep = line = strdup(buffer);
2092 if (!line) {
2093 SYSERROR("failed to allocate memory for '%s'", buffer);
2094 return -1;
2095 }
2096
2097 if (!plc->from_include)
2098 if ((ret = append_unexp_config_line(line, plc->conf)))
2099 goto out;
2100
2101 line += lxc_char_left_gc(line, strlen(line));
2102
2103 /* ignore comments */
2104 if (line[0] == '#')
2105 goto out;
2106
2107 /* martian option - don't add it to the config itself */
2108 if (strncmp(line, "lxc.", 4))
2109 goto out;
2110
2111 ret = -1;
2112
2113 dot = strstr(line, "=");
2114 if (!dot) {
2115 ERROR("invalid configuration line: %s", line);
2116 goto out;
2117 }
2118
2119 *dot = '\0';
2120 value = dot + 1;
2121
2122 key = line;
2123 key[lxc_char_right_gc(key, strlen(key))] = '\0';
2124
2125 value += lxc_char_left_gc(value, strlen(value));
2126 value[lxc_char_right_gc(value, strlen(value))] = '\0';
2127
2128 if (*value == '\'' || *value == '\"') {
2129 size_t len = strlen(value);
2130 if (len > 1 && value[len - 1] == *value) {
2131 value[len - 1] = '\0';
2132 value++;
2133 }
2134 }
2135
2136 config = lxc_getconfig(key);
2137 if (!config) {
2138 ERROR("unknown key %s", key);
2139 goto out;
2140 }
2141
2142 ret = config->set(key, value, plc->conf, NULL);
2143
2144 out:
2145 free(linep);
2146 return ret;
2147 }
2148
2149 static int lxc_config_readline(char *buffer, struct lxc_conf *conf)
2150 {
2151 struct parse_line_conf c;
2152
2153 c.conf = conf;
2154 c.from_include = false;
2155
2156 return parse_line(buffer, &c);
2157 }
2158
2159 int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
2160 {
2161 struct parse_line_conf c;
2162
2163 c.conf = conf;
2164 c.from_include = from_include;
2165
2166 if (access(file, R_OK) == -1) {
2167 return -1;
2168 }
2169
2170 /* Catch only the top level config file name in the structure */
2171 if (!conf->rcfile)
2172 conf->rcfile = strdup(file);
2173
2174 return lxc_file_for_each_line(file, parse_line, &c);
2175 }
2176
2177 int lxc_config_define_add(struct lxc_list *defines, char *arg)
2178 {
2179 struct lxc_list *dent;
2180
2181 dent = malloc(sizeof(struct lxc_list));
2182 if (!dent)
2183 return -1;
2184
2185 dent->elem = arg;
2186 lxc_list_add_tail(defines, dent);
2187 return 0;
2188 }
2189
2190 int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
2191 {
2192 struct lxc_list *it, *next;
2193 int ret = 0;
2194
2195 lxc_list_for_each(it, defines) {
2196 ret = lxc_config_readline(it->elem, conf);
2197 if (ret)
2198 break;
2199 }
2200
2201 lxc_list_for_each_safe(it, defines, next) {
2202 lxc_list_del(it);
2203 free(it);
2204 }
2205
2206 return ret;
2207 }
2208
2209 signed long lxc_config_parse_arch(const char *arch)
2210 {
2211 #if HAVE_SYS_PERSONALITY_H
2212 size_t i;
2213 struct per_name {
2214 char *name;
2215 unsigned long per;
2216 } pername[] = {
2217 { "x86", PER_LINUX32 },
2218 { "linux32", PER_LINUX32 },
2219 { "i386", PER_LINUX32 },
2220 { "i486", PER_LINUX32 },
2221 { "i586", PER_LINUX32 },
2222 { "i686", PER_LINUX32 },
2223 { "athlon", PER_LINUX32 },
2224 { "mips", PER_LINUX32 },
2225 { "mipsel", PER_LINUX32 },
2226 { "ppc", PER_LINUX32 },
2227 { "arm", PER_LINUX32 },
2228 { "armv7l", PER_LINUX32 },
2229 { "armhf", PER_LINUX32 },
2230 { "armel", PER_LINUX32 },
2231 { "powerpc", PER_LINUX32 },
2232 { "linux64", PER_LINUX },
2233 { "x86_64", PER_LINUX },
2234 { "amd64", PER_LINUX },
2235 { "mips64", PER_LINUX },
2236 { "mips64el", PER_LINUX },
2237 { "ppc64", PER_LINUX },
2238 { "ppc64le", PER_LINUX },
2239 { "ppc64el", PER_LINUX },
2240 { "powerpc64", PER_LINUX },
2241 { "s390x", PER_LINUX },
2242 { "aarch64", PER_LINUX },
2243 { "arm64", PER_LINUX },
2244 };
2245 size_t len = sizeof(pername) / sizeof(pername[0]);
2246
2247 for (i = 0; i < len; i++) {
2248 if (!strcmp(pername[i].name, arch))
2249 return pername[i].per;
2250 }
2251 #endif
2252
2253 return -1;
2254 }
2255
2256 int lxc_fill_elevated_privileges(char *flaglist, int *flags)
2257 {
2258 char *token, *saveptr = NULL;
2259 int i, aflag;
2260 struct {
2261 const char *token;
2262 int flag;
2263 } all_privs[] = {
2264 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
2265 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
2266 { "LSM", LXC_ATTACH_LSM_EXEC },
2267 { NULL, 0 }
2268 };
2269
2270 if (!flaglist) {
2271 /* For the sake of backward compatibility, drop all privileges
2272 * if none is specified.
2273 */
2274 for (i = 0; all_privs[i].token; i++) {
2275 *flags |= all_privs[i].flag;
2276 }
2277 return 0;
2278 }
2279
2280 token = strtok_r(flaglist, "|", &saveptr);
2281 while (token) {
2282 aflag = -1;
2283 for (i = 0; all_privs[i].token; i++) {
2284 if (!strcmp(all_privs[i].token, token))
2285 aflag = all_privs[i].flag;
2286 }
2287 if (aflag < 0)
2288 return -1;
2289
2290 *flags |= aflag;
2291
2292 token = strtok_r(NULL, "|", &saveptr);
2293 }
2294
2295 return 0;
2296 }
2297
2298 /* Write out a configuration file. */
2299 void write_config(FILE *fout, struct lxc_conf *c)
2300 {
2301 int ret;
2302 size_t len = c->unexpanded_len;
2303
2304 if (!len)
2305 return;
2306
2307 ret = fwrite(c->unexpanded_config, 1, len, fout);
2308 if (ret != len)
2309 SYSERROR("Error writing configuration file");
2310 }
2311
2312 bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key,
2313 const char *v)
2314 {
2315 int ret;
2316 size_t len;
2317 char *tmp;
2318
2319 len = strlen(key) + strlen(v) + 4;
2320 tmp = alloca(len);
2321
2322 if (lxc_config_value_empty(v))
2323 ret = snprintf(tmp, len, "%s =", key);
2324 else
2325 ret = snprintf(tmp, len, "%s = %s", key, v);
2326 if (ret < 0 || ret >= len)
2327 return false;
2328
2329 /* Save the line verbatim into unexpanded_conf */
2330 if (append_unexp_config_line(tmp, conf))
2331 return false;
2332
2333 return true;
2334 }
2335
2336 void clear_unexp_config_line(struct lxc_conf *conf, const char *key,
2337 bool rm_subkeys)
2338 {
2339 char *lend;
2340 char *lstart = conf->unexpanded_config;
2341
2342 if (!conf->unexpanded_config)
2343 return;
2344
2345 while (*lstart) {
2346 lend = strchr(lstart, '\n');
2347 char v;
2348 if (!lend)
2349 lend = lstart + strlen(lstart);
2350 else
2351 lend++;
2352 if (strncmp(lstart, key, strlen(key)) != 0) {
2353 lstart = lend;
2354 continue;
2355 }
2356 if (!rm_subkeys) {
2357 v = lstart[strlen(key)];
2358 if (!isspace(v) && v != '=') {
2359 lstart = lend;
2360 continue;
2361 }
2362 }
2363 conf->unexpanded_len -= (lend - lstart);
2364 if (*lend == '\0') {
2365 *lstart = '\0';
2366 return;
2367 }
2368 memmove(lstart, lend, strlen(lend) + 1);
2369 }
2370 }
2371
2372 bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
2373 const char *newpath, const char *oldname,
2374 const char *newname, const char *ovldir)
2375 {
2376 int ret;
2377 char *lend, *newdir, *olddir, *p, *q;
2378 size_t newdirlen, olddirlen;
2379 char *lstart = conf->unexpanded_config;
2380 const char *key = "lxc.mount.entry";
2381
2382 olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2;
2383 olddir = alloca(olddirlen + 1);
2384 ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath,
2385 oldname);
2386 if (ret < 0 || ret >= olddirlen + 1) {
2387 ERROR("failed to create string");
2388 return false;
2389 }
2390
2391 newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2;
2392 newdir = alloca(newdirlen + 1);
2393 ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath,
2394 newname);
2395 if (ret < 0 || ret >= newdirlen + 1) {
2396 ERROR("failed to create string");
2397 return false;
2398 }
2399
2400 if (!conf->unexpanded_config)
2401 return true;
2402
2403 while (*lstart) {
2404 lend = strchr(lstart, '\n');
2405 if (!lend)
2406 lend = lstart + strlen(lstart);
2407 else
2408 lend++;
2409
2410 if (strncmp(lstart, key, strlen(key)) != 0)
2411 goto next;
2412
2413 p = strchr(lstart + strlen(key), '=');
2414 if (!p)
2415 goto next;
2416 p++;
2417
2418 while (isblank(*p))
2419 p++;
2420
2421 if (p >= lend)
2422 goto next;
2423
2424 /* Whenever an lxc.mount.entry entry is found in a line we check
2425 * if the substring " overlay" or the substring " aufs" is
2426 * present before doing any further work. We check for "
2427 * overlay" and " aufs" since both substrings need to have at
2428 * least one space before them in a valid overlay
2429 * lxc.mount.entry (/A B overlay). When the space before is
2430 * missing it is very likely that these substrings are part of a
2431 * path or something else. (Checking q >= lend ensures that we
2432 * only count matches in the current line.) */
2433 if ((!(q = strstr(p, " overlay")) || q >= lend) &&
2434 (!(q = strstr(p, " aufs")) || q >= lend))
2435 goto next;
2436
2437 if (!(q = strstr(p, olddir)) || (q >= lend))
2438 goto next;
2439
2440 /* replace the olddir with newdir */
2441 if (olddirlen >= newdirlen) {
2442 size_t diff = olddirlen - newdirlen;
2443 memcpy(q, newdir, newdirlen);
2444 if (olddirlen != newdirlen) {
2445 memmove(q + newdirlen, q + newdirlen + diff,
2446 strlen(q) - newdirlen - diff + 1);
2447 lend -= diff;
2448 conf->unexpanded_len -= diff;
2449 }
2450 } else {
2451 char *new;
2452 size_t diff = newdirlen - olddirlen;
2453 size_t oldlen = conf->unexpanded_len;
2454 size_t newlen = oldlen + diff;
2455 size_t poffset = q - conf->unexpanded_config;
2456
2457 new = realloc(conf->unexpanded_config, newlen + 1);
2458 if (!new) {
2459 ERROR("Out of memory");
2460 return false;
2461 }
2462 conf->unexpanded_len = newlen;
2463 conf->unexpanded_alloced = newlen + 1;
2464 new[newlen - 1] = '\0';
2465 lend = new + (lend - conf->unexpanded_config);
2466 /* move over the remainder to make room for the newdir
2467 */
2468 memmove(new + poffset + newdirlen,
2469 new + poffset + olddirlen,
2470 oldlen - poffset - olddirlen + 1);
2471 conf->unexpanded_config = new;
2472 memcpy(new + poffset, newdir, newdirlen);
2473 lend += diff;
2474 }
2475 next:
2476 lstart = lend;
2477 }
2478
2479 return true;
2480 }
2481
2482 bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath,
2483 const char *newpath, const char *oldname,
2484 const char *newname)
2485 {
2486 int ret;
2487 char *lend, *newdir, *olddir, *p;
2488 char *lstart = conf->unexpanded_config;
2489 size_t newdirlen, olddirlen;
2490 const char *key = "lxc.hook";
2491
2492 olddirlen = strlen(oldpath) + strlen(oldname) + 1;
2493 olddir = alloca(olddirlen + 1);
2494 ret = snprintf(olddir, olddirlen + 1, "%s/%s", oldpath, oldname);
2495 if (ret < 0 || ret >= olddirlen + 1) {
2496 ERROR("failed to create string");
2497 return false;
2498 }
2499
2500 newdirlen = strlen(newpath) + strlen(newname) + 1;
2501 newdir = alloca(newdirlen + 1);
2502 ret = snprintf(newdir, newdirlen + 1, "%s/%s", newpath, newname);
2503 if (ret < 0 || ret >= newdirlen + 1) {
2504 ERROR("failed to create string");
2505 return false;
2506 }
2507 if (!conf->unexpanded_config)
2508 return true;
2509 while (*lstart) {
2510 lend = strchr(lstart, '\n');
2511 if (!lend)
2512 lend = lstart + strlen(lstart);
2513 else
2514 lend++;
2515
2516 if (strncmp(lstart, key, strlen(key)) != 0)
2517 goto next;
2518
2519 p = strchr(lstart + strlen(key), '=');
2520 if (!p)
2521 goto next;
2522 p++;
2523
2524 while (isblank(*p))
2525 p++;
2526
2527 if (p >= lend)
2528 goto next;
2529
2530 if (strncmp(p, olddir, strlen(olddir)) != 0)
2531 goto next;
2532
2533 /* replace the olddir with newdir */
2534 if (olddirlen >= newdirlen) {
2535 size_t diff = olddirlen - newdirlen;
2536 memcpy(p, newdir, newdirlen);
2537 if (olddirlen != newdirlen) {
2538 memmove(p + newdirlen, p + newdirlen + diff,
2539 strlen(p) - newdirlen - diff + 1);
2540 lend -= diff;
2541 conf->unexpanded_len -= diff;
2542 }
2543 } else {
2544 char *new;
2545 size_t diff = newdirlen - olddirlen;
2546 size_t oldlen = conf->unexpanded_len;
2547 size_t newlen = oldlen + diff;
2548 size_t poffset = p - conf->unexpanded_config;
2549
2550 new = realloc(conf->unexpanded_config, newlen + 1);
2551 if (!new) {
2552 ERROR("failed to allocate memory");
2553 return false;
2554 }
2555 conf->unexpanded_len = newlen;
2556 conf->unexpanded_alloced = newlen + 1;
2557 new[newlen - 1] = '\0';
2558 lend = new + (lend - conf->unexpanded_config);
2559 /* move over the remainder to make room for the newdir
2560 */
2561 memmove(new + poffset + newdirlen,
2562 new + poffset + olddirlen,
2563 oldlen - poffset - olddirlen + 1);
2564 conf->unexpanded_config = new;
2565 memcpy(new + poffset, newdir, newdirlen);
2566 lend += diff;
2567 }
2568 next:
2569 lstart = lend;
2570 }
2571
2572 return true;
2573 }
2574
2575 #define DO(cmd) \
2576 { \
2577 if (!(cmd)) { \
2578 ERROR("Error writing to new config"); \
2579 return false; \
2580 } \
2581 }
2582
2583 /*
2584 * This is called only from clone. We wish to update all hwaddrs in the
2585 * unexpanded config file. We can't/don't want to update any which come from
2586 * lxc.includes (there shouldn't be any).
2587 * We can't just walk the c->lxc-conf->network list because that includes netifs
2588 * from the include files. So we update the ones which we find in the unexp
2589 * config file, then find the original macaddr in the conf->network, and update
2590 * that to the same value.
2591 */
2592 bool network_new_hwaddrs(struct lxc_conf *conf)
2593 {
2594 char *lend, *p, *p2;
2595 struct lxc_list *it;
2596 char *lstart = conf->unexpanded_config;
2597
2598 if (!conf->unexpanded_config)
2599 return true;
2600
2601 while (*lstart) {
2602 char newhwaddr[18], oldhwaddr[17];
2603
2604 lend = strchr(lstart, '\n');
2605 if (!lend)
2606 lend = lstart + strlen(lstart);
2607 else
2608 lend++;
2609
2610 if (!lxc_config_net_hwaddr(lstart)) {
2611 lstart = lend;
2612 continue;
2613 }
2614
2615 p = strchr(lstart, '=');
2616 if (!p) {
2617 lstart = lend;
2618 continue;
2619 }
2620
2621 p++;
2622 while (isblank(*p))
2623 p++;
2624 if (!*p)
2625 return true;
2626
2627 p2 = p;
2628 while (*p2 && !isblank(*p2) && *p2 != '\n')
2629 p2++;
2630
2631 if ((p2 - p) != 17) {
2632 WARN("Bad hwaddr entry");
2633 lstart = lend;
2634 continue;
2635 }
2636
2637 memcpy(oldhwaddr, p, 17);
2638
2639 if (!new_hwaddr(newhwaddr))
2640 return false;
2641
2642 memcpy(p, newhwaddr, 17);
2643 lxc_list_for_each(it, &conf->network)
2644 {
2645 struct lxc_netdev *n = it->elem;
2646 if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0)
2647 memcpy(n->hwaddr, newhwaddr, 17);
2648 }
2649
2650 lstart = lend;
2651 }
2652
2653 return true;
2654 }
2655
2656 static int set_config_ephemeral(const char *key, const char *value,
2657 struct lxc_conf *lxc_conf, void *data)
2658 {
2659 /* Set config value to default. */
2660 if (lxc_config_value_empty(value)) {
2661 lxc_conf->ephemeral = 0;
2662 return 0;
2663 }
2664
2665 /* Parse new config value. */
2666 if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0)
2667 return -1;
2668
2669 if (lxc_conf->ephemeral > 1) {
2670 ERROR(
2671 "Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
2672 return -1;
2673 }
2674
2675 return 0;
2676 }
2677
2678 static int set_config_syslog(const char *key, const char *value,
2679 struct lxc_conf *lxc_conf, void *data)
2680 {
2681 int facility;
2682
2683 /* Clear any previously set value. */
2684 if (lxc_conf->syslog) {
2685 free(lxc_conf->syslog);
2686 lxc_conf->syslog = NULL;
2687 }
2688
2689 /* Check if value is empty. */
2690 if (lxc_config_value_empty(value))
2691 return 0;
2692
2693 /* Parse value. */
2694 facility = lxc_syslog_priority_to_int(value);
2695 if (facility == -EINVAL) {
2696 ERROR("Wrong value for lxc.syslog.");
2697 return -1;
2698 }
2699
2700 lxc_log_syslog(facility);
2701 return set_config_string_item(&lxc_conf->syslog, value);
2702 }
2703
2704 static int set_config_no_new_privs(const char *key, const char *value,
2705 struct lxc_conf *lxc_conf, void *data)
2706 {
2707 unsigned int v;
2708
2709 /* Set config value to default. */
2710 if (lxc_config_value_empty(value)) {
2711 lxc_conf->no_new_privs = false;
2712 return 0;
2713 }
2714
2715 /* Parse new config value. */
2716 if (lxc_safe_uint(value, &v) < 0)
2717 return -1;
2718
2719 if (v > 1) {
2720 ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 "
2721 "or 1");
2722 return -1;
2723 }
2724
2725 lxc_conf->no_new_privs = v ? true : false;
2726
2727 return 0;
2728 }
2729
2730 /* Callbacks to get configuration items. */
2731 static int get_config_personality(const char *key, char *retv, int inlen,
2732 struct lxc_conf *c, void *data)
2733 {
2734 int fulllen = 0;
2735
2736 if (!retv)
2737 inlen = 0;
2738 else
2739 memset(retv, 0, inlen);
2740
2741 #if HAVE_SYS_PERSONALITY_H
2742 int len = 0;
2743
2744 switch (c->personality) {
2745 case PER_LINUX32:
2746 strprint(retv, inlen, "i686");
2747 break;
2748 case PER_LINUX:
2749 strprint(retv, inlen, "x86_64");
2750 break;
2751 default:
2752 break;
2753 }
2754 #endif
2755
2756 return fulllen;
2757 }
2758
2759 static int get_config_pts(const char *key, char *retv, int inlen,
2760 struct lxc_conf *c, void *data)
2761 {
2762 return lxc_get_conf_int(c, retv, inlen, c->pts);
2763 }
2764
2765 static int get_config_tty(const char *key, char *retv, int inlen,
2766 struct lxc_conf *c, void *data)
2767 {
2768 return lxc_get_conf_int(c, retv, inlen, c->tty);
2769 }
2770
2771 static int get_config_ttydir(const char *key, char *retv, int inlen,
2772 struct lxc_conf *c, void *data)
2773 {
2774 return lxc_get_conf_str(retv, inlen, c->ttydir);
2775 }
2776
2777 static int get_config_apparmor_profile(const char *key, char *retv, int inlen,
2778 struct lxc_conf *c, void *data)
2779 {
2780 return lxc_get_conf_str(retv, inlen, c->lsm_aa_profile);
2781 }
2782
2783 static int get_config_apparmor_allow_incomplete(const char *key, char *retv,
2784 int inlen, struct lxc_conf *c,
2785 void *data)
2786 {
2787 return lxc_get_conf_int(c, retv, inlen,
2788 c->lsm_aa_allow_incomplete);
2789 }
2790
2791 static int get_config_selinux_context(const char *key, char *retv, int inlen,
2792 struct lxc_conf *c, void *data)
2793 {
2794 return lxc_get_conf_str(retv, inlen, c->lsm_se_context);
2795 }
2796
2797 /*
2798 * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
2799 * then just the value(s) will be printed. Since there still could be
2800 * more than one, it is newline-separated.
2801 * (Maybe that's ambigous, since some values, i.e. devices.list, will
2802 * already have newlines?)
2803 * If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
2804 * in 'lxc.cgroup.subsystem.key = value' format.
2805 */
2806 static int get_config_cgroup(const char *key, char *retv, int inlen,
2807 struct lxc_conf *c, void *data)
2808 {
2809 struct lxc_list *it;
2810 int len;
2811 int fulllen = 0;
2812 bool get_all = false;
2813
2814 if (!retv)
2815 inlen = 0;
2816 else
2817 memset(retv, 0, inlen);
2818
2819 if (!strcmp(key, "lxc.cgroup"))
2820 get_all = true;
2821 else if (!strncmp(key, "lxc.cgroup.", 11))
2822 key += 11;
2823 else
2824 return -1;
2825
2826 lxc_list_for_each(it, &c->cgroup) {
2827 struct lxc_cgroup *cg = it->elem;
2828 if (get_all) {
2829 strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value);
2830 } else if (!strcmp(cg->subsystem, key)) {
2831 strprint(retv, inlen, "%s\n", cg->value);
2832 }
2833 }
2834
2835 return fulllen;
2836 }
2837
2838 static int get_config_idmaps(const char *key, char *retv, int inlen,
2839 struct lxc_conf *c, void *data)
2840 {
2841 struct lxc_list *it;
2842 int len, listlen, ret;
2843 int fulllen = 0;
2844 /* "u 1000 1000000 65536"
2845 *
2846 * let's render this as
2847 *
2848 * sizeof(char)
2849 * +
2850 * sizeof(" ")
2851 * +
2852 * sizeof(uint64_t)
2853 * +
2854 * sizeof(" ")
2855 * +
2856 * sizeof(uint64_t)
2857 * +
2858 * sizeof(" ")
2859 * +
2860 * sizeof(uint64_t)
2861 * +
2862 * \0
2863 */
2864 #define __LXC_IDMAP_STR_BUF (3 * LXC_NUMSTRLEN64 + 3 + 1 + 1)
2865 char buf[__LXC_IDMAP_STR_BUF];
2866
2867 if (!retv)
2868 inlen = 0;
2869 else
2870 memset(retv, 0, inlen);
2871
2872 listlen = lxc_list_len(&c->id_map);
2873 lxc_list_for_each(it, &c->id_map)
2874 {
2875 struct id_map *map = it->elem;
2876 ret = snprintf(buf, __LXC_IDMAP_STR_BUF, "%c %lu %lu %lu",
2877 (map->idtype == ID_TYPE_UID) ? 'u' : 'g',
2878 map->nsid, map->hostid, map->range);
2879 if (ret < 0 || ret >= __LXC_IDMAP_STR_BUF)
2880 return -1;
2881
2882 strprint(retv, inlen, "%s%s", buf, (listlen-- > 1) ? "\n" : "");
2883 }
2884 return fulllen;
2885 }
2886
2887 static int get_config_loglevel(const char *key, char *retv, int inlen,
2888 struct lxc_conf *c, void *data)
2889 {
2890 const char *v;
2891 v = lxc_log_priority_to_string(c->loglevel);
2892 return lxc_get_conf_str(retv, inlen, v);
2893 }
2894
2895 static int get_config_logfile(const char *key, char *retv, int inlen,
2896 struct lxc_conf *c, void *data)
2897 {
2898 return lxc_get_conf_str(retv, inlen, c->logfile);
2899 }
2900
2901 static int get_config_fstab(const char *key, char *retv, int inlen,
2902 struct lxc_conf *c, void *data)
2903 {
2904 return lxc_get_conf_str(retv, inlen, c->fstab);
2905 }
2906
2907 static int get_config_mount_auto(const char *key, char *retv, int inlen,
2908 struct lxc_conf *c, void *data)
2909 {
2910 int len, fulllen = 0;
2911 const char *sep = "";
2912
2913 if (!retv)
2914 inlen = 0;
2915 else
2916 memset(retv, 0, inlen);
2917
2918 if (!(c->auto_mounts & LXC_AUTO_ALL_MASK))
2919 return 0;
2920
2921 switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
2922 case LXC_AUTO_PROC_MIXED:
2923 strprint(retv, inlen, "%sproc:mixed", sep);
2924 sep = " ";
2925 break;
2926 case LXC_AUTO_PROC_RW:
2927 strprint(retv, inlen, "%sproc:rw", sep);
2928 sep = " ";
2929 break;
2930 default:
2931 break;
2932 }
2933
2934 switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
2935 case LXC_AUTO_SYS_RO:
2936 strprint(retv, inlen, "%ssys:ro", sep);
2937 sep = " ";
2938 break;
2939 case LXC_AUTO_SYS_RW:
2940 strprint(retv, inlen, "%ssys:rw", sep);
2941 sep = " ";
2942 break;
2943 case LXC_AUTO_SYS_MIXED:
2944 strprint(retv, inlen, "%ssys:mixed", sep);
2945 sep = " ";
2946 break;
2947 default:
2948 break;
2949 }
2950
2951 switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
2952 case LXC_AUTO_CGROUP_NOSPEC:
2953 strprint(retv, inlen, "%scgroup", sep);
2954 sep = " ";
2955 break;
2956 case LXC_AUTO_CGROUP_MIXED:
2957 strprint(retv, inlen, "%scgroup:mixed", sep);
2958 sep = " ";
2959 break;
2960 case LXC_AUTO_CGROUP_RO:
2961 strprint(retv, inlen, "%scgroup:ro", sep);
2962 sep = " ";
2963 break;
2964 case LXC_AUTO_CGROUP_RW:
2965 strprint(retv, inlen, "%scgroup:rw", sep);
2966 sep = " ";
2967 break;
2968 case LXC_AUTO_CGROUP_FULL_NOSPEC:
2969 strprint(retv, inlen, "%scgroup-full", sep);
2970 sep = " ";
2971 break;
2972 case LXC_AUTO_CGROUP_FULL_MIXED:
2973 strprint(retv, inlen, "%scgroup-full:mixed", sep);
2974 sep = " ";
2975 break;
2976 case LXC_AUTO_CGROUP_FULL_RO:
2977 strprint(retv, inlen, "%scgroup-full:ro", sep);
2978 sep = " ";
2979 break;
2980 case LXC_AUTO_CGROUP_FULL_RW:
2981 strprint(retv, inlen, "%scgroup-full:rw", sep);
2982 sep = " ";
2983 break;
2984 default:
2985 break;
2986 }
2987
2988 return fulllen;
2989 }
2990
2991 static int get_config_mount(const char *key, char *retv, int inlen,
2992 struct lxc_conf *c, void *data)
2993 {
2994 int len, fulllen = 0;
2995 struct lxc_list *it;
2996
2997 if (!retv)
2998 inlen = 0;
2999 else
3000 memset(retv, 0, inlen);
3001
3002 lxc_list_for_each(it, &c->mount_list)
3003 {
3004 strprint(retv, inlen, "%s\n", (char *)it->elem);
3005 }
3006
3007 return fulllen;
3008 }
3009
3010 static int get_config_rootfs(const char *key, char *retv, int inlen,
3011 struct lxc_conf *c, void *data)
3012 {
3013 return lxc_get_conf_str(retv, inlen, c->rootfs.path);
3014 }
3015
3016 static int get_config_rootfs_mount(const char *key, char *retv, int inlen,
3017 struct lxc_conf *c, void *data)
3018 {
3019 return lxc_get_conf_str(retv, inlen, c->rootfs.mount);
3020 }
3021
3022 static int get_config_rootfs_options(const char *key, char *retv, int inlen,
3023 struct lxc_conf *c, void *data)
3024 {
3025 return lxc_get_conf_str(retv, inlen, c->rootfs.options);
3026 }
3027
3028 static int get_config_rootfs_backend(const char *key, char *retv, int inlen,
3029 struct lxc_conf *c, void *data)
3030 {
3031 return lxc_get_conf_str(retv, inlen, c->rootfs.bdev_type);
3032 }
3033
3034 static int get_config_utsname(const char *key, char *retv, int inlen,
3035 struct lxc_conf *c, void *data)
3036 {
3037 return lxc_get_conf_str(
3038 retv, inlen,
3039 c->utsname ? c->utsname->nodename : NULL);
3040 }
3041
3042 static int get_config_hooks(const char *key, char *retv, int inlen,
3043 struct lxc_conf *c, void *data)
3044 {
3045 char *subkey;
3046 int len, fulllen = 0, found = -1;
3047 struct lxc_list *it;
3048 int i;
3049
3050 /* "lxc.hook.mount" */
3051 subkey = strchr(key, '.');
3052 if (subkey)
3053 subkey = strchr(subkey + 1, '.');
3054 if (!subkey)
3055 return -1;
3056 subkey++;
3057 if (!*subkey)
3058 return -1;
3059 for (i = 0; i < NUM_LXC_HOOKS; i++) {
3060 if (strcmp(lxchook_names[i], subkey) == 0) {
3061 found = i;
3062 break;
3063 }
3064 }
3065 if (found == -1)
3066 return -1;
3067
3068 if (!retv)
3069 inlen = 0;
3070 else
3071 memset(retv, 0, inlen);
3072
3073 lxc_list_for_each(it, &c->hooks[found]) {
3074 strprint(retv, inlen, "%s\n", (char *)it->elem);
3075 }
3076 return fulllen;
3077 }
3078
3079 static int get_config_net(const char *key, char *retv, int inlen,
3080 struct lxc_conf *c, void *data)
3081 {
3082 int len, fulllen = 0;
3083 struct lxc_list *it;
3084
3085 if (!retv)
3086 inlen = 0;
3087 else
3088 memset(retv, 0, inlen);
3089
3090 lxc_list_for_each(it, &c->network) {
3091 struct lxc_netdev *n = it->elem;
3092 const char *t = lxc_net_type_to_str(n->type);
3093 strprint(retv, inlen, "%s\n", t ? t : "(invalid)");
3094 }
3095
3096 return fulllen;
3097 }
3098
3099 static int get_config_cap_drop(const char *key, char *retv, int inlen,
3100 struct lxc_conf *c, void *data)
3101 {
3102 int len, fulllen = 0;
3103 struct lxc_list *it;
3104
3105 if (!retv)
3106 inlen = 0;
3107 else
3108 memset(retv, 0, inlen);
3109
3110 lxc_list_for_each(it, &c->caps) {
3111 strprint(retv, inlen, "%s\n", (char *)it->elem);
3112 }
3113 return fulllen;
3114 }
3115
3116 static int get_config_cap_keep(const char *key, char *retv, int inlen,
3117 struct lxc_conf *c, void *data)
3118 {
3119 int len, fulllen = 0;
3120 struct lxc_list *it;
3121
3122 if (!retv)
3123 inlen = 0;
3124 else
3125 memset(retv, 0, inlen);
3126
3127 lxc_list_for_each(it, &c->keepcaps) {
3128 strprint(retv, inlen, "%s\n", (char *)it->elem);
3129 }
3130 return fulllen;
3131 }
3132
3133 static int get_config_console(const char *key, char *retv, int inlen,
3134 struct lxc_conf *c, void *data)
3135 {
3136 return lxc_get_conf_str(retv, inlen, c->console.path);
3137 }
3138
3139 static int get_config_console_logfile(const char *key, char *retv, int inlen,
3140 struct lxc_conf *c, void *data)
3141 {
3142 return lxc_get_conf_str(retv, inlen, c->console.log_path);
3143 }
3144
3145 static int get_config_seccomp(const char *key, char *retv, int inlen,
3146 struct lxc_conf *c, void *data)
3147 {
3148 return lxc_get_conf_str(retv, inlen, c->seccomp);
3149 }
3150
3151 static int get_config_autodev(const char *key, char *retv, int inlen,
3152 struct lxc_conf *c, void *data)
3153 {
3154 return lxc_get_conf_int(c, retv, inlen, c->autodev);
3155 }
3156
3157 static int get_config_haltsignal(const char *key, char *retv, int inlen,
3158 struct lxc_conf *c, void *data)
3159 {
3160 return lxc_get_conf_int(c, retv, inlen, c->haltsignal);
3161 }
3162
3163 static int get_config_rebootsignal(const char *key, char *retv, int inlen,
3164 struct lxc_conf *c, void *data)
3165 {
3166 return lxc_get_conf_int(c, retv, inlen, c->rebootsignal);
3167 }
3168
3169 static int get_config_stopsignal(const char *key, char *retv, int inlen,
3170 struct lxc_conf *c, void *data)
3171 {
3172 return lxc_get_conf_int(c, retv, inlen, c->stopsignal);
3173 }
3174
3175 static int get_config_start(const char *key, char *retv, int inlen,
3176 struct lxc_conf *c, void *data)
3177 {
3178 if (strcmp(key + 10, "auto") == 0)
3179 return lxc_get_conf_int(c, retv, inlen, c->start_auto);
3180 else if (strcmp(key + 10, "delay") == 0)
3181 return lxc_get_conf_int(c, retv, inlen, c->start_delay);
3182 else if (strcmp(key + 10, "order") == 0)
3183 return lxc_get_conf_int(c, retv, inlen, c->start_order);
3184
3185 return -1;
3186 }
3187
3188 static int get_config_syslog(const char *key, char *retv, int inlen,
3189 struct lxc_conf *c, void *data)
3190 {
3191 return lxc_get_conf_str(retv, inlen, c->syslog);
3192 }
3193
3194 static int get_config_monitor(const char *key, char *retv, int inlen,
3195 struct lxc_conf *c, void *data)
3196 {
3197 return lxc_get_conf_int(c, retv, inlen, c->monitor_unshare);
3198 }
3199
3200 static int get_config_group(const char *key, char *retv, int inlen,
3201 struct lxc_conf *c, void *data)
3202 {
3203 int len, fulllen = 0;
3204 struct lxc_list *it;
3205
3206 if (!retv)
3207 inlen = 0;
3208 else
3209 memset(retv, 0, inlen);
3210
3211 lxc_list_for_each(it, &c->groups) {
3212 strprint(retv, inlen, "%s\n", (char *)it->elem);
3213 }
3214 return fulllen;
3215 }
3216
3217 static int get_config_environment(const char *key, char *retv, int inlen,
3218 struct lxc_conf *c, void *data)
3219 {
3220 int len, fulllen = 0;
3221 struct lxc_list *it;
3222
3223 if (!retv)
3224 inlen = 0;
3225 else
3226 memset(retv, 0, inlen);
3227
3228 lxc_list_for_each(it, &c->environment) {
3229 strprint(retv, inlen, "%s\n", (char *)it->elem);
3230 }
3231 return fulllen;
3232 }
3233
3234 static int get_config_init_cmd(const char *key, char *retv, int inlen,
3235 struct lxc_conf *c, void *data)
3236 {
3237 return lxc_get_conf_str(retv, inlen, c->init_cmd);
3238 }
3239
3240 static int get_config_init_uid(const char *key, char *retv, int inlen,
3241 struct lxc_conf *c, void *data)
3242 {
3243 return lxc_get_conf_int(c, retv, inlen, c->init_uid);
3244 }
3245
3246 static int get_config_init_gid(const char *key, char *retv, int inlen,
3247 struct lxc_conf *c, void *data)
3248 {
3249 return lxc_get_conf_int(c, retv, inlen, c->init_gid);
3250 }
3251
3252 static int get_config_ephemeral(const char *key, char *retv, int inlen,
3253 struct lxc_conf *c, void *data)
3254 {
3255 return lxc_get_conf_int(c, retv, inlen, c->ephemeral);
3256 }
3257
3258 static int get_config_no_new_privs(const char *key, char *retv, int inlen,
3259 struct lxc_conf *c, void *data)
3260 {
3261 return lxc_get_conf_int(c, retv, inlen, c->no_new_privs);
3262 }
3263
3264 /*
3265 * If you ask for a specific value, i.e. lxc.prlimit.nofile, then just the value
3266 * will be printed. If you ask for 'lxc.prlimit', then all limit entries will be
3267 * printed, in 'lxc.prlimit.resource = value' format.
3268 */
3269 static int get_config_prlimit(const char *key, char *retv, int inlen,
3270 struct lxc_conf *c, void *data)
3271 {
3272 int fulllen = 0, len;
3273 bool get_all = false;
3274 struct lxc_list *it;
3275
3276 if (!retv)
3277 inlen = 0;
3278 else
3279 memset(retv, 0, inlen);
3280
3281 if (!strcmp(key, "lxc.prlimit"))
3282 get_all = true;
3283 else if (strncmp(key, "lxc.prlimit.", 12) == 0)
3284 key += 12;
3285 else
3286 return -1;
3287
3288 lxc_list_for_each(it, &c->limits) {
3289 char buf[LXC_NUMSTRLEN64 * 2 + 2]; /* 2 colon separated 64 bit
3290 integers or the word
3291 'unlimited' */
3292 int partlen;
3293 struct lxc_limit *lim = it->elem;
3294
3295 if (lim->limit.rlim_cur == RLIM_INFINITY) {
3296 memcpy(buf, "unlimited", sizeof("unlimited"));
3297 partlen = sizeof("unlimited") - 1;
3298 } else {
3299 partlen = sprintf(buf, "%" PRIu64,
3300 (uint64_t)lim->limit.rlim_cur);
3301 }
3302 if (lim->limit.rlim_cur != lim->limit.rlim_max) {
3303 if (lim->limit.rlim_max == RLIM_INFINITY) {
3304 memcpy(buf + partlen, ":unlimited",
3305 sizeof(":unlimited"));
3306 } else {
3307 sprintf(buf + partlen, ":%" PRIu64,
3308 (uint64_t)lim->limit.rlim_max);
3309 }
3310 }
3311
3312 if (get_all) {
3313 strprint(retv, inlen, "lxc.prlimit.%s = %s\n",
3314 lim->resource, buf);
3315 } else if (strcmp(lim->resource, key) == 0) {
3316 strprint(retv, inlen, "%s", buf);
3317 }
3318 }
3319
3320 return fulllen;
3321 }
3322
3323 /* Callbacks to clear config items. */
3324 static inline int clr_config_personality(const char *key, struct lxc_conf *c,
3325 void *data)
3326 {
3327 c->personality = -1;
3328 return 0;
3329 }
3330
3331 static inline int clr_config_pts(const char *key, struct lxc_conf *c,
3332 void *data)
3333 {
3334 c->pts = 0;
3335 return 0;
3336 }
3337
3338 static inline int clr_config_tty(const char *key, struct lxc_conf *c,
3339 void *data)
3340 {
3341 c->tty = 0;
3342 return 0;
3343 }
3344
3345 static inline int clr_config_ttydir(const char *key, struct lxc_conf *c,
3346 void *data)
3347 {
3348 free(c->ttydir);
3349 c->ttydir = NULL;
3350 return 0;
3351 }
3352
3353 static inline int clr_config_apparmor_profile(const char *key,
3354 struct lxc_conf *c, void *data)
3355 {
3356 free(c->lsm_aa_profile);
3357 c->lsm_aa_profile = NULL;
3358 return 0;
3359 }
3360
3361 static inline int clr_config_apparmor_allow_incomplete(const char *key,
3362 struct lxc_conf *c,
3363 void *data)
3364 {
3365 c->lsm_aa_allow_incomplete = 0;
3366 return 0;
3367 }
3368
3369 static inline int clr_config_selinux_context(const char *key,
3370 struct lxc_conf *c, void *data)
3371 {
3372 free(c->lsm_se_context);
3373 c->lsm_se_context = NULL;
3374 return 0;
3375 }
3376
3377 static inline int clr_config_cgroup(const char *key, struct lxc_conf *c,
3378 void *data)
3379 {
3380 return lxc_clear_cgroups(c, key);
3381 }
3382
3383 static inline int clr_config_idmaps(const char *key, struct lxc_conf *c,
3384 void *data)
3385 {
3386 return lxc_clear_idmaps(c);
3387 }
3388
3389 static inline int clr_config_loglevel(const char *key, struct lxc_conf *c,
3390 void *data)
3391 {
3392 c->loglevel = LXC_LOG_LEVEL_NOTSET;
3393 return 0;
3394 }
3395
3396 static inline int clr_config_logfile(const char *key, struct lxc_conf *c,
3397 void *data)
3398 {
3399 free(c->logfile);
3400 c->logfile = NULL;
3401 return 0;
3402 }
3403
3404 static inline int clr_config_mount(const char *key, struct lxc_conf *c,
3405 void *data)
3406 {
3407 return lxc_clear_mount_entries(c);
3408 }
3409
3410 static inline int clr_config_mount_auto(const char *key, struct lxc_conf *c,
3411 void *data)
3412 {
3413 return lxc_clear_automounts(c);
3414 }
3415
3416 static inline int clr_config_fstab(const char *key, struct lxc_conf *c,
3417 void *data)
3418 {
3419 free(c->fstab);
3420 c->fstab = NULL;
3421 return 0;
3422 }
3423
3424 static inline int clr_config_rootfs(const char *key, struct lxc_conf *c,
3425 void *data)
3426 {
3427 free(c->rootfs.path);
3428 c->rootfs.path = NULL;
3429 return 0;
3430 }
3431
3432 static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c,
3433 void *data)
3434 {
3435 free(c->rootfs.mount);
3436 c->rootfs.mount = NULL;
3437 return 0;
3438 }
3439
3440 static inline int clr_config_rootfs_options(const char *key, struct lxc_conf *c,
3441 void *data)
3442 {
3443 free(c->rootfs.options);
3444 c->rootfs.options = NULL;
3445 return 0;
3446 }
3447
3448 static inline int clr_config_rootfs_backend(const char *key, struct lxc_conf *c,
3449 void *data)
3450 {
3451 free(c->rootfs.bdev_type);
3452 c->rootfs.bdev_type = NULL;
3453 return 0;
3454 }
3455
3456 static inline int clr_config_utsname(const char *key, struct lxc_conf *c,
3457 void *data)
3458 {
3459 free(c->utsname);
3460 c->utsname = NULL;
3461 return 0;
3462 }
3463
3464 static inline int clr_config_hooks(const char *key, struct lxc_conf *c,
3465 void *data)
3466 {
3467 return lxc_clear_hooks(c, key);
3468 }
3469
3470 static inline int clr_config_net(const char *key, struct lxc_conf *c,
3471 void *data)
3472 {
3473 lxc_free_networks(&c->network);
3474
3475 return 0;
3476 }
3477
3478 static inline int clr_config_cap_drop(const char *key, struct lxc_conf *c,
3479 void *data)
3480 {
3481 return lxc_clear_config_caps(c);
3482 }
3483
3484 static inline int clr_config_cap_keep(const char *key, struct lxc_conf *c,
3485 void *data)
3486 {
3487 return lxc_clear_config_keepcaps(c);
3488 }
3489
3490 static inline int clr_config_console(const char *key, struct lxc_conf *c,
3491 void *data)
3492 {
3493 free(c->console.path);
3494 c->console.path = NULL;
3495 return 0;
3496 }
3497
3498 static inline int clr_config_console_logfile(const char *key,
3499 struct lxc_conf *c, void *data)
3500 {
3501 free(c->console.log_path);
3502 c->console.log_path = NULL;
3503 return 0;
3504 }
3505
3506 static inline int clr_config_seccomp(const char *key, struct lxc_conf *c,
3507 void *data)
3508 {
3509 free(c->seccomp);
3510 c->seccomp = NULL;
3511 return 0;
3512 }
3513
3514 static inline int clr_config_autodev(const char *key, struct lxc_conf *c,
3515 void *data)
3516 {
3517 c->autodev = 1;
3518 return 0;
3519 }
3520
3521 static inline int clr_config_haltsignal(const char *key, struct lxc_conf *c,
3522 void *data)
3523 {
3524 c->haltsignal = 0;
3525 return 0;
3526 }
3527
3528 static inline int clr_config_rebootsignal(const char *key, struct lxc_conf *c,
3529 void *data)
3530 {
3531 c->rebootsignal = 0;
3532 return 0;
3533 }
3534
3535 static inline int clr_config_stopsignal(const char *key, struct lxc_conf *c,
3536 void *data)
3537 {
3538 c->stopsignal = 0;
3539 return 0;
3540 }
3541
3542 static inline int clr_config_start(const char *key, struct lxc_conf *c,
3543 void *data)
3544 {
3545 if (strcmp(key + 10, "auto") == 0)
3546 c->start_auto = 0;
3547 else if (strcmp(key + 10, "delay") == 0)
3548 c->start_delay = 0;
3549 else if (strcmp(key + 10, "order") == 0)
3550 c->start_order = 0;
3551
3552 return 0;
3553 }
3554
3555 static inline int clr_config_syslog(const char *key, struct lxc_conf *c,
3556 void *data)
3557 {
3558 free(c->syslog);
3559 c->syslog = NULL;
3560 return 0;
3561 }
3562
3563 static inline int clr_config_monitor(const char *key, struct lxc_conf *c,
3564 void *data)
3565 {
3566 c->monitor_unshare = 0;
3567 return 0;
3568 }
3569
3570 static inline int clr_config_group(const char *key, struct lxc_conf *c,
3571 void *data)
3572 {
3573 return lxc_clear_groups(c);
3574 }
3575
3576 static inline int clr_config_environment(const char *key, struct lxc_conf *c,
3577 void *data)
3578 {
3579 return lxc_clear_environment(c);
3580 }
3581
3582 static inline int clr_config_init_cmd(const char *key, struct lxc_conf *c,
3583 void *data)
3584 {
3585 free(c->init_cmd);
3586 c->init_cmd = NULL;
3587 return 0;
3588 }
3589
3590 static inline int clr_config_init_uid(const char *key, struct lxc_conf *c,
3591 void *data)
3592 {
3593 c->init_uid = 0;
3594 return 0;
3595 }
3596
3597 static inline int clr_config_init_gid(const char *key, struct lxc_conf *c,
3598 void *data)
3599 {
3600 c->init_gid = 0;
3601 return 0;
3602 }
3603
3604 static inline int clr_config_ephemeral(const char *key, struct lxc_conf *c,
3605 void *data)
3606 {
3607 c->ephemeral = 0;
3608 return 0;
3609 }
3610
3611 static inline int clr_config_no_new_privs(const char *key, struct lxc_conf *c,
3612 void *data)
3613 {
3614 c->no_new_privs = false;
3615 return 0;
3616 }
3617
3618 static inline int clr_config_prlimit(const char *key, struct lxc_conf *c,
3619 void *data)
3620 {
3621 return lxc_clear_limits(c, key);
3622 }
3623
3624 static inline int clr_config_includefiles(const char *key, struct lxc_conf *c,
3625 void *data)
3626 {
3627 lxc_clear_includes(c);
3628 return 0;
3629 }
3630
3631 static int get_config_includefiles(const char *key, char *retv, int inlen,
3632 struct lxc_conf *c, void *data)
3633 {
3634 return -ENOSYS;
3635 }
3636
3637 static struct lxc_config_t *
3638 get_network_config_ops(const char *key, struct lxc_conf *lxc_conf, ssize_t *idx)
3639 {
3640 char *copy, *idx_start, *idx_end;
3641 struct lxc_config_t *config = NULL;
3642
3643 /* check that this is a sensible network key */
3644 if (strncmp("lxc.net.", key, 8))
3645 return NULL;
3646
3647 copy = strdup(key);
3648 if (!copy)
3649 return NULL;
3650
3651 /* lxc.net.<n> */
3652 if (isdigit(*(key + 8))) {
3653 int ret;
3654 unsigned int tmpidx;
3655 size_t numstrlen;
3656
3657 /* beginning of index string */
3658 idx_start = (copy + 7);
3659 *idx_start = '\0';
3660
3661 /* end of index string */
3662 idx_end = strchr((copy + 8), '.');
3663 if (!idx_end)
3664 goto on_error;
3665 *idx_end = '\0';
3666
3667 /* parse current index */
3668 ret = lxc_safe_uint((idx_start + 1), &tmpidx);
3669 if (ret < 0) {
3670 *idx = ret;
3671 goto on_error;
3672 }
3673
3674 /* This, of course is utterly nonsensical on so many levels, but
3675 * better safe than sorry.
3676 * (Checking for INT_MAX here is intentional.)
3677 */
3678 if (tmpidx == INT_MAX) {
3679 SYSERROR(
3680 "number of configured networks would overflow the "
3681 "counter... what are you doing?");
3682 goto on_error;
3683 }
3684 *idx = tmpidx;
3685
3686 numstrlen = strlen((idx_start + 1));
3687
3688 /* repair configuration key */
3689 *idx_start = '.';
3690 *idx_end = '.';
3691
3692 memmove(copy + 8, idx_end + 1, strlen(idx_end + 1));
3693 copy[strlen(key) - numstrlen + 1] = '\0';
3694 }
3695
3696 config = lxc_getconfig(copy);
3697 if (!config)
3698 ERROR("unknown network configuration key %s", key);
3699
3700 on_error:
3701 free(copy);
3702 return config;
3703 }
3704
3705 /*
3706 * Config entry is something like "lxc.net.0.ipv4" the key 'lxc.net.'
3707 * was found. So we make sure next comes an integer, find the right callback
3708 * (by rewriting the key), and call it.
3709 */
3710 static int set_config_net_nic(const char *key, const char *value,
3711 struct lxc_conf *lxc_conf, void *data)
3712 {
3713 struct lxc_config_t *config;
3714 struct lxc_netdev *netdev;
3715 ssize_t idx = -1;
3716
3717 if (lxc_config_value_empty(value))
3718 return clr_config_net_nic(key, lxc_conf, data);
3719
3720 config = get_network_config_ops(key, lxc_conf, &idx);
3721 if (!config || idx < 0)
3722 return -1;
3723
3724 netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, true);
3725 if (!netdev)
3726 return -1;
3727
3728 return config->set(key, value, lxc_conf, netdev);
3729 }
3730
3731 /*
3732 * Config entry is something like "lxc.net.0.ipv4" the key 'lxc.net.'
3733 * was found. So we make sure next comes an integer, find the right callback
3734 * (by rewriting the key), and call it.
3735 */
3736 static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf,
3737 void *data)
3738 {
3739 const char *idxstring;
3740 struct lxc_config_t *config;
3741 struct lxc_netdev *netdev;
3742 ssize_t idx;
3743
3744 /* If we get passed "lxc.net.<n>" we clear the whole network. */
3745 if (strncmp("lxc.net.", key, 8))
3746 return -1;
3747
3748 idxstring = key + 8;
3749 /* The left conjunct is pretty self-explanatory. The right conjunct
3750 * checks whether the two pointers are equal. If they are we now that
3751 * this is not a key that is namespaced any further and so we are
3752 * supposed to clear the whole network.
3753 */
3754 if (isdigit(*idxstring) && (strrchr(key, '.') == (idxstring - 1))) {
3755 unsigned int rmnetdevidx;
3756
3757 if (lxc_safe_uint(idxstring, &rmnetdevidx) < 0)
3758 return -1;
3759
3760 /* Remove network from network list. */
3761 lxc_remove_nic_by_idx(lxc_conf, rmnetdevidx);
3762 return 0;
3763 }
3764
3765 config = get_network_config_ops(key, lxc_conf, &idx);
3766 if (!config || idx < 0)
3767 return -1;
3768
3769 netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, false);
3770 if (!netdev)
3771 return -1;
3772
3773 return config->clr(key, lxc_conf, netdev);
3774 }
3775
3776 static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf,
3777 void *data)
3778 {
3779 struct lxc_netdev *netdev;
3780
3781 if (!data)
3782 return -1;
3783 else
3784 netdev = data;
3785 if (!netdev)
3786 return -1;
3787
3788 netdev->type = -1;
3789
3790 return 0;
3791 }
3792
3793 static int clr_config_net_name(const char *key, struct lxc_conf *lxc_conf,
3794 void *data)
3795 {
3796 struct lxc_netdev *netdev;
3797
3798 if (!data)
3799 return -1;
3800 else
3801 netdev = data;
3802 if (!netdev)
3803 return -1;
3804
3805 free(netdev->name);
3806 netdev->name = NULL;
3807
3808 return 0;
3809 }
3810
3811 static int clr_config_net_flags(const char *key, struct lxc_conf *lxc_conf,
3812 void *data)
3813 {
3814 struct lxc_netdev *netdev;
3815
3816 if (!data)
3817 return -1;
3818 else
3819 netdev = data;
3820 if (!netdev)
3821 return -1;
3822
3823 netdev->flags = 0;
3824
3825 return 0;
3826 }
3827
3828 static int clr_config_net_link(const char *key, struct lxc_conf *lxc_conf,
3829 void *data)
3830 {
3831 struct lxc_netdev *netdev;
3832
3833 if (!data)
3834 return -1;
3835 else
3836 netdev = data;
3837 if (!netdev)
3838 return -1;
3839
3840 free(netdev->link);
3841 netdev->link = NULL;
3842
3843 return 0;
3844 }
3845
3846 static int clr_config_net_macvlan_mode(const char *key,
3847 struct lxc_conf *lxc_conf, void *data)
3848 {
3849 struct lxc_netdev *netdev;
3850
3851 if (!data)
3852 return -1;
3853 else
3854 netdev = data;
3855 if (!netdev)
3856 return -1;
3857
3858 if (netdev->type != LXC_NET_MACVLAN)
3859 return 0;
3860
3861 netdev->priv.macvlan_attr.mode = -1;
3862
3863 return 0;
3864 }
3865
3866 static int clr_config_net_veth_pair(const char *key, struct lxc_conf *lxc_conf,
3867 void *data)
3868 {
3869 struct lxc_netdev *netdev;
3870
3871 if (!data)
3872 return -1;
3873 else
3874 netdev = data;
3875 if (!netdev)
3876 return -1;
3877
3878 free(netdev->priv.veth_attr.pair);
3879 netdev->priv.veth_attr.pair = NULL;
3880
3881 return 0;
3882 }
3883
3884 static int clr_config_net_script_up(const char *key, struct lxc_conf *lxc_conf,
3885 void *data)
3886 {
3887 struct lxc_netdev *netdev;
3888
3889 if (!data)
3890 return -1;
3891 else
3892 netdev = data;
3893 if (!netdev)
3894 return -1;
3895
3896 free(netdev->upscript);
3897 netdev->upscript = NULL;
3898
3899 return 0;
3900 }
3901
3902 static int clr_config_net_script_down(const char *key,
3903 struct lxc_conf *lxc_conf, void *data)
3904 {
3905 struct lxc_netdev *netdev;
3906
3907 if (!data)
3908 return -1;
3909 else
3910 netdev = data;
3911 if (!netdev)
3912 return -1;
3913
3914 free(netdev->downscript);
3915 netdev->downscript = NULL;
3916
3917 return 0;
3918 }
3919
3920 static int clr_config_net_hwaddr(const char *key, struct lxc_conf *lxc_conf,
3921 void *data)
3922 {
3923 struct lxc_netdev *netdev;
3924
3925 if (!data)
3926 return -1;
3927 else
3928 netdev = data;
3929 if (!netdev)
3930 return -1;
3931
3932 free(netdev->hwaddr);
3933 netdev->hwaddr = NULL;
3934
3935 return 0;
3936 }
3937
3938 static int clr_config_net_mtu(const char *key, struct lxc_conf *lxc_conf,
3939 void *data)
3940 {
3941 struct lxc_netdev *netdev;
3942
3943 if (!data)
3944 return -1;
3945 else
3946 netdev = data;
3947 if (!netdev)
3948 return -1;
3949
3950 free(netdev->mtu);
3951 netdev->mtu = NULL;
3952
3953 return 0;
3954 }
3955
3956 static int clr_config_net_vlan_id(const char *key, struct lxc_conf *lxc_conf,
3957 void *data)
3958 {
3959 struct lxc_netdev *netdev;
3960
3961 if (!data)
3962 return -1;
3963 else
3964 netdev = data;
3965 if (!netdev)
3966 return -1;
3967
3968 netdev->priv.vlan_attr.vid = 0;
3969
3970 return 0;
3971 }
3972
3973 static int clr_config_net_ipv4_gateway(const char *key,
3974 struct lxc_conf *lxc_conf, void *data)
3975 {
3976 struct lxc_netdev *netdev;
3977
3978 if (!data)
3979 return -1;
3980 else
3981 netdev = data;
3982 if (!netdev)
3983 return -1;
3984
3985 free(netdev->ipv4_gateway);
3986 netdev->ipv4_gateway = NULL;
3987
3988 return 0;
3989 }
3990
3991 static int clr_config_net_ipv4(const char *key, struct lxc_conf *lxc_conf,
3992 void *data)
3993 {
3994 struct lxc_netdev *netdev;
3995 struct lxc_list *cur, *next;
3996
3997 if (!data)
3998 return -1;
3999 else
4000 netdev = data;
4001 if (!netdev)
4002 return -1;
4003
4004 lxc_list_for_each_safe(cur, &netdev->ipv4, next) {
4005 lxc_list_del(cur);
4006 free(cur->elem);
4007 free(cur);
4008 }
4009
4010 return 0;
4011 }
4012
4013 static int clr_config_net_ipv6_gateway(const char *key,
4014 struct lxc_conf *lxc_conf, void *data)
4015 {
4016 struct lxc_netdev *netdev;
4017
4018 if (!data)
4019 return -1;
4020 else
4021 netdev = data;
4022 if (!netdev)
4023 return -1;
4024
4025 free(netdev->ipv6_gateway);
4026 netdev->ipv6_gateway = NULL;
4027
4028 return 0;
4029 }
4030
4031 static int clr_config_net_ipv6(const char *key, struct lxc_conf *lxc_conf,
4032 void *data)
4033 {
4034 struct lxc_netdev *netdev;
4035 struct lxc_list *cur, *next;
4036
4037 if (!data)
4038 return -1;
4039 else
4040 netdev = data;
4041 if (!netdev)
4042 return -1;
4043
4044 lxc_list_for_each_safe(cur, &netdev->ipv6, next) {
4045 lxc_list_del(cur);
4046 free(cur->elem);
4047 free(cur);
4048 }
4049
4050 return 0;
4051 }
4052
4053 static int get_config_net_nic(const char *key, char *retv, int inlen,
4054 struct lxc_conf *c, void *data)
4055 {
4056 struct lxc_config_t *config;
4057 struct lxc_netdev *netdev;
4058 ssize_t idx = -1;
4059
4060 config = get_network_config_ops(key, c, &idx);
4061 if (!config || idx < 0)
4062 return -1;
4063
4064 netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false);
4065 if (!netdev)
4066 return -1;
4067
4068 return config->get(key, retv, inlen, c, netdev);
4069 }
4070
4071 static int get_config_net_type(const char *key, char *retv, int inlen,
4072 struct lxc_conf *c, void *data)
4073 {
4074 int len, fulllen = 0;
4075 struct lxc_netdev *netdev;
4076
4077 if (!retv)
4078 inlen = 0;
4079 else
4080 memset(retv, 0, inlen);
4081
4082 if (!data)
4083 return -1;
4084 else
4085 netdev = data;
4086 if (!netdev)
4087 return -1;
4088
4089 strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type));
4090
4091 return fulllen;
4092 }
4093
4094 static int get_config_net_flags(const char *key, char *retv, int inlen,
4095 struct lxc_conf *c, void *data)
4096 {
4097 int len, fulllen = 0;
4098 struct lxc_netdev *netdev;
4099
4100 if (!retv)
4101 inlen = 0;
4102 else
4103 memset(retv, 0, inlen);
4104
4105 if (!data)
4106 return -1;
4107 else
4108 netdev = data;
4109 if (!netdev)
4110 return -1;
4111
4112 if (netdev->flags & IFF_UP)
4113 strprint(retv, inlen, "up");
4114
4115 return fulllen;
4116 }
4117
4118 static int get_config_net_link(const char *key, char *retv, int inlen,
4119 struct lxc_conf *c, void *data)
4120 {
4121 int len, fulllen = 0;
4122 struct lxc_netdev *netdev;
4123
4124 if (!retv)
4125 inlen = 0;
4126 else
4127 memset(retv, 0, inlen);
4128
4129 if (!data)
4130 return -1;
4131 else
4132 netdev = data;
4133 if (!netdev)
4134 return -1;
4135
4136 if (netdev->link)
4137 strprint(retv, inlen, "%s", netdev->link);
4138
4139 return fulllen;
4140 }
4141
4142 static int get_config_net_name(const char *key, char *retv, int inlen,
4143 struct lxc_conf *c, void *data)
4144 {
4145 int len, fulllen = 0;
4146 struct lxc_netdev *netdev;
4147
4148 if (!retv)
4149 inlen = 0;
4150 else
4151 memset(retv, 0, inlen);
4152
4153 if (!data)
4154 return -1;
4155 else
4156 netdev = data;
4157 if (!netdev)
4158 return -1;
4159
4160 if (netdev->name)
4161 strprint(retv, inlen, "%s", netdev->name);
4162
4163 return fulllen;
4164 }
4165
4166 static int get_config_net_macvlan_mode(const char *key, char *retv, int inlen,
4167 struct lxc_conf *c, void *data)
4168 {
4169 const char *mode;
4170 int len, fulllen = 0;
4171 struct lxc_netdev *netdev;
4172
4173 if (!retv)
4174 inlen = 0;
4175 else
4176 memset(retv, 0, inlen);
4177
4178 if (!data)
4179 return -1;
4180 else
4181 netdev = data;
4182 if (!netdev)
4183 return -1;
4184
4185 if (netdev->type != LXC_NET_MACVLAN)
4186 return 0;
4187
4188 switch (netdev->priv.macvlan_attr.mode) {
4189 case MACVLAN_MODE_PRIVATE:
4190 mode = "private";
4191 break;
4192 case MACVLAN_MODE_VEPA:
4193 mode = "vepa";
4194 break;
4195 case MACVLAN_MODE_BRIDGE:
4196 mode = "bridge";
4197 break;
4198 case MACVLAN_MODE_PASSTHRU:
4199 mode = "passthru";
4200 break;
4201 default:
4202 mode = "(invalid)";
4203 break;
4204 }
4205
4206 strprint(retv, inlen, "%s", mode);
4207
4208 return fulllen;
4209 }
4210
4211 static int get_config_net_veth_pair(const char *key, char *retv, int inlen,
4212 struct lxc_conf *c, void *data)
4213 {
4214 int len, fulllen = 0;
4215 struct lxc_netdev *netdev;
4216
4217 if (!retv)
4218 inlen = 0;
4219 else
4220 memset(retv, 0, inlen);
4221
4222 if (!data)
4223 return -1;
4224 else
4225 netdev = data;
4226 if (!netdev)
4227 return -1;
4228
4229 if (netdev->type != LXC_NET_VETH)
4230 return 0;
4231
4232 strprint(retv, inlen, "%s",
4233 netdev->priv.veth_attr.pair ? netdev->priv.veth_attr.pair
4234 : netdev->priv.veth_attr.veth1);
4235
4236 return fulllen;
4237 }
4238
4239 static int get_config_net_script_up(const char *key, char *retv, int inlen,
4240 struct lxc_conf *c, void *data)
4241 {
4242 int len, fulllen = 0;
4243 struct lxc_netdev *netdev;
4244
4245 if (!retv)
4246 inlen = 0;
4247 else
4248 memset(retv, 0, inlen);
4249
4250 if (!data)
4251 return -1;
4252 else
4253 netdev = data;
4254 if (!netdev)
4255 return -1;
4256
4257 if (netdev->upscript)
4258 strprint(retv, inlen, "%s", netdev->upscript);
4259
4260 return fulllen;
4261 }
4262
4263 static int get_config_net_script_down(const char *key, char *retv, int inlen,
4264 struct lxc_conf *c, void *data)
4265 {
4266 int len, fulllen = 0;
4267 struct lxc_netdev *netdev;
4268
4269 if (!retv)
4270 inlen = 0;
4271 else
4272 memset(retv, 0, inlen);
4273
4274 if (!data)
4275 return -1;
4276 else
4277 netdev = data;
4278 if (!netdev)
4279 return -1;
4280
4281 if (netdev->downscript)
4282 strprint(retv, inlen, "%s", netdev->downscript);
4283
4284 return fulllen;
4285 }
4286
4287 static int get_config_net_hwaddr(const char *key, char *retv, int inlen,
4288 struct lxc_conf *c, void *data)
4289 {
4290 int len, fulllen = 0;
4291 struct lxc_netdev *netdev;
4292
4293 if (!retv)
4294 inlen = 0;
4295 else
4296 memset(retv, 0, inlen);
4297
4298 if (!data)
4299 return -1;
4300 else
4301 netdev = data;
4302 if (!netdev)
4303 return -1;
4304
4305 if (netdev->hwaddr)
4306 strprint(retv, inlen, "%s", netdev->hwaddr);
4307
4308 return fulllen;
4309 }
4310
4311 static int get_config_net_mtu(const char *key, char *retv, int inlen,
4312 struct lxc_conf *c, void *data)
4313 {
4314 int len, fulllen = 0;
4315 struct lxc_netdev *netdev;
4316
4317 if (!retv)
4318 inlen = 0;
4319 else
4320 memset(retv, 0, inlen);
4321
4322 if (!data)
4323 return -1;
4324 else
4325 netdev = data;
4326 if (!netdev)
4327 return -1;
4328
4329 if (netdev->mtu)
4330 strprint(retv, inlen, "%s", netdev->mtu);
4331
4332 return fulllen;
4333 }
4334
4335 static int get_config_net_vlan_id(const char *key, char *retv, int inlen,
4336 struct lxc_conf *c, void *data)
4337 {
4338 int len, fulllen = 0;
4339 struct lxc_netdev *netdev;
4340
4341 if (!retv)
4342 inlen = 0;
4343 else
4344 memset(retv, 0, inlen);
4345
4346 if (!data)
4347 return -1;
4348 else
4349 netdev = data;
4350 if (!netdev)
4351 return -1;
4352
4353 if (netdev->type != LXC_NET_VLAN)
4354 return 0;
4355
4356 strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
4357
4358 return fulllen;
4359 }
4360
4361 static int get_config_net_ipv4_gateway(const char *key, char *retv, int inlen,
4362 struct lxc_conf *c, void *data)
4363 {
4364 int len, fulllen = 0;
4365 char buf[INET_ADDRSTRLEN];
4366 struct lxc_netdev *netdev;
4367
4368 if (!retv)
4369 inlen = 0;
4370 else
4371 memset(retv, 0, inlen);
4372
4373 if (!data)
4374 return -1;
4375 else
4376 netdev = data;
4377 if (!netdev)
4378 return -1;
4379
4380 if (netdev->ipv4_gateway_auto) {
4381 strprint(retv, inlen, "auto");
4382 } else if (netdev->ipv4_gateway) {
4383 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
4384 strprint(retv, inlen, "%s", buf);
4385 }
4386
4387 return fulllen;
4388 }
4389
4390 static int get_config_net_ipv4(const char *key, char *retv, int inlen,
4391 struct lxc_conf *c, void *data)
4392 {
4393 int len, fulllen = 0;
4394 size_t listlen;
4395 char buf[INET_ADDRSTRLEN];
4396 struct lxc_netdev *netdev;
4397 struct lxc_list *it;
4398
4399 if (!retv)
4400 inlen = 0;
4401 else
4402 memset(retv, 0, inlen);
4403
4404 if (!data)
4405 return -1;
4406 else
4407 netdev = data;
4408 if (!netdev)
4409 return -1;
4410
4411 listlen = lxc_list_len(&netdev->ipv4);
4412 lxc_list_for_each(it, &netdev->ipv4) {
4413 struct lxc_inetdev *i = it->elem;
4414 inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
4415 strprint(retv, inlen, "%s/%d%s", buf, i->prefix,
4416 (listlen-- > 1) ? "\n" : "");
4417 }
4418
4419 return fulllen;
4420 }
4421
4422 static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen,
4423 struct lxc_conf *c, void *data)
4424 {
4425 int len, fulllen = 0;
4426 char buf[INET6_ADDRSTRLEN];
4427 struct lxc_netdev *netdev;
4428
4429 if (!retv)
4430 inlen = 0;
4431 else
4432 memset(retv, 0, inlen);
4433
4434 if (!data)
4435 return -1;
4436 else
4437 netdev = data;
4438 if (!netdev)
4439 return -1;
4440
4441 if (netdev->ipv6_gateway_auto) {
4442 strprint(retv, inlen, "auto");
4443 } else if (netdev->ipv6_gateway) {
4444 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
4445 strprint(retv, inlen, "%s", buf);
4446 }
4447
4448 return fulllen;
4449 }
4450
4451 static int get_config_net_ipv6(const char *key, char *retv, int inlen,
4452 struct lxc_conf *c, void *data)
4453 {
4454 int len, fulllen = 0;
4455 size_t listlen;
4456 char buf[INET6_ADDRSTRLEN];
4457 struct lxc_netdev *netdev;
4458 struct lxc_list *it;
4459
4460 if (!retv)
4461 inlen = 0;
4462 else
4463 memset(retv, 0, inlen);
4464
4465 if (!data)
4466 return -1;
4467 else
4468 netdev = data;
4469 if (!netdev)
4470 return -1;
4471
4472 listlen = lxc_list_len(&netdev->ipv6);
4473 lxc_list_for_each(it, &netdev->ipv6) {
4474 struct lxc_inet6dev *i = it->elem;
4475 inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
4476 strprint(retv, inlen, "%s/%d%s", buf, i->prefix,
4477 (listlen-- > 1) ? "\n" : "");
4478 }
4479
4480 return fulllen;
4481 }