diff options
author | Thomas Haller <thaller@redhat.com> | 2023-07-24 15:11:10 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-07-24 15:11:54 (GMT) |
commit | e2cacc26a6e560baa7887bb257884f05fb4df31b (patch) | |
tree | 38799479f1f4858f5fffc99489e566f76da6506c | |
parent | ec8c493c4ee9d0955390fbefbfb6e843a4fe24b8 (diff) | |
download | libnl-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.c | 19 |
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; |