diff --git a/bsd/sys/net/routecache.hh b/bsd/sys/net/routecache.hh index 0c5c1f40bc..bdcdf4964f 100644 --- a/bsd/sys/net/routecache.hh +++ b/bsd/sys/net/routecache.hh @@ -44,17 +44,9 @@ #ifndef INCLUDED_ROUTECACHE_HH #define INCLUDED_ROUTECACHE_HH -// FIXME: probably most of these includes are unnecessary #include -#include -#include -#include -#include -#include #include -#include #include - #include #include @@ -88,6 +80,10 @@ public: #endif return *this; } + + bool is_loopback(void) const { + return (rt_ifp && (rt_ifp->if_flags & IFF_LOOPBACK)) ? true : false; + } }; // Silly routing table implementation, allowing search given address in list @@ -116,10 +112,35 @@ public: } entries.emplace_front(a, n, r); } + // address should be in host order + bool is_loopback_net(u32 address) const { + return ((address >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) ? true : false; + } nonlockable_rtentry *search(u32 address) { for (silly_rtable_entry &e : entries) { - if ((e.address & e.netmask) == (address & e.netmask)) { - return &e.rte; + if (e.rte.is_loopback() == false) { + // The interface associated with this entry is non-loopback + // so it is enough to compare the networks of the addresses + if ((e.address & e.netmask) == (address & e.netmask)) { + return &e.rte; + } + } else { + // Given the interface associated with this entry is a loopback one, + // consider addresses like 127.0.0.1 or 127.0.0.2 as a match + if (is_loopback_net(address)) { + return &e.rte; + } + // Otherwise, we shouldn't use this entry on IP addresses just because they're + // on the same network as our non-loopback address. So match the entire + // address. + // This would handle a case when this route entry was added + // when looking up a non-loopback address like 192.168.122.15 but + // "converted" or handled as loopback as part of an optimization. + // The good practical example is an app like golang-httpclient + // which calls httpserver-api listening on 192.168.122.15 + if (e.address == address) { + return &e.rte; + } } } return nullptr;