patchpanel: track interface index in ShillClient::Device

This patch is the first step in a more consistent strategy for creating
and cleaning any state associated with interface indexes.

This patch centralizes the interface name -> interface index map into
the System class and updateds ShillClient to pass the interface index of
into ShillClient::Device structs.

A follow-up patch will pass the interface index down to the various
subprocesses like ndproxy and multicast_forwader.

/var/log/net.log example:

INFO patchpaneld[1942]: INFO patchpaneld: [shill_client.cc(211)] Default
  physical device changed from {ifname: eth0, ifindex: 2, type: Ethernet,
  service: /service/2} to {ifname: rmnet_data0, ifindex: 4, type:
  Cellular, service: /service/5}

BUG=b:225282717
TEST=FEATURES=test emerge-$BOARD patchpanel

Change-Id: I5322a24225baabe961f5c57e45a965c6ba9f0728
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3534488
Reviewed-by: Taoyu Li <taoyl@chromium.org>
Commit-Queue: Hugo Benichi <hugobenichi@google.com>
Tested-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/system.cc b/patchpanel/system.cc
index e3cc04f..fb4b773e 100644
--- a/patchpanel/system.cc
+++ b/patchpanel/system.cc
@@ -5,6 +5,7 @@
 #include "patchpanel/system.h"
 
 #include <fcntl.h>
+#include <net/if.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -101,6 +102,29 @@
   }
 }
 
+std::string System::IfIndextoname(int ifindex) {
+  char ifname[IFNAMSIZ];
+  if (if_indextoname(ifindex, ifname) == nullptr) {
+    return "";
+  }
+  return ifname;
+}
+
+uint32_t System::IfNametoindex(const std::string& ifname) {
+  uint32_t ifindex = if_nametoindex(ifname.c_str());
+  if (ifindex > 0) {
+    if_nametoindex_[ifname] = ifindex;
+    return ifindex;
+  }
+
+  const auto it = if_nametoindex_.find(ifname);
+  if (it != if_nametoindex_.end())
+    return it->second;
+
+  return 0;
+}
+
+// static
 bool System::Write(const std::string& path, const std::string& content) {
   base::ScopedFD fd(open(path.c_str(), O_WRONLY | O_TRUNC | O_CLOEXEC));
   if (!fd.is_valid()) {