blob: a5ff5e32a8de453431df7c9fa49e9d2447882806 [file] [log] [blame]
Ratan Gupta6811f822017-04-14 16:34:56 +05301#include "config.h"
2#include "network_manager.hpp"
Michael Tritz29f2fd62017-05-22 15:27:26 -05003#include "network_config.hpp"
Ratan Gupta44ae86e2017-05-15 21:52:14 +05304#include "xyz/openbmc_project/Common/error.hpp"
Ratan Gupta6811f822017-04-14 16:34:56 +05305
6#include <phosphor-logging/log.hpp>
Ratan Gupta44ae86e2017-05-15 21:52:14 +05307#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta6811f822017-04-14 16:34:56 +05308
9#include <algorithm>
Ratan Gupta738a67f2017-04-21 10:38:05 +053010#include <bitset>
Ratan Gupta82549cc2017-04-21 08:45:23 +053011#include <experimental/filesystem>
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 Gupta82549cc2017-04-21 08:45:23 +053027namespace fs = std::experimental::filesystem;
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 Gupta29b0e432017-05-25 12:51:40 +053034}
35
36void Manager::createInterfaces()
37{
38
Ratan Gupta82549cc2017-04-21 08:45:23 +053039 auto interfaceInfoList = getInterfaceAddrs();
Ratan Gupta6811f822017-04-14 16:34:56 +053040
Ratan Gupta738a67f2017-04-21 10:38:05 +053041 for (const auto& intfInfo : interfaceInfoList)
Ratan Gupta6811f822017-04-14 16:34:56 +053042 {
Ratan Gupta29b0e432017-05-25 12:51:40 +053043 fs::path objPath = objectPath;
44 objPath /= intfInfo.first;
Ratan Gupta6811f822017-04-14 16:34:56 +053045
46 this->interfaces.emplace(std::make_pair(
Ratan Gupta738a67f2017-04-21 10:38:05 +053047 intfInfo.first,
48 std::make_unique<
49 phosphor::network::EthernetInterface>
50 (bus,
Ratan Gupta29b0e432017-05-25 12:51:40 +053051 objPath.string(),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053052 false,
53 *this)));
Ratan Gupta29b0e432017-05-25 12:51:40 +053054
55 interfaces[intfInfo.first]->setAddressList(intfInfo.second);
Ratan Gupta6811f822017-04-14 16:34:56 +053056 }
57}
58
Ratan Gupta82549cc2017-04-21 08:45:23 +053059void Manager::vLAN(IntfName interfaceName, uint16_t id)
Ratan Gupta6811f822017-04-14 16:34:56 +053060{
61}
62
Michael Tritz29f2fd62017-05-22 15:27:26 -050063void Manager::reset()
64{
65 const std::string networkConfig = "/etc/systemd/network/";
66 bool filesExist, interfacesMapped = false;
67
68 if(fs::is_directory(networkConfig))
69 {
70 for(auto& file : fs::directory_iterator(networkConfig))
71 {
72 std::string filename = file.path().filename().c_str();
73
74 if(filename.substr(filename.find_last_of(".") + 1) == "network")
75 {
76 fs::remove(file.path());
77 filesExist = true;
78 }
79 }
80
81 if(!filesExist)
82 {
83 log<level::INFO>("No existing network configuration was found.");
84 }
85
86 for (auto& intf : interfaces)
87 {
88 std::string filename = networkConfig + "00-bmc-" + intf.first +
89 ".network";
90
91 bmc::writeDHCPDefault(filename, intf.first);
92 interfacesMapped = true;
93 }
94
95 if(interfacesMapped)
96 {
97 log<level::INFO>("Network configuration reset to DHCP.");
98 }
99 else
100 {
101 log<level::ERR>("No network interfaces are mapped.");
102 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
103 }
104 }
105 else
106 {
107 log<level::ERR>("Network configuration directory not found!");
108 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
109 }
110
111 return;
112}
113
Ratan Gupta82549cc2017-04-21 08:45:23 +0530114IntfAddrMap Manager::getInterfaceAddrs() const
Ratan Gupta6811f822017-04-14 16:34:56 +0530115{
Ratan Gupta8804feb2017-05-25 10:49:57 +0530116 IntfAddrMap intfMap{};
117 AddrList addrList{};
118 struct ifaddrs* ifaddr = nullptr;
Ratan Gupta44ae86e2017-05-15 21:52:14 +0530119
120 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta6811f822017-04-14 16:34:56 +0530121 // attempt to fill struct with ifaddrs
122 if (getifaddrs(&ifaddr) == -1)
123 {
Ratan Gupta44ae86e2017-05-15 21:52:14 +0530124 auto error = errno;
125 log<level::ERR>("Error occurred during the getifaddrs call",
126 entry("ERRNO=%s", strerror(error)));
127 elog<InternalFailure>();
Ratan Gupta6811f822017-04-14 16:34:56 +0530128 }
129
130 details::AddrPtr ifaddrPtr(ifaddr);
131 ifaddr = nullptr;
132
Ratan Gupta8804feb2017-05-25 10:49:57 +0530133 std::string intfName{};
Ratan Gupta6811f822017-04-14 16:34:56 +0530134
135 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
136 {
137 // walk interfaces
138 if (ifa->ifa_addr == nullptr)
139 {
140 continue;
141 }
142
143 // get only INET interfaces not ipv6
144 if (ifa->ifa_addr->sa_family == AF_INET ||
145 ifa->ifa_addr->sa_family == AF_INET6)
146 {
147 // if loopback, or not running ignore
148 if ((ifa->ifa_flags & IFF_LOOPBACK) ||
149 !(ifa->ifa_flags & IFF_RUNNING))
150 {
151 continue;
152 }
153 // if the interface name is not same as the previous
154 // iteration then add the addr list into
155 // the map.
156 if (intfName != "" && intfName != std::string(ifa->ifa_name))
157 {
158 intfMap.emplace(intfName, addrList);
159 addrList.clear();
160 }
161 intfName = ifa->ifa_name;
Ratan Gupta8804feb2017-05-25 10:49:57 +0530162 AddrInfo info{};
Ratan Gupta82549cc2017-04-21 08:45:23 +0530163 char ip[INET6_ADDRSTRLEN] = { 0 };
Ratan Gupta738a67f2017-04-21 10:38:05 +0530164 char subnetMask[INET6_ADDRSTRLEN] = { 0 };
Ratan Gupta6811f822017-04-14 16:34:56 +0530165
166 if (ifa->ifa_addr->sa_family == AF_INET)
167 {
168
169 inet_ntop(ifa->ifa_addr->sa_family,
170 &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr),
Ratan Gupta82549cc2017-04-21 08:45:23 +0530171 ip,
172 sizeof(ip));
Ratan Gupta738a67f2017-04-21 10:38:05 +0530173
174 inet_ntop(ifa->ifa_addr->sa_family,
175 &(((struct sockaddr_in*)(ifa->ifa_netmask))->sin_addr),
176 subnetMask,
177 sizeof(subnetMask));
178
Ratan Gupta6811f822017-04-14 16:34:56 +0530179 }
180 else
181 {
182 inet_ntop(ifa->ifa_addr->sa_family,
183 &(((struct sockaddr_in6*)(ifa->ifa_addr))->sin6_addr),
Ratan Gupta82549cc2017-04-21 08:45:23 +0530184 ip,
185 sizeof(ip));
Ratan Gupta6811f822017-04-14 16:34:56 +0530186
Ratan Gupta738a67f2017-04-21 10:38:05 +0530187 inet_ntop(ifa->ifa_addr->sa_family,
188 &(((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr),
189 subnetMask,
190 sizeof(subnetMask));
191
Ratan Gupta6811f822017-04-14 16:34:56 +0530192 }
193
194 info.addrType = ifa->ifa_addr->sa_family;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530195 info.ipaddress = ip;
Ratan Gupta8804feb2017-05-25 10:49:57 +0530196 info.prefix = toCidr(info.addrType, std::string(subnetMask));
Ratan Gupta6811f822017-04-14 16:34:56 +0530197 addrList.emplace_back(info);
198 }
199 }
200 intfMap.emplace(intfName, addrList);
201 return intfMap;
202}
Ratan Gupta738a67f2017-04-21 10:38:05 +0530203
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530204// Need to merge the below function with the code which writes the
205// config file during factory reset.
206//TODO openbmc/openbmc#1751
207void Manager::writeToConfigurationFile()
208{
209 // write all the static ip address in the systemd-network conf file
210
211 using namespace std::string_literals;
212 using AddressOrigin =
213 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
214 namespace fs = std::experimental::filesystem;
215
216 for (const auto& intf : interfaces)
217 {
218
219 fs::path confPath {NETWORK_CONF_DIR};
220 std::string fileName = "00-bmc-"s + intf.first + ".network"s;
221 confPath /= fileName;
222 std::fstream stream;
223 stream.open(confPath.c_str(), std::fstream::out);
224
225 // Write the device
226 stream << "[" << "Match" << "]\n";
227 stream << "Name=" << intf.first << "\n";
228
229 auto addrs = intf.second->getAddresses();
230
231 // write the network section
232 stream << "[" << "Network" << "]\n";
233 for (const auto& addr : addrs)
234 {
235 if (addr.second->origin() == AddressOrigin::Static)
236 {
237 std::string address = addr.second->address() + "/" + std::to_string(
238 addr.second->prefixLength());
239
240 stream << "Address=" << address << "\n";
241 stream << "Gateway=" << addr.second->gateway() << "\n";
242
243 }
244 }
245 stream.close();
246 }
247 restartSystemdNetworkd();
248}
249
250void Manager::restartSystemdNetworkd()
251{
252 constexpr auto systemdNetworkdService = "systemd-networkd.service";
253
254 auto method = bus.new_method_call(
255 SYSTEMD_BUSNAME,
256 SYSTEMD_PATH,
257 SYSTEMD_INTERFACE,
258 "RestartUnit");
259
260 method.append(systemdNetworkdService,
261 "replace");
262
263 bus.call_noreply(method);
264}
265
Ratan Gupta6811f822017-04-14 16:34:56 +0530266}//namespace network
267}//namespace phosphor