test: Mock out MAC address access
This makes it possible for our ethernet interfaces to have MAC Addresses
detected and configured for testing without the system providing a real
NIC.
Change-Id: Ie985efec0a5e393b0b76f3d02bd3015fef6349e4
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/mock_syscall.cpp b/test/mock_syscall.cpp
index d6338c5..3f96e1d 100644
--- a/test/mock_syscall.cpp
+++ b/test/mock_syscall.cpp
@@ -1,10 +1,14 @@
#include <arpa/inet.h>
+#include <dlfcn.h>
#include <ifaddrs.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <cstdarg>
#include <cstring>
#include <map>
#include <stdexcept>
@@ -35,8 +39,9 @@
std::map<std::string, int> mock_if_nametoindex;
std::map<int, std::string> mock_if_indextoname;
+std::map<std::string, ether_addr> mock_macs;
-void mock_addIF(const std::string& name, int idx)
+void mock_addIF(const std::string& name, int idx, const ether_addr& mac)
{
if (idx == 0)
{
@@ -45,6 +50,7 @@
mock_if_nametoindex[name] = idx;
mock_if_indextoname[idx] = name;
+ mock_macs[name] = mac;
}
void mock_addIP(const char* name, const char* addr, const char* mask,
@@ -78,6 +84,8 @@
mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
}
+extern "C" {
+
int getifaddrs(ifaddrs** ifap)
{
*ifap = mock_ifaddrs;
@@ -112,3 +120,30 @@
}
return std::strcpy(ifname, it->second.c_str());
}
+
+int ioctl(int fd, unsigned long int request, ...)
+{
+ va_list vl;
+ va_start(vl, request);
+ void* data = va_arg(vl, void*);
+ va_end(vl);
+
+ if (request == SIOCGIFHWADDR)
+ {
+ auto req = reinterpret_cast<ifreq*>(data);
+ auto it = mock_macs.find(req->ifr_name);
+ if (it == mock_macs.end())
+ {
+ errno = ENXIO;
+ return -1;
+ }
+ std::memcpy(req->ifr_hwaddr.sa_data, &it->second, sizeof(it->second));
+ return 0;
+ }
+
+ static auto real_ioctl =
+ reinterpret_cast<decltype(&ioctl)>(dlsym(RTLD_NEXT, "ioctl"));
+ return real_ioctl(fd, request, data);
+}
+
+} // extern "C"