test/ethernet_interface: Improve syscall test coverage

Change-Id: Ia71a030f2e2e19f2cc191992929ef08d0fa917c2
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/mock_syscall.cpp b/test/mock_syscall.cpp
index e4101a3..349a79a 100644
--- a/test/mock_syscall.cpp
+++ b/test/mock_syscall.cpp
@@ -49,34 +49,40 @@
 
 std::map<int, std::queue<std::string>> mock_rtnetlinks;
 
-std::map<std::string, int> mock_if_nametoindex;
+struct MockInfo
+{
+    unsigned idx;
+    unsigned flags;
+    std::optional<ether_addr> mac;
+    std::optional<unsigned> mtu;
+};
+
+std::map<std::string, MockInfo> mock_if;
 std::map<int, std::string> mock_if_indextoname;
-std::map<std::string, ether_addr> mock_macs;
 
 void mock_clear()
 {
     mock_ifaddrs = nullptr;
     ifaddr_count = 0;
     mock_rtnetlinks.clear();
-    mock_if_nametoindex.clear();
+    mock_if.clear();
     mock_if_indextoname.clear();
-    mock_macs.clear();
 }
 
-void mock_addIF(const std::string& name, int idx, const ether_addr& mac)
+void mock_addIF(const std::string& name, unsigned idx, unsigned flags,
+                std::optional<ether_addr> mac, std::optional<unsigned> mtu)
 {
     if (idx == 0)
     {
         throw std::invalid_argument("Bad interface index");
     }
 
-    mock_if_nametoindex[name] = idx;
-    mock_if_indextoname[idx] = name;
-    mock_macs[name] = mac;
+    mock_if.emplace(
+        name, MockInfo{.idx = idx, .flags = flags, .mac = mac, .mtu = mtu});
+    mock_if_indextoname.emplace(idx, name);
 }
 
-void mock_addIP(const char* name, const char* addr, const char* mask,
-                unsigned int flags)
+void mock_addIP(const char* name, const char* addr, const char* mask)
 {
     struct ifaddrs* ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr;
 
@@ -95,7 +101,7 @@
 
     ifaddr->ifa_next = nullptr;
     ifaddr->ifa_name = const_cast<char*>(name);
-    ifaddr->ifa_flags = flags;
+    ifaddr->ifa_flags = 0;
     ifaddr->ifa_addr = reinterpret_cast<struct sockaddr*>(in);
     ifaddr->ifa_netmask = reinterpret_cast<struct sockaddr*>(mask_in);
     ifaddr->ifa_data = nullptr;
@@ -135,10 +141,11 @@
         return 0;
     }
 
-    for (const auto& [name, idx] : mock_if_nametoindex)
+    for (const auto& [name, i] : mock_if)
     {
         ifinfomsg info{};
-        info.ifi_index = idx;
+        info.ifi_index = i.idx;
+        info.ifi_flags = i.flags;
         nlmsghdr hdr{};
         hdr.nlmsg_len = NLMSG_LENGTH(sizeof(info));
         hdr.nlmsg_type = RTM_NEWLINK;
@@ -181,13 +188,13 @@
 
 unsigned if_nametoindex(const char* ifname)
 {
-    auto it = mock_if_nametoindex.find(ifname);
-    if (it == mock_if_nametoindex.end())
+    auto it = mock_if.find(ifname);
+    if (it == mock_if.end())
     {
         errno = ENXIO;
         return 0;
     }
-    return it->second;
+    return it->second.idx;
 }
 
 char* if_indextoname(unsigned ifindex, char* ifname)
@@ -208,16 +215,49 @@
     void* data = va_arg(vl, void*);
     va_end(vl);
 
+    auto req = reinterpret_cast<ifreq*>(data);
     if (request == SIOCGIFHWADDR)
     {
-        auto req = reinterpret_cast<ifreq*>(data);
-        auto it = mock_macs.find(req->ifr_name);
-        if (it == mock_macs.end())
+        auto it = mock_if.find(req->ifr_name);
+        if (it == mock_if.end())
         {
             errno = ENXIO;
             return -1;
         }
-        std::memcpy(req->ifr_hwaddr.sa_data, &it->second, sizeof(it->second));
+        if (!it->second.mac)
+        {
+            errno = EOPNOTSUPP;
+            return -1;
+        }
+        std::memcpy(req->ifr_hwaddr.sa_data, &*it->second.mac,
+                    sizeof(*it->second.mac));
+        return 0;
+    }
+    else if (request == SIOCGIFFLAGS)
+    {
+        auto it = mock_if.find(req->ifr_name);
+        if (it == mock_if.end())
+        {
+            errno = ENXIO;
+            return -1;
+        }
+        req->ifr_flags = it->second.flags;
+        return 0;
+    }
+    else if (request == SIOCGIFMTU)
+    {
+        auto it = mock_if.find(req->ifr_name);
+        if (it == mock_if.end())
+        {
+            errno = ENXIO;
+            return -1;
+        }
+        if (!it->second.mtu)
+        {
+            errno = EOPNOTSUPP;
+            return -1;
+        }
+        req->ifr_mtu = *it->second.mtu;
         return 0;
     }