blob: 8ea82d592f283dee07a8c5b3ad54274c57f8517d [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>
13
Ratan Gupta6811f822017-04-14 16:34:56 +053014#include <arpa/inet.h>
15#include <dirent.h>
16#include <net/if.h>
17
Michael Tritz29f2fd62017-05-22 15:27:26 -050018#include <string>
Ratan Gupta6811f822017-04-14 16:34:56 +053019
20namespace phosphor
21{
22namespace network
23{
Ratan Gupta82549cc2017-04-21 08:45:23 +053024
Ratan Gupta6811f822017-04-14 16:34:56 +053025using namespace phosphor::logging;
Ratan Gupta82549cc2017-04-21 08:45:23 +053026namespace fs = std::experimental::filesystem;
Ratan Gupta6811f822017-04-14 16:34:56 +053027
28Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath):
29 details::VLANCreateIface(bus, objPath, true)
30{
Ratan Gupta82549cc2017-04-21 08:45:23 +053031 auto interfaceInfoList = getInterfaceAddrs();
Ratan Gupta6811f822017-04-14 16:34:56 +053032
Ratan Gupta738a67f2017-04-21 10:38:05 +053033 for (const auto& intfInfo : interfaceInfoList)
34
Ratan Gupta6811f822017-04-14 16:34:56 +053035 {
Ratan Gupta82549cc2017-04-21 08:45:23 +053036
37 fs::path objectPath = std::string(OBJ_NETWORK);
38 objectPath /= intfInfo.first;
Ratan Gupta6811f822017-04-14 16:34:56 +053039
40 this->interfaces.emplace(std::make_pair(
Ratan Gupta738a67f2017-04-21 10:38:05 +053041 intfInfo.first,
42 std::make_unique<
43 phosphor::network::EthernetInterface>
44 (bus,
45 objectPath.string(),
46 false,
47 intfInfo.second)));
Ratan Gupta6811f822017-04-14 16:34:56 +053048 }
49}
50
Ratan Gupta82549cc2017-04-21 08:45:23 +053051void Manager::vLAN(IntfName interfaceName, uint16_t id)
Ratan Gupta6811f822017-04-14 16:34:56 +053052{
53}
54
Michael Tritz29f2fd62017-05-22 15:27:26 -050055void Manager::reset()
56{
57 const std::string networkConfig = "/etc/systemd/network/";
58 bool filesExist, interfacesMapped = false;
59
60 if(fs::is_directory(networkConfig))
61 {
62 for(auto& file : fs::directory_iterator(networkConfig))
63 {
64 std::string filename = file.path().filename().c_str();
65
66 if(filename.substr(filename.find_last_of(".") + 1) == "network")
67 {
68 fs::remove(file.path());
69 filesExist = true;
70 }
71 }
72
73 if(!filesExist)
74 {
75 log<level::INFO>("No existing network configuration was found.");
76 }
77
78 for (auto& intf : interfaces)
79 {
80 std::string filename = networkConfig + "00-bmc-" + intf.first +
81 ".network";
82
83 bmc::writeDHCPDefault(filename, intf.first);
84 interfacesMapped = true;
85 }
86
87 if(interfacesMapped)
88 {
89 log<level::INFO>("Network configuration reset to DHCP.");
90 }
91 else
92 {
93 log<level::ERR>("No network interfaces are mapped.");
94 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
95 }
96 }
97 else
98 {
99 log<level::ERR>("Network configuration directory not found!");
100 // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
101 }
102
103 return;
104}
105
Ratan Gupta82549cc2017-04-21 08:45:23 +0530106IntfAddrMap Manager::getInterfaceAddrs() const
Ratan Gupta6811f822017-04-14 16:34:56 +0530107{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530108 IntfAddrMap intfMap;
109 AddrList addrList;
Ratan Gupta6811f822017-04-14 16:34:56 +0530110 struct ifaddrs* ifaddr;
Ratan Gupta44ae86e2017-05-15 21:52:14 +0530111
112 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta6811f822017-04-14 16:34:56 +0530113 // attempt to fill struct with ifaddrs
114 if (getifaddrs(&ifaddr) == -1)
115 {
Ratan Gupta44ae86e2017-05-15 21:52:14 +0530116 auto error = errno;
117 log<level::ERR>("Error occurred during the getifaddrs call",
118 entry("ERRNO=%s", strerror(error)));
119 elog<InternalFailure>();
Ratan Gupta6811f822017-04-14 16:34:56 +0530120 }
121
122 details::AddrPtr ifaddrPtr(ifaddr);
123 ifaddr = nullptr;
124
125 std::string intfName;
126
127 for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
128 {
129 // walk interfaces
130 if (ifa->ifa_addr == nullptr)
131 {
132 continue;
133 }
134
135 // get only INET interfaces not ipv6
136 if (ifa->ifa_addr->sa_family == AF_INET ||
137 ifa->ifa_addr->sa_family == AF_INET6)
138 {
139 // if loopback, or not running ignore
140 if ((ifa->ifa_flags & IFF_LOOPBACK) ||
141 !(ifa->ifa_flags & IFF_RUNNING))
142 {
143 continue;
144 }
145 // if the interface name is not same as the previous
146 // iteration then add the addr list into
147 // the map.
148 if (intfName != "" && intfName != std::string(ifa->ifa_name))
149 {
150 intfMap.emplace(intfName, addrList);
151 addrList.clear();
152 }
153 intfName = ifa->ifa_name;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530154 AddrInfo info;
155 char ip[INET6_ADDRSTRLEN] = { 0 };
Ratan Gupta738a67f2017-04-21 10:38:05 +0530156 char subnetMask[INET6_ADDRSTRLEN] = { 0 };
Ratan Gupta6811f822017-04-14 16:34:56 +0530157
158 if (ifa->ifa_addr->sa_family == AF_INET)
159 {
160
161 inet_ntop(ifa->ifa_addr->sa_family,
162 &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr),
Ratan Gupta82549cc2017-04-21 08:45:23 +0530163 ip,
164 sizeof(ip));
Ratan Gupta738a67f2017-04-21 10:38:05 +0530165
166 inet_ntop(ifa->ifa_addr->sa_family,
167 &(((struct sockaddr_in*)(ifa->ifa_netmask))->sin_addr),
168 subnetMask,
169 sizeof(subnetMask));
170
Ratan Gupta6811f822017-04-14 16:34:56 +0530171 }
172 else
173 {
174 inet_ntop(ifa->ifa_addr->sa_family,
175 &(((struct sockaddr_in6*)(ifa->ifa_addr))->sin6_addr),
Ratan Gupta82549cc2017-04-21 08:45:23 +0530176 ip,
177 sizeof(ip));
Ratan Gupta6811f822017-04-14 16:34:56 +0530178
Ratan Gupta738a67f2017-04-21 10:38:05 +0530179 inet_ntop(ifa->ifa_addr->sa_family,
180 &(((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr),
181 subnetMask,
182 sizeof(subnetMask));
183
Ratan Gupta6811f822017-04-14 16:34:56 +0530184 }
185
186 info.addrType = ifa->ifa_addr->sa_family;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530187 info.ipaddress = ip;
Ratan Guptac41692c2017-05-09 18:35:36 +0530188
189 info.prefix = toCidr(info.addrType, subnetMask);
190
Ratan Gupta6811f822017-04-14 16:34:56 +0530191 addrList.emplace_back(info);
192 }
193 }
194 intfMap.emplace(intfName, addrList);
195 return intfMap;
196}
Ratan Gupta738a67f2017-04-21 10:38:05 +0530197
Ratan Guptac41692c2017-05-09 18:35:36 +0530198uint8_t Manager::toCidr(int addressFamily, const std::string& subnetMask) const
Ratan Gupta738a67f2017-04-21 10:38:05 +0530199{
200 uint32_t buff = 0;
201
Ratan Guptac41692c2017-05-09 18:35:36 +0530202 if (addressFamily == AF_INET6)
203 {
204 return toV6Cidr(std::string(subnetMask));
205 }
206
207 auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
Ratan Gupta738a67f2017-04-21 10:38:05 +0530208 if (rc <= 0)
209 {
210 log<level::ERR>("inet_pton failed:",
Ratan Guptac41692c2017-05-09 18:35:36 +0530211 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Gupta738a67f2017-04-21 10:38:05 +0530212 }
213
214 buff = be32toh(buff);
215 // total no of bits - total no of leading zero == total no of ones
216 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff))
217 {
218 return __builtin_popcount(buff);
219 }
220 else
221 {
222 log<level::ERR>("Invalid Mask",
Ratan Guptac41692c2017-05-09 18:35:36 +0530223 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Gupta738a67f2017-04-21 10:38:05 +0530224 return 0;
225 }
226}
Ratan Guptac41692c2017-05-09 18:35:36 +0530227
228uint8_t Manager::toV6Cidr(const std::string& subnetMask) const
229{
230 uint8_t pos {};
231 uint8_t prevPos {};
232 uint8_t cidr {};
233 uint16_t buff {};
234
235 log<level::INFO>("toV6Cidr called with",
236 entry("SUBNETMASK=%s", subnetMask));
237 do
238 {
239 //subnet mask look like ffff:ffff::
240 // or ffff:c000::
241 pos = subnetMask.find(":", prevPos);
242 if (pos == std::string::npos)
243 {
244 return cidr;
245 }
246
247 auto str = subnetMask.substr(prevPos, (pos - prevPos));
248 prevPos = pos + 1;
249
250 // String length is 0
251 if (!str.length())
252 {
253 return cidr;
254 }
255 //converts it into number.
256 if (sscanf(str.c_str(), "%hx", &buff) <= 0)
257 {
258 log<level::ERR>("Invalid SubnetMask",
259 entry("SUBNETMASK=%s", subnetMask));
260
261 return 0;
262 }
263
264 // convert the number into bitset
265 // and check for how many ones are there.
266 // if we don't have all the ones then make
267 // sure that all the ones should be left justify.
268
269 if (__builtin_popcount(buff) != 16)
270 {
271 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) != __builtin_popcount(buff))
272 {
273 log<level::ERR>("Invalid SubnetMask",
274 entry("SUBNETMASK=%s", subnetMask));
275
276 return 0;
277 }
278 cidr += __builtin_popcount(buff);
279 return cidr;
280 }
281 cidr += 16;
282
283 }
284 while (1);
285
286 return cidr;
287}
288
Ratan Gupta6811f822017-04-14 16:34:56 +0530289}//namespace network
290}//namespace phosphor