blob: d6338c5a9122eb97ce915570fc4031d97492a1de [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include <arpa/inet.h>
2#include <ifaddrs.h>
Ratan Gupta8ab17922017-05-25 13:07:05 +05303#include <net/if.h>
4#include <netinet/in.h>
Gunnar Mills57d9c502018-09-14 14:42:34 -05005#include <sys/socket.h>
6#include <sys/types.h>
Ratan Gupta8ab17922017-05-25 13:07:05 +05307
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -07008#include <cstring>
9#include <map>
10#include <stdexcept>
11#include <string>
12
Ratan Gupta8ab17922017-05-25 13:07:05 +053013#define MAX_IFADDRS 5
14
15int debugging = false;
16
17/* Data for mocking getifaddrs */
Gunnar Mills57d9c502018-09-14 14:42:34 -050018struct ifaddr_storage
19{
Ratan Gupta8ab17922017-05-25 13:07:05 +053020 struct ifaddrs ifaddr;
21 struct sockaddr_storage addr;
22 struct sockaddr_storage mask;
23 struct sockaddr_storage bcast;
24} mock_ifaddr_storage[MAX_IFADDRS];
25
Gunnar Mills57d9c502018-09-14 14:42:34 -050026struct ifaddrs* mock_ifaddrs = nullptr;
Ratan Gupta8ab17922017-05-25 13:07:05 +053027
28int ifaddr_count = 0;
29
30/* Stub library functions */
Gunnar Mills57d9c502018-09-14 14:42:34 -050031void freeifaddrs(ifaddrs* ifp)
Ratan Gupta8ab17922017-05-25 13:07:05 +053032{
Gunnar Mills57d9c502018-09-14 14:42:34 -050033 return;
Ratan Gupta8ab17922017-05-25 13:07:05 +053034}
35
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070036std::map<std::string, int> mock_if_nametoindex;
37std::map<int, std::string> mock_if_indextoname;
38
39void mock_addIF(const std::string& name, int idx)
40{
41 if (idx == 0)
42 {
43 throw std::invalid_argument("Bad interface index");
44 }
45
46 mock_if_nametoindex[name] = idx;
47 mock_if_indextoname[idx] = name;
48}
49
Ratan Gupta8ab17922017-05-25 13:07:05 +053050void mock_addIP(const char* name, const char* addr, const char* mask,
51 unsigned int flags)
52{
Gunnar Mills57d9c502018-09-14 14:42:34 -050053 struct ifaddrs* ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr;
Ratan Gupta8ab17922017-05-25 13:07:05 +053054
Gunnar Mills57d9c502018-09-14 14:42:34 -050055 struct sockaddr_in* in =
56 reinterpret_cast<sockaddr_in*>(&mock_ifaddr_storage[ifaddr_count].addr);
57 struct sockaddr_in* mask_in =
58 reinterpret_cast<sockaddr_in*>(&mock_ifaddr_storage[ifaddr_count].mask);
Ratan Gupta8ab17922017-05-25 13:07:05 +053059
60 in->sin_family = AF_INET;
61 in->sin_port = 0;
62 in->sin_addr.s_addr = inet_addr(addr);
63
64 mask_in->sin_family = AF_INET;
65 mask_in->sin_port = 0;
66 mask_in->sin_addr.s_addr = inet_addr(mask);
67
68 ifaddr->ifa_next = nullptr;
69 ifaddr->ifa_name = const_cast<char*>(name);
70 ifaddr->ifa_flags = flags;
71 ifaddr->ifa_addr = reinterpret_cast<struct sockaddr*>(in);
72 ifaddr->ifa_netmask = reinterpret_cast<struct sockaddr*>(mask_in);
73 ifaddr->ifa_data = nullptr;
74
75 if (ifaddr_count > 0)
76 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
77 ifaddr_count++;
78 mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
Ratan Gupta8ab17922017-05-25 13:07:05 +053079}
80
Gunnar Mills57d9c502018-09-14 14:42:34 -050081int getifaddrs(ifaddrs** ifap)
Ratan Gupta8ab17922017-05-25 13:07:05 +053082{
83 *ifap = mock_ifaddrs;
84 if (mock_ifaddrs == nullptr)
85 return -1;
86 return (0);
87}
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070088
89unsigned if_nametoindex(const char* ifname)
90{
91 auto it = mock_if_nametoindex.find(ifname);
92 if (it == mock_if_nametoindex.end())
93 {
94 errno = ENXIO;
95 return 0;
96 }
97 return it->second;
98}
99
100char* if_indextoname(unsigned ifindex, char* ifname)
101{
102 if (ifindex == 0)
103 {
104 errno = ENXIO;
105 return NULL;
106 }
107 auto it = mock_if_indextoname.find(ifindex);
108 if (it == mock_if_indextoname.end())
109 {
110 // TODO: Return ENXIO once other code is mocked out
111 return std::strcpy(ifname, "invalid");
112 }
113 return std::strcpy(ifname, it->second.c_str());
114}