summaryrefslogtreecommitdiffhomepage
path: root/src/config.c
diff options
context:
space:
mode:
authorChristian Marangi <ansuelsmth@gmail.com>2023-03-17 00:56:25 +0100
committerChristian Marangi <ansuelsmth@gmail.com>2023-03-22 06:34:20 +0100
commit7c0f603abc1481ddabcdeae0eaaf72d5535ecefa (patch)
treeb1bc03b59fba8f20580fa2ee8aef888f0a569218 /src/config.c
parentba30afcfec0a26ce4bcd96ea4d687c498b0ba4df (diff)
router: skip RA and wait for LINK-LOCAL to be assigned
This fix a specific and corner case when the following error and similar is printed in the log: Failed to send to ff02::1%br-lan (Address not available) The cause for this was tracked down to the lack of the interface of a configured LINK-LOCAL IPV6 address resulting in odhcpd_send() always failing. A LINK-LOCAL IPV6 address is assigned only after the interface has carrier and is set to IFF_RUNNING and require some time for the address to be assigned due to DAD logic. In the case where an interface was just UP, odhcpd RA may fail since the LINK-LOCAL IPV6 address still needs to be assigned as it still need to be "trained". From the kernel view this is flagged in the IPV6 interface address with the flag IFA_F_TENTATIVE, that means the address still needs to be checked and follow DAD process. This is only a transient problem and the DAD process is required only once till the interface is not set DOWN. To handle this, add some check to verify if the address has to be checked and add an additional bool to flag if the interface have a LINK-LOCAL assigned. Skip sending RA if the interface still doesn't have finished the DAD process and retry at the next RA. A notice log is added to track this special case to track problematic case and even more corner case. Logic to check if interface have LINK-LOCAL are: - When interface is setup, on scanning for the interface ipv6 address check if at least one address is NOT in IFA_F_TENTATIVE state. - With interface already up but with still no LINK-LOCAL react on the RTM_NEWADDR event and set LINK-LOCAL if the addrs added by the event is a LINK-LOCAL reflecting that the interface finally ended the DAD process and have a correct address. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> Acked-by: Hans Dedecker <dedeckeh@gmail.com>
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/config.c b/src/config.c
index 30da879..ee7219f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -594,6 +594,15 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
if (len > 0)
iface->addr6_len = len;
+ for (size_t i = 0; i < iface->addr6_len; i++) {
+ struct odhcpd_ipaddr *addr = &iface->addr6[i];
+
+ if (!addr->tentative) {
+ iface->have_link_local = true;
+ break;
+ }
+ }
+
len = netlink_get_interface_addrs(iface->ifindex,
false, &iface->addr4);
if (len > 0)