1 #include "config_parser.hpp"
2 #include "ipaddress.hpp"
3 #include "mock_network_manager.hpp"
4 #include "mock_syscall.hpp"
5 #include "util.hpp"
6 
7 #include <arpa/inet.h>
8 #include <net/if.h>
9 #include <netinet/in.h>
10 #include <stdlib.h>
11 
12 #include <exception>
13 #include <fstream>
14 #include <sdbusplus/bus.hpp>
15 #include <xyz/openbmc_project/Common/error.hpp>
16 
17 #include <gtest/gtest.h>
18 
19 namespace phosphor
20 {
21 namespace network
22 {
23 
24 class TestEthernetInterface : public testing::Test
25 {
26   public:
27     sdbusplus::bus::bus bus;
28     MockManager manager;
29     MockEthernetInterface interface;
30     std::string confDir;
31     TestEthernetInterface() :
32         bus(sdbusplus::bus::new_default()),
33         manager(bus, "/xyz/openbmc_test/network", "/tmp/"),
34         interface(makeInterface(bus, manager))
35 
36     {
37         setConfDir();
38     }
39 
40     void setConfDir()
41     {
42         char tmp[] = "/tmp/EthernetInterface.XXXXXX";
43         confDir = mkdtemp(tmp);
44         manager.setConfDir(confDir);
45     }
46 
47     ~TestEthernetInterface()
48     {
49         if (confDir != "")
50         {
51             fs::remove_all(confDir);
52         }
53     }
54 
55     static constexpr ether_addr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
56 
57     static MockEthernetInterface makeInterface(sdbusplus::bus::bus& bus,
58                                                MockManager& manager)
59     {
60         mock_clear();
61         mock_addIF("test0", 1, mac);
62         return {bus, "/xyz/openbmc_test/network/test0",
63                 EthernetInterface::DHCPConf::none, manager, true};
64     }
65 
66     int countIPObjects()
67     {
68         return interface.getAddresses().size();
69     }
70 
71     bool isIPObjectExist(const std::string& ipaddress)
72     {
73         auto address = interface.getAddresses().find(ipaddress);
74         if (address == interface.getAddresses().end())
75         {
76             return false;
77         }
78         return true;
79     }
80 
81     bool deleteIPObject(const std::string& ipaddress)
82     {
83         auto address = interface.getAddresses().find(ipaddress);
84         if (address == interface.getAddresses().end())
85         {
86             return false;
87         }
88         address->second->delete_();
89         return true;
90     }
91 
92     std::string getObjectPath(const std::string& ipaddress, uint8_t subnetMask,
93                               const std::string& gateway,
94                               IP::AddressOrigin origin)
95     {
96         IP::Protocol addressType = IP::Protocol::IPv4;
97 
98         return interface.generateObjectPath(addressType, ipaddress, subnetMask,
99                                             gateway, origin);
100     }
101 
102     void createIPObject(IP::Protocol addressType, const std::string& ipaddress,
103                         uint8_t subnetMask, const std::string& gateway)
104     {
105         interface.ip(addressType, ipaddress, subnetMask, gateway);
106     }
107 };
108 
109 TEST_F(TestEthernetInterface, NoIPaddress)
110 {
111     EXPECT_EQ(countIPObjects(), 0);
112     EXPECT_EQ(mac_address::toString(mac), interface.macAddress());
113 }
114 
115 TEST_F(TestEthernetInterface, AddIPAddress)
116 {
117     IP::Protocol addressType = IP::Protocol::IPv4;
118     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
119     EXPECT_EQ(true, isIPObjectExist("10.10.10.10"));
120 }
121 
122 TEST_F(TestEthernetInterface, AddMultipleAddress)
123 {
124     IP::Protocol addressType = IP::Protocol::IPv4;
125     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
126     createIPObject(addressType, "20.20.20.20", 16, "20.20.20.1");
127     EXPECT_EQ(true, isIPObjectExist("10.10.10.10"));
128     EXPECT_EQ(true, isIPObjectExist("20.20.20.20"));
129 }
130 
131 TEST_F(TestEthernetInterface, DeleteIPAddress)
132 {
133     IP::Protocol addressType = IP::Protocol::IPv4;
134     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
135     createIPObject(addressType, "20.20.20.20", 16, "20.20.20.1");
136     deleteIPObject("10.10.10.10");
137     EXPECT_EQ(false, isIPObjectExist("10.10.10.10"));
138     EXPECT_EQ(true, isIPObjectExist("20.20.20.20"));
139 }
140 
141 TEST_F(TestEthernetInterface, DeleteInvalidIPAddress)
142 {
143     EXPECT_EQ(false, deleteIPObject("10.10.10.10"));
144 }
145 
146 TEST_F(TestEthernetInterface, CheckObjectPath)
147 {
148     std::string ipaddress = "10.10.10.10";
149     uint8_t prefix = 16;
150     std::string gateway = "10.10.10.1";
151     IP::AddressOrigin origin = IP::AddressOrigin::Static;
152 
153     std::string expectedObjectPath = "/xyz/openbmc_test/network/test0/ipv4/";
154     std::stringstream hexId;
155 
156     std::string hashString = ipaddress;
157     hashString += std::to_string(prefix);
158     hashString += gateway;
159     hashString += convertForMessage(origin);
160 
161     hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
162     expectedObjectPath += hexId.str();
163 
164     EXPECT_EQ(expectedObjectPath,
165               getObjectPath(ipaddress, prefix, gateway, origin));
166 
167     origin = IP::AddressOrigin::DHCP;
168     EXPECT_NE(expectedObjectPath,
169               getObjectPath(ipaddress, prefix, gateway, origin));
170 }
171 
172 TEST_F(TestEthernetInterface, addStaticNameServers)
173 {
174     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
175     EXPECT_CALL(manager, reloadConfigs());
176     interface.staticNameServers(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 
186 TEST_F(TestEthernetInterface, addDynamicNameServers)
187 {
188     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
189     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
190     EXPECT_THROW(interface.nameservers(servers), NotAllowed);
191 }
192 
193 TEST_F(TestEthernetInterface, getDynamicNameServers)
194 {
195     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
196     EXPECT_CALL(interface, getNameServerFromResolvd())
197         .WillRepeatedly(testing::Return(servers));
198     EXPECT_EQ(interface.getNameServerFromResolvd(), servers);
199 }
200 
201 TEST_F(TestEthernetInterface, addNTPServers)
202 {
203     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
204     EXPECT_CALL(manager, reloadConfigs());
205     interface.ntpServers(servers);
206     fs::path filePath = confDir;
207     filePath /= "00-bmc-test0.network";
208     config::Parser parser(filePath.string());
209     config::ReturnCode rc = config::ReturnCode::SUCCESS;
210     config::ValueList values;
211     std::tie(rc, values) = parser.getValues("Network", "NTP");
212     EXPECT_EQ(servers, values);
213 }
214 
215 TEST_F(TestEthernetInterface, addGateway)
216 {
217     std::string gateway = "10.3.3.3";
218     interface.defaultGateway(gateway);
219     EXPECT_EQ(interface.defaultGateway(), gateway);
220     interface.defaultGateway("");
221     EXPECT_EQ(interface.defaultGateway(), "");
222 }
223 
224 TEST_F(TestEthernetInterface, addGateway6)
225 {
226     std::string gateway6 = "ffff:ffff:ffff:fe80::1";
227     interface.defaultGateway6(gateway6);
228     EXPECT_EQ(interface.defaultGateway6(), gateway6);
229     interface.defaultGateway6("");
230     EXPECT_EQ(interface.defaultGateway6(), "");
231 }
232 
233 } // namespace network
234 } // namespace phosphor
235