Skip to content

Commit

Permalink
Merge pull request #3762 from brauner/2021-03-31/fixes
Browse files Browse the repository at this point in the history
fixes: Makefile, lxc-user-nic, simplify get_network_config_ops()
  • Loading branch information
stgraber committed Apr 1, 2021
2 parents b405dec + 7707b0e commit 8aa6025
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 172 deletions.
45 changes: 21 additions & 24 deletions src/lxc/cmd/lxc_user_nic.c
Expand Up @@ -233,43 +233,40 @@ struct alloted_s {
struct alloted_s *next;
};

static struct alloted_s *append_alloted(struct alloted_s **head, char *name,
int n)
static struct alloted_s *append_alloted(struct alloted_s **head, char *name, int n)
{
struct alloted_s *cur, *al;
__do_free struct alloted_s *al = NULL;
struct alloted_s *cur;

if (!head || !name) {
/* Sanity check. Parameters should not be null. */
usernic_error("%s\n", "Unexpected NULL argument");
return NULL;
}

al = malloc(sizeof(struct alloted_s));
al = zalloc(sizeof(struct alloted_s));
if (!al) {
CMD_SYSERROR("Failed to allocate memory\n");
return NULL;
}

al->name = strdup(name);
if (!al->name) {
free(al);
if (!al->name)
return NULL;
}

al->allowed = n;
al->next = NULL;

if (!*head) {
if (*head) {
cur = *head;
while (cur->next)
cur = cur->next;
cur->next = al;
} else {
*head = al;
return al;
}

cur = *head;
while (cur->next)
cur = cur->next;
cur->next = al;

return al;
return move_ptr(al);
}

static void free_alloted(struct alloted_s **head)
Expand Down Expand Up @@ -321,28 +318,28 @@ static int get_alloted(char *me, char *intype, char *link,
if (ret != 4)
continue;

if (strlen(name) == 0)
if (is_empty_string(name))
continue;

if (strcmp(name, me)) {
if (!strequal(name, me)) {
if (name[0] != '@')
continue;

if (!name_is_in_groupnames(name + 1, groups))
continue;
}

if (strcmp(type, intype))
if (!strequal(type, intype))
continue;

if (strcmp(link, br))
if (!strequal(link, br))
continue;

/* Found the user or group with the appropriate settings,
* therefore finish the search. What to do if there are more
* than one applicable lines? not specified in the docs. Since
* getline is implemented with realloc, we don't need to free
* line until exiting func.
/*
* Found the user or group with the appropriate settings,
* therefore finish the search. What to do if there are is more
* than one applicable line? Currently this is not specified in
* the docs.
*
* If append_alloted returns NULL, e.g. due to a malloc error,
* we set count to 0 and break the loop, allowing cleanup and
Expand Down
172 changes: 85 additions & 87 deletions src/lxc/confile.c
Expand Up @@ -95,6 +95,7 @@ lxc_config_define(init_cwd);
lxc_config_define(init_gid);
lxc_config_define(init_uid);
lxc_config_define(init_groups);
lxc_config_define(jump_table_net);
lxc_config_define(keyring_session);
lxc_config_define(log_file);
lxc_config_define(log_level);
Expand Down Expand Up @@ -123,7 +124,6 @@ lxc_config_define(net_ipvlan_mode);
lxc_config_define(net_ipvlan_isolation);
lxc_config_define(net_mtu);
lxc_config_define(net_name);
lxc_config_define(net_nic);
lxc_config_define(net_script_down);
lxc_config_define(net_script_up);
lxc_config_define(net_type);
Expand Down Expand Up @@ -227,9 +227,9 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.namespace.clone", true, set_config_namespace_clone, get_config_namespace_clone, clr_config_namespace_clone, },
{ "lxc.namespace.keep", true, set_config_namespace_keep, get_config_namespace_keep, clr_config_namespace_keep, },
{ "lxc.namespace.share", true, set_config_namespace_share, get_config_namespace_share, clr_config_namespace_share, },
{ "lxc.time.offset.boot", true, set_config_time_offset_boot, get_config_time_offset_boot, clr_config_time_offset_boot, },
{ "lxc.time.offset.boot", true, set_config_time_offset_boot, get_config_time_offset_boot, clr_config_time_offset_boot, },
{ "lxc.time.offset.monotonic", true, set_config_time_offset_monotonic, get_config_time_offset_monotonic, clr_config_time_offset_monotonic, },
{ "lxc.net.", false, set_config_net_nic, get_config_net_nic, clr_config_net_nic, },
{ "lxc.net.", false, set_config_jump_table_net, get_config_jump_table_net, clr_config_jump_table_net, },
{ "lxc.net", true, set_config_net, get_config_net, clr_config_net, },
{ "lxc.no_new_privs", true, set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
{ "lxc.prlimit", false, set_config_prlimit, get_config_prlimit, clr_config_prlimit, },
Expand Down Expand Up @@ -257,7 +257,11 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.proc", false, set_config_proc, get_config_proc, clr_config_proc, },
};

static struct lxc_config_t config_jump_table_net[] = {
struct lxc_config_net_t {
LXC_CONFIG_MEMBERS;
};

static struct lxc_config_net_t config_jump_table_net[] = {
/* If a longer key is added please update. */
#define NETWORK_SUBKEY_SIZE_MAX (STRLITERALLEN("veth.vlan.tagged.id") * 2)
{ "flags", true, set_config_net_flags, get_config_net_flags, clr_config_net_flags, },
Expand Down Expand Up @@ -318,12 +322,20 @@ struct lxc_config_t *lxc_get_config(const char *key)
return NULL;
}

static struct lxc_config_t *lxc_get_config_net(const char *key)
static inline bool match_config_net_item(const struct lxc_config_net_t *entry,
const char *key)
{
if (entry->strict)
return strequal(entry->name, key);
return strnequal(entry->name, key, strlen(entry->name));
}

static struct lxc_config_net_t *lxc_get_config_net(const char *key)
{
for (size_t i = 0; i < ARRAY_SIZE(config_jump_table_net); i++) {
struct lxc_config_t *cur = &config_jump_table_net[i];
struct lxc_config_net_t *cur = &config_jump_table_net[i];

if (!match_config_item(cur, key))
if (!match_config_net_item(cur, key))
continue;

return cur;
Expand Down Expand Up @@ -5204,97 +5216,94 @@ static int get_config_includefiles(const char *key, char *retv, int inlen,
return ret_errno(ENOSYS);
}

static struct lxc_config_t *get_network_config_ops(const char *key,
struct lxc_conf *lxc_conf,
ssize_t *idx,
const char **const subkey)
struct config_net_info {
char buf[NETWORK_SUBKEY_SIZE_MAX];
const char *subkey;
const struct lxc_config_net_t *ops;
struct lxc_netdev *netdev;
};

static int get_network_config_ops(const char *key, struct lxc_conf *lxc_conf,
struct config_net_info *info, bool allocate)
{
struct lxc_config_t *config = NULL;
int ret;
int64_t tmpidx;
const char *idx_start, *subkey_start;
char buf[NETWORK_SUBKEY_SIZE_MAX];

if (!idx)
return ret_set_errno(NULL, EINVAL);
unsigned int idx;
const char *idx_start;

if (is_empty_string(key))
return ret_set_errno(NULL, EINVAL);
return ret_errno(EINVAL);

/* check that this is a sensible network key */
if (!strnequal("lxc.net.", key, STRLITERALLEN("lxc.net.")))
return log_error_errno(NULL, EINVAL, "Invalid network configuration key \"%s\"", key);
return syserror_set(-EINVAL, "Invalid network configuration key \"%s\"", key);

/* lxc.net.<n> */
/* beginning of index string */
idx_start = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idx_start))
return log_error_errno(NULL, EINVAL, "Failed to detect digit in string \"%s\"", key + 8);
return syserror_set(-EINVAL, "Failed to detect digit in string \"%s\"", key + 8);

ret = lxc_safe_int64_residual(idx_start, &tmpidx, 10, buf, sizeof(buf));
ret = lxc_safe_int64_residual(idx_start, &tmpidx, 10, info->buf, sizeof(info->buf));
if (ret)
return log_error_errno(NULL, -ret, "Failed to parse network index");
return syserror("Failed to parse network index");

if (tmpidx < 0 || tmpidx >= INT_MAX)
return log_error_errno(NULL, ERANGE, "Number of configured networks would overflow the counter");
*idx = (ssize_t)tmpidx;
return syserror_set(-ERANGE, "Number of configured networks would overflow the counter");
idx = (unsigned int)tmpidx;

if (!subkey)
return NULL;
info->netdev = lxc_get_netdev_by_idx(lxc_conf, idx, allocate);
if (!info->netdev)
return ret_errno(EINVAL);

/* Make sure subkey points to the empty string. */
info->subkey = info->buf;
if (is_empty_string(info->subkey))
return ret_errno(ENOENT);

subkey_start = &buf[1];
if (is_empty_string(subkey_start))
return log_error_errno(NULL, EINVAL, "No network subkey specified");
if (info->subkey[0] != '.')
return syserror_set(-EINVAL, "Invalid subkey");
info->subkey++;

/* lxc.net.<idx>.<subkey> */
*subkey = subkey_start;
config = lxc_get_config_net(*subkey);
if (!config)
return log_error_errno(NULL, ENOENT, "Unknown network configuration key \"%s\"", key);
info->ops = lxc_get_config_net(info->subkey);
if (!info->ops)
return syserror_set(-ENOENT, "Unknown network configuration key \"%s\"", key);

return config;
return 0;
}

/* Config entry is something like "lxc.net.0.ipv4" the key 'lxc.net.' was
* found. So we make sure next comes an integer, find the right callback (by
* rewriting the key), and call it.
*/
static int set_config_net_nic(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
static int set_config_jump_table_net(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
const char *subkey = NULL;
ssize_t idx = -1;
struct config_net_info info = {};
int ret;
const char *idxstring;
struct lxc_config_t *config;
struct lxc_netdev *netdev;

idxstring = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idxstring))
return ret_errno(EINVAL);

if (lxc_config_value_empty(value))
return clr_config_net_nic(key, lxc_conf, data);

config = get_network_config_ops(key, lxc_conf, &idx, &subkey);
if (!config || idx < 0)
return -errno;
return clr_config_jump_table_net(key, lxc_conf, data);

netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, true);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, lxc_conf, &info, true);
if (ret)
return ret;

return config->set(subkey, value, lxc_conf, netdev);
return info.ops->set(info.subkey, value, lxc_conf, info.netdev);
}

static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf,
void *data)
static int clr_config_jump_table_net(const char *key, struct lxc_conf *lxc_conf,
void *data)
{
const char *subkey = NULL;
ssize_t idx = -1;
struct config_net_info info = {};
int ret;
const char *idxstring;
struct lxc_config_t *config;
struct lxc_netdev *netdev;

idxstring = key + 8;
if (!isdigit(*idxstring))
Expand All @@ -5317,15 +5326,11 @@ static int clr_config_net_nic(const char *key, struct lxc_conf *lxc_conf,
return 0;
}

config = get_network_config_ops(key, lxc_conf, &idx, &subkey);
if (!config || idx < 0)
return -errno;

netdev = lxc_get_netdev_by_idx(lxc_conf, (unsigned int)idx, false);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, lxc_conf, &info, false);
if (ret)
return ret;

return config->clr(subkey, lxc_conf, netdev);
return info.ops->clr(info.subkey, lxc_conf, info.netdev);
}

static int clr_config_net_type(const char *key, struct lxc_conf *lxc_conf,
Expand Down Expand Up @@ -5683,28 +5688,22 @@ static int clr_config_net_veth_ipv6_route(const char *key,
return 0;
}

static int get_config_net_nic(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
static int get_config_jump_table_net(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
const char *subkey = NULL;
ssize_t idx = -1;
struct config_net_info info = {};
int ret;
const char *idxstring;
struct lxc_config_t *config;
struct lxc_netdev *netdev;

idxstring = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idxstring))
return ret_errno(EINVAL);

config = get_network_config_ops(key, c, &idx, &subkey);
if (!config || idx < 0)
return -errno;

netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, c, &info, false);
if (ret)
return ret;

return config->get(subkey, retv, inlen, c, netdev);
return info.ops->get(info.subkey, retv, inlen, c, info.netdev);
}

static int get_config_net_type(const char *key, char *retv, int inlen,
Expand Down Expand Up @@ -6427,23 +6426,22 @@ int lxc_list_subkeys(struct lxc_conf *conf, const char *key, char *retv,

int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen)
{
int len;
const char *idxstring;
struct config_net_info info = {};
struct lxc_netdev *netdev;
int len, ret;
const char *idxstring;
int fulllen = 0;
ssize_t idx = -1;

idxstring = key + STRLITERALLEN("lxc.net.");
if (!isdigit(*idxstring))
return ret_errno(EINVAL);

(void)get_network_config_ops(key, c, &idx, NULL);
if (idx < 0)
return ret_errno(EINVAL);

netdev = lxc_get_netdev_by_idx(c, (unsigned int)idx, false);
if (!netdev)
return ret_errno(EINVAL);
ret = get_network_config_ops(key, c, &info, false);
if (ret) {
if (ret != -ENOENT)
return ret_errno(EINVAL);
}
netdev = info.netdev;

if (!retv)
inlen = 0;
Expand Down

0 comments on commit 8aa6025

Please sign in to comment.