Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 1 | #include <arpa/inet.h> |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 2 | #include <dlfcn.h> |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 3 | #include <ifaddrs.h> |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 4 | #include <net/ethernet.h> |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 5 | #include <net/if.h> |
| 6 | #include <netinet/in.h> |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 7 | #include <sys/ioctl.h> |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 8 | #include <sys/socket.h> |
| 9 | #include <sys/types.h> |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 10 | |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 11 | #include <cstdarg> |
William A. Kennington III | ebb1ad0 | 2019-04-21 18:02:49 -0700 | [diff] [blame] | 12 | #include <cstring> |
| 13 | #include <map> |
| 14 | #include <stdexcept> |
| 15 | #include <string> |
| 16 | |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 17 | #define MAX_IFADDRS 5 |
| 18 | |
| 19 | int debugging = false; |
| 20 | |
| 21 | /* Data for mocking getifaddrs */ |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 22 | struct ifaddr_storage |
| 23 | { |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 24 | struct ifaddrs ifaddr; |
| 25 | struct sockaddr_storage addr; |
| 26 | struct sockaddr_storage mask; |
| 27 | struct sockaddr_storage bcast; |
| 28 | } mock_ifaddr_storage[MAX_IFADDRS]; |
| 29 | |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 30 | struct ifaddrs* mock_ifaddrs = nullptr; |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 31 | |
| 32 | int ifaddr_count = 0; |
| 33 | |
| 34 | /* Stub library functions */ |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 35 | void freeifaddrs(ifaddrs* ifp) |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 36 | { |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 37 | return; |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 38 | } |
| 39 | |
William A. Kennington III | ebb1ad0 | 2019-04-21 18:02:49 -0700 | [diff] [blame] | 40 | std::map<std::string, int> mock_if_nametoindex; |
| 41 | std::map<int, std::string> mock_if_indextoname; |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 42 | std::map<std::string, ether_addr> mock_macs; |
William A. Kennington III | ebb1ad0 | 2019-04-21 18:02:49 -0700 | [diff] [blame] | 43 | |
William A. Kennington III | 862275a | 2019-04-22 20:37:08 -0700 | [diff] [blame^] | 44 | void mock_clear() |
| 45 | { |
| 46 | mock_ifaddrs = nullptr; |
| 47 | ifaddr_count = 0; |
| 48 | mock_if_nametoindex.clear(); |
| 49 | mock_if_indextoname.clear(); |
| 50 | mock_macs.clear(); |
| 51 | } |
| 52 | |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 53 | void mock_addIF(const std::string& name, int idx, const ether_addr& mac) |
William A. Kennington III | ebb1ad0 | 2019-04-21 18:02:49 -0700 | [diff] [blame] | 54 | { |
| 55 | if (idx == 0) |
| 56 | { |
| 57 | throw std::invalid_argument("Bad interface index"); |
| 58 | } |
| 59 | |
| 60 | mock_if_nametoindex[name] = idx; |
| 61 | mock_if_indextoname[idx] = name; |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 62 | mock_macs[name] = mac; |
William A. Kennington III | ebb1ad0 | 2019-04-21 18:02:49 -0700 | [diff] [blame] | 63 | } |
| 64 | |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 65 | void mock_addIP(const char* name, const char* addr, const char* mask, |
| 66 | unsigned int flags) |
| 67 | { |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 68 | struct ifaddrs* ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr; |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 69 | |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 70 | struct sockaddr_in* in = |
| 71 | reinterpret_cast<sockaddr_in*>(&mock_ifaddr_storage[ifaddr_count].addr); |
| 72 | struct sockaddr_in* mask_in = |
| 73 | reinterpret_cast<sockaddr_in*>(&mock_ifaddr_storage[ifaddr_count].mask); |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 74 | |
| 75 | in->sin_family = AF_INET; |
| 76 | in->sin_port = 0; |
| 77 | in->sin_addr.s_addr = inet_addr(addr); |
| 78 | |
| 79 | mask_in->sin_family = AF_INET; |
| 80 | mask_in->sin_port = 0; |
| 81 | mask_in->sin_addr.s_addr = inet_addr(mask); |
| 82 | |
| 83 | ifaddr->ifa_next = nullptr; |
| 84 | ifaddr->ifa_name = const_cast<char*>(name); |
| 85 | ifaddr->ifa_flags = flags; |
| 86 | ifaddr->ifa_addr = reinterpret_cast<struct sockaddr*>(in); |
| 87 | ifaddr->ifa_netmask = reinterpret_cast<struct sockaddr*>(mask_in); |
| 88 | ifaddr->ifa_data = nullptr; |
| 89 | |
| 90 | if (ifaddr_count > 0) |
| 91 | mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr; |
| 92 | ifaddr_count++; |
| 93 | mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr; |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 94 | } |
| 95 | |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 96 | extern "C" { |
| 97 | |
Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 98 | int getifaddrs(ifaddrs** ifap) |
Ratan Gupta | 8ab1792 | 2017-05-25 13:07:05 +0530 | [diff] [blame] | 99 | { |
| 100 | *ifap = mock_ifaddrs; |
| 101 | if (mock_ifaddrs == nullptr) |
| 102 | return -1; |
| 103 | return (0); |
| 104 | } |
William A. Kennington III | ebb1ad0 | 2019-04-21 18:02:49 -0700 | [diff] [blame] | 105 | |
| 106 | unsigned if_nametoindex(const char* ifname) |
| 107 | { |
| 108 | auto it = mock_if_nametoindex.find(ifname); |
| 109 | if (it == mock_if_nametoindex.end()) |
| 110 | { |
| 111 | errno = ENXIO; |
| 112 | return 0; |
| 113 | } |
| 114 | return it->second; |
| 115 | } |
| 116 | |
| 117 | char* if_indextoname(unsigned ifindex, char* ifname) |
| 118 | { |
| 119 | if (ifindex == 0) |
| 120 | { |
| 121 | errno = ENXIO; |
| 122 | return NULL; |
| 123 | } |
| 124 | auto it = mock_if_indextoname.find(ifindex); |
| 125 | if (it == mock_if_indextoname.end()) |
| 126 | { |
| 127 | // TODO: Return ENXIO once other code is mocked out |
| 128 | return std::strcpy(ifname, "invalid"); |
| 129 | } |
| 130 | return std::strcpy(ifname, it->second.c_str()); |
| 131 | } |
William A. Kennington III | cb64b99 | 2019-04-21 18:45:07 -0700 | [diff] [blame] | 132 | |
| 133 | int ioctl(int fd, unsigned long int request, ...) |
| 134 | { |
| 135 | va_list vl; |
| 136 | va_start(vl, request); |
| 137 | void* data = va_arg(vl, void*); |
| 138 | va_end(vl); |
| 139 | |
| 140 | if (request == SIOCGIFHWADDR) |
| 141 | { |
| 142 | auto req = reinterpret_cast<ifreq*>(data); |
| 143 | auto it = mock_macs.find(req->ifr_name); |
| 144 | if (it == mock_macs.end()) |
| 145 | { |
| 146 | errno = ENXIO; |
| 147 | return -1; |
| 148 | } |
| 149 | std::memcpy(req->ifr_hwaddr.sa_data, &it->second, sizeof(it->second)); |
| 150 | return 0; |
| 151 | } |
| 152 | |
| 153 | static auto real_ioctl = |
| 154 | reinterpret_cast<decltype(&ioctl)>(dlsym(RTLD_NEXT, "ioctl")); |
| 155 | return real_ioctl(fd, request, data); |
| 156 | } |
| 157 | |
| 158 | } // extern "C" |