1 #include "config_parser.hpp"
2 #include "ipaddress.hpp"
3 #include "mock_syscall.hpp"
4 #include "network_manager.hpp"
5 
6 #include <arpa/inet.h>
7 #include <net/if.h>
8 #include <netinet/in.h>
9 #include <stdlib.h>
10 
11 #include <exception>
12 #include <fstream>
13 #include <sdbusplus/bus.hpp>
14 
15 #include <gtest/gtest.h>
16 
17 namespace phosphor
18 {
19 namespace network
20 {
21 
22 class TestEthernetInterface : public testing::Test
23 {
24   public:
25     sdbusplus::bus::bus bus;
26     Manager manager;
27     EthernetInterface interface;
28     std::string confDir;
29     TestEthernetInterface() :
30         bus(sdbusplus::bus::new_default()),
31         manager(bus, "/xyz/openbmc_test/network", "/tmp/"),
32         interface(bus, "/xyz/openbmc_test/network/test0", false, manager)
33 
34     {
35         setConfDir();
36     }
37 
38     void setConfDir()
39     {
40         char tmp[] = "/tmp/EthernetInterface.XXXXXX";
41         confDir = mkdtemp(tmp);
42         manager.setConfDir(confDir);
43     }
44 
45     ~TestEthernetInterface()
46     {
47         if (confDir != "")
48         {
49             fs::remove_all(confDir);
50         }
51     }
52 
53     int countIPObjects()
54     {
55         return interface.getAddresses().size();
56     }
57 
58     bool isIPObjectExist(const std::string& ipaddress)
59     {
60         auto address = interface.getAddresses().find(ipaddress);
61         if (address == interface.getAddresses().end())
62         {
63             return false;
64         }
65         return true;
66     }
67 
68     bool deleteIPObject(const std::string& ipaddress)
69     {
70         auto address = interface.getAddresses().find(ipaddress);
71         if (address == interface.getAddresses().end())
72         {
73             return false;
74         }
75         address->second->delete_();
76         return true;
77     }
78 
79     std::string getObjectPath(const std::string& ipaddress, uint8_t subnetMask,
80                               const std::string& gateway)
81     {
82         IP::Protocol addressType = IP::Protocol::IPv4;
83 
84         return interface.generateObjectPath(addressType, ipaddress, subnetMask,
85                                             gateway);
86     }
87 
88     void createIPObject(IP::Protocol addressType, const std::string& ipaddress,
89                         uint8_t subnetMask, const std::string& gateway)
90     {
91         interface.iP(addressType, ipaddress, subnetMask, gateway);
92     }
93 
94     // Validates if the DNS entries have been correctly processed
95     void validateResolvFile(ServerList values)
96     {
97         // Check whether the entries has been written to resolv.conf
98         fs::path resolvFile = confDir;
99         resolvFile /= "resolv.conf";
100 
101         // Passed in "value" is what is read from the config file
102         interface.writeDNSEntries(values, resolvFile);
103         std::string expectedServers =
104             "### Generated manually via dbus settings ###";
105         expectedServers +=
106             "nameserver 9.1.1.1nameserver 9.2.2.2nameserver 9.3.3.3";
107 
108         std::string actualServers{};
109         std::fstream stream(resolvFile.string().c_str(), std::fstream::in);
110         for (std::string line; std::getline(stream, line);)
111         {
112             actualServers += line;
113         }
114         EXPECT_EQ(expectedServers, actualServers);
115     }
116 };
117 
118 TEST_F(TestEthernetInterface, NoIPaddress)
119 {
120     EXPECT_EQ(countIPObjects(), 0);
121 }
122 
123 TEST_F(TestEthernetInterface, AddIPAddress)
124 {
125     IP::Protocol addressType = IP::Protocol::IPv4;
126     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
127     EXPECT_EQ(true, isIPObjectExist("10.10.10.10"));
128 }
129 
130 TEST_F(TestEthernetInterface, AddMultipleAddress)
131 {
132     IP::Protocol addressType = IP::Protocol::IPv4;
133     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
134     createIPObject(addressType, "20.20.20.20", 16, "20.20.20.1");
135     EXPECT_EQ(true, isIPObjectExist("10.10.10.10"));
136     EXPECT_EQ(true, isIPObjectExist("20.20.20.20"));
137 }
138 
139 TEST_F(TestEthernetInterface, DeleteIPAddress)
140 {
141     IP::Protocol addressType = IP::Protocol::IPv4;
142     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
143     createIPObject(addressType, "20.20.20.20", 16, "20.20.20.1");
144     deleteIPObject("10.10.10.10");
145     EXPECT_EQ(false, isIPObjectExist("10.10.10.10"));
146     EXPECT_EQ(true, isIPObjectExist("20.20.20.20"));
147 }
148 
149 TEST_F(TestEthernetInterface, DeleteInvalidIPAddress)
150 {
151     EXPECT_EQ(false, deleteIPObject("10.10.10.10"));
152 }
153 
154 TEST_F(TestEthernetInterface, CheckObjectPath)
155 {
156     std::string ipaddress = "10.10.10.10";
157     uint8_t prefix = 16;
158     std::string gateway = "10.10.10.1";
159 
160     std::string expectedObjectPath = "/xyz/openbmc_test/network/test0/ipv4/";
161     std::stringstream hexId;
162 
163     std::string hashString = ipaddress;
164     hashString += std::to_string(prefix);
165     hashString += gateway;
166 
167     hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
168     expectedObjectPath += hexId.str();
169 
170     EXPECT_EQ(expectedObjectPath, getObjectPath(ipaddress, prefix, gateway));
171 }
172 
173 TEST_F(TestEthernetInterface, addNameServers)
174 {
175     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
176     interface.nameservers(servers);
177     fs::path filePath = confDir;
178     filePath /= "00-bmc-test0.network";
179     config::Parser parser(filePath.string());
180     config::ReturnCode rc = config::ReturnCode::SUCCESS;
181     config::ValueList values;
182     std::tie(rc, values) = parser.getValues("Network", "DNS");
183     EXPECT_EQ(servers, values);
184 
185     validateResolvFile(values);
186 }
187 
188 TEST_F(TestEthernetInterface, addNTPServers)
189 {
190     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
191     interface.nTPServers(servers);
192     fs::path filePath = confDir;
193     filePath /= "00-bmc-test0.network";
194     config::Parser parser(filePath.string());
195     config::ReturnCode rc = config::ReturnCode::SUCCESS;
196     config::ValueList values;
197     std::tie(rc, values) = parser.getValues("Network", "NTP");
198     EXPECT_EQ(servers, values);
199 }
200 
201 } // namespace network
202 } // namespace phosphor
203