confile.c revision f24a52d5f588ff4e4575046903fb9498c376d833
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <daniel.lezcano at free.fr>
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <dirent.h>
#include "parse.h"
#include "config.h"
#include "confile.h"
#include "utils.h"
#include "log.h"
#include "conf.h"
#include "network.h"
#include "lxcseccomp.h"
#include <sys/personality.h>
#endif
static int config_personality(const char *, const char *, struct lxc_conf *);
static int config_pts(const char *, const char *, struct lxc_conf *);
static int config_tty(const char *, const char *, struct lxc_conf *);
static int config_ttydir(const char *, const char *, struct lxc_conf *);
static int config_kmsg(const char *, const char *, struct lxc_conf *);
static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *);
static int config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf *);
static int config_lsm_se_context(const char *, const char *, struct lxc_conf *);
static int config_cgroup(const char *, const char *, struct lxc_conf *);
static int config_idmap(const char *, const char *, struct lxc_conf *);
static int config_loglevel(const char *, const char *, struct lxc_conf *);
static int config_logfile(const char *, const char *, struct lxc_conf *);
static int config_mount(const char *, const char *, struct lxc_conf *);
static int config_rootfs(const char *, const char *, struct lxc_conf *);
static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
static int config_rootfs_options(const char *, const char *, struct lxc_conf *);
static int config_pivotdir(const char *, const char *, struct lxc_conf *);
static int config_utsname(const char *, const char *, struct lxc_conf *);
static int config_network(const char *, const char *, struct lxc_conf *);
static int config_network_type(const char *, const char *, struct lxc_conf *);
static int config_network_flags(const char *, const char *, struct lxc_conf *);
static int config_network_link(const char *, const char *, struct lxc_conf *);
static int config_network_name(const char *, const char *, struct lxc_conf *);
static int config_network_veth_pair(const char *, const char *, struct lxc_conf *);
static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *);
static int config_network_hwaddr(const char *, const char *, struct lxc_conf *);
static int config_network_vlan_id(const char *, const char *, struct lxc_conf *);
static int config_network_mtu(const char *, const char *, struct lxc_conf *);
static int config_network_ipv4(const char *, const char *, struct lxc_conf *);
static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *);
static int config_network_script_up(const char *, const char *, struct lxc_conf *);
static int config_network_script_down(const char *, const char *, struct lxc_conf *);
static int config_network_ipv6(const char *, const char *, struct lxc_conf *);
static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *);
static int config_cap_drop(const char *, const char *, struct lxc_conf *);
static int config_cap_keep(const char *, const char *, struct lxc_conf *);
static int config_console(const char *, const char *, struct lxc_conf *);
static int config_console_logfile(const char *, const char *, struct lxc_conf *);
static int config_seccomp(const char *, const char *, struct lxc_conf *);
static int config_includefile(const char *, const char *, struct lxc_conf *);
static int config_network_nic(const char *, const char *, struct lxc_conf *);
static int config_autodev(const char *, const char *, struct lxc_conf *);
static int config_haltsignal(const char *, const char *, struct lxc_conf *);
static int config_stopsignal(const char *, const char *, struct lxc_conf *);
static int config_start(const char *, const char *, struct lxc_conf *);
static int config_group(const char *, const char *, struct lxc_conf *);
static int config_environment(const char *, const char *, struct lxc_conf *);
static int config_init_cmd(const char *, const char *, struct lxc_conf *);
static struct lxc_config_t config[] = {
{ "lxc.arch", config_personality },
{ "lxc.pts", config_pts },
{ "lxc.tty", config_tty },
{ "lxc.devttydir", config_ttydir },
{ "lxc.kmsg", config_kmsg },
{ "lxc.aa_profile", config_lsm_aa_profile },
{ "lxc.aa_allow_incomplete", config_lsm_aa_incomplete },
{ "lxc.se_context", config_lsm_se_context },
{ "lxc.cgroup", config_cgroup },
{ "lxc.id_map", config_idmap },
{ "lxc.loglevel", config_loglevel },
{ "lxc.logfile", config_logfile },
{ "lxc.mount", config_mount },
{ "lxc.rootfs.mount", config_rootfs_mount },
{ "lxc.rootfs.options", config_rootfs_options },
{ "lxc.rootfs", config_rootfs },
{ "lxc.pivotdir", config_pivotdir },
{ "lxc.utsname", config_utsname },
{ "lxc.hook.pre-start", config_hook },
{ "lxc.hook.pre-mount", config_hook },
{ "lxc.hook.mount", config_hook },
{ "lxc.hook.autodev", config_hook },
{ "lxc.hook.start", config_hook },
{ "lxc.hook.post-stop", config_hook },
{ "lxc.hook.clone", config_hook },
{ "lxc.hook", config_hook },
{ "lxc.network.type", config_network_type },
{ "lxc.network.flags", config_network_flags },
{ "lxc.network.link", config_network_link },
{ "lxc.network.name", config_network_name },
{ "lxc.network.macvlan.mode", config_network_macvlan_mode },
{ "lxc.network.veth.pair", config_network_veth_pair },
{ "lxc.network.script.up", config_network_script_up },
{ "lxc.network.script.down", config_network_script_down },
{ "lxc.network.hwaddr", config_network_hwaddr },
{ "lxc.network.mtu", config_network_mtu },
{ "lxc.network.vlan.id", config_network_vlan_id },
{ "lxc.network.ipv4.gateway", config_network_ipv4_gateway },
{ "lxc.network.ipv4", config_network_ipv4 },
{ "lxc.network.ipv6.gateway", config_network_ipv6_gateway },
{ "lxc.network.ipv6", config_network_ipv6 },
/* config_network_nic must come after all other 'lxc.network.*' entries */
{ "lxc.network.", config_network_nic },
{ "lxc.network", config_network },
{ "lxc.cap.drop", config_cap_drop },
{ "lxc.cap.keep", config_cap_keep },
{ "lxc.console.logfile", config_console_logfile },
{ "lxc.console", config_console },
{ "lxc.seccomp", config_seccomp },
{ "lxc.include", config_includefile },
{ "lxc.autodev", config_autodev },
{ "lxc.haltsignal", config_haltsignal },
{ "lxc.stopsignal", config_stopsignal },
{ "lxc.start.auto", config_start },
{ "lxc.start.delay", config_start },
{ "lxc.start.order", config_start },
{ "lxc.group", config_group },
{ "lxc.environment", config_environment },
{ "lxc.init_cmd", config_init_cmd },
};
struct signame {
int num;
const char *name;
};
{ SIGHUP, "HUP" },
{ SIGINT, "INT" },
{ SIGQUIT, "QUIT" },
{ SIGILL, "ILL" },
{ SIGABRT, "ABRT" },
{ SIGFPE, "FPE" },
{ SIGKILL, "KILL" },
{ SIGSEGV, "SEGV" },
{ SIGPIPE, "PIPE" },
{ SIGALRM, "ALRM" },
{ SIGTERM, "TERM" },
{ SIGUSR1, "USR1" },
{ SIGUSR2, "USR2" },
{ SIGCHLD, "CHLD" },
{ SIGCONT, "CONT" },
{ SIGSTOP, "STOP" },
{ SIGTSTP, "TSTP" },
{ SIGTTIN, "TTIN" },
{ SIGTTOU, "TTOU" },
};
{
int i;
for (i = 0; i < config_size; i++)
return &config[i];
return NULL;
}
do { \
if (inlen > 0) { \
} \
} while (0);
{
if (!retv)
inlen = 0;
else
for (i = 0; i < config_size; i++) {
continue;
}
return fulllen;
}
{
char *new_value;
return 0;
}
if (!new_value) {
return -1;
}
return 0;
}
{
return -1;
}
}
{
}
/*
* config entry is something like "lxc.network.0.ipv4"
* the key 'lxc.network.' was found. So we make sure next
* comes an integer, find the right callback (by rewriting
* the key), and call it.
*/
{
int ret = -1;
struct lxc_config_t *config;
if (!copy) {
SYSERROR("failed to allocate memory");
return -1;
}
/*
* ok we know that to get here we've got "lxc.network."
* and it isn't any of the other network entries. So
* after the second . should come an integer (# of defined
* nic) followed by a valid entry.
*/
goto out;
if (!p)
goto out;
if (!config) {
goto out;
}
out:
return ret;
}
{
ERROR("lxc.network must not have a value");
return -1;
}
return lxc_clear_config_network(lxc_conf);
}
{
struct lxc_netdev *netdev;
return lxc_clear_config_network(lxc_conf);
if (!netdev) {
SYSERROR("failed to allocate memory");
return -1;
}
if (!list) {
SYSERROR("failed to allocate memory");
return -1;
}
}
else {
return -1;
}
return 0;
}
{
return 32 - IN_CLASSA_NSHIFT;
return 32 - IN_CLASSB_NSHIFT;
return 32 - IN_CLASSC_NSHIFT;
return 0;
}
/*
* if you have p="lxc.network.0.link", pass it p+12
* to get back '0' (the index of the nic)
*/
static int get_network_netdev_idx(const char *key)
{
return -1;
if (ret != 1)
return -1;
return idx;
}
/*
* if you have p="lxc.network.0", pass this p+12 and it will return
* the netdev of the first configured nic
*/
{
if (idx == -1)
return NULL;
if (idx == i++) {
break;
}
}
return netdev;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
if (!retv)
inlen = 0;
else
}
case LXC_NET_VETH:
break;
case LXC_NET_MACVLAN:
break;
case LXC_NET_VLAN:
break;
case LXC_NET_PHYS:
break;
}
return fulllen;
}
{
if (lxc_list_empty(network)) {
ERROR("network is not created for '%s' = '%s' option",
return NULL;
}
else
if (!netdev) {
ERROR("no network device defined for '%s' = '%s' option",
return NULL;
}
return netdev;
}
{
}
#ifndef MACVLAN_MODE_PRIVATE
# define MACVLAN_MODE_PRIVATE 1
#endif
#ifndef MACVLAN_MODE_VEPA
# define MACVLAN_MODE_VEPA 2
#endif
#ifndef MACVLAN_MODE_BRIDGE
# define MACVLAN_MODE_BRIDGE 4
#endif
{
struct mc_mode {
char *name;
int mode;
} m[] = {
{ "private", MACVLAN_MODE_PRIVATE },
{ "vepa", MACVLAN_MODE_VEPA },
{ "bridge", MACVLAN_MODE_BRIDGE },
};
int i;
for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
continue;
return 0;
}
return -1;
}
static int rand_complete_hwaddr(char *hwaddr)
{
const char hex[] = "0123456789abcdef";
#ifndef HAVE_RAND_R
randseed(true);
#else
#endif
{
//ensure address is unicast
#ifdef HAVE_RAND_R
} else {
#else
} else {
#endif
}
}
curs++;
}
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
ERROR("Invalid veth pair for a non-veth netdev");
return -1;
}
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
ERROR("Invalid macvlan.mode for a non-macvlan netdev");
return -1;
}
}
{
struct lxc_netdev *netdev;
if (!new_value) {
return -1;
}
if (!netdev) {
return -1;
};
return 0;
}
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
ERROR("Invalid vlan.id for a non-macvlan netdev");
return -1;
}
return -1;
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
}
{
struct lxc_netdev *netdev;
struct lxc_inetdev *inetdev;
if (!netdev)
return -1;
if (!inetdev) {
SYSERROR("failed to allocate ipv4 address");
return -1;
}
if (!list) {
SYSERROR("failed to allocate memory");
return -1;
}
if (!addr) {
ERROR("no address specified");
return -1;
}
if (cursor) {
*cursor = '\0';
}
if (slash) {
*slash = '\0';
}
return -1;
}
return -1;
}
/* no prefix specified, determine it from the network class */
/* if no broadcast address, let compute one from the
* prefix and address
*/
if (!bcast) {
}
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
netdev->ipv4_gateway_auto = true;
} else {
if (!gw) {
SYSERROR("failed to allocate ipv4 gateway address");
return -1;
}
return -1;
}
netdev->ipv4_gateway_auto = false;
}
return 0;
}
{
struct lxc_netdev *netdev;
struct lxc_inet6dev *inet6dev;
char *netmask;
if (!netdev)
return -1;
if (!inet6dev) {
SYSERROR("failed to allocate ipv6 address");
return -1;
}
if (!list) {
SYSERROR("failed to allocate memory");
return -1;
}
if (!valdup) {
ERROR("no address specified");
return -1;
}
if (slash) {
*slash = '\0';
}
return -1;
}
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
netdev->ipv6_gateway_auto = true;
} else {
if (!gw) {
SYSERROR("failed to allocate ipv6 gateway address");
return -1;
}
return -1;
}
netdev->ipv6_gateway_auto = false;
}
return 0;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
}
{
struct lxc_netdev *netdev;
if (!netdev)
return -1;
}
{
if (!hooklist) {
return -1;
}
return 0;
}
{
}
{
}
{
char *copy;
return -1;
}
if (!copy) {
return -1;
}
return -1;
}
{
if (personality >= 0)
else
return 0;
}
{
return 0;
}
{
return 0;
}
return 0;
}
return 0;
}
return -1;
}
{
int ret = -1;
return lxc_clear_groups(lxc_conf);
if (!groups) {
return -1;
}
/* in case several groups are specified in a single line
* split these groups in a single element for the list */
if (!token) {
ret = 0;
break;
}
if (!grouplist) {
SYSERROR("failed to allocate groups list");
break;
}
break;
}
}
return ret;
}
{
return lxc_clear_environment(lxc_conf);
if (!list_item)
goto freak_out;
goto freak_out;
return 0;
return -1;
}
{
return 0;
}
{
}
{
return 0;
}
{
}
{
return 0;
}
{
}
{
int ret;
// store these values in the lxc_conf, and then try to set for
// actual current logging.
if (ret == 0)
return ret;
}
{
int newlevel;
return 0;
else
// store these values in the lxc_conf, and then try to set for
// actual current logging.
return lxc_log_set_level(newlevel);
}
{
return 0;
}
{
int n;
errno = 0;
return -1;
return n;
}
static int rt_sig_num(const char *signame)
{
int sig_n = 0;
int rtmax = 0;
rtmax = 1;
}
signame += 4;
return -1;
return -1;
return sig_n;
}
int n;
signame += 3;
}
}
return -1;
}
{
if (sig_n < 0)
return -1;
return 0;
}
{
if (sig_n < 0)
return -1;
return 0;
}
{
char *subkey;
if (!subkey)
return -1;
return -1;
return -1;
if (!cglist)
goto out;
if (!cgelem)
goto out;
goto out;
return 0;
out:
if (cgelem) {
}
return -1;
}
{
char *token = "lxc.id_map";
char *subkey;
char type;
int ret;
return lxc_clear_idmaps(lxc_conf);
if (!subkey)
return -1;
return -1;
if (!idmaplist)
goto out;
if (!idmap)
goto out;
if (ret != 4)
goto out;
if (type == 'u')
else if (type == 'g')
else
goto out;
return 0;
out:
if (idmap) {
}
return -1;
}
{
return -1;
}
{
* no options: keep mask and flag identical and just define the
* enum value as an unused bit so far
*/
{ NULL, 0 }
};
int i;
int ret = -1;
lxc_conf->auto_mounts = 0;
return 0;
}
if (!autos) {
return -1;
}
if (!token) {
ret = 0;
break;
}
for (i = 0; allowed_auto_mounts[i].token; i++) {
break;
}
if (!allowed_auto_mounts[i].token) {
break;
}
}
return ret;
}
/*
* TODO
* This fn is handling lxc.mount, lxc.mount.entry, and lxc.mount.auto.
* It should probably be split into 3 separate functions indexed by
* the config[] entries at top.
*/
{
char *fstab_token = "lxc.mount";
char *token = "lxc.mount.entry";
char *auto_token = "lxc.mount.auto";
char *subkey;
char *mntelem;
if (!subkey) {
if (!subkey) {
if (!subkey)
return -1;
}
}
/* At this point we definitely have key = lxc.mount.entry */
return lxc_clear_mount_entries(lxc_conf);
if (!mntlist)
return -1;
if (!mntelem) {
return -1;
}
return 0;
}
{
int ret = -1;
return lxc_clear_config_keepcaps(lxc_conf);
if (!keepcaps) {
return -1;
}
/* in case several capability keep is specified in a single line
* split these caps in a single element for the list */
if (!token) {
ret = 0;
break;
}
if (!keeplist) {
SYSERROR("failed to allocate keepcap list");
break;
}
break;
}
}
return ret;
}
{
int ret = -1;
return lxc_clear_config_caps(lxc_conf);
if (!dropcaps) {
return -1;
}
/* in case several capability drop is specified in a single line
* split these caps in a single element for the list */
if (!token) {
ret = 0;
break;
}
if (!droplist) {
SYSERROR("failed to allocate drop list");
break;
}
break;
}
}
return ret;
}
{
}
{
}
/*
* If we find a lxc.network.hwaddr in the original config file,
* we expand it in the unexpanded_config, so that after a save_config
* we store the hwaddr for re-use.
* This is only called when reading the config file, not when executing
* a lxc.include.
* 'x' and 'X' are substituted in-place.
*/
static void update_hwaddr(const char *line)
{
char *p;
if (line[0] == '#')
return;
return;
if (!p)
return; // let config_network_hwaddr raise the error
p++;
while (isblank(*p))
p++;
if (!*p)
return;
}
{
if (!tmp)
return -1;
if (!conf->unexpanded_config)
*tmp = '\0';
}
conf->unexpanded_len++;
}
return 0;
}
{
char path[MAXPATHLEN];
if (!dir) {
return -1;
}
const char *fnam;
if (!direntp)
break;
continue;
continue;
continue;
ret = -1;
goto out;
}
if (ret < 0)
goto out;
}
ret = 0;
out:
WARN("lxc.include dir: failed to close directory");
return ret;
}
{
}
{
}
{
}
{
}
{
WARN("lxc.pivotdir is ignored. It will soon become an error.");
}
{
if (!utsname) {
SYSERROR("failed to allocate memory");
return -1;
}
ERROR("node name '%s' is too long",
value);
return -1;
}
return 0;
}
struct parse_line_conf {
bool from_include;
};
{
struct lxc_config_t *config;
char *dot;
char *key;
char *value;
int ret = 0;
if (lxc_is_line_empty(buffer))
return 0;
/* we have to dup the buffer otherwise, at the re-exec for
* reboot we modified the original string on the stack by
* replacing '=' by '\0' below
*/
if (!line) {
return -1;
}
if (!plc->from_include)
goto out;
/* ignore comments */
if (line[0] == '#')
goto out;
/* martian option - don't add it to the config itself */
goto out;
ret = -1;
if (!dot) {
goto out;
}
*dot = '\0';
if (!config) {
goto out;
}
out:
return ret;
}
{
struct parse_line_conf c;
c.from_include = false;
return parse_line(buffer, &c);
}
{
struct parse_line_conf c;
c.from_include = from_include;
return -1;
}
/* Catch only the top level config file name in the structure */
}
{
if (!dent)
return -1;
return 0;
}
{
int ret = 0;
if (ret)
break;
}
}
return ret;
}
signed long lxc_config_parse_arch(const char *arch)
{
struct per_name {
char *name;
unsigned long per;
} pername[] = {
{ "x86", PER_LINUX32 },
{ "linux32", PER_LINUX32 },
{ "i386", PER_LINUX32 },
{ "i486", PER_LINUX32 },
{ "i586", PER_LINUX32 },
{ "i686", PER_LINUX32 },
{ "athlon", PER_LINUX32 },
{ "linux64", PER_LINUX },
{ "x86_64", PER_LINUX },
{ "amd64", PER_LINUX },
};
int i;
for (i = 0; i < len; i++) {
}
#endif
return -1;
}
{
int i, aflag;
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
{ "LSM", LXC_ATTACH_LSM_EXEC },
{ NULL, 0 }
};
if (!flaglist) {
/* for the sake of backward compatibility, drop all privileges
if none is specified */
}
return 0;
}
while (token) {
aflag = -1;
}
if (aflag < 0)
return -1;
}
return 0;
}
{
if (!retv)
inlen = 0;
else
}
{
int fulllen = 0;
if (!retv)
inlen = 0;
else
int len = 0;
switch(c->personality) {
default: break;
}
#endif
return fulllen;
}
/*
* If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list,
* then just the value(s) will be printed. Since there still could be
* more than one, it is newline-separated.
* (Maybe that's ambigous, since some values, i.e. devices.list, will
* already have newlines?)
* If you ask for 'lxc.cgroup", then all cgroup entries will be printed,
* in 'lxc.cgroup.subsystem.key = value' format.
*/
const char *key)
{
int all = 0;
if (!retv)
inlen = 0;
else
all = 1;
if (all) {
}
}
return fulllen;
}
const char *key)
{
char *subkey;
int i;
/* "lxc.hook.mount" */
if (!subkey)
return -1;
subkey++;
if (!*subkey)
return -1;
for (i=0; i<NUM_LXC_HOOKS; i++) {
found=i;
break;
}
}
if (found == -1)
return -1;
if (!retv)
inlen = 0;
else
}
return fulllen;
}
{
if (!retv)
inlen = 0;
else
}
return fulllen;
}
{
if (!retv)
inlen = 0;
else
}
return fulllen;
}
{
if (!retv)
inlen = 0;
else
}
return fulllen;
}
{
if (!retv)
inlen = 0;
else
}
return fulllen;
}
{
if (!retv)
inlen = 0;
else
}
return fulllen;
}
{
const char *sep = "";
if (!retv)
inlen = 0;
else
if (!(c->auto_mounts & LXC_AUTO_ALL_MASK))
return 0;
switch (c->auto_mounts & LXC_AUTO_PROC_MASK) {
default: break;
}
switch (c->auto_mounts & LXC_AUTO_SYS_MASK) {
default: break;
}
switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) {
case LXC_AUTO_CGROUP_FULL_MIXED: strprint(retv, inlen, "%scgroup-full:mixed", sep); sep = " "; break;
default: break;
}
return fulllen;
}
/*
* lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
* macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
* ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead
* of an address. ipv4 and ipv6 return lists (newline-separated).
* things like veth.pair return '' if invalid (i.e. if called for vlan
* type).
*/
const char *key)
{
char *p1;
struct lxc_netdev *netdev;
if (!retv)
inlen = 0;
else
p1++;
if (!netdev)
return -1;
if (netdev->downscript)
const char *mode;
default: mode = "(invalid)"; break;
}
}
}
}
if (netdev->ipv4_gateway_auto) {
} else if (netdev->ipv4_gateway) {
char buf[INET_ADDRSTRLEN];
}
char buf[INET_ADDRSTRLEN];
}
if (netdev->ipv6_gateway_auto) {
} else if (netdev->ipv6_gateway) {
char buf[INET6_ADDRSTRLEN];
}
char buf[INET6_ADDRSTRLEN];
}
}
return fulllen;
}
{
if (!retv)
inlen = 0;
else
const char *t = lxc_net_type_to_str(n->type);
}
return fulllen;
}
int inlen)
{
const char *v = NULL;
v = c->fstab;
v = c->ttydir;
v = c->lsm_aa_profile;
v = c->lsm_se_context;
v = lxc_log_get_file();
v = c->seccomp;
v = c->init_cmd;
else return -1;
if (!v)
return 0;
return strlen(v);
}
{
return lxc_clear_config_network(c);
return lxc_clear_config_caps(c);
return lxc_clear_config_keepcaps(c);
return lxc_clear_cgroups(c, key);
return lxc_clear_mount_entries(c);
return lxc_clear_automounts(c);
return lxc_clear_hooks(c, key);
return lxc_clear_groups(c);
return lxc_clear_environment(c);
return lxc_clear_idmaps(c);
return -1;
}
/*
* writing out a confile.
*/
{
int ret;
if (!len)
return;
SYSERROR("Error writing configuration file");
}
{
int ret;
return false;
/* Save the line verbatim into unexpanded_conf */
return false;
return true;
}
{
if (!conf->unexpanded_config)
return;
while (*lstart) {
char v;
if (!lend)
else
lend++;
continue;
}
if (!rm_subkeys) {
if (!isspace(v) && v != '=') {
continue;
}
}
if (*lend == '\0') {
*lstart = '\0';
return;
}
}
}
{
int ret;
return false;
}
return false;
}
if (!conf->unexpanded_config)
return true;
while (*lstart) {
if (!lend)
else
lend++;
continue;
}
if (!p) {
continue;
}
p++;
while (isblank(*p))
p++;
if (!*p)
return true;
continue;
}
/* replace the olddir with newdir */
}
} else {
char *new;
if (!new) {
ERROR("Out of memory");
return false;
}
/* move over the remainder, /$hookname\n$rest */
}
}
return true;
}
if (!(cmd)) { \
ERROR("Error writing to new config"); \
return false; \
} \
}
static void new_hwaddr(char *hwaddr)
{
FILE *f;
if (f) {
unsigned int seed;
if (ret != 1)
fclose(f);
} else
}
/*
* This is called only from clone.
* We wish to update all hwaddrs in the unexpanded config file. We
* shouldn't be any).
* We can't just walk the c->lxc-conf->network list because that includes
* netifs from the include files. So we update the ones which we find in
* the unexp config file, then find the original macaddr in the
* conf->network, and update that to the same value.
*/
{
const char *key = "lxc.network.hwaddr";
if (!conf->unexpanded_config)
return true;
while (*lstart) {
if (!lend)
else
lend++;
continue;
}
if (!p) {
continue;
}
p++;
while (isblank(*p))
p++;
if (!*p)
return true;
p2 = p;
p2++;
if (p2-p != 17) {
WARN("Bad hwaddr entry");
continue;
}
}
}
return true;
}