From 45e441ada6d3ea4355d623cf12d9a559a5c2afde Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 23 May 2023 22:14:57 +0100 Subject: [PATCH] Linux: Improve learning IPv6 address flags Rather than matching addresses during netlink message processing, extract the local, address and flag parts. Once done, then match local and address to the address we are looking for and if equal apply the flags. Fixes #201 and maybe #149. --- src/if-linux.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/if-linux.c b/src/if-linux.c index f2f609ed..212ed5df 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -1996,7 +1996,8 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx, size_t len; struct rtattr *rta; struct ifaddrmsg *ifa; - bool matches_addr = false; + struct in6_addr *local = NULL, *address = NULL; + uint32_t *flags = NULL; ifa = NLMSG_DATA(nlm); if (ifa->ifa_index != ia->ifa_ifindex || ifa->ifa_family != AF_INET6) @@ -2007,17 +2008,26 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx, for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { switch (rta->rta_type) { case IFA_ADDRESS: - if (IN6_ARE_ADDR_EQUAL(&ia->ifa_addr, (struct in6_addr *)RTA_DATA(rta))) - ia->ifa_found = matches_addr = true; - else - matches_addr = false; + address = (struct in6_addr *)RTA_DATA(rta); + break; + case IFA_LOCAL: + local = (struct in6_addr *)RTA_DATA(rta); break; case IFA_FLAGS: - if (matches_addr) - memcpy(&ia->ifa_flags, RTA_DATA(rta), sizeof(ia->ifa_flags)); + flags = (uint32_t *)RTA_DATA(rta); break; } } + + if (local) { + if (IN6_ARE_ADDR_EQUAL(&ia->ifa_addr, local)) + ia->ifa_found = true; + } else if (address) { + if (IN6_ARE_ADDR_EQUAL(&ia->ifa_addr, address)) + ia->ifa_found = true; + } + if (flags && ia->ifa_found) + memcpy(&ia->ifa_flags, flags, sizeof(ia->ifa_flags)); return 0; }