#include "../include/netns_ifaddrs.h"
#include "log.h"
#include "lxcseccomp.h"
+#include "macro.h"
#include "memory_utils.h"
#include "network.h"
#include "parse.h"
lxc_config_define(cgroup_controller);
lxc_config_define(cgroup2_controller);
lxc_config_define(cgroup_dir);
+lxc_config_define(cgroup_monitor_dir);
+lxc_config_define(cgroup_monitor_pivot_dir);
+lxc_config_define(cgroup_container_dir);
+lxc_config_define(cgroup_container_inner_dir);
lxc_config_define(cgroup_relative);
lxc_config_define(console_buffer_size);
lxc_config_define(console_logfile);
lxc_config_define(mount_fstab);
lxc_config_define(namespace_clone);
lxc_config_define(namespace_keep);
+lxc_config_define(time_offset_boot);
+lxc_config_define(time_offset_monotonic);
lxc_config_define(namespace_share);
lxc_config_define(net);
lxc_config_define(net_flags);
lxc_config_define(net_veth_pair);
lxc_config_define(net_veth_ipv4_route);
lxc_config_define(net_veth_ipv6_route);
+lxc_config_define(net_veth_vlan_id);
+lxc_config_define(net_veth_vlan_tagged_id);
lxc_config_define(net_vlan_id);
lxc_config_define(no_new_privs);
lxc_config_define(personality);
lxc_config_define(sysctl);
lxc_config_define(proc);
+/*
+ * Important Note:
+ * If a new config option is added to this table, be aware that
+ * the order in which the options are places into the table matters.
+ * That means that more specific options of a namespace have to be
+ * placed above more generic ones.
+ *
+ * For instance: If lxc.ab is placed before lxc.ab.c, the config option
+ * lxc.ab.c will always be matched to lxc.ab. That is, the lxc.ab.c option
+ * has to be placed above lxc.ab.
+ */
static struct lxc_config_t config_jump_table[] = {
- { "lxc.arch", set_config_personality, get_config_personality, clr_config_personality, },
- { "lxc.apparmor.profile", set_config_apparmor_profile, get_config_apparmor_profile, clr_config_apparmor_profile, },
- { "lxc.apparmor.allow_incomplete", set_config_apparmor_allow_incomplete, get_config_apparmor_allow_incomplete, clr_config_apparmor_allow_incomplete, },
- { "lxc.apparmor.allow_nesting", set_config_apparmor_allow_nesting, get_config_apparmor_allow_nesting, clr_config_apparmor_allow_nesting, },
- { "lxc.apparmor.raw", set_config_apparmor_raw, get_config_apparmor_raw, clr_config_apparmor_raw, },
- { "lxc.autodev.tmpfs.size", set_config_autodev_tmpfs_size, get_config_autodev_tmpfs_size, clr_config_autodev_tmpfs_size, },
- { "lxc.autodev", set_config_autodev, get_config_autodev, clr_config_autodev, },
- { "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, },
- { "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
- { "lxc.cgroup2", set_config_cgroup2_controller, get_config_cgroup2_controller, clr_config_cgroup2_controller, },
- { "lxc.cgroup.dir", set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, },
- { "lxc.cgroup.relative", set_config_cgroup_relative, get_config_cgroup_relative, clr_config_cgroup_relative, },
- { "lxc.cgroup", set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, },
- { "lxc.console.buffer.size", set_config_console_buffer_size, get_config_console_buffer_size, clr_config_console_buffer_size, },
- { "lxc.console.logfile", set_config_console_logfile, get_config_console_logfile, clr_config_console_logfile, },
- { "lxc.console.path", set_config_console_path, get_config_console_path, clr_config_console_path, },
- { "lxc.console.rotate", set_config_console_rotate, get_config_console_rotate, clr_config_console_rotate, },
- { "lxc.console.size", set_config_console_size, get_config_console_size, clr_config_console_size, },
- { "lxc.environment", set_config_environment, get_config_environment, clr_config_environment, },
- { "lxc.ephemeral", set_config_ephemeral, get_config_ephemeral, clr_config_ephemeral, },
- { "lxc.execute.cmd", set_config_execute_cmd, get_config_execute_cmd, clr_config_execute_cmd, },
- { "lxc.group", set_config_group, get_config_group, clr_config_group, },
- { "lxc.hook.autodev", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.clone", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.destroy", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.mount", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.post-stop", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.pre-mount", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.pre-start", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.start", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.start-host", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.stop", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.hook.version", set_config_hooks_version, get_config_hooks_version, clr_config_hooks_version, },
- { "lxc.hook", set_config_hooks, get_config_hooks, clr_config_hooks, },
- { "lxc.idmap", set_config_idmaps, get_config_idmaps, clr_config_idmaps, },
- { "lxc.include", set_config_includefiles, get_config_includefiles, clr_config_includefiles, },
- { "lxc.init.cmd", set_config_init_cmd, get_config_init_cmd, clr_config_init_cmd, },
- { "lxc.init.gid", set_config_init_gid, get_config_init_gid, clr_config_init_gid, },
- { "lxc.init.uid", set_config_init_uid, get_config_init_uid, clr_config_init_uid, },
- { "lxc.init.cwd", set_config_init_cwd, get_config_init_cwd, clr_config_init_cwd, },
- { "lxc.keyring.session", set_config_keyring_session, get_config_keyring_session, clr_config_keyring_session },
- { "lxc.log.file", set_config_log_file, get_config_log_file, clr_config_log_file, },
- { "lxc.log.level", set_config_log_level, get_config_log_level, clr_config_log_level, },
- { "lxc.log.syslog", set_config_log_syslog, get_config_log_syslog, clr_config_log_syslog, },
- { "lxc.monitor.unshare", set_config_monitor, get_config_monitor, clr_config_monitor, },
- { "lxc.monitor.signal.pdeath", set_config_monitor_signal_pdeath, get_config_monitor_signal_pdeath, clr_config_monitor_signal_pdeath, },
- { "lxc.mount.auto", set_config_mount_auto, get_config_mount_auto, clr_config_mount_auto, },
- { "lxc.mount.entry", set_config_mount, get_config_mount, clr_config_mount, },
- { "lxc.mount.fstab", set_config_mount_fstab, get_config_mount_fstab, clr_config_mount_fstab, },
- { "lxc.namespace.clone", set_config_namespace_clone, get_config_namespace_clone, clr_config_namespace_clone, },
- { "lxc.namespace.keep", set_config_namespace_keep, get_config_namespace_keep, clr_config_namespace_keep, },
- { "lxc.namespace.share", set_config_namespace_share, get_config_namespace_share, clr_config_namespace_share, },
- { "lxc.net.flags", set_config_net_flags, get_config_net_flags, clr_config_net_flags, },
- { "lxc.net.hwaddr", set_config_net_hwaddr, get_config_net_hwaddr, clr_config_net_hwaddr, },
- { "lxc.net.ipv4.address", set_config_net_ipv4_address, get_config_net_ipv4_address, clr_config_net_ipv4_address, },
- { "lxc.net.ipv4.gateway", set_config_net_ipv4_gateway, get_config_net_ipv4_gateway, clr_config_net_ipv4_gateway, },
- { "lxc.net.ipv6.address", set_config_net_ipv6_address, get_config_net_ipv6_address, clr_config_net_ipv6_address, },
- { "lxc.net.ipv6.gateway", set_config_net_ipv6_gateway, get_config_net_ipv6_gateway, clr_config_net_ipv6_gateway, },
- { "lxc.net.link", set_config_net_link, get_config_net_link, clr_config_net_link, },
- { "lxc.net.l2proxy", set_config_net_l2proxy, get_config_net_l2proxy, clr_config_net_l2proxy, },
- { "lxc.net.macvlan.mode", set_config_net_macvlan_mode, get_config_net_macvlan_mode, clr_config_net_macvlan_mode, },
- { "lxc.net.ipvlan.mode", set_config_net_ipvlan_mode, get_config_net_ipvlan_mode, clr_config_net_ipvlan_mode, },
- { "lxc.net.ipvlan.isolation", set_config_net_ipvlan_isolation, get_config_net_ipvlan_isolation, clr_config_net_ipvlan_isolation, },
- { "lxc.net.mtu", set_config_net_mtu, get_config_net_mtu, clr_config_net_mtu, },
- { "lxc.net.name", set_config_net_name, get_config_net_name, clr_config_net_name, },
- { "lxc.net.script.down", set_config_net_script_down, get_config_net_script_down, clr_config_net_script_down, },
- { "lxc.net.script.up", set_config_net_script_up, get_config_net_script_up, clr_config_net_script_up, },
- { "lxc.net.type", set_config_net_type, get_config_net_type, clr_config_net_type, },
- { "lxc.net.vlan.id", set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, },
- { "lxc.net.veth.mode", set_config_net_veth_mode, get_config_net_veth_mode, clr_config_net_veth_mode, },
- { "lxc.net.veth.pair", set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, },
- { "lxc.net.veth.ipv4.route", set_config_net_veth_ipv4_route, get_config_net_veth_ipv4_route, clr_config_net_veth_ipv4_route, },
- { "lxc.net.veth.ipv6.route", set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, },
- { "lxc.net.", set_config_net_nic, get_config_net_nic, clr_config_net_nic, },
- { "lxc.net", set_config_net, get_config_net, clr_config_net, },
- { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
- { "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, },
- { "lxc.pty.max", set_config_pty_max, get_config_pty_max, clr_config_pty_max, },
- { "lxc.rootfs.managed", set_config_rootfs_managed, get_config_rootfs_managed, clr_config_rootfs_managed, },
- { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, },
- { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, },
- { "lxc.rootfs.path", set_config_rootfs_path, get_config_rootfs_path, clr_config_rootfs_path, },
- { "lxc.seccomp.allow_nesting", set_config_seccomp_allow_nesting, get_config_seccomp_allow_nesting, clr_config_seccomp_allow_nesting, },
- { "lxc.seccomp.notify.cookie", set_config_seccomp_notify_cookie, get_config_seccomp_notify_cookie, clr_config_seccomp_notify_cookie, },
- { "lxc.seccomp.notify.proxy", set_config_seccomp_notify_proxy, get_config_seccomp_notify_proxy, clr_config_seccomp_notify_proxy, },
- { "lxc.seccomp.profile", set_config_seccomp_profile, get_config_seccomp_profile, clr_config_seccomp_profile, },
- { "lxc.selinux.context.keyring", set_config_selinux_context_keyring, get_config_selinux_context_keyring, clr_config_selinux_context_keyring },
- { "lxc.selinux.context", set_config_selinux_context, get_config_selinux_context, clr_config_selinux_context, },
- { "lxc.signal.halt", set_config_signal_halt, get_config_signal_halt, clr_config_signal_halt, },
- { "lxc.signal.reboot", set_config_signal_reboot, get_config_signal_reboot, clr_config_signal_reboot, },
- { "lxc.signal.stop", set_config_signal_stop, get_config_signal_stop, clr_config_signal_stop, },
- { "lxc.start.auto", set_config_start, get_config_start, clr_config_start, },
- { "lxc.start.delay", set_config_start, get_config_start, clr_config_start, },
- { "lxc.start.order", set_config_start, get_config_start, clr_config_start, },
- { "lxc.tty.dir", set_config_tty_dir, get_config_tty_dir, clr_config_tty_dir, },
- { "lxc.tty.max", set_config_tty_max, get_config_tty_max, clr_config_tty_max, },
- { "lxc.uts.name", set_config_uts_name, get_config_uts_name, clr_config_uts_name, },
- { "lxc.sysctl", set_config_sysctl, get_config_sysctl, clr_config_sysctl, },
- { "lxc.proc", set_config_proc, get_config_proc, clr_config_proc, },
+ { "lxc.arch", set_config_personality, get_config_personality, clr_config_personality, },
+ { "lxc.apparmor.profile", set_config_apparmor_profile, get_config_apparmor_profile, clr_config_apparmor_profile, },
+ { "lxc.apparmor.allow_incomplete", set_config_apparmor_allow_incomplete, get_config_apparmor_allow_incomplete, clr_config_apparmor_allow_incomplete, },
+ { "lxc.apparmor.allow_nesting", set_config_apparmor_allow_nesting, get_config_apparmor_allow_nesting, clr_config_apparmor_allow_nesting, },
+ { "lxc.apparmor.raw", set_config_apparmor_raw, get_config_apparmor_raw, clr_config_apparmor_raw, },
+ { "lxc.autodev.tmpfs.size", set_config_autodev_tmpfs_size, get_config_autodev_tmpfs_size, clr_config_autodev_tmpfs_size, },
+ { "lxc.autodev", set_config_autodev, get_config_autodev, clr_config_autodev, },
+ { "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, },
+ { "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
+ { "lxc.cgroup2", set_config_cgroup2_controller, get_config_cgroup2_controller, clr_config_cgroup2_controller, },
+ { "lxc.cgroup.dir.monitor.pivot", set_config_cgroup_monitor_pivot_dir, get_config_cgroup_monitor_pivot_dir, clr_config_cgroup_monitor_pivot_dir, },
+ { "lxc.cgroup.dir.monitor", set_config_cgroup_monitor_dir, get_config_cgroup_monitor_dir, clr_config_cgroup_monitor_dir, },
+ { "lxc.cgroup.dir.container.inner", set_config_cgroup_container_inner_dir, get_config_cgroup_container_inner_dir, clr_config_cgroup_container_inner_dir, },
+ { "lxc.cgroup.dir.container", set_config_cgroup_container_dir, get_config_cgroup_container_dir, clr_config_cgroup_container_dir, },
+ { "lxc.cgroup.dir", set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, },
+ { "lxc.cgroup.relative", set_config_cgroup_relative, get_config_cgroup_relative, clr_config_cgroup_relative, },
+ { "lxc.cgroup", set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, },
+ { "lxc.console.buffer.size", set_config_console_buffer_size, get_config_console_buffer_size, clr_config_console_buffer_size, },
+ { "lxc.console.logfile", set_config_console_logfile, get_config_console_logfile, clr_config_console_logfile, },
+ { "lxc.console.path", set_config_console_path, get_config_console_path, clr_config_console_path, },
+ { "lxc.console.rotate", set_config_console_rotate, get_config_console_rotate, clr_config_console_rotate, },
+ { "lxc.console.size", set_config_console_size, get_config_console_size, clr_config_console_size, },
+ { "lxc.environment", set_config_environment, get_config_environment, clr_config_environment, },
+ { "lxc.ephemeral", set_config_ephemeral, get_config_ephemeral, clr_config_ephemeral, },
+ { "lxc.execute.cmd", set_config_execute_cmd, get_config_execute_cmd, clr_config_execute_cmd, },
+ { "lxc.group", set_config_group, get_config_group, clr_config_group, },
+ { "lxc.hook.autodev", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.clone", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.destroy", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.mount", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.post-stop", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.pre-mount", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.pre-start", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.start", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.start-host", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.stop", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.hook.version", set_config_hooks_version, get_config_hooks_version, clr_config_hooks_version, },
+ { "lxc.hook", set_config_hooks, get_config_hooks, clr_config_hooks, },
+ { "lxc.idmap", set_config_idmaps, get_config_idmaps, clr_config_idmaps, },
+ { "lxc.include", set_config_includefiles, get_config_includefiles, clr_config_includefiles, },
+ { "lxc.init.cmd", set_config_init_cmd, get_config_init_cmd, clr_config_init_cmd, },
+ { "lxc.init.gid", set_config_init_gid, get_config_init_gid, clr_config_init_gid, },
+ { "lxc.init.uid", set_config_init_uid, get_config_init_uid, clr_config_init_uid, },
+ { "lxc.init.cwd", set_config_init_cwd, get_config_init_cwd, clr_config_init_cwd, },
+ { "lxc.keyring.session", set_config_keyring_session, get_config_keyring_session, clr_config_keyring_session },
+ { "lxc.log.file", set_config_log_file, get_config_log_file, clr_config_log_file, },
+ { "lxc.log.level", set_config_log_level, get_config_log_level, clr_config_log_level, },
+ { "lxc.log.syslog", set_config_log_syslog, get_config_log_syslog, clr_config_log_syslog, },
+ { "lxc.monitor.unshare", set_config_monitor, get_config_monitor, clr_config_monitor, },
+ { "lxc.monitor.signal.pdeath", set_config_monitor_signal_pdeath, get_config_monitor_signal_pdeath, clr_config_monitor_signal_pdeath, },
+ { "lxc.mount.auto", set_config_mount_auto, get_config_mount_auto, clr_config_mount_auto, },
+ { "lxc.mount.entry", set_config_mount, get_config_mount, clr_config_mount, },
+ { "lxc.mount.fstab", set_config_mount_fstab, get_config_mount_fstab, clr_config_mount_fstab, },
+ { "lxc.namespace.clone", set_config_namespace_clone, get_config_namespace_clone, clr_config_namespace_clone, },
+ { "lxc.namespace.keep", set_config_namespace_keep, get_config_namespace_keep, clr_config_namespace_keep, },
+ { "lxc.namespace.share", set_config_namespace_share, get_config_namespace_share, clr_config_namespace_share, },
+ { "lxc.time.offset.boot", set_config_time_offset_boot, get_config_time_offset_boot, clr_config_time_offset_boot, },
+ { "lxc.time.offset.monotonic", set_config_time_offset_monotonic, get_config_time_offset_monotonic, clr_config_time_offset_monotonic, },
+ { "lxc.net.flags", set_config_net_flags, get_config_net_flags, clr_config_net_flags, },
+ { "lxc.net.hwaddr", set_config_net_hwaddr, get_config_net_hwaddr, clr_config_net_hwaddr, },
+ { "lxc.net.ipv4.address", set_config_net_ipv4_address, get_config_net_ipv4_address, clr_config_net_ipv4_address, },
+ { "lxc.net.ipv4.gateway", set_config_net_ipv4_gateway, get_config_net_ipv4_gateway, clr_config_net_ipv4_gateway, },
+ { "lxc.net.ipv6.address", set_config_net_ipv6_address, get_config_net_ipv6_address, clr_config_net_ipv6_address, },
+ { "lxc.net.ipv6.gateway", set_config_net_ipv6_gateway, get_config_net_ipv6_gateway, clr_config_net_ipv6_gateway, },
+ { "lxc.net.link", set_config_net_link, get_config_net_link, clr_config_net_link, },
+ { "lxc.net.l2proxy", set_config_net_l2proxy, get_config_net_l2proxy, clr_config_net_l2proxy, },
+ { "lxc.net.macvlan.mode", set_config_net_macvlan_mode, get_config_net_macvlan_mode, clr_config_net_macvlan_mode, },
+ { "lxc.net.ipvlan.mode", set_config_net_ipvlan_mode, get_config_net_ipvlan_mode, clr_config_net_ipvlan_mode, },
+ { "lxc.net.ipvlan.isolation", set_config_net_ipvlan_isolation, get_config_net_ipvlan_isolation, clr_config_net_ipvlan_isolation, },
+ { "lxc.net.mtu", set_config_net_mtu, get_config_net_mtu, clr_config_net_mtu, },
+ { "lxc.net.name", set_config_net_name, get_config_net_name, clr_config_net_name, },
+ { "lxc.net.script.down", set_config_net_script_down, get_config_net_script_down, clr_config_net_script_down, },
+ { "lxc.net.script.up", set_config_net_script_up, get_config_net_script_up, clr_config_net_script_up, },
+ { "lxc.net.type", set_config_net_type, get_config_net_type, clr_config_net_type, },
+ { "lxc.net.vlan.id", set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, },
+ { "lxc.net.veth.mode", set_config_net_veth_mode, get_config_net_veth_mode, clr_config_net_veth_mode, },
+ { "lxc.net.veth.pair", set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, },
+ { "lxc.net.veth.ipv4.route", set_config_net_veth_ipv4_route, get_config_net_veth_ipv4_route, clr_config_net_veth_ipv4_route, },
+ { "lxc.net.veth.ipv6.route", set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, },
+ { "lxc.net.veth.vlan.id", set_config_net_veth_vlan_id, get_config_net_veth_vlan_id, clr_config_net_veth_vlan_id, },
+ { "lxc.net.veth.vlan.tagged.id", set_config_net_veth_vlan_tagged_id, get_config_net_veth_vlan_tagged_id, clr_config_net_veth_vlan_tagged_id, },
+ { "lxc.net.", set_config_net_nic, get_config_net_nic, clr_config_net_nic, },
+ { "lxc.net", set_config_net, get_config_net, clr_config_net, },
+ { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
+ { "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, },
+ { "lxc.pty.max", set_config_pty_max, get_config_pty_max, clr_config_pty_max, },
+ { "lxc.rootfs.managed", set_config_rootfs_managed, get_config_rootfs_managed, clr_config_rootfs_managed, },
+ { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, },
+ { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, },
+ { "lxc.rootfs.path", set_config_rootfs_path, get_config_rootfs_path, clr_config_rootfs_path, },
+ { "lxc.seccomp.allow_nesting", set_config_seccomp_allow_nesting, get_config_seccomp_allow_nesting, clr_config_seccomp_allow_nesting, },
+ { "lxc.seccomp.notify.cookie", set_config_seccomp_notify_cookie, get_config_seccomp_notify_cookie, clr_config_seccomp_notify_cookie, },
+ { "lxc.seccomp.notify.proxy", set_config_seccomp_notify_proxy, get_config_seccomp_notify_proxy, clr_config_seccomp_notify_proxy, },
+ { "lxc.seccomp.profile", set_config_seccomp_profile, get_config_seccomp_profile, clr_config_seccomp_profile, },
+ { "lxc.selinux.context.keyring", set_config_selinux_context_keyring, get_config_selinux_context_keyring, clr_config_selinux_context_keyring },
+ { "lxc.selinux.context", set_config_selinux_context, get_config_selinux_context, clr_config_selinux_context, },
+ { "lxc.signal.halt", set_config_signal_halt, get_config_signal_halt, clr_config_signal_halt, },
+ { "lxc.signal.reboot", set_config_signal_reboot, get_config_signal_reboot, clr_config_signal_reboot, },
+ { "lxc.signal.stop", set_config_signal_stop, get_config_signal_stop, clr_config_signal_stop, },
+ { "lxc.start.auto", set_config_start, get_config_start, clr_config_start, },
+ { "lxc.start.delay", set_config_start, get_config_start, clr_config_start, },
+ { "lxc.start.order", set_config_start, get_config_start, clr_config_start, },
+ { "lxc.tty.dir", set_config_tty_dir, get_config_tty_dir, clr_config_tty_dir, },
+ { "lxc.tty.max", set_config_tty_max, get_config_tty_max, clr_config_tty_max, },
+ { "lxc.uts.name", set_config_uts_name, get_config_uts_name, clr_config_uts_name, },
+ { "lxc.sysctl", set_config_sysctl, get_config_sysctl, clr_config_sysctl, },
+ { "lxc.proc", set_config_proc, get_config_proc, clr_config_proc, },
};
static const size_t config_jump_table_size = sizeof(config_jump_table) / sizeof(struct lxc_config_t);
+struct lxc_config_t *lxc_get_config_exact(const char *key)
+{
+ size_t i;
+
+ for (i = 0; i < config_jump_table_size; i++)
+ if (!strcmp(config_jump_table[i].name, key))
+ return &config_jump_table[i];
+
+ return NULL;
+}
+
+
struct lxc_config_t *lxc_get_config(const char *key)
{
size_t i;
return clr_config_net_type(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
if (strcmp(value, "veth") == 0) {
netdev->type = LXC_NET_VETH;
lxc_list_init(&netdev->priv.veth_attr.ipv4_routes);
lxc_list_init(&netdev->priv.veth_attr.ipv6_routes);
- lxc_veth_mode_to_flag(&netdev->priv.veth_attr.mode, "bridge");
+ lxc_list_init(&netdev->priv.veth_attr.vlan_tagged_ids);
+ if (!lxc_veth_flag_to_mode(netdev->priv.veth_attr.mode))
+ lxc_veth_mode_to_flag(&netdev->priv.veth_attr.mode, "bridge");
} else if (strcmp(value, "macvlan") == 0) {
netdev->type = LXC_NET_MACVLAN;
- lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, "private");
+ if (!lxc_macvlan_flag_to_mode(netdev->priv.veth_attr.mode))
+ lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, "private");
} else if (strcmp(value, "ipvlan") == 0) {
netdev->type = LXC_NET_IPVLAN;
- lxc_ipvlan_mode_to_flag(&netdev->priv.ipvlan_attr.mode, "l3");
- lxc_ipvlan_isolation_to_flag(&netdev->priv.ipvlan_attr.isolation, "bridge");
+ if (!lxc_ipvlan_flag_to_mode(netdev->priv.ipvlan_attr.mode))
+ lxc_ipvlan_mode_to_flag(&netdev->priv.ipvlan_attr.mode, "l3");
+ if (!lxc_ipvlan_flag_to_isolation(netdev->priv.ipvlan_attr.isolation))
+ lxc_ipvlan_isolation_to_flag(&netdev->priv.ipvlan_attr.isolation, "bridge");
} else if (strcmp(value, "vlan") == 0) {
netdev->type = LXC_NET_VLAN;
} else if (strcmp(value, "phys") == 0) {
} else if (strcmp(value, "none") == 0) {
netdev->type = LXC_NET_NONE;
} else {
- ERROR("Invalid network type %s", value);
- return -1;
+ return log_error(-1, "Invalid network type %s", value);
}
return 0;
return clr_config_net_flags(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
netdev->flags |= IFF_UP;
static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf,
struct lxc_netdev *netdev)
{
- struct netns_ifaddrs *ifaddr, *ifa;
+ call_cleaner(netns_freeifaddrs) struct netns_ifaddrs *ifaddr = NULL;
+ struct netns_ifaddrs *ifa;
int n;
int ret = 0;
const char *type_key = "lxc.net.type";
const char *link_key = "lxc.net.link";
const char *tmpvalue = "phys";
- if (netns_getifaddrs(&ifaddr, -1, &(bool){false}) < 0) {
- SYSERROR("Failed to get network interfaces");
- return -1;
- }
+ if (netns_getifaddrs(&ifaddr, -1, &(bool){false}) < 0)
+ return log_error_errno(-1, errno, "Failed to get network interfaces");
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
if (!ifa->ifa_addr)
}
}
- netns_freeifaddrs(ifaddr);
- ifaddr = NULL;
-
return ret;
}
return clr_config_net_link(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
if (value[strlen(value) - 1] == '+' && netdev->type == LXC_NET_PHYS)
ret = create_matched_ifnames(value, lxc_conf, netdev);
return clr_config_net_l2proxy(key, lxc_conf, data);
if (!netdev)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
ret = lxc_safe_uint(value, &val);
if (ret < 0)
- return ret_set_errno(-1, -ret);
+ return ret_errno(-ret);
switch (val) {
case 0:
return clr_config_net_name(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
return network_ifname(netdev->name, value, sizeof(netdev->name));
}
return clr_config_net_veth_mode(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
return lxc_veth_mode_to_flag(&netdev->priv.veth_attr.mode, value);
}
return clr_config_net_veth_pair(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
+
+ return network_ifname(netdev->priv.veth_attr.pair, value,
+ sizeof(netdev->priv.veth_attr.pair));
+}
+
+static int set_config_net_veth_vlan_id(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
- return network_ifname(netdev->priv.veth_attr.pair, value, sizeof(netdev->priv.veth_attr.pair));
+ if (lxc_config_value_empty(value))
+ return clr_config_net_veth_vlan_id(key, lxc_conf, data);
+
+ if (strcmp(value, "none") == 0) {
+ netdev->priv.veth_attr.vlan_id = BRIDGE_VLAN_NONE;
+ } else {
+ unsigned short vlan_id;
+ ret = get_u16(&vlan_id, value, 0);
+ if (ret < 0)
+ return ret_errno(EINVAL);
+
+ if (vlan_id > BRIDGE_VLAN_ID_MAX)
+ return ret_errno(EINVAL);
+
+ netdev->priv.veth_attr.vlan_id = vlan_id;
+ }
+
+ netdev->priv.veth_attr.vlan_id_set = true;
+ return 0;
+}
+
+static int set_config_net_veth_vlan_tagged_id(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ __do_free struct lxc_list *list = NULL;
+ int ret;
+ unsigned short vlan_id;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_veth_vlan_tagged_id(key, lxc_conf, data);
+
+ ret = get_u16(&vlan_id, value, 0);
+ if (ret < 0)
+ ret_errno(EINVAL);
+
+ if (vlan_id > BRIDGE_VLAN_ID_MAX)
+ ret_errno(EINVAL);
+
+ list = malloc(sizeof(*list));
+ if (!list)
+ return ret_errno(ENOMEM);
+
+ lxc_list_init(list);
+ list->elem = UINT_TO_PTR(vlan_id);
+
+ lxc_list_add_tail(&netdev->priv.veth_attr.vlan_tagged_ids, move_ptr(list));
+
+ return 0;
}
static int set_config_net_macvlan_mode(const char *key, const char *value,
return clr_config_net_macvlan_mode(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
return lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, value);
}
return clr_config_net_ipvlan_mode(key, lxc_conf, data);
if (!netdev)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
- if (netdev->type != LXC_NET_IPVLAN) {
- SYSERROR("Invalid ipvlan mode \"%s\", can only be used with ipvlan network", value);
- return ret_set_errno(-1, EINVAL);
- }
+ if (netdev->type != LXC_NET_IPVLAN)
+ return log_error_errno(-EINVAL,
+ EINVAL, "Invalid ipvlan mode \"%s\", can only be used with ipvlan network",
+ value);
return lxc_ipvlan_mode_to_flag(&netdev->priv.ipvlan_attr.mode, value);
}
return clr_config_net_ipvlan_isolation(key, lxc_conf, data);
if (!netdev)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
- if (netdev->type != LXC_NET_IPVLAN) {
- SYSERROR("Invalid ipvlan isolation \"%s\", can only be used with ipvlan network", value);
- return ret_set_errno(-1, EINVAL);
- }
+ if (netdev->type != LXC_NET_IPVLAN)
+ return log_error_errno(-EINVAL,
+ EINVAL, "Invalid ipvlan isolation \"%s\", can only be used with ipvlan network",
+ value);
return lxc_ipvlan_isolation_to_flag(&netdev->priv.ipvlan_attr.isolation, value);
}
return clr_config_net_hwaddr(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
new_value = strdup(value);
if (!new_value)
- return -1;
+ return ret_errno(ENOMEM);
rand_complete_hwaddr(new_value);
return clr_config_net_vlan_id(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
ret = get_u16(&netdev->priv.vlan_attr.vid, value, 0);
if (ret < 0)
- return -1;
+ return ret;
return 0;
}
return clr_config_net_mtu(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
return set_config_string_item(&netdev->mtu, value);
}
static int set_config_net_ipv4_address(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free char *addr = NULL;
+ __do_free struct lxc_inetdev *inetdev = NULL;
+ __do_free struct lxc_list *list = NULL;
int ret;
struct lxc_netdev *netdev = data;
- struct lxc_inetdev *inetdev;
- struct lxc_list *list;
char *cursor, *slash;
- char *addr = NULL, *bcast = NULL, *prefix = NULL;
+ char *bcast = NULL, *prefix = NULL;
if (lxc_config_value_empty(value))
return clr_config_net_ipv4_address(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
inetdev = malloc(sizeof(*inetdev));
if (!inetdev)
- return -1;
+ return ret_errno(ENOMEM);
memset(inetdev, 0, sizeof(*inetdev));
list = malloc(sizeof(*list));
- if (!list) {
- free(inetdev);
- return -1;
- }
+ if (!list)
+ return ret_errno(ENOMEM);
lxc_list_init(list);
- list->elem = inetdev;
addr = strdup(value);
- if (!addr) {
- free(inetdev);
- free(list);
- return -1;
- }
+ if (!addr)
+ return ret_errno(ENOMEM);
cursor = strstr(addr, " ");
if (cursor) {
}
ret = inet_pton(AF_INET, addr, &inetdev->addr);
- if (!ret || ret < 0) {
- SYSERROR("Invalid ipv4 address \"%s\"", value);
- free(inetdev);
- free(addr);
- free(list);
- return -1;
- }
+ if (!ret || ret < 0)
+ return log_error_errno(-1, errno, "Invalid ipv4 address \"%s\"", value);
if (bcast) {
ret = inet_pton(AF_INET, bcast, &inetdev->bcast);
- if (!ret || ret < 0) {
- SYSERROR("Invalid ipv4 broadcast address \"%s\"", value);
- free(inetdev);
- free(list);
- free(addr);
- return -1;
- }
+ if (!ret || ret < 0)
+ return log_error_errno(-1, errno, "Invalid ipv4 broadcast address \"%s\"", value);
}
/* No prefix specified, determine it from the network class. */
if (prefix) {
ret = lxc_safe_uint(prefix, &inetdev->prefix);
- if (ret < 0) {
- free(inetdev);
- free(list);
- free(addr);
- return -1;
- }
+ if (ret < 0)
+ return ret;
} else {
inetdev->prefix = config_ip_prefix(&inetdev->addr);
}
inetdev->bcast.s_addr |= htonl(INADDR_BROADCAST >> inetdev->prefix);
}
+ list->elem = inetdev;
lxc_list_add_tail(&netdev->ipv4, list);
- free(addr);
+ move_ptr(inetdev);
+ move_ptr(list);
return 0;
}
netdev->ipv4_gateway_auto = false;
netdev->ipv4_gateway_dev = true;
} else {
+ __do_free struct in_addr *gw = NULL;
int ret;
- struct in_addr *gw;
gw = malloc(sizeof(*gw));
if (!gw)
- return -1;
+ return ret_errno(ENOMEM);
ret = inet_pton(AF_INET, value, gw);
- if (!ret || ret < 0) {
- SYSERROR("Invalid ipv4 gateway address \"%s\"", value);
- free(gw);
- return -1;
- }
+ if (!ret || ret < 0)
+ return log_error_errno(-1, errno, "Invalid ipv4 gateway address \"%s\"", value);
- netdev->ipv4_gateway = gw;
+ netdev->ipv4_gateway = move_ptr(gw);
netdev->ipv4_gateway_auto = false;
}
return clr_config_net_veth_ipv4_route(key, lxc_conf, data);
if (!netdev)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
- if (netdev->type != LXC_NET_VETH) {
- SYSERROR("Invalid ipv4 route \"%s\", can only be used with veth network", value);
- return ret_set_errno(-1, EINVAL);
- }
+ if (netdev->type != LXC_NET_VETH)
+ return log_error_errno(-EINVAL,
+ EINVAL, "Invalid ipv4 route \"%s\", can only be used with veth network",
+ value);
inetdev = malloc(sizeof(*inetdev));
if (!inetdev)
- return -1;
+ return ret_errno(ENOMEM);
memset(inetdev, 0, sizeof(*inetdev));
list = malloc(sizeof(*list));
if (!list)
- return -1;
+ return ret_errno(ENOMEM);
lxc_list_init(list);
list->elem = inetdev;
valdup = strdup(value);
if (!valdup)
- return -1;
+ return ret_errno(ENOMEM);
slash = strchr(valdup, '/');
if (!slash)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
*slash = '\0';
slash++;
if (*slash == '\0')
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
netmask = slash;
ret = lxc_safe_uint(netmask, &inetdev->prefix);
if (ret < 0 || inetdev->prefix > 32)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
ret = inet_pton(AF_INET, valdup, &inetdev->addr);
if (!ret || ret < 0)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
lxc_list_add_tail(&netdev->priv.veth_attr.ipv4_routes, list);
move_ptr(inetdev);
static int set_config_net_ipv6_address(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free char *valdup = NULL;
+ __do_free struct lxc_inet6dev *inet6dev = NULL;
+ __do_free struct lxc_list *list = NULL;
int ret;
struct lxc_netdev *netdev = data;
- struct lxc_inet6dev *inet6dev;
- struct lxc_list *list;
- char *slash, *valdup, *netmask;
+ char *slash, *netmask;
if (lxc_config_value_empty(value))
return clr_config_net_ipv6_address(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
inet6dev = malloc(sizeof(*inet6dev));
if (!inet6dev)
- return -1;
+ return ret_errno(ENOMEM);
memset(inet6dev, 0, sizeof(*inet6dev));
list = malloc(sizeof(*list));
- if (!list) {
- free(inet6dev);
- return -1;
- }
+ if (!list)
+ return ret_errno(ENOMEM);
lxc_list_init(list);
- list->elem = inet6dev;
valdup = strdup(value);
- if (!valdup) {
- free(list);
- free(inet6dev);
- return -1;
- }
+ if (!valdup)
+ return ret_errno(ENOMEM);
inet6dev->prefix = 64;
slash = strstr(valdup, "/");
netmask = slash + 1;
ret = lxc_safe_uint(netmask, &inet6dev->prefix);
- if (ret < 0) {
- free(list);
- free(inet6dev);
- free(valdup);
- return -1;
- }
+ if (ret < 0)
+ return ret;
}
ret = inet_pton(AF_INET6, valdup, &inet6dev->addr);
- if (!ret || ret < 0) {
- SYSERROR("Invalid ipv6 address \"%s\"", valdup);
- free(list);
- free(inet6dev);
- free(valdup);
- return -1;
- }
+ if (!ret || ret < 0)
+ return log_error_errno(-EINVAL, EINVAL, "Invalid ipv6 address \"%s\"", valdup);
+ list->elem = inet6dev;
lxc_list_add_tail(&netdev->ipv6, list);
- free(valdup);
+ move_ptr(inet6dev);
+ move_ptr(list);
return 0;
}
return clr_config_net_ipv6_gateway(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
free(netdev->ipv6_gateway);
netdev->ipv6_gateway_dev = true;
} else {
int ret;
- struct in6_addr *gw;
+ __do_free struct in6_addr *gw = NULL;
gw = malloc(sizeof(*gw));
if (!gw)
- return -1;
+ return ret_errno(ENOMEM);
ret = inet_pton(AF_INET6, value, gw);
- if (!ret || ret < 0) {
- SYSERROR("Invalid ipv6 gateway address \"%s\"", value);
- free(gw);
- return -1;
- }
+ if (!ret || ret < 0)
+ return log_error_errno(-EINVAL, EINVAL,
+ "Invalid ipv6 gateway address \"%s\"", value);
- netdev->ipv6_gateway = gw;
+ netdev->ipv6_gateway = move_ptr(gw);
netdev->ipv6_gateway_auto = false;
}
return clr_config_net_veth_ipv6_route(key, lxc_conf, data);
if (!netdev)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
- if (netdev->type != LXC_NET_VETH) {
- SYSERROR("Invalid ipv6 route \"%s\", can only be used with veth network", value);
- return ret_set_errno(-1, EINVAL);
- }
+ if (netdev->type != LXC_NET_VETH)
+ return log_error_errno(-EINVAL,
+ EINVAL, "Invalid ipv6 route \"%s\", can only be used with veth network",
+ value);
inet6dev = malloc(sizeof(*inet6dev));
if (!inet6dev)
- return -1;
+ return ret_errno(ENOMEM);
memset(inet6dev, 0, sizeof(*inet6dev));
list = malloc(sizeof(*list));
if (!list)
- return -1;
+ return ret_errno(ENOMEM);
lxc_list_init(list);
- list->elem = inet6dev;
valdup = strdup(value);
if (!valdup)
slash = strchr(valdup, '/');
if (!slash)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
*slash = '\0';
slash++;
if (*slash == '\0')
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
netmask = slash;
ret = lxc_safe_uint(netmask, &inet6dev->prefix);
if (ret < 0 || inet6dev->prefix > 128)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
ret = inet_pton(AF_INET6, valdup, &inet6dev->addr);
if (!ret || ret < 0)
- return ret_set_errno(-1, EINVAL);
+ return ret_errno(EINVAL);
+ list->elem = inet6dev;
lxc_list_add_tail(&netdev->priv.veth_attr.ipv6_routes, list);
move_ptr(inet6dev);
move_ptr(list);
return clr_config_net_script_up(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
return set_config_string_item(&netdev->upscript, value);
}
return clr_config_net_script_down(key, lxc_conf, data);
if (!netdev)
- return -1;
+ return ret_errno(EINVAL);
return set_config_string_item(&netdev->downscript, value);
}
-static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
+static int add_hook(struct lxc_conf *lxc_conf, int which, __owns char *hook)
{
+ __do_free char *val = hook;
struct lxc_list *hooklist;
hooklist = malloc(sizeof(*hooklist));
- if (!hooklist) {
- free(hook);
- return -1;
- }
+ if (!hooklist)
+ return ret_errno(ENOMEM);
- hooklist->elem = hook;
+ hooklist->elem = move_ptr(val);
lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
return 0;
static int set_config_hooks(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *copy;
+ __do_free char *copy = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_hooks(lxc_conf, key);
- if (strcmp(key + 4, "hook") == 0) {
- ERROR("lxc.hook must not have a value");
- return -1;
- }
+ if (strcmp(key + 4, "hook") == 0)
+ return log_error_errno(-EINVAL, EINVAL, "lxc.hook must not have a value");
copy = strdup(value);
if (!copy)
- return -1;
+ return ret_errno(ENOMEM);
if (strcmp(key + 9, "pre-start") == 0)
- return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
+ return add_hook(lxc_conf, LXCHOOK_PRESTART, move_ptr(copy));
else if (strcmp(key + 9, "start-host") == 0)
- return add_hook(lxc_conf, LXCHOOK_START_HOST, copy);
+ return add_hook(lxc_conf, LXCHOOK_START_HOST, move_ptr(copy));
else if (strcmp(key + 9, "pre-mount") == 0)
- return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy);
+ return add_hook(lxc_conf, LXCHOOK_PREMOUNT, move_ptr(copy));
else if (strcmp(key + 9, "autodev") == 0)
- return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy);
+ return add_hook(lxc_conf, LXCHOOK_AUTODEV, move_ptr(copy));
else if (strcmp(key + 9, "mount") == 0)
- return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
+ return add_hook(lxc_conf, LXCHOOK_MOUNT, move_ptr(copy));
else if (strcmp(key + 9, "start") == 0)
- return add_hook(lxc_conf, LXCHOOK_START, copy);
+ return add_hook(lxc_conf, LXCHOOK_START, move_ptr(copy));
else if (strcmp(key + 9, "stop") == 0)
- return add_hook(lxc_conf, LXCHOOK_STOP, copy);
+ return add_hook(lxc_conf, LXCHOOK_STOP, move_ptr(copy));
else if (strcmp(key + 9, "post-stop") == 0)
- return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
+ return add_hook(lxc_conf, LXCHOOK_POSTSTOP, move_ptr(copy));
else if (strcmp(key + 9, "clone") == 0)
- return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
+ return add_hook(lxc_conf, LXCHOOK_CLONE, move_ptr(copy));
else if (strcmp(key + 9, "destroy") == 0)
- return add_hook(lxc_conf, LXCHOOK_DESTROY, copy);
-
- free(copy);
+ return add_hook(lxc_conf, LXCHOOK_DESTROY, move_ptr(copy));
return -1;
}
if (ret < 0)
return -1;
- if (tmp > 1) {
- ERROR("Invalid hook version specified. Currently only 0 "
- "(legacy) and 1 are supported");
- return -1;
- }
+ if (tmp > 1)
+ return log_error_errno(-EINVAL,
+ EINVAL, "Invalid hook version specified. Currently only 0 (legacy) and 1 are supported");
lxc_conf->hooks_version = tmp;
static int set_config_personality(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- signed long personality = lxc_config_parse_arch(value);
+ signed long personality;
+ personality = lxc_config_parse_arch(value);
if (personality >= 0)
lxc_conf->personality = personality;
else
ret = lxc_safe_uint(value, &max);
if (ret < 0)
- return -1;
+ return ret_errno(EINVAL);
lxc_conf->pty_max = max;
static int set_config_start(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ int ret;
bool is_empty;
is_empty = lxc_config_value_empty(value);
return 0;
}
- if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0)
- return -1;
+ ret = lxc_safe_uint(value, &lxc_conf->start_auto);
+ if (ret)
+ return ret;
if (lxc_conf->start_auto > 1)
- return -1;
+ return ret_errno(EINVAL);
return 0;
} else if (*(key + 10) == 'd') { /* lxc.start.delay */
return lxc_safe_int(value, &lxc_conf->start_order);
}
- return -1;
+ return ret_errno(EINVAL);
}
static int set_config_monitor(const char *key, const char *value,
if (strcmp(key + 12, "unshare") == 0)
return lxc_safe_uint(value, &lxc_conf->monitor_unshare);
- return -1;
+ return ret_errno(EINVAL);
}
static int set_config_monitor_signal_pdeath(const char *key, const char *value,
sig_n = sig_parse(value);
if (sig_n < 0)
- return -1;
+ return ret_errno(EINVAL);
lxc_conf->monitor_signal_pdeath = sig_n;
return 0;
}
- return -EINVAL;
+ return ret_errno(EINVAL);
}
static int set_config_group(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *groups, *token;
- struct lxc_list *grouplist;
- int ret = 0;
+ __do_free char *groups = NULL;
+ char *token;
if (lxc_config_value_empty(value))
return lxc_clear_groups(lxc_conf);
groups = strdup(value);
if (!groups)
- return -1;
+ return ret_errno(ENOMEM);
/* In case several groups are specified in a single line split these
* groups in a single element for the list.
*/
lxc_iterate_parts(token, groups, " \t") {
+ __do_free struct lxc_list *grouplist = NULL;
+
grouplist = malloc(sizeof(*grouplist));
- if (!grouplist) {
- ret = -1;
- break;
- }
+ if (!grouplist)
+ return ret_errno(ENOMEM);
grouplist->elem = strdup(token);
- if (!grouplist->elem) {
- free(grouplist);
- ret = -1;
- break;
- }
+ if (!grouplist->elem)
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->groups, grouplist);
+ lxc_list_add_tail(&lxc_conf->groups, move_ptr(grouplist));
}
- free(groups);
-
- return ret;
+ return 0;
}
static int set_config_environment(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- struct lxc_list *list_item = NULL;
+ __do_free struct lxc_list *list_item = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_environment(lxc_conf);
list_item = malloc(sizeof(*list_item));
if (!list_item)
- goto on_error;
+ return ret_errno(ENOMEM);
if (!strchr(value, '=')) {
const char *env_val;
env_val = getenv(env_key);
if (!env_val)
- goto on_error;
+ return ret_errno(ENOENT);
env_var[0] = env_key;
env_var[1] = env_val;
}
if (!list_item->elem)
- goto on_error;
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->environment, list_item);
+ lxc_list_add_tail(&lxc_conf->environment, move_ptr(list_item));
return 0;
-
-on_error:
- free(list_item);
-
- return -1;
}
static int set_config_tty_max(const char *key, const char *value,
ret = lxc_safe_uint(value, &nbtty);
if (ret < 0)
- return -1;
+ return ret;
lxc_conf->ttys.max = nbtty;
struct lxc_conf *lxc_conf,
void *data)
{
+ int ret;
+
if (lxc_config_value_empty(value)) {
lxc_conf->lsm_aa_allow_incomplete = 0;
return 0;
}
- if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0)
- return -1;
+ ret = lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete);
+ if (ret)
+ return ret;
if (lxc_conf->lsm_aa_allow_incomplete > 1)
- return -1;
+ return ret_errno(EINVAL);
return 0;
}
struct lxc_conf *lxc_conf,
void *data)
{
+ int ret;
+
if (lxc_config_value_empty(value))
return clr_config_apparmor_allow_nesting(key, lxc_conf, NULL);
- if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_nesting) < 0)
- return -1;
+ ret = lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_nesting);
+ if (ret)
+ return ret;
if (lxc_conf->lsm_aa_allow_nesting > 1)
- return -1;
+ return ret_errno(EINVAL);
return 0;
}
struct lxc_conf *lxc_conf,
void *data)
{
- char *elem;
- struct lxc_list *list;
+ __do_free char *elem = NULL;
+ __do_free struct lxc_list *list = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_apparmor_raw(lxc_conf);
list = malloc(sizeof(*list));
- if (!list) {
- errno = ENOMEM;
- return -1;
- }
+ if (!list)
+ return ret_errno(ENOMEM);
elem = strdup(value);
- if (!elem) {
- free(list);
- return -1;
- }
- list->elem = elem;
+ if (!elem)
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->lsm_aa_raw, list);
+ list->elem = move_ptr(elem);
+ lxc_list_add_tail(&lxc_conf->lsm_aa_raw, move_ptr(list));
return 0;
}
int ret;
if (lxc_config_value_empty(value)) {
- free(c->logfile);
- c->logfile = NULL;
+ free_disarm(c->logfile);
return 0;
}
- /* Store these values in the lxc_conf, and then try to set for actual
+ /*
+ * Store these values in the lxc_conf, and then try to set for actual
* current logging.
*/
ret = set_config_path_item(&c->logfile, value);
}
if (value[0] >= '0' && value[0] <= '9') {
- if (lxc_safe_int(value, &newlevel) < 0)
- return -1;
+ int ret;
+
+ ret = lxc_safe_int(value, &newlevel);
+ if (ret)
+ return ret_errno(EINVAL);
} else {
newlevel = lxc_log_priority_to_int(value);
}
- /* Store these values in the lxc_conf, and then try to set for actual
+ /*
+ * Store these values in the lxc_conf, and then try to set for actual
* current logging.
*/
lxc_conf->loglevel = newlevel;
static int set_config_autodev(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ int ret;
+
if (lxc_config_value_empty(value)) {
lxc_conf->autodev = 0;
return 0;
}
- if (lxc_safe_uint(value, &lxc_conf->autodev) < 0)
- return -1;
+ ret = lxc_safe_uint(value, &lxc_conf->autodev);
+ if (ret)
+ return ret_errno(EINVAL);
if (lxc_conf->autodev > 1)
- return -1;
+ return ret_errno(EINVAL);
return 0;
}
sig_n = sig_parse(value);
if (sig_n < 0)
- return -1;
+ return ret_errno(EINVAL);
lxc_conf->haltsignal = sig_n;
sig_n = sig_parse(value);
if (sig_n < 0)
- return -1;
+ return ret_errno(EINVAL);
lxc_conf->rebootsignal = sig_n;
sig_n = sig_parse(value);
if (sig_n < 0)
- return -1;
+ return ret_errno(EINVAL);
lxc_conf->stopsignal = sig_n;
static int __set_config_cgroup_controller(const char *key, const char *value,
struct lxc_conf *lxc_conf, int version)
{
+ __do_free struct lxc_list *cglist = NULL;
+ call_cleaner(free_lxc_cgroup) struct lxc_cgroup *cgelem = NULL;
const char *subkey, *token;
size_t token_len;
- struct lxc_list *cglist = NULL;
- struct lxc_cgroup *cgelem = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_cgroups(lxc_conf, key, version);
token = "lxc.cgroup.";
token_len = 11;
} else {
- return -EINVAL;
+ return ret_errno(EINVAL);
}
if (strncmp(key, token, token_len) != 0)
- return -EINVAL;
+ return ret_errno(EINVAL);
subkey = key + token_len;
if (*subkey == '\0')
- return -EINVAL;
+ return ret_errno(EINVAL);
cglist = malloc(sizeof(*cglist));
if (!cglist)
- goto out;
+ return ret_errno(ENOMEM);
cgelem = malloc(sizeof(*cgelem));
if (!cgelem)
- goto out;
+ return ret_errno(ENOMEM);
memset(cgelem, 0, sizeof(*cgelem));
cgelem->subsystem = strdup(subkey);
if (!cgelem->subsystem)
- goto out;
+ return ret_errno(ENOMEM);
cgelem->value = strdup(value);
if (!cgelem->value)
- goto out;
+ return ret_errno(ENOMEM);
cgelem->version = version;
- lxc_list_add_elem(cglist, cgelem);
+ lxc_list_add_elem(cglist, move_ptr(cgelem));
if (version == CGROUP2_SUPER_MAGIC)
lxc_list_add_tail(&lxc_conf->cgroup2, cglist);
else
lxc_list_add_tail(&lxc_conf->cgroup, cglist);
+ move_ptr(cglist);
return 0;
-
-out:
- free(cglist);
- if (cgelem) {
- free(cgelem->subsystem);
- free(cgelem->value);
- free(cgelem);
- }
-
- return -1;
}
static int set_config_cgroup_controller(const char *key, const char *value,
return set_config_string_item(&lxc_conf->cgroup_meta.dir, value);
}
+static int set_config_cgroup_monitor_dir(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_monitor_dir(key, lxc_conf, NULL);
+
+ return set_config_string_item(&lxc_conf->cgroup_meta.monitor_dir,
+ value);
+}
+
+static int set_config_cgroup_monitor_pivot_dir(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_monitor_pivot_dir(key, lxc_conf, NULL);
+
+ return set_config_string_item(&lxc_conf->cgroup_meta.monitor_pivot_dir,
+ value);
+}
+
+static int set_config_cgroup_container_dir(const char *key, const char *value,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_container_dir(key, lxc_conf, NULL);
+
+ return set_config_string_item(&lxc_conf->cgroup_meta.container_dir,
+ value);
+}
+
+static int set_config_cgroup_container_inner_dir(const char *key,
+ const char *value,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ if (lxc_config_value_empty(value))
+ return clr_config_cgroup_container_inner_dir(key, lxc_conf, NULL);
+
+ if (strchr(value, '/') ||
+ strcmp(value, ".") == 0 ||
+ strcmp(value, "..") == 0)
+ return log_error_errno(-EINVAL, EINVAL, "lxc.cgroup.dir.container.inner must be a single directory name");
+
+ return set_config_string_item(&lxc_conf->cgroup_meta.namespace_dir, value);
+}
+
static int set_config_cgroup_relative(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
return clr_config_cgroup_relative(key, lxc_conf, NULL);
ret = lxc_safe_uint(value, &converted);
- if (ret < 0)
- return -ret;
+ if (ret)
+ return ret;
if (converted == 1) {
lxc_conf->cgroup_meta.relative = true;
return 0;
}
- return -EINVAL;
+ return ret_errno(EINVAL);
}
static bool parse_limit_value(const char **value, rlim_t *res)
static int set_config_prlimit(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free struct lxc_list *limlist = NULL;
+ call_cleaner(free_lxc_limit) struct lxc_limit *limelem = NULL;
struct lxc_list *iter;
struct rlimit limit;
rlim_t limit_value;
- struct lxc_list *limlist = NULL;
- struct lxc_limit *limelem = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_limits(lxc_conf, key);
if (strncmp(key, "lxc.prlimit.", STRLITERALLEN("lxc.prlimit.")) != 0)
- return -1;
+ return ret_errno(EINVAL);
key += STRLITERALLEN("lxc.prlimit.");
/* soft limit comes first in the value */
if (!parse_limit_value(&value, &limit_value))
- return -1;
+ return ret_errno(EINVAL);
limit.rlim_cur = limit_value;
if (*value == ':')
++value;
else if (*value) /* any other character is an error here */
- return -1;
+ return ret_errno(EINVAL);
while (isspace(*value))
++value;
/* optional hard limit */
if (*value) {
if (!parse_limit_value(&value, &limit_value))
- return -1;
+ return ret_errno(EINVAL);
limit.rlim_max = limit_value;
++value;
if (*value)
- return -1;
+ return ret_errno(EINVAL);
} else {
/* a single value sets both hard and soft limit */
limit.rlim_max = limit.rlim_cur;
/* allocate list element */
limlist = malloc(sizeof(*limlist));
if (!limlist)
- goto on_error;
+ return ret_errno(ENOMEM);
limelem = malloc(sizeof(*limelem));
if (!limelem)
- goto on_error;
+ return ret_errno(ENOMEM);
memset(limelem, 0, sizeof(*limelem));
limelem->resource = strdup(key);
if (!limelem->resource)
- goto on_error;
+ return ret_errno(ENOMEM);
limelem->limit = limit;
- lxc_list_add_elem(limlist, limelem);;
- lxc_list_add_tail(&lxc_conf->limits, limlist);
+ lxc_list_add_elem(limlist, move_ptr(limelem));;
+ lxc_list_add_tail(&lxc_conf->limits, move_ptr(limlist));
return 0;
-
-on_error:
- free(limlist);
-
- if (limelem) {
- free(limelem->resource);
- free(limelem);
- }
-
- return -1;
}
static int set_config_sysctl(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free struct lxc_list *sysctl_list = NULL;
+ call_cleaner(free_lxc_sysctl) struct lxc_sysctl *sysctl_elem = NULL;
struct lxc_list *iter;
- char *replace_value = NULL;
- struct lxc_list *sysctl_list = NULL;
- struct lxc_sysctl *sysctl_elem = NULL;
if (lxc_config_value_empty(value))
return clr_config_sysctl(key, lxc_conf, NULL);
/* find existing list element */
lxc_list_for_each(iter, &lxc_conf->sysctls) {
+ __do_free char *replace_value = NULL;
+
sysctl_elem = iter->elem;
if (strcmp(key, sysctl_elem->key) != 0)
replace_value = strdup(value);
if (!replace_value)
- return -1;
+ return ret_errno(EINVAL);
free(sysctl_elem->value);
- sysctl_elem->value = replace_value;
+ sysctl_elem->value = move_ptr(replace_value);
return 0;
}
/* allocate list element */
sysctl_list = malloc(sizeof(*sysctl_list));
if (!sysctl_list)
- goto on_error;
+ return ret_errno(ENOMEM);
sysctl_elem = malloc(sizeof(*sysctl_elem));
if (!sysctl_elem)
- goto on_error;
+ return ret_errno(ENOMEM);
memset(sysctl_elem, 0, sizeof(*sysctl_elem));
sysctl_elem->key = strdup(key);
if (!sysctl_elem->key)
- goto on_error;
+ return ret_errno(ENOMEM);
sysctl_elem->value = strdup(value);
if (!sysctl_elem->value)
- goto on_error;
+ return ret_errno(ENOMEM);
- lxc_list_add_elem(sysctl_list, sysctl_elem);
- lxc_list_add_tail(&lxc_conf->sysctls, sysctl_list);
+ lxc_list_add_elem(sysctl_list, move_ptr(sysctl_elem));
+ lxc_list_add_tail(&lxc_conf->sysctls, move_ptr(sysctl_list));
return 0;
-
-on_error:
- free(sysctl_list);
-
- if (sysctl_elem) {
- free(sysctl_elem->key);
- free(sysctl_elem->value);
- free(sysctl_elem);
- }
-
- return -1;
}
static int set_config_proc(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free struct lxc_list *proclist = NULL;
+ call_cleaner(free_lxc_proc) struct lxc_proc *procelem = NULL;
const char *subkey;
- struct lxc_list *proclist = NULL;
- struct lxc_proc *procelem = NULL;
if (lxc_config_value_empty(value))
return clr_config_proc(key, lxc_conf, NULL);
subkey = key + STRLITERALLEN("lxc.proc.");
if (*subkey == '\0')
- return -EINVAL;
+ return ret_errno(EINVAL);
proclist = malloc(sizeof(*proclist));
if (!proclist)
- goto on_error;
+ return ret_errno(ENOMEM);
procelem = malloc(sizeof(*procelem));
if (!procelem)
- goto on_error;
+ return ret_errno(ENOMEM);
memset(procelem, 0, sizeof(*procelem));
procelem->filename = strdup(subkey);
- procelem->value = strdup(value);
-
- if (!procelem->filename || !procelem->value)
- goto on_error;
+ if (!procelem->filename)
+ return ret_errno(ENOMEM);
- proclist->elem = procelem;
+ procelem->value = strdup(value);
+ if (!procelem->value)
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->procs, proclist);
+ proclist->elem = move_ptr(procelem);
+ lxc_list_add_tail(&lxc_conf->procs, move_ptr(proclist));
return 0;
-
-on_error:
- free(proclist);
-
- if (procelem) {
- free(procelem->filename);
- free(procelem->value);
- free(procelem);
- }
-
- return -1;
}
static int set_config_idmaps(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free struct lxc_list *idmaplist = NULL;
+ __do_free struct id_map *idmap = NULL;
unsigned long hostid, nsid, range;
char type;
int ret;
- struct lxc_list *idmaplist = NULL;
- struct id_map *idmap = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_idmaps(lxc_conf);
idmaplist = malloc(sizeof(*idmaplist));
if (!idmaplist)
- goto on_error;
+ return ret_errno(ENOMEM);
idmap = malloc(sizeof(*idmap));
if (!idmap)
- goto on_error;
+ return ret_errno(ENOMEM);
memset(idmap, 0, sizeof(*idmap));
ret = parse_idmaps(value, &type, &nsid, &hostid, &range);
- if (ret < 0) {
- ERROR("Failed to parse id mappings");
- goto on_error;
- }
+ if (ret < 0)
+ return log_error_errno(-EINVAL, EINVAL, "Failed to parse id mappings");
INFO("Read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
if (type == 'u')
else if (type == 'g')
idmap->idtype = ID_TYPE_GID;
else
- goto on_error;
+ return ret_errno(EINVAL);
idmap->hostid = hostid;
idmap->nsid = nsid;
if (idmap->nsid == 0)
lxc_conf->root_nsgid_map = idmap;
- idmap = NULL;
+ move_ptr(idmap);
+ move_ptr(idmaplist);
return 0;
-
-on_error:
- free(idmaplist);
- free(idmap);
-
- return -1;
}
static int set_config_mount_fstab(const char *key, const char *value,
{
if (lxc_config_value_empty(value)) {
clr_config_mount_fstab(key, lxc_conf, NULL);
- return -1;
+ return ret_errno(EINVAL);
}
return set_config_path_item(&lxc_conf->fstab, value);
static int set_config_mount_auto(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *autos, *token;
+ __do_free char *autos = NULL;
+ char *token;
int i;
- int ret = -1;
static struct {
const char *token;
int mask;
int flag;
} allowed_auto_mounts[] = {
- { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
- { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
- { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
- { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
- { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
- { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
- { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
- { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
- { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
- { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
- { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
- { "cgroup:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC | LXC_AUTO_CGROUP_FORCE },
- { "cgroup:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED | LXC_AUTO_CGROUP_FORCE },
- { "cgroup:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO | LXC_AUTO_CGROUP_FORCE },
- { "cgroup:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW | LXC_AUTO_CGROUP_FORCE },
- { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
- { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
- { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
- { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
- { "cgroup-full:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC | LXC_AUTO_CGROUP_FORCE },
- { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE },
- { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE },
- { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE },
- { "shmounts:", LXC_AUTO_SHMOUNTS_MASK, LXC_AUTO_SHMOUNTS },
- /* For adding anything that is just a single on/off, but has no
- * options: keep mask and flag identical and just define the enum
- * value as an unused bit so far
- */
- { NULL, 0, 0 }
+ { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
+ { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED },
+ { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW },
+ { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
+ { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO },
+ { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED },
+ { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW },
+ { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC },
+ { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED },
+ { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO },
+ { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW },
+ { "cgroup:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC },
+ { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED },
+ { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO },
+ { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW },
+ { "cgroup-full:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup-full:mixed:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup-full:ro:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO | LXC_AUTO_CGROUP_FORCE },
+ { "cgroup-full:rw:force", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW | LXC_AUTO_CGROUP_FORCE },
+ { "shmounts:", LXC_AUTO_SHMOUNTS_MASK, LXC_AUTO_SHMOUNTS },
+ /*
+ * For adding anything that is just a single on/off, but has no
+ * options: keep mask and flag identical and just define the
+ * enum value as an unused bit so far
+ */
+ { NULL, 0, 0 }
};
if (lxc_config_value_empty(value)) {
autos = strdup(value);
if (!autos)
- return -1;
+ return ret_errno(ENOMEM);
lxc_iterate_parts(token, autos, " \t") {
bool is_shmounts = false;
}
}
- if (!allowed_auto_mounts[i].token) {
- ERROR("Invalid filesystem to automount \"%s\"", token);
- goto on_error;
- }
+ if (!allowed_auto_mounts[i].token)
+ return log_error_errno(-EINVAL, EINVAL, "Invalid filesystem to automount \"%s\"", token);
lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask;
lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag;
if (is_shmounts) {
- char *container_path;
- char *host_path;
+ __do_free char *container_path = NULL, *host_path = NULL;
+ char *val;
- host_path = token + STRLITERALLEN("shmounts:");
- if (*host_path == '\0') {
- SYSERROR("Failed to copy shmounts host path");
- goto on_error;
- }
+ val = token + STRLITERALLEN("shmounts:");
+ if (*val == '\0')
+ return log_error_errno(-EINVAL, EINVAL, "Failed to copy shmounts host path");
+
+ host_path = strdup(val);
+ if (!host_path)
+ return log_error_errno(-EINVAL, EINVAL, "Failed to copy shmounts host path");
- container_path = strchr(host_path, ':');
- if (!container_path || *(container_path + 1) == '\0')
- container_path = "/dev/.lxc-mounts";
+ val = strchr(host_path, ':');
+ if (!val || *(val + 1) == '\0')
+ val = "/dev/.lxc-mounts";
else
- *container_path++ = '\0';
+ *val++ = '\0';
- lxc_conf->shmount.path_host = strdup(host_path);
- if (!lxc_conf->shmount.path_host) {
- SYSERROR("Failed to copy shmounts host path");
- goto on_error;
- }
+ container_path = strdup(val);
+ if(!container_path)
+ return log_error_errno(-EINVAL, EINVAL, "Failed to copy shmounts container path");
- lxc_conf->shmount.path_cont = strdup(container_path);
- if(!lxc_conf->shmount.path_cont) {
- SYSERROR("Failed to copy shmounts container path");
- goto on_error;
- }
+ lxc_conf->shmount.path_host = move_ptr(host_path);
+ lxc_conf->shmount.path_cont = move_ptr(container_path);
}
}
- ret = 0;
-
-on_error:
- free(autos);
-
- return ret;
+ return 0;
}
static int set_config_mount(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *mntelem;
- struct lxc_list *mntlist;
+ __do_free char *mntelem = NULL;
+ __do_free struct lxc_list *mntlist = NULL;
if (lxc_config_value_empty(value))
return lxc_clear_mount_entries(lxc_conf);
mntlist = malloc(sizeof(*mntlist));
if (!mntlist)
- return -1;
+ return ret_errno(ENOMEM);
mntelem = strdup(value);
- if (!mntelem) {
- free(mntlist);
- return -1;
- }
- mntlist->elem = mntelem;
+ if (!mntelem)
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
+ mntlist->elem = move_ptr(mntelem);
+ lxc_list_add_tail(&lxc_conf->mount_list, move_ptr(mntlist));
return 0;
}
static int set_config_cap_keep(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *keepcaps, *token;
- struct lxc_list *keeplist;
- int ret = -1;
+ __do_free char *keepcaps = NULL;
+ __do_free struct lxc_list *keeplist = NULL;
+ char *token;
if (lxc_config_value_empty(value))
return lxc_clear_config_keepcaps(lxc_conf);
keepcaps = strdup(value);
if (!keepcaps)
- return -1;
+ return ret_errno(ENOMEM);
/* In case several capability keep is specified in a single line
* split these caps in a single element for the list.
keeplist = malloc(sizeof(*keeplist));
if (!keeplist)
- goto on_error;
+ return ret_errno(ENOMEM);
keeplist->elem = strdup(token);
- if (!keeplist->elem) {
- free(keeplist);
- goto on_error;
- }
+ if (!keeplist->elem)
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->keepcaps, keeplist);
+ lxc_list_add_tail(&lxc_conf->keepcaps, move_ptr(keeplist));
}
- ret = 0;
-
-on_error:
- free(keepcaps);
-
- return ret;
+ return 0;
}
static int set_config_cap_drop(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *dropcaps, *token;
- struct lxc_list *droplist;
- int ret = -1;
+ __do_free char *dropcaps = NULL;
+ __do_free struct lxc_list *droplist = NULL;
+ char *token;
if (lxc_config_value_empty(value))
return lxc_clear_config_caps(lxc_conf);
dropcaps = strdup(value);
if (!dropcaps)
- return -1;
+ return ret_errno(ENOMEM);
/* In case several capability drop is specified in a single line
* split these caps in a single element for the list.
lxc_iterate_parts(token, dropcaps, " \t") {
droplist = malloc(sizeof(*droplist));
if (!droplist)
- goto on_error;
+ return ret_errno(ENOMEM);
droplist->elem = strdup(token);
- if (!droplist->elem) {
- free(droplist);
- goto on_error;
- }
+ if (!droplist->elem)
+ return ret_errno(ENOMEM);
- lxc_list_add_tail(&lxc_conf->caps, droplist);
+ lxc_list_add_tail(&lxc_conf->caps, move_ptr(droplist));
}
- ret = 0;
-
-on_error:
- free(dropcaps);
-
- return ret;
+ return 0;
}
static int set_config_console_path(const char *key, const char *value,
static int set_config_console_rotate(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ int ret;
+
if (lxc_config_value_empty(value)) {
lxc_conf->console.log_rotate = 0;
return 0;
}
- if (lxc_safe_uint(value, &lxc_conf->console.log_rotate) < 0)
- return -1;
+ ret = lxc_safe_uint(value, &lxc_conf->console.log_rotate);
+ if (ret)
+ return ret_errno(EINVAL);
- if (lxc_conf->console.log_rotate > 1) {
- ERROR("The \"lxc.console.rotate\" config key can only be set "
- "to 0 or 1");
- return -1;
- }
+ if (lxc_conf->console.log_rotate > 1)
+ return log_error_errno(-EINVAL, EINVAL, "The \"lxc.console.rotate\" config key can only be set to 0 or 1");
return 0;
}
}
ret = parse_byte_size_string(value, &size);
- if (ret < 0)
- return -1;
+ if (ret)
+ return ret;
if (size < 0)
- return -EINVAL;
+ return ret_errno(EINVAL);
/* must be at least a page size */
pgsz = lxc_getpagesize();
if ((uint64_t)size < pgsz) {
- NOTICE("Requested ringbuffer size for the console is %" PRId64
- " but must be at least %" PRId64
- " bytes. Setting ringbuffer size to %" PRId64 " bytes",
+ NOTICE("Requested ringbuffer size for the console is %" PRId64 " but must be at least %" PRId64 " bytes. Setting ringbuffer size to %" PRId64 " bytes",
size, pgsz, pgsz);
size = pgsz;
}
buffer_size = lxc_find_next_power2((uint64_t)size);
if (buffer_size == 0)
- return -EINVAL;
+ return ret_errno(EINVAL);
if (buffer_size != size)
- NOTICE("Passed size was not a power of 2. Rounding log size to "
- "next power of two: %" PRIu64 " bytes", buffer_size);
+ NOTICE("Passed size was not a power of 2. Rounding log size to next power of two: %" PRIu64 " bytes", buffer_size);
lxc_conf->console.buffer_size = buffer_size;
}
ret = parse_byte_size_string(value, &size);
- if (ret < 0)
- return -1;
+ if (ret)
+ return ret_errno(EINVAL);
if (size < 0)
- return -EINVAL;
+ return ret_errno(EINVAL);
/* must be at least a page size */
pgsz = lxc_getpagesize();
if ((uint64_t)size < pgsz) {
- NOTICE("Requested ringbuffer size for the console is %" PRId64
- " but must be at least %" PRId64
- " bytes. Setting ringbuffer size to %" PRId64 " bytes",
+ NOTICE("Requested ringbuffer size for the console is %" PRId64 " but must be at least %" PRId64 " bytes. Setting ringbuffer size to %" PRId64 " bytes",
size, pgsz, pgsz);
size = pgsz;
}
log_size = lxc_find_next_power2((uint64_t)size);
if (log_size == 0)
- return -EINVAL;
+ return ret_errno(EINVAL);
if (log_size != size)
- NOTICE("Passed size was not a power of 2. Rounding log size to "
- "next power of two: %" PRIu64 " bytes", log_size);
+ NOTICE("Passed size was not a power of 2. Rounding log size to next power of two: %" PRIu64 " bytes", log_size);
lxc_conf->console.log_size = log_size;
linelen = strlen(line);
while (conf->unexpanded_alloced <= len + linelen + 2) {
- char *tmp = realloc(conf->unexpanded_config,
- conf->unexpanded_alloced + 1024);
+ char *tmp;
+
+ tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024);
if (!tmp)
- return -1;
+ return ret_errno(EINVAL);
if (!conf->unexpanded_config)
*tmp = '\0';
static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
{
+ __do_closedir DIR *dir = NULL;
struct dirent *direntp;
- DIR *dir;
- char path[PATH_MAX];
- int len;
- int ret = -1;
+ int len, ret;
dir = opendir(dirp);
if (!dir)
- return -1;
+ return -errno;
while ((direntp = readdir(dir))) {
const char *fnam;
+ char path[PATH_MAX];
fnam = direntp->d_name;
if (!strcmp(fnam, "."))
continue;
len = snprintf(path, PATH_MAX, "%s/%s", dirp, fnam);
- if (len < 0 || len >= PATH_MAX) {
- ret = -1;
- goto out;
- }
+ if (len < 0 || len >= PATH_MAX)
+ return ret_errno(EIO);
ret = lxc_config_read(path, lxc_conf, true);
if (ret < 0)
- goto out;
+ return ret;
}
- ret = 0;
-
-out:
- closedir(dir);
- return ret;
+ return 0;
}
static int set_config_includefiles(const char *key, const char *value,
static int set_config_rootfs_path(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
+ __do_free char *dup = NULL;
int ret;
- char *dup, *tmp;
+ char *tmp;
const char *container_path;
if (lxc_config_value_empty(value)) {
dup = strdup(value);
if (!dup)
- return -1;
+ return ret_errno(ENOMEM);
/* Split <storage type>:<container path> into <storage type> and
* <container path>. Set "rootfs.bdev_type" to <storage type> and
*tmp = '\0';
ret = set_config_path_item(&lxc_conf->rootfs.bdev_type, dup);
- if (ret < 0) {
- free(dup);
- return -1;
- }
+ if (ret < 0)
+ return ret_errno(ENOMEM);
tmp++;
container_path = tmp;
container_path = value;
}
- ret = set_config_path_item(&lxc_conf->rootfs.path, container_path);
- free(dup);
-
- return ret;
+ return set_config_path_item(&lxc_conf->rootfs.path, container_path);
}
static int set_config_rootfs_managed(const char *key, const char *value,
static int set_config_rootfs_options(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- int ret;
+ __do_free char *mdata = NULL, *opts = NULL;
unsigned long mflags = 0, pflags = 0;
- char *mdata = NULL, *opts = NULL;
struct lxc_rootfs *rootfs = &lxc_conf->rootfs;
+ int ret;
ret = parse_mntopts(value, &mflags, &mdata);
if (ret < 0)
- return -EINVAL;
+ return ret_errno(EINVAL);
ret = parse_propagationopts(value, &pflags);
- if (ret < 0) {
- free(mdata);
- return -EINVAL;
- }
+ if (ret < 0)
+ return ret_errno(EINVAL);
ret = set_config_string_item(&opts, value);
- if (ret < 0) {
- free(mdata);
- return -ENOMEM;
- }
+ if (ret < 0)
+ return ret_errno(ENOMEM);
rootfs->mountflags = mflags | pflags;
- rootfs->options = opts;
- rootfs->data = mdata;
+ rootfs->options = move_ptr(opts);
+ rootfs->data = move_ptr(mdata);
return 0;
}
static int set_config_uts_name(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- struct utsname *utsname;
+ __do_free struct utsname *utsname = NULL;
if (lxc_config_value_empty(value)) {
clr_config_uts_name(key, lxc_conf, NULL);
utsname = malloc(sizeof(*utsname));
if (!utsname)
- return -1;
+ return ret_errno(ENOMEM);
- if (strlen(value) >= sizeof(utsname->nodename)) {
- free(utsname);
- return -1;
- }
+ if (strlen(value) >= sizeof(utsname->nodename))
+ return ret_errno(EINVAL);
(void)strlcpy(utsname->nodename, value, sizeof(utsname->nodename));
free(lxc_conf->utsname);
- lxc_conf->utsname = utsname;
+ lxc_conf->utsname = move_ptr(utsname);
return 0;
}
static int set_config_namespace_clone(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *ns, *token;
+ __do_free char *ns = NULL;
+ char *token;
int cloneflag = 0;
if (lxc_config_value_empty(value))
return clr_config_namespace_clone(key, lxc_conf, data);
- if (lxc_conf->ns_keep != 0) {
- errno = EINVAL;
- SYSERROR("Cannot set both \"lxc.namespace.clone\" and "
- "\"lxc.namespace.keep\"");
- return -EINVAL;
- }
+ if (lxc_conf->ns_keep != 0)
+ return log_error_errno(-EINVAL, EINVAL, "Cannot set both \"lxc.namespace.clone\" and \"lxc.namespace.keep\"");
ns = strdup(value);
if (!ns)
- return -1;
+ return ret_errno(ENOMEM);
lxc_iterate_parts(token, ns, " \t") {
token += lxc_char_left_gc(token, strlen(token));
token[lxc_char_right_gc(token, strlen(token))] = '\0';
cloneflag = lxc_namespace_2_cloneflag(token);
- if (cloneflag < 0) {
- free(ns);
- return -EINVAL;
- }
+ if (cloneflag < 0)
+ return ret_errno(EINVAL);
lxc_conf->ns_clone |= cloneflag;
}
- free(ns);
return 0;
}
static int set_config_namespace_keep(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- char *ns, *token;
+ __do_free char *ns = NULL;
+ char *token;
int cloneflag = 0;
if (lxc_config_value_empty(value))
return clr_config_namespace_keep(key, lxc_conf, data);
- if (lxc_conf->ns_clone != 0) {
- errno = EINVAL;
- SYSERROR("Cannot set both \"lxc.namespace.clone\" and "
- "\"lxc.namespace.keep\"");
- return -EINVAL;
- }
+ if (lxc_conf->ns_clone != 0)
+ return log_error_errno(-EINVAL, EINVAL, "Cannot set both \"lxc.namespace.clone\" and \"lxc.namespace.keep\"");
ns = strdup(value);
if (!ns)
- return -1;
+ return ret_errno(ENOMEM);
lxc_iterate_parts(token, ns, " \t") {
token += lxc_char_left_gc(token, strlen(token));
token[lxc_char_right_gc(token, strlen(token))] = '\0';
cloneflag = lxc_namespace_2_cloneflag(token);
- if (cloneflag < 0) {
- free(ns);
- return -EINVAL;
- }
+ if (cloneflag < 0)
+ return ret_errno(EINVAL);
lxc_conf->ns_keep |= cloneflag;
}
- free(ns);
+
+ return 0;
+}
+
+static int set_config_time_offset_boot(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ char *unit;
+ int64_t offset = 0;
+ char buf[STRLITERALLEN("ms") + 1];
+
+ if (lxc_config_value_empty(value))
+ return clr_config_time_offset_boot(key, lxc_conf, data);
+
+ ret = lxc_safe_int64_residual(value, &offset, 10, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ unit = lxc_trim_whitespace_in_place(buf);
+ if (strcmp(unit, "h") == 0) {
+ if (!multiply_overflow(offset, 3600, &lxc_conf->timens.s_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "m") == 0) {
+ if (!multiply_overflow(offset, 60, &lxc_conf->timens.s_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "s") == 0) {
+ lxc_conf->timens.s_boot = offset;
+ } else if (strcmp(unit, "ms") == 0) {
+ if (!multiply_overflow(offset, 1000000, &lxc_conf->timens.ns_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "us") == 0) {
+ if (!multiply_overflow(offset, 1000, &lxc_conf->timens.ns_boot))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "ns") == 0) {
+ lxc_conf->timens.ns_boot = offset;
+ } else {
+ return ret_errno(EINVAL);
+ }
+
+ return 0;
+}
+
+static int set_config_time_offset_monotonic(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ char *unit;
+ int64_t offset = 0;
+ char buf[STRLITERALLEN("ms") + 1];
+
+ if (lxc_config_value_empty(value))
+ return clr_config_time_offset_monotonic(key, lxc_conf, data);
+
+ ret = lxc_safe_int64_residual(value, &offset, 10, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ unit = lxc_trim_whitespace_in_place(buf);
+ if (strcmp(unit, "h") == 0) {
+ if (!multiply_overflow(offset, 3600, &lxc_conf->timens.s_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "m") == 0) {
+ if (!multiply_overflow(offset, 60, &lxc_conf->timens.s_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "s") == 0) {
+ lxc_conf->timens.s_monotonic = offset;
+ } else if (strcmp(unit, "ms") == 0) {
+ if (!multiply_overflow(offset, 1000000, &lxc_conf->timens.ns_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "us") == 0) {
+ if (!multiply_overflow(offset, 1000, &lxc_conf->timens.ns_monotonic))
+ return ret_errno(EOVERFLOW);
+ } else if (strcmp(unit, "ns") == 0) {
+ lxc_conf->timens.ns_monotonic = offset;
+ } else {
+ return ret_errno(EINVAL);
+ }
return 0;
}
static int parse_line(char *buffer, void *data)
{
- char *dot, *key, *line, *linep, *value;
+ __do_free char *linep = NULL;
+ char *dot, *key, *line, *value;
bool empty_line;
struct lxc_config_t *config;
- int ret = 0;
+ int ret;
char *dup = buffer;
struct parse_line_conf *plc = data;
*/
linep = line = strdup(dup);
if (!line)
- return -1;
+ return ret_errno(ENOMEM);
if (!plc->from_include) {
ret = append_unexp_config_line(line, plc->conf);
if (ret < 0)
- goto on_error;
+ return ret;
}
if (empty_line)
- goto on_error;
+ return 0;
line += lxc_char_left_gc(line, strlen(line));
/* ignore comments */
if (line[0] == '#')
- goto on_error;
+ return 0;
/* martian option - don't add it to the config itself */
if (strncmp(line, "lxc.", 4))
- goto on_error;
-
- ret = -1;
+ return 0;
dot = strchr(line, '=');
- if (!dot) {
- ERROR("Invalid configuration line: %s", line);
- goto on_error;
- }
+ if (!dot)
+ return log_error_errno(-EINVAL, EINVAL, "Invalid configuration line: %s", line);
*dot = '\0';
value = dot + 1;
}
config = lxc_get_config(key);
- if (!config) {
- ERROR("Unknown configuration key \"%s\"", key);
- goto on_error;
- }
-
- ret = config->set(key, value, plc->conf, NULL);
+ if (!config)
+ return log_error_errno(-EINVAL, EINVAL, "Unknown configuration key \"%s\"", key);
-on_error:
- free(linep);
-
- return ret;
+ return config->set(key, value, plc->conf, NULL);
}
static struct new_config_item *parse_new_conf_line(char *buffer)
return fulllen;
}
+static int get_config_cgroup_monitor_dir(const char *key, char *retv, int inlen,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.monitor_dir);
+
+ return fulllen;
+}
+
+static int get_config_cgroup_monitor_pivot_dir(const char *key, char *retv, int inlen,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.monitor_pivot_dir);
+
+ return fulllen;
+}
+
+static int get_config_cgroup_container_dir(const char *key, char *retv,
+ int inlen,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.container_dir);
+
+ return fulllen;
+}
+
+static int get_config_cgroup_container_inner_dir(const char *key, char *retv,
+ int inlen,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.namespace_dir);
+
+ return fulllen;
+}
+
static inline int get_config_cgroup_relative(const char *key, char *retv,
int inlen, struct lxc_conf *lxc_conf,
void *data)
return fulllen;
}
+static int get_config_time_offset_boot(const char *key, char *retv, int inlen, struct lxc_conf *c,
+ void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ if (c->timens.s_boot) {
+ strprint(retv, inlen, "%" PRId64 " s\n", c->timens.s_boot);
+ } else {
+ strprint(retv, inlen, "%" PRId64 " ns\n", c->timens.ns_boot);
+ }
+
+ return fulllen;
+}
+
+static int get_config_time_offset_monotonic(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ if (c->timens.s_monotonic) {
+ strprint(retv, inlen, "%" PRId64 "s\n", c->timens.s_monotonic);
+ } else {
+ strprint(retv, inlen, "%" PRId64 "ns\n", c->timens.ns_monotonic);
+ }
+
+ return fulllen;
+}
+
static int get_config_namespace_share(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
return 0;
}
+static int clr_config_cgroup_monitor_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.monitor_dir);
+ return 0;
+}
+
+static int clr_config_cgroup_monitor_pivot_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.monitor_pivot_dir);
+ return 0;
+}
+
+static int clr_config_cgroup_container_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.container_dir);
+ return 0;
+}
+
+static int clr_config_cgroup_container_inner_dir(const char *key,
+ struct lxc_conf *lxc_conf,
+ void *data)
+{
+ free_disarm(lxc_conf->cgroup_meta.namespace_dir);
+ return 0;
+}
+
static inline int clr_config_cgroup_relative(const char *key,
struct lxc_conf *lxc_conf,
void *data)
return 0;
}
+static int clr_config_time_offset_boot(const char *key, struct lxc_conf *lxc_conf, void *data)
+{
+ lxc_conf->timens.s_boot = 0;
+ lxc_conf->timens.ns_boot = 0;
+ return 0;
+}
+
+static int clr_config_time_offset_monotonic(const char *key, struct lxc_conf *lxc_conf, void *data)
+{
+ lxc_conf->timens.s_monotonic = 0;
+ lxc_conf->timens.ns_monotonic = 0;
+ return 0;
+}
+
static int clr_config_namespace_share(const char *key,
struct lxc_conf *lxc_conf, void *data)
{
return 0;
}
+static int clr_config_net_veth_vlan_id(const char *key, struct lxc_conf *lxc_conf,
+ void *data)
+{
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ netdev->priv.veth_attr.vlan_id = 0;
+ netdev->priv.veth_attr.vlan_id_set = false;
+
+ return 0;
+}
+
+static int clr_config_net_veth_vlan_tagged_id(const char *key,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ struct lxc_netdev *netdev = data;
+ struct lxc_list *cur, *next;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.vlan_tagged_ids, next) {
+ lxc_list_del(cur);
+ free(cur);
+ }
+
+ return 0;
+}
+
+
static int clr_config_net_script_up(const char *key, struct lxc_conf *lxc_conf,
void *data)
{
return fulllen;
}
+static int get_config_net_veth_vlan_id(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ int fulllen = 0;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ strprint(retv, inlen, "%d", netdev->priv.veth_attr.vlan_id);
+
+ return fulllen;
+}
+
+static int get_config_net_veth_vlan_tagged_id(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ size_t listlen;
+ struct lxc_list *it;
+ int fulllen = 0;
+ struct lxc_netdev *netdev = data;
+
+ if (!netdev)
+ return ret_errno(EINVAL);
+
+ if (netdev->type != LXC_NET_VETH)
+ return 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ listlen = lxc_list_len(&netdev->priv.veth_attr.vlan_tagged_ids);
+
+ lxc_list_for_each(it, &netdev->priv.veth_attr.vlan_tagged_ids) {
+ unsigned short i = PTR_TO_USHORT(it->elem);
+ strprint(retv, inlen, "%u%s", i,
+ (listlen-- > 1) ? "\n" : "");
+ }
+
+ return fulllen;
+}
+
static int get_config_net_script_up(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
strprint(retv, inlen, "veth.pair\n");
strprint(retv, inlen, "veth.ipv4.route\n");
strprint(retv, inlen, "veth.ipv6.route\n");
+ strprint(retv, inlen, "veth.vlan.id\n");
break;
case LXC_NET_MACVLAN:
strprint(retv, inlen, "macvlan.mode\n");