blob: ee88c3f1c236b2882dd59595997fdc9ada2ef583 [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 Gupta6811f822017-04-14 16:34:56 +05303#include "network_manager.hpp"
Michael Tritz29f2fd62017-05-22 15:27:26 -05004#include "network_config.hpp"
Ratan Gupta44ae86e2017-05-15 21:52:14 +05305#include "xyz/openbmc_project/Common/error.hpp"
Ratan Gupta6811f822017-04-14 16:34:56 +05306
7#include <phosphor-logging/log.hpp>
Ratan Gupta44ae86e2017-05-15 21:52:14 +05308#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta6811f822017-04-14 16:34:56 +05309
10#include <algorithm>
Ratan Gupta738a67f2017-04-21 10:38:05 +053011#include <bitset>
Ratan Gupta738a67f2017-04-21 10:38:05 +053012#include <map>
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053013#include <fstream>
Ratan Gupta738a67f2017-04-21 10:38:05 +053014
Ratan Gupta6811f822017-04-14 16:34:56 +053015#include <arpa/inet.h>
16#include <dirent.h>
17#include <net/if.h>
18
Michael Tritz29f2fd62017-05-22 15:27:26 -050019#include <string>
Ratan Gupta6811f822017-04-14 16:34:56 +053020
21namespace phosphor
22{
23namespace network
24{
Ratan Gupta82549cc2017-04-21 08:45:23 +053025
Ratan Gupta6811f822017-04-14 16:34:56 +053026using namespace phosphor::logging;
Ratan Guptaef85eb92017-06-15 08:57:54 +053027using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta6811f822017-04-14 16:34:56 +053028
29Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath):
Ratan Gupta29b0e432017-05-25 12:51:40 +053030 details::VLANCreateIface(bus, objPath, true),
31 bus(bus),
32 objectPath(objPath)
Ratan Gupta6811f822017-04-14 16:34:56 +053033{
Ratan Guptaef85eb92017-06-15 08:57:54 +053034 confDir = NETWORK_CONF_DIR;
35}
36
37void Manager::setConfDir(const fs::path& dir)
38{
39 confDir = dir;
Ratan Gupta29b0e432017-05-25 12:51:40 +053040}
41
42void Manager::createInterfaces()
43{
Ratan Guptaef85eb92017-06-15 08:57:54 +053044 //clear all the interfaces first
45 interfaces.clear();
Ratan Gupta29b0e432017-05-25 12:51:40 +053046
Ratan Gupta82549cc2017-04-21 08:45:23 +053047 auto interfaceInfoList = getInterfaceAddrs();
Ratan Gupta6811f822017-04-14 16:34:56 +053048
Ratan Gupta738a67f2017-04-21 10:38:05 +053049 for (const auto& intfInfo : interfaceInfoList)
Ratan Gupta6811f822017-04-14 16:34:56 +053050 {
Ratan Gupta29b0e432017-05-25 12:51:40 +053051 fs::path objPath = objectPath;
52 objPath /= intfInfo.first;
Ratan Gupta6811f822017-04-14 16:34:56 +053053
Ratan Gupta34f96d62017-06-15 09:16:22 +053054 auto dhcp = getDHCPValue(intfInfo.first);
55
Ratan Gupta6811f822017-04-14 16:34:56 +053056 this->interfaces.emplace(std::make_pair(
Ratan Gupta738a67f2017-04-21 10:38:05 +053057 intfInfo.first,
58 std::make_unique<
59 phosphor::network::EthernetInterface>
60 (bus,
Ratan Gupta29b0e432017-05-25 12:51:40 +053061 objPath.string(),
Ratan Gupta34f96d62017-06-15 09:16:22 +053062 dhcp,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053063 *this)));
Ratan Gupta29b0e432017-05-25 12:51:40 +053064
65 interfaces[intfInfo.first]->setAddressList(intfInfo.second);
Ratan Gupta6811f822017-04-14 16:34:56 +053066 }
67}
68
Ratan Guptaef85eb92017-06-15 08:57:54 +053069void Manager::createChildObjects()
70{
71 // creates the ethernet interface dbus object.
72 createInterfaces();
73 // create the system conf object.
74 fs::path objPath = objectPath;
75 objPath /= "config";
76 systemConf = std::make_unique<phosphor::network::SystemConfiguration>(
77 bus, objPath.string(), *this);
78
79}
80
Ratan Gupta82549cc2017-04-21 08:45:23 +053081void Manager::vLAN(IntfName interfaceName, uint16_t id)
Ratan Gupta6811f822017-04-14 16:34:56 +053082{
83}
84
Michael Tritz29f2fd62017-05-22 15:27:26 -050085void Manager::reset()
86{
87 const std::string networkConfig = "/etc/systemd/network/";
88 bool filesExist, interfacesMapped = false;
89
90 if(fs::is_directory(networkConfig))
91 {
92 for(auto& file : fs::directory_iterator(networkConfig))
93 {
94 std::string filename = file.path().filename().c_str();
95
96 if(filename.substr(filename.find_last_of(".") + 1) == "network")
97 {
98 fs::remove(file.path());
99 filesExist = true;
100 }
101 }
102
103 if(!filesExist)
104 {
105 log<level::INFO>("No existing network configuration was found.");
106 }
107
108 for (auto& intf : interfaces)
109 {
110 std::string filename = networkConfig + "00-bmc-" + intf.first +
111 ".network";
112
113 bmc::writeDHCPDefault(filename, intf.first);
114 interfacesMapped = true;
115 }
116
117 if(interfacesMapped)
118 {
119 log<level::INFO>("Network configuration reset to DHCP.");
120 }
121 else
122 {
123 log<level::ERR>("No network interfaces are mapped.");
124 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
125 }
126 }
127 else
128 {
129 log<level::ERR>("Network configuration directory not found!");
130 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
131 }
132
133 return;
134}
135
Ratan Gupta82549cc2017-04-21 08:45:23 +0530136IntfAddrMap Manager::getInterfaceAddrs() const
Ratan Gupta6811f822017-04-14 16:34:56 +0530137{
Ratan Gupta8804feb2017-05-25 10:49:57 +0530138 IntfAddrMap intfMap{};
139 AddrList addrList{};
140 struct ifaddrs* ifaddr = nullptr;
Ratan Gupta44ae86e2017-05-15 21:52:14 +0530141
Ratan Gupta6811f822017-04-14 16:34:56 +0530142 // attempt to fill struct with ifaddrs
143 if (getifaddrs(&ifaddr) == -1)
144 {
Ratan Gupta44ae86e2017-05-15 21:52:14 +0530145 auto error = errno;
146 log<level::ERR>("Error occurred during the getifaddrs call",
147 entry("ERRNO=%s", strerror(error)));
148 elog<InternalFailure>();
Ratan Gupta6811f822017-04-14 16:34:56 +0530149 }
150
151 details::AddrPtr ifaddrPtr(ifaddr);
152 ifaddr = nullptr;
153
Ratan Gupta8804feb2017-05-25 10:49:57 +0530154 std::string intfName{};
Ratan Gupta6811f822017-04-14 16:34:56 +0530155
156 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
157 {
158 // walk interfaces
159 if (ifa->ifa_addr == nullptr)
160 {
161 continue;
162 }
163
164 // get only INET interfaces not ipv6
165 if (ifa->ifa_addr->sa_family == AF_INET ||
166 ifa->ifa_addr->sa_family == AF_INET6)
167 {
168 // if loopback, or not running ignore
169 if ((ifa->ifa_flags & IFF_LOOPBACK) ||
170 !(ifa->ifa_flags & IFF_RUNNING))
171 {
172 continue;
173 }
174 // if the interface name is not same as the previous
175 // iteration then add the addr list into
176 // the map.
177 if (intfName != "" && intfName != std::string(ifa->ifa_name))
178 {
179 intfMap.emplace(intfName, addrList);
180 addrList.clear();
181 }
182 intfName = ifa->ifa_name;
Ratan Gupta8804feb2017-05-25 10:49:57 +0530183 AddrInfo info{};
Ratan Gupta82549cc2017-04-21 08:45:23 +0530184 char ip[INET6_ADDRSTRLEN] = { 0 };
Ratan Gupta738a67f2017-04-21 10:38:05 +0530185 char subnetMask[INET6_ADDRSTRLEN] = { 0 };
Ratan Gupta6811f822017-04-14 16:34:56 +0530186
187 if (ifa->ifa_addr->sa_family == AF_INET)
188 {
189
190 inet_ntop(ifa->ifa_addr->sa_family,
191 &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr),
Ratan Gupta82549cc2017-04-21 08:45:23 +0530192 ip,
193 sizeof(ip));
Ratan Gupta738a67f2017-04-21 10:38:05 +0530194
195 inet_ntop(ifa->ifa_addr->sa_family,
196 &(((struct sockaddr_in*)(ifa->ifa_netmask))->sin_addr),
197 subnetMask,
198 sizeof(subnetMask));
199
Ratan Gupta6811f822017-04-14 16:34:56 +0530200 }
201 else
202 {
203 inet_ntop(ifa->ifa_addr->sa_family,
204 &(((struct sockaddr_in6*)(ifa->ifa_addr))->sin6_addr),
Ratan Gupta82549cc2017-04-21 08:45:23 +0530205 ip,
206 sizeof(ip));
Ratan Gupta6811f822017-04-14 16:34:56 +0530207
Ratan Gupta738a67f2017-04-21 10:38:05 +0530208 inet_ntop(ifa->ifa_addr->sa_family,
209 &(((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr),
210 subnetMask,
211 sizeof(subnetMask));
212
Ratan Gupta6811f822017-04-14 16:34:56 +0530213 }
214
215 info.addrType = ifa->ifa_addr->sa_family;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530216 info.ipaddress = ip;
Ratan Gupta8804feb2017-05-25 10:49:57 +0530217 info.prefix = toCidr(info.addrType, std::string(subnetMask));
Ratan Gupta6811f822017-04-14 16:34:56 +0530218 addrList.emplace_back(info);
219 }
220 }
221 intfMap.emplace(intfName, addrList);
222 return intfMap;
223}
Ratan Gupta738a67f2017-04-21 10:38:05 +0530224
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530225// Need to merge the below function with the code which writes the
226// config file during factory reset.
227//TODO openbmc/openbmc#1751
228void Manager::writeToConfigurationFile()
229{
230 // write all the static ip address in the systemd-network conf file
231
232 using namespace std::string_literals;
233 using AddressOrigin =
234 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
235 namespace fs = std::experimental::filesystem;
236
237 for (const auto& intf : interfaces)
238 {
239
Ratan Guptaef85eb92017-06-15 08:57:54 +0530240 fs::path confPath = confDir;
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530241 std::string fileName = "00-bmc-"s + intf.first + ".network"s;
242 confPath /= fileName;
243 std::fstream stream;
244 stream.open(confPath.c_str(), std::fstream::out);
245
246 // Write the device
247 stream << "[" << "Match" << "]\n";
248 stream << "Name=" << intf.first << "\n";
249
250 auto addrs = intf.second->getAddresses();
251
252 // write the network section
253 stream << "[" << "Network" << "]\n";
Ratan Gupta34f96d62017-06-15 09:16:22 +0530254 // DHCP
255 if (intf.second->dHCPEnabled() == true)
256 {
257 stream << "DHCP=true\n";
258 // write the dhcp section
259 stream << "[DHCP]\n";
260 stream << "ClientIdentifier=mac\n";
261 stream.close();
262 continue;
263 }
264 // Static
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530265 for (const auto& addr : addrs)
266 {
267 if (addr.second->origin() == AddressOrigin::Static)
268 {
269 std::string address = addr.second->address() + "/" + std::to_string(
270 addr.second->prefixLength());
271
272 stream << "Address=" << address << "\n";
Ratan Guptaef85eb92017-06-15 08:57:54 +0530273 if (addr.second->gateway() != "0.0.0.0" &&
274 addr.second->gateway() != "")
275 {
276 stream << "Gateway=" << addr.second->gateway() << "\n";
277 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530278
279 }
280 }
Ratan Guptaef85eb92017-06-15 08:57:54 +0530281 stream << "Gateway=" << systemConf->defaultGateway() << "\n";
282 // write the route section
Ratan Guptafc2c7242017-05-29 08:46:06 +0530283 stream << "[" << "Route" << "]\n";
284 for(const auto& addr : addrs)
285 {
286 if (addr.second->origin() == AddressOrigin::Static)
287 {
288 int addressFamily = addr.second->type() == IP::Protocol::IPv4 ? AF_INET : AF_INET6;
289 std::string destination = getNetworkID(
290 addressFamily,
291 addr.second->address(),
292 addr.second->prefixLength());
293
Ratan Guptaef85eb92017-06-15 08:57:54 +0530294 if (addr.second->gateway() != "0.0.0.0" &&
295 addr.second->gateway() != "" &&
296 destination != "0.0.0.0" &&
297 destination != "")
Ratan Guptafc2c7242017-05-29 08:46:06 +0530298 {
299
300 stream << "Gateway=" << addr.second->gateway() << "\n";
301 stream << "Destination=" << destination << "\n";
302 }
303
304 }
305 }
306
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530307 stream.close();
308 }
309 restartSystemdNetworkd();
310}
311
312void Manager::restartSystemdNetworkd()
313{
314 constexpr auto systemdNetworkdService = "systemd-networkd.service";
315
316 auto method = bus.new_method_call(
317 SYSTEMD_BUSNAME,
318 SYSTEMD_PATH,
319 SYSTEMD_INTERFACE,
320 "RestartUnit");
321
322 method.append(systemdNetworkdService,
323 "replace");
324
325 bus.call_noreply(method);
326}
327
Ratan Gupta34f96d62017-06-15 09:16:22 +0530328bool Manager::getDHCPValue(const std::string& intf)
329{
330 bool dhcp = false;
331 // Get the interface mode value from systemd conf
332 using namespace std::string_literals;
333 fs::path confPath = confDir;
334 std::string fileName = "00-bmc-"s + intf + ".network"s;
335 confPath /= fileName;
336
337 try
338 {
339 config::Parser parser(confPath.string());
340 auto values = parser.getValues("Network","DHCP");
341 // There will be only single value for DHCP key.
342 if (values[0] == "true")
343 {
344 dhcp = true;
345 }
346 }
347 catch (InternalFailure& e)
348 {
349 commit<InternalFailure>();
350 }
351 return dhcp;
352}
353
Ratan Gupta6811f822017-04-14 16:34:56 +0530354}//namespace network
355}//namespace phosphor