network_manager: Add neighbors to undiscovered interfaces

This will make it possible to disable neighbor dumping on interface
creation.

Change-Id: I3c6ca49774730b96a33c3c36c7c425f52c5c2e2a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index bc33243..7f54f5e 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -9,7 +9,6 @@
 
 #include <fmt/compile.h>
 #include <fmt/format.h>
-#include <linux/neighbour.h>
 #include <linux/rtnetlink.h>
 #include <net/if.h>
 
@@ -207,10 +206,6 @@
 
 void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
 {
-    if ((info.state & NUD_PERMANENT) == 0)
-    {
-        return;
-    }
     if (!info.mac || !info.addr)
     {
         auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
@@ -228,7 +223,7 @@
     staticNeighbors.clear();
     for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
     {
-        addStaticNeigh(neighbor);
+        manager.addNeighbor(neighbor);
     }
 }
 
diff --git a/src/network_manager.cpp b/src/network_manager.cpp
index cdbade9..655fe5a 100644
--- a/src/network_manager.cpp
+++ b/src/network_manager.cpp
@@ -9,6 +9,7 @@
 #include "util.hpp"
 
 #include <linux/if_addr.h>
+#include <linux/neighbour.h>
 #include <net/if.h>
 
 #include <filesystem>
@@ -263,17 +264,40 @@
 
 void Manager::addNeighbor(const NeighborInfo& info)
 {
-    getIntfOrLog(interfacesByIdx, info.ifidx,
-                 [&](auto& intf) { intf.addStaticNeigh(info); });
+    if (!(info.state & NUD_PERMANENT) || !info.addr)
+    {
+        return;
+    }
+    if (auto it = interfacesByIdx.find(info.ifidx); it != interfacesByIdx.end())
+    {
+        it->second->addStaticNeigh(info);
+    }
+    else if (auto it = undiscoveredIntfInfo.find(info.ifidx);
+             it != undiscoveredIntfInfo.end())
+    {
+        it->second.staticNeighs.insert_or_assign(*info.addr, info);
+    }
+    else
+    {
+        throw std::runtime_error(
+            fmt::format("Interface `{}` not found for neigh", info.ifidx));
+    }
 }
 
 void Manager::removeNeighbor(const NeighborInfo& info)
 {
-    if (info.addr)
+    if (!info.addr)
     {
-        getIntfOrLog(interfacesByIdx, info.ifidx, [&](auto& intf) {
-            intf.staticNeighbors.erase(*info.addr);
-        });
+        return;
+    }
+    if (auto it = interfacesByIdx.find(info.ifidx); it != interfacesByIdx.end())
+    {
+        it->second->staticNeighbors.erase(*info.addr);
+    }
+    else if (auto it = undiscoveredIntfInfo.find(info.ifidx);
+             it != undiscoveredIntfInfo.end())
+    {
+        it->second.staticNeighs.erase(*info.addr);
     }
 }