Commit ac14ad9755d4 ("ipv6: use xarray iterator to implement
inet6_dump_ifinfo()") and commit 9cc4cc329d30 ("ipv6: use xa_array
iterator to implement inet6_dump_addr()") made the IPv6 RTM_GETLINK and
RTM_GETADDR dumps put NLM_DONE into the same recv() as the last
objects.
However, some applications expect NLM_DONE in a separate recv(). As of
now, Kamailio waits for it when it looks for the IPv6 addresses of the
host. It gives up after 4 seconds and listens on localhost only.
A similar issue happened before in the route dumps and in the IPv4
address dump. It was fixed by commit 460b0d33cf10 ("inet: bring
NLM_DONE out to a separate recv() again") and commit 5b4b62a169e1
("rtnetlink: make the "split" NLM_DONE handling generic"). Perhaps
these two dumps need the same.
The issue can be reproduced with:
python3 tools/net/ynl/pyynl/cli.py --dbg-small-recv 4096 --no-schema \
--spec Documentation/netlink/specs/rt-addr.yaml \
--dump getaddr --json '{"ifa-family": 10}' 2>&1 | grep Recv
Before commit 9cc4cc329d30 ("ipv6: use xa_array iterator to implement
inet6_dump_addr()"), the result is:
Recv: read 232 bytes, 3 messages
Recv: read 20 bytes, 1 messages
After that commit, the result is:
Recv: read 252 bytes, 4 messages
This patch will set RTNL_FLAG_DUMP_SPLIT_NLM_DONE for both dumps.
Fixes: ac14ad9755d4 ("ipv6: use xarray iterator to implement inet6_dump_ifinfo()")
Fixes: 9cc4cc329d30 ("ipv6: use xa_array iterator to implement inet6_dump_addr()")
Signed-off-by: Hengyu Liang <redacted>
---
Application impact (Ubuntu 26.04 user space): Kamailio 6.0.5 with
"auto_bind_ipv6=1" added to the shipped kamailio.cfg, on a host with
one IPv4 and one global IPv6 address. On v6.8, it listens on both
addresses and on localhost. On v6.9 and on net, it logs "Could not get
network interface list" and listens on 127.0.0.1 only.
Kamailio looks only at the first message of each recv() for NLM_DONE
(src/core/socket_info.c, same in its master branch).
Tested on net: with this patch, Kamailio listens on all addresses again
and starts without the 4 second wait.
net/ipv6/addrconf.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d9d13e78bf13..cbee883e8b01 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7561,14 +7561,16 @@ static struct rtnl_af_ops inet6_ops __read_mostly = {
static const struct rtnl_msg_handler addrconf_rtnl_msg_handlers[] __initconst_or_module = {
{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETLINK,
- .dumpit = inet6_dump_ifinfo, .flags = RTNL_FLAG_DUMP_UNLOCKED},
+ .dumpit = inet6_dump_ifinfo,
+ .flags = RTNL_FLAG_DUMP_UNLOCKED | RTNL_FLAG_DUMP_SPLIT_NLM_DONE},
{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_NEWADDR,
.doit = inet6_rtm_newaddr, .flags = RTNL_FLAG_DOIT_PERNET},
{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_DELADDR,
.doit = inet6_rtm_deladdr, .flags = RTNL_FLAG_DOIT_PERNET},
{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETADDR,
.doit = inet6_rtm_getaddr, .dumpit = inet6_dump_ifaddr,
- .flags = RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED},
+ .flags = RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED |
+ RTNL_FLAG_DUMP_SPLIT_NLM_DONE},
{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETMULTICAST,
.dumpit = inet6_dump_ifmcaddr,
.flags = RTNL_FLAG_DUMP_UNLOCKED},
base-commit: 19ec8416a76c08326fe5f814410a1b43046e63be
--
2.53.0