diff --git a/src/linux/netlinkutil/Address.cpp b/src/linux/netlinkutil/Address.cpp index 19c1d62d9d..e0b2d1ea8f 100644 --- a/src/linux/netlinkutil/Address.cpp +++ b/src/linux/netlinkutil/Address.cpp @@ -141,6 +141,22 @@ bool Address::IsIpv4() const noexcept return m_family == AF_INET; } +bool Address::IsLinkLocal() const +{ + if (m_family == AF_INET) + { + return (ntohl(AsBytes().s_addr) & 0xFFFF0000) == 0xA9FE0000; + } + + if (m_family == AF_INET6) + { + const auto bytes = AsBytes(); + return bytes.s6_addr[0] == 0xFE && (bytes.s6_addr[1] & 0xC0) == 0x80; + } + + return false; +} + bool Address::IsPrefixRouteAutogenerationDisabled() const noexcept { return m_disableAutogeneratedPrefixRoute; diff --git a/src/linux/netlinkutil/RoutingTable.cpp b/src/linux/netlinkutil/RoutingTable.cpp index 56be77537a..9ff9e24d58 100644 --- a/src/linux/netlinkutil/RoutingTable.cpp +++ b/src/linux/netlinkutil/RoutingTable.cpp @@ -139,6 +139,10 @@ void RoutingTable::SendMessage(const Route& route, int operation, int flags, con message.route.rtm_type = route.IsMulticast() ? RTN_MULTICAST : RTN_UNICAST; message.route.rtm_scope = route.IsOnlink() ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; message.route.rtm_flags = RTM_F_NOTIFY; + if (route.via.has_value() && route.via.value().IsLinkLocal()) + { + message.route.rtm_flags |= RTNH_F_ONLINK; + } message.route.rtm_dst_len = route.to.has_value() ? route.to.value().PrefixLength() : 0; utils::InitializeIntegerAttribute(message.tableId, m_table, RTA_TABLE); diff --git a/src/linux/netlinkutil/address.h b/src/linux/netlinkutil/address.h index 06baa88801..1119aa18ee 100644 --- a/src/linux/netlinkutil/address.h +++ b/src/linux/netlinkutil/address.h @@ -75,6 +75,7 @@ class Address int Scope() const noexcept; int PreferredLifetime() const noexcept; bool IsIpv4() const noexcept; + bool IsLinkLocal() const; bool IsPrefixRouteAutogenerationDisabled() const noexcept; private: