summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-07-24 15:11:10 (GMT)
committerThomas Haller <thaller@redhat.com>2023-07-24 15:11:54 (GMT)
commite2cacc26a6e560baa7887bb257884f05fb4df31b (patch)
tree38799479f1f4858f5fffc99489e566f76da6506c
parentec8c493c4ee9d0955390fbefbfb6e843a4fe24b8 (diff)
downloadlibnl-e2cacc26a6e560baa7887bb257884f05fb4df31b.zip
libnl-e2cacc26a6e560baa7887bb257884f05fb4df31b.tar.gz
libnl-e2cacc26a6e560baa7887bb257884f05fb4df31b.tar.bz2
route/link: improve handling of IFLA_INET6_CONF
On the netlink API, IFLA_INET6_CONF is a list of uint32_t integers, but the number of actually provided values depends on the kernel version (and the DEVCONF_MAX value that it was compiled with. We clone the kernel header in our source tree, so DEVCONF_MAX from the libnl3 build may differ from the running kernel. We need to keep track how many values kernel actually provides.
-rw-r--r--lib/route/link/inet6.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c
index efb126c..08b29a8 100644
--- a/lib/route/link/inet6.c
+++ b/lib/route/link/inet6.c
@@ -21,6 +21,7 @@ struct inet6_data
struct ifla_cacheinfo i6_cacheinfo;
uint32_t i6_conf[DEVCONF_MAX];
struct in6_addr i6_token;
+ uint8_t i6_conf_len;
uint8_t i6_addr_gen_mode;
};
@@ -165,9 +166,13 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
sizeof(i6->i6_cacheinfo));
- if (tb[IFLA_INET6_CONF])
+ if (tb[IFLA_INET6_CONF]) {
+ i6->i6_conf_len = min(ARRAY_SIZE(i6->i6_conf),
+ nla_len(tb[IFLA_INET6_CONF]) /
+ sizeof(i6->i6_conf[0]));
nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
- sizeof(i6->i6_conf));
+ sizeof(i6->i6_conf[0]) * i6->i6_conf_len);
+ }
if (tb[IFLA_INET6_TOKEN])
nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN],
@@ -351,7 +356,7 @@ static void inet6_dump_details(struct rtnl_link *link,
nl_dump_line(p, " devconf:\n");
nl_dump_line(p, " ");
- for (i = 0; i < DEVCONF_MAX; i++) {
+ for (i = 0; i < (int) i6->i6_conf_len; i++) {
char buf2[64];
uint32_t value = i6->i6_conf[i];
int x, offset;
@@ -699,7 +704,7 @@ int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *link, uint8_t mode)
* result pointer.
*
* @return 0 on success or a negative error code.
- * @return -NLE_RANGE cfgid is out of range, 0..DEVCONF_MAX
+ * @return -NLE_RANGE cfgid is out of range or not provided by kernel.
* @return -NLE_NOATTR configuration setting not available
*/
int rtnl_link_inet6_get_conf(struct rtnl_link *link, unsigned int cfgid,
@@ -707,12 +712,12 @@ int rtnl_link_inet6_get_conf(struct rtnl_link *link, unsigned int cfgid,
{
struct inet6_data *id;
- if (cfgid >= DEVCONF_MAX)
- return -NLE_RANGE;
-
if (!(id = rtnl_link_af_data(link, &inet6_ops)))
return -NLE_NOATTR;
+ if (cfgid >= id->i6_conf_len)
+ return -NLE_RANGE;
+
*res = id->i6_conf[cfgid];
return 0;