]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
confile: simplify get_network_config_ops() 3762/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 1 Apr 2021 08:07:59 +0000 (10:07 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 1 Apr 2021 09:08:13 +0000 (11:08 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/confile.c
src/lxc/confile.h

index dbb7e3b01020810273291da57b672f9ee276f623..a07572dc5bd3b07c868556e9aa88c06d93d24ee9 100644 (file)
@@ -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);
@@ -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);
@@ -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,                    },
@@ -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,                  },
@@ -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;
@@ -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))
@@ -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,
@@ -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,
@@ -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;
index b04252b8f780f5f605fcbf6ae61a893d41b68a8f..c49dc87228b4578b702df2193348edc291f9a1a6 100644 (file)
@@ -32,12 +32,15 @@ typedef int (*config_get_cb)(const char *key, char *value, int inlen,
 typedef int (*config_clr_cb)(const char *key, struct lxc_conf *conf,
                             void *data);
 
+#define LXC_CONFIG_MEMBERS \
+       char *name;        \
+       bool strict;       \
+       config_set_cb set; \
+       config_get_cb get; \
+       config_clr_cb clr
+
 struct lxc_config_t {
-       char *name;
-       bool strict;
-       config_set_cb set;
-       config_get_cb get;
-       config_clr_cb clr;
+       LXC_CONFIG_MEMBERS;
 };
 
 struct new_config_item {