blob: 24f35689eeb2d328f445bee62a55132bdde1e674 [file] [log] [blame]
Ratan Gupta6811f822017-04-14 16:34:56 +05301#include "config.h"
Ratan Gupta34f96d62017-06-15 09:16:22 +05302#include "config_parser.hpp"
Ratan Gupta3681a502017-06-17 19:20:04 +05303#include "util.hpp"
Ratan Gupta6811f822017-04-14 16:34:56 +05304#include "network_manager.hpp"
Michael Tritz29f2fd62017-05-22 15:27:26 -05005#include "network_config.hpp"
Ratan Gupta5978dd12017-07-25 13:47:13 +05306#include "ipaddress.hpp"
Ratan Gupta44ae86e2017-05-15 21:52:14 +05307#include "xyz/openbmc_project/Common/error.hpp"
Ratan Gupta6811f822017-04-14 16:34:56 +05308
9#include <phosphor-logging/log.hpp>
Ratan Gupta44ae86e2017-05-15 21:52:14 +053010#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta6811f822017-04-14 16:34:56 +053011
12#include <algorithm>
Ratan Gupta738a67f2017-04-21 10:38:05 +053013#include <bitset>
Ratan Gupta738a67f2017-04-21 10:38:05 +053014#include <map>
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053015#include <fstream>
Ratan Gupta738a67f2017-04-21 10:38:05 +053016
Ratan Gupta6811f822017-04-14 16:34:56 +053017#include <arpa/inet.h>
18#include <dirent.h>
19#include <net/if.h>
20
Michael Tritz29f2fd62017-05-22 15:27:26 -050021#include <string>
Ratan Gupta6811f822017-04-14 16:34:56 +053022
23namespace phosphor
24{
25namespace network
26{
Ratan Gupta82549cc2017-04-21 08:45:23 +053027
Ratan Gupta6811f822017-04-14 16:34:56 +053028using namespace phosphor::logging;
Ratan Guptaef85eb92017-06-15 08:57:54 +053029using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta6811f822017-04-14 16:34:56 +053030
Ratan Gupta255d5142017-08-10 09:02:08 +053031Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath,
32 const std::string& path):
Ratan Gupta29b0e432017-05-25 12:51:40 +053033 details::VLANCreateIface(bus, objPath, true),
34 bus(bus),
35 objectPath(objPath)
Ratan Gupta6811f822017-04-14 16:34:56 +053036{
Ratan Gupta255d5142017-08-10 09:02:08 +053037 fs::path confDir(path);
38 setConfDir(confDir);
Ratan Guptaef85eb92017-06-15 08:57:54 +053039}
40
41void Manager::setConfDir(const fs::path& dir)
42{
43 confDir = dir;
Ratan Gupta255d5142017-08-10 09:02:08 +053044
45 if (!fs::exists(confDir))
46 {
47 if (!fs::create_directories(confDir))
48 {
49 log<level::ERR>("Unable to create the network conf dir",
50 entry("DIR=%s", confDir.c_str()));
51 elog<InternalFailure>();
52 }
53 }
54
Ratan Gupta29b0e432017-05-25 12:51:40 +053055}
56
57void Manager::createInterfaces()
58{
Ratan Guptaef85eb92017-06-15 08:57:54 +053059 //clear all the interfaces first
60 interfaces.clear();
Ratan Gupta29b0e432017-05-25 12:51:40 +053061
Ratan Gupta82549cc2017-04-21 08:45:23 +053062 auto interfaceInfoList = getInterfaceAddrs();
Ratan Gupta6811f822017-04-14 16:34:56 +053063
Ratan Gupta738a67f2017-04-21 10:38:05 +053064 for (const auto& intfInfo : interfaceInfoList)
Ratan Gupta6811f822017-04-14 16:34:56 +053065 {
Ratan Gupta29b0e432017-05-25 12:51:40 +053066 fs::path objPath = objectPath;
67 objPath /= intfInfo.first;
Ratan Gupta6811f822017-04-14 16:34:56 +053068
Ratan Gupta34f96d62017-06-15 09:16:22 +053069 auto dhcp = getDHCPValue(intfInfo.first);
70
Ratan Gupta6811f822017-04-14 16:34:56 +053071 this->interfaces.emplace(std::make_pair(
Ratan Gupta738a67f2017-04-21 10:38:05 +053072 intfInfo.first,
73 std::make_unique<
74 phosphor::network::EthernetInterface>
75 (bus,
Ratan Gupta29b0e432017-05-25 12:51:40 +053076 objPath.string(),
Ratan Gupta34f96d62017-06-15 09:16:22 +053077 dhcp,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053078 *this)));
Ratan Gupta29b0e432017-05-25 12:51:40 +053079
Ratan Gupta6811f822017-04-14 16:34:56 +053080 }
Ratan Gupta87c13982017-06-15 09:27:27 +053081
Ratan Gupta6811f822017-04-14 16:34:56 +053082}
83
Ratan Guptaef85eb92017-06-15 08:57:54 +053084void Manager::createChildObjects()
85{
86 // creates the ethernet interface dbus object.
87 createInterfaces();
88 // create the system conf object.
89 fs::path objPath = objectPath;
90 objPath /= "config";
91 systemConf = std::make_unique<phosphor::network::SystemConfiguration>(
92 bus, objPath.string(), *this);
Ratan Guptad16f88c2017-07-11 17:47:57 +053093 // create the dhcp conf object.
94 objPath /= "dhcp";
95 dhcpConf = std::make_unique<phosphor::network::dhcp::Configuration>(
96 bus, objPath.string(), *this);
Ratan Guptaef85eb92017-06-15 08:57:54 +053097
98}
99
Ratan Gupta584df832017-07-31 16:21:54 +0530100void Manager::vLAN(IntfName interfaceName, uint32_t id)
Ratan Gupta6811f822017-04-14 16:34:56 +0530101{
Ratan Gupta5978dd12017-07-25 13:47:13 +0530102 auto& intf = interfaces[interfaceName];
103 intf->createVLAN(id);
104 writeToConfigurationFile();
Ratan Gupta6811f822017-04-14 16:34:56 +0530105}
106
Michael Tritz29f2fd62017-05-22 15:27:26 -0500107void Manager::reset()
108{
109 const std::string networkConfig = "/etc/systemd/network/";
110 bool filesExist, interfacesMapped = false;
111
112 if(fs::is_directory(networkConfig))
113 {
114 for(auto& file : fs::directory_iterator(networkConfig))
115 {
116 std::string filename = file.path().filename().c_str();
117
118 if(filename.substr(filename.find_last_of(".") + 1) == "network")
119 {
120 fs::remove(file.path());
121 filesExist = true;
122 }
123 }
124
125 if(!filesExist)
126 {
127 log<level::INFO>("No existing network configuration was found.");
128 }
129
130 for (auto& intf : interfaces)
131 {
132 std::string filename = networkConfig + "00-bmc-" + intf.first +
133 ".network";
134
135 bmc::writeDHCPDefault(filename, intf.first);
136 interfacesMapped = true;
137 }
138
139 if(interfacesMapped)
140 {
141 log<level::INFO>("Network configuration reset to DHCP.");
142 }
143 else
144 {
145 log<level::ERR>("No network interfaces are mapped.");
146 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
147 }
148 }
149 else
150 {
151 log<level::ERR>("Network configuration directory not found!");
152 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
153 }
154
155 return;
156}
157
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530158// Need to merge the below function with the code which writes the
159// config file during factory reset.
160//TODO openbmc/openbmc#1751
161void Manager::writeToConfigurationFile()
162{
163 // write all the static ip address in the systemd-network conf file
164
165 using namespace std::string_literals;
166 using AddressOrigin =
167 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
168 namespace fs = std::experimental::filesystem;
169
170 for (const auto& intf : interfaces)
171 {
172
Ratan Guptaef85eb92017-06-15 08:57:54 +0530173 fs::path confPath = confDir;
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530174 std::string fileName = "00-bmc-"s + intf.first + ".network"s;
175 confPath /= fileName;
176 std::fstream stream;
177 stream.open(confPath.c_str(), std::fstream::out);
178
179 // Write the device
180 stream << "[" << "Match" << "]\n";
181 stream << "Name=" << intf.first << "\n";
182
183 auto addrs = intf.second->getAddresses();
184
185 // write the network section
186 stream << "[" << "Network" << "]\n";
Ratan Gupta34f96d62017-06-15 09:16:22 +0530187 // DHCP
188 if (intf.second->dHCPEnabled() == true)
189 {
Ratan Gupta70c7e5b2017-07-12 11:41:55 +0530190 // write the dhcp section if interface is
191 // configured as dhcp.
192 writeDHCPSection(stream);
Ratan Gupta34f96d62017-06-15 09:16:22 +0530193 stream.close();
194 continue;
195 }
Ratan Gupta70c7e5b2017-07-12 11:41:55 +0530196
Ratan Gupta34f96d62017-06-15 09:16:22 +0530197 // Static
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530198 for (const auto& addr : addrs)
199 {
200 if (addr.second->origin() == AddressOrigin::Static)
201 {
202 std::string address = addr.second->address() + "/" + std::to_string(
203 addr.second->prefixLength());
204
205 stream << "Address=" << address << "\n";
Ratan Guptaef85eb92017-06-15 08:57:54 +0530206 if (addr.second->gateway() != "0.0.0.0" &&
207 addr.second->gateway() != "")
208 {
209 stream << "Gateway=" << addr.second->gateway() << "\n";
210 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530211
212 }
213 }
Ratan Gupta5978dd12017-07-25 13:47:13 +0530214
Ratan Guptaef85eb92017-06-15 08:57:54 +0530215 stream << "Gateway=" << systemConf->defaultGateway() << "\n";
216 // write the route section
Ratan Guptafc2c7242017-05-29 08:46:06 +0530217 stream << "[" << "Route" << "]\n";
218 for(const auto& addr : addrs)
219 {
220 if (addr.second->origin() == AddressOrigin::Static)
221 {
222 int addressFamily = addr.second->type() == IP::Protocol::IPv4 ? AF_INET : AF_INET6;
223 std::string destination = getNetworkID(
224 addressFamily,
225 addr.second->address(),
226 addr.second->prefixLength());
227
Ratan Guptaef85eb92017-06-15 08:57:54 +0530228 if (addr.second->gateway() != "0.0.0.0" &&
229 addr.second->gateway() != "" &&
230 destination != "0.0.0.0" &&
231 destination != "")
Ratan Guptafc2c7242017-05-29 08:46:06 +0530232 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530233 stream << "Gateway=" << addr.second->gateway() << "\n";
234 stream << "Destination=" << destination << "\n";
235 }
236
237 }
238 }
239
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530240 stream.close();
241 }
Ratan Gupta068a8cf2017-07-11 19:18:29 +0530242 restartSystemdUnit("systemd-networkd.service");
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530243}
244
Ratan Gupta70c7e5b2017-07-12 11:41:55 +0530245void Manager::writeDHCPSection(std::fstream& stream)
246{
247 using namespace std::string_literals;
248 stream << "DHCP=true\n";
249 // write the dhcp section
250 stream << "[DHCP]\n";
251
252 // Hardcoding the client identifier to mac, to address below issue
253 // https://github.com/openbmc/openbmc/issues/1280
254 stream << "ClientIdentifier=mac\n";
255
256 auto value = dhcpConf->dNSEnabled() ? "true"s : "false"s;
257 stream << "UseDNS="s + value + "\n";
258
259 value = dhcpConf->nTPEnabled() ? "true"s : "false"s;
260 stream << "UseNTP="s + value + "\n";
261
262 value = dhcpConf->hostNameEnabled() ? "true"s : "false"s;
263 stream << "UseHostname="s + value + "\n";
264}
265
Ratan Gupta34f96d62017-06-15 09:16:22 +0530266bool Manager::getDHCPValue(const std::string& intf)
267{
268 bool dhcp = false;
269 // Get the interface mode value from systemd conf
270 using namespace std::string_literals;
271 fs::path confPath = confDir;
272 std::string fileName = "00-bmc-"s + intf + ".network"s;
273 confPath /= fileName;
274
275 try
276 {
277 config::Parser parser(confPath.string());
278 auto values = parser.getValues("Network","DHCP");
279 // There will be only single value for DHCP key.
280 if (values[0] == "true")
281 {
282 dhcp = true;
283 }
284 }
285 catch (InternalFailure& e)
286 {
Ratan Guptadea3ead2017-08-02 18:09:25 +0530287 log<level::INFO>("Exception occured during getting of DHCP value");
Ratan Gupta34f96d62017-06-15 09:16:22 +0530288 }
289 return dhcp;
290}
291
Ratan Gupta6811f822017-04-14 16:34:56 +0530292}//namespace network
293}//namespace phosphor