blob: ffaac745cf974bf5abbcea694069570df9ee594b [file] [log] [blame]
Ratan Gupta82549cc2017-04-21 08:45:23 +05301#include "config.h"
Ratan Gupta497c0c92017-08-22 19:15:59 +05302#include "config_parser.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05303#include "ethernet_interface.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05304#include "ipaddress.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05305#include "network_manager.hpp"
Ratan Guptafc2c7242017-05-29 08:46:06 +05306#include "routing_table.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05307#include "vlan_interface.hpp"
8#include "xyz/openbmc_project/Common/error.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309
Ratan Gupta2b106532017-07-25 16:05:02 +053010#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053011#include <phosphor-logging/log.hpp>
12
Ratan Gupta82549cc2017-04-21 08:45:23 +053013#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014#include <linux/ethtool.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053016#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053017#include <netinet/in.h>
18#include <sys/ioctl.h>
19#include <sys/socket.h>
20#include <unistd.h>
21
Ratan Gupta2b106532017-07-25 16:05:02 +053022
Ratan Gupta82549cc2017-04-21 08:45:23 +053023#include <algorithm>
24#include <experimental/filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053025#include <fstream>
26#include <sstream>
27#include <string>
Ratan Gupta82549cc2017-04-21 08:45:23 +053028
Ratan Gupta91a99cc2017-04-14 16:32:09 +053029namespace phosphor
30{
31namespace network
32{
33
34using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053035using namespace sdbusplus::xyz::openbmc_project::Common::Error;
36
Ratan Gupta91a99cc2017-04-14 16:32:09 +053037EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
38 const std::string& objPath,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053039 bool dhcpEnabled,
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053040 Manager& parent,
41 bool emitSignal) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053042 Ifaces(bus, objPath.c_str(), true),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053043 bus(bus),
Ratan Gupta47722dc2017-05-26 18:32:23 +053044 manager(parent),
45 objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053046{
47 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053048 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053049 interfaceName(intfName);
Ratan Guptac35481d2017-08-18 06:12:26 +053050 EthernetInterfaceIntf::dHCPEnabled(dhcpEnabled);
Ratan Guptabd303b12017-08-18 17:10:07 +053051 MacAddressIntf::mACAddress(getMACAddress(intfName));
Ratan Gupta497c0c92017-08-22 19:15:59 +053052 EthernetInterfaceIntf::nTPServers(getNTPServersFromConf());
Ratan Gupta29b0e432017-05-25 12:51:40 +053053 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053054 if (emitSignal)
55 {
56 this->emit_object_added();
57 }
Ratan Gupta29b0e432017-05-25 12:51:40 +053058}
59
Ratan Gupta87c13982017-06-15 09:27:27 +053060void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +053061{
Ratan Gupta82549cc2017-04-21 08:45:23 +053062 std::string gateway;
Ratan Gupta87c13982017-06-15 09:27:27 +053063 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +053064
Ratan Gupta87c13982017-06-15 09:27:27 +053065 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +053066
Ratan Gupta82549cc2017-04-21 08:45:23 +053067 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053068 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Guptafc2c7242017-05-29 08:46:06 +053069 route::Table routingTable;
Ratan Gupta5978dd12017-07-25 13:47:13 +053070
Ratan Gupta6a387c12017-08-03 13:26:19 +053071 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +053072 {
73 if (addr.addrType == AF_INET6)
74 {
75 addressType = IP::Protocol::IPv6;
76 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053077 if (dHCPEnabled())
78 {
79 origin = IP::AddressOrigin::DHCP;
80 }
81 else if (isLinkLocal(addr.ipaddress))
82 {
83 origin = IP::AddressOrigin::LinkLocal;
84 }
85 gateway = routingTable.getGateway(addr.addrType, addr.ipaddress, addr.prefix);
Ratan Gupta82549cc2017-04-21 08:45:23 +053086
Ratan Gupta65e5abe2017-05-23 13:20:44 +053087 std::string ipAddressObjectPath = generateObjectPath(addressType,
88 addr.ipaddress,
89 addr.prefix,
90 gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +053091
Ratan Gupta82549cc2017-04-21 08:45:23 +053092 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +053093 std::move(addr.ipaddress),
94 std::make_shared<phosphor::network::IPAddress>(
Ratan Gupta719f83a2017-06-02 11:54:53 +053095 bus,
96 ipAddressObjectPath.c_str(),
97 *this,
98 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053099 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +0530100 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +0530101 addr.prefix,
Ratan Guptae578d562017-08-02 07:04:16 +0530102 gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530103 }
Ratan Guptafc2c7242017-05-29 08:46:06 +0530104
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530105}
106
Ratan Gupta82549cc2017-04-21 08:45:23 +0530107void EthernetInterface::iP(IP::Protocol protType,
108 std::string ipaddress,
109 uint8_t prefixLength,
110 std::string gateway)
111{
Ratan Guptafc2c7242017-05-29 08:46:06 +0530112
113 if (dHCPEnabled())
114 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530115 log<level::INFO>("DHCP enabled on the interface"),
Ratan Guptabd303b12017-08-18 17:10:07 +0530116 entry("INTERFACE=%s",interfaceName().c_str());
Ratan Guptafc2c7242017-05-29 08:46:06 +0530117 return;
118 }
119
Ratan Gupta29b0e432017-05-25 12:51:40 +0530120 IP::AddressOrigin origin = IP::AddressOrigin::Static;
121
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530122 std::string objectPath = generateObjectPath(protType,
123 ipaddress,
124 prefixLength,
125 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530126 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +0530127 std::move(ipaddress),
128 std::make_shared<phosphor::network::IPAddress>(
129 bus,
130 objectPath.c_str(),
131 *this,
132 protType,
133 ipaddress,
134 origin,
135 prefixLength,
136 gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530137
Ratan Guptae05083a2017-09-16 07:12:11 +0530138 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530139}
140
141
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530142/*
143Note: We don't have support for ethtool now
144will enable this code once we bring the ethtool
145in the image.
146TODO: https://github.com/openbmc/openbmc/issues/1484
147*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530148
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530149InterfaceInfo EthernetInterface::getInterfaceInfo() const
150{
151 int sock{-1};
152 struct ifreq ifr{0};
153 struct ethtool_cmd edata{0};
154 LinkSpeed speed {0};
155 Autoneg autoneg {0};
156 DuplexMode duplex {0};
157 do
158 {
159 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
160 if (sock < 0)
161 {
162 log<level::ERR>("socket creation failed:",
163 entry("ERROR=%s", strerror(errno)));
164 break;
165 }
166
167 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
168 ifr.ifr_data = reinterpret_cast<char*>(&edata);
169
170 edata.cmd = ETHTOOL_GSET;
171
172 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
173 {
174 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
175 entry("ERROR=%s", strerror(errno)));
176 break;
177
178 }
179 speed = edata.speed;
180 duplex = edata.duplex;
181 autoneg = edata.autoneg;
182 }
183 while (0);
184
185 if (sock)
186 {
187 close(sock);
188 }
189 return std::make_tuple(speed, duplex, autoneg);
190}
191
192/** @brief get the mac address of the interface.
193 * @return macaddress on success
194 */
195
Ratan Guptada7d3af2017-08-13 17:49:56 +0530196std::string EthernetInterface::getMACAddress(
197 const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530198{
Ratan Guptada7d3af2017-08-13 17:49:56 +0530199 struct ifreq ifr{};
Ratan Guptabd303b12017-08-18 17:10:07 +0530200 char macAddress[mac_address::size] {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530201
202 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
203 if (sock < 0)
204 {
205 log<level::ERR>("socket creation failed:",
206 entry("ERROR=%s", strerror(errno)));
207 return macAddress;
208 }
209
Ratan Guptada7d3af2017-08-13 17:49:56 +0530210 strcpy(ifr.ifr_name, interfaceName.c_str());
211 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530212 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530213 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
214 entry("ERROR=%s", strerror(errno)));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530215 return macAddress;
216 }
217
Ratan Guptabd303b12017-08-18 17:10:07 +0530218 snprintf(macAddress, mac_address::size, mac_address::format,
Ratan Guptada7d3af2017-08-13 17:49:56 +0530219 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
220 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
221 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530222
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530223 return macAddress;
224}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530225
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530226std::string EthernetInterface::generateId(const std::string& ipaddress,
227 uint8_t prefixLength,
228 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530229{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530230 std::stringstream hexId;
231 std::string hashString = ipaddress;
232 hashString += std::to_string(prefixLength);
233 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530234
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530235 // Only want 8 hex digits.
236 hexId << std::hex << ((std::hash<std::string> {}(
Ratan Guptafc2c7242017-05-29 08:46:06 +0530237 hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530238 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530239}
240
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530241void EthernetInterface::deleteObject(const std::string& ipaddress)
242{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530243 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530244 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530245 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530246 log<level::ERR>("DeleteObject:Unable to find the object.");
247 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530248 }
249 this->addrs.erase(it);
Ratan Guptae05083a2017-09-16 07:12:11 +0530250 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530251}
252
Ratan Guptae9c9b812017-09-22 17:15:37 +0530253void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530254{
Ratan Guptabc886292017-07-25 18:29:57 +0530255 auto confDir = manager.getConfDir();
256 fs::path networkFile = confDir;
257 networkFile /= systemd::config::networkFilePrefix + interface +
258 systemd::config::networkFileSuffix;
259
260 fs::path deviceFile = confDir;
261 deviceFile /= interface + systemd::config::deviceFileSuffix;
262
263 // delete the vlan network file
264 if (fs::is_regular_file(networkFile))
265 {
266 fs::remove(networkFile);
267 }
268
269 // delete the vlan device file
270 if (fs::is_regular_file(deviceFile))
271 {
272 fs::remove(deviceFile);
273 }
Ratan Guptabc886292017-07-25 18:29:57 +0530274
275 // TODO systemd doesn't delete the virtual network interface
276 // even after deleting all the related configuartion.
277 // https://github.com/systemd/systemd/issues/6600
278 try
279 {
280 deleteInterface(interface);
281 }
282 catch (InternalFailure& e)
283 {
284 commit<InternalFailure>();
285 }
Ratan Guptae05083a2017-09-16 07:12:11 +0530286
Ratan Guptae9c9b812017-09-22 17:15:37 +0530287}
288
289void EthernetInterface::deleteVLANObject(const std::string& interface)
290{
291 auto it = vlanInterfaces.find(interface);
292 if (it == vlanInterfaces.end())
293 {
294 log<level::ERR>("DeleteVLANObject:Unable to find the object",
295 entry("INTERFACE=%s",interface.c_str()));
296 return;
297 }
298
299 deleteVLANFromSystem(interface);
300 // delete the interface
301 vlanInterfaces.erase(it);
302
Ratan Guptae05083a2017-09-16 07:12:11 +0530303 manager.writeToConfigurationFile();
Ratan Guptabc886292017-07-25 18:29:57 +0530304}
305
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530306std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
307 const std::string& ipaddress,
308 uint8_t prefixLength,
309 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530310{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530311 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530312 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530313 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
314
315 std::experimental::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530316 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530317 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530318 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530319 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530320}
321
Ratan Gupta87c13982017-06-15 09:27:27 +0530322bool EthernetInterface::dHCPEnabled(bool value)
323{
Ratan Gupta5978dd12017-07-25 13:47:13 +0530324 if (value == EthernetInterfaceIntf::dHCPEnabled())
325 {
326 return value;
327 }
328
Ratan Gupta87c13982017-06-15 09:27:27 +0530329 EthernetInterfaceIntf::dHCPEnabled(value);
Ratan Guptae05083a2017-09-16 07:12:11 +0530330 manager.writeToConfigurationFile();
Ratan Gupta87c13982017-06-15 09:27:27 +0530331 return value;
332}
333
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530334void EthernetInterface::loadVLAN(VlanId id)
335{
336 std::string vlanInterfaceName = interfaceName() + "." +
337 std::to_string(id);
338 std::string path = objPath;
339 path += "_" + std::to_string(id);
340
Ratan Gupta6e8df632017-08-13 09:41:58 +0530341 auto dhcpEnabled = getDHCPValue(manager.getConfDir().string(),
342 vlanInterfaceName);
343
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530344 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
345 bus,
346 path.c_str(),
Ratan Gupta6e8df632017-08-13 09:41:58 +0530347 dhcpEnabled,
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530348 id,
349 *this,
350 manager);
351
352 // Fetch the ip address from the system
353 // and create the dbus object.
354 vlanIntf->createIPAddressObjects();
355
356 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
357 std::move(vlanIntf));
358}
359
Ratan Gupta5978dd12017-07-25 13:47:13 +0530360void EthernetInterface::createVLAN(VlanId id)
361{
362 std::string vlanInterfaceName = interfaceName() + "." +
363 std::to_string(id);
364 std::string path = objPath;
365 path += "_" + std::to_string(id);
366
367
368 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
369 bus,
370 path.c_str(),
Ratan Guptae05083a2017-09-16 07:12:11 +0530371 false,
Ratan Gupta5978dd12017-07-25 13:47:13 +0530372 id,
373 *this,
374 manager);
375
376 // write the device file for the vlan interface.
377 vlanIntf->writeDeviceFile();
378
Ratan Gupta6e8df632017-08-13 09:41:58 +0530379 this->vlanInterfaces.emplace(vlanInterfaceName,
Ratan Gupta5978dd12017-07-25 13:47:13 +0530380 std::move(vlanIntf));
381 // write the new vlan device entry to the configuration(network) file.
Ratan Guptae05083a2017-09-16 07:12:11 +0530382 manager.writeToConfigurationFile();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530383}
Ratan Gupta2b106532017-07-25 16:05:02 +0530384
Ratan Gupta497c0c92017-08-22 19:15:59 +0530385ServerList EthernetInterface::getNTPServersFromConf()
386{
387 fs::path confPath = manager.getConfDir();
388
389 std::string fileName = systemd::config::networkFilePrefix + interfaceName() +
390 systemd::config::networkFileSuffix;
391 confPath /= fileName;
392 ServerList servers;
393 try
394 {
395 config::Parser parser(confPath.string());
396 servers = parser.getValues("Network", "NTP");
397 }
398 catch (InternalFailure& e)
399 {
400 log<level::INFO>("Unable to find the NTP server configuration.");
401 }
402 return servers;
403}
404
405ServerList EthernetInterface::nTPServers(ServerList servers)
406{
407 auto ntpServers = EthernetInterfaceIntf::nTPServers(servers);
408
409 writeConfigurationFile();
410 // timesynchd reads the NTP server configuration from the
411 // network file.
412 restartSystemdUnit(timeSynchdService);
413 return ntpServers;
414}
Ratan Gupta2b106532017-07-25 16:05:02 +0530415// Need to merge the below function with the code which writes the
416// config file during factory reset.
417// TODO openbmc/openbmc#1751
418
419void EthernetInterface::writeConfigurationFile()
420{
421 // write all the static ip address in the systemd-network conf file
422
423 using namespace std::string_literals;
424 using AddressOrigin =
425 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
426 namespace fs = std::experimental::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530427
428 // if there is vlan interafce then write the configuration file
429 // for vlan also.
430
431 for (const auto& intf: vlanInterfaces)
432 {
433 intf.second->writeConfigurationFile();
434 }
435
Ratan Gupta2b106532017-07-25 16:05:02 +0530436 fs::path confPath = manager.getConfDir();
437
Ratan Guptabc886292017-07-25 18:29:57 +0530438 std::string fileName = systemd::config::networkFilePrefix + interfaceName() +
439 systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +0530440 confPath /= fileName;
441 std::fstream stream;
442
443 stream.open(confPath.c_str(), std::fstream::out);
444 if (!stream.is_open())
445 {
446 log<level::ERR>("Unable to open the file",
447 entry("FILE=%s", confPath.c_str()));
448 elog<InternalFailure>();
449 }
450
451 // Write the device
452 stream << "[" << "Match" << "]\n";
453 stream << "Name=" << interfaceName() << "\n";
454
455 auto addrs = getAddresses();
456
457 // write the network section
458 stream << "[" << "Network" << "]\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +0530459
460 // Add the VLAN entry
461 for (const auto& intf: vlanInterfaces)
462 {
463 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
464 << "\n";
465 }
466
Ratan Gupta2b106532017-07-25 16:05:02 +0530467 // DHCP
468 if (dHCPEnabled() == true)
469 {
470 // write the dhcp section if interface is
471 // configured as dhcp.
472 writeDHCPSection(stream);
473 stream.close();
474 return;
475 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530476
Ratan Gupta497c0c92017-08-22 19:15:59 +0530477 //Add the NTP server
478 for(const auto& ntp: EthernetInterfaceIntf::nTPServers())
479 {
480 stream << "NTP=" << ntp << "\n";
481 }
482
Ratan Gupta2b106532017-07-25 16:05:02 +0530483 // Static
484 for (const auto& addr : addrs)
485 {
486 if (addr.second->origin() == AddressOrigin::Static)
487 {
488 std::string address = addr.second->address() + "/" + std::to_string(
489 addr.second->prefixLength());
490
491 stream << "Address=" << address << "\n";
492 }
493 }
494
495 if (manager.getSystemConf())
496 {
497 stream << "Gateway=" << manager.getSystemConf()->defaultGateway()
498 << "\n";
499 }
500 // write the route section
501 stream << "[" << "Route" << "]\n";
502 for(const auto& addr : addrs)
503 {
504 if (addr.second->origin() == AddressOrigin::Static)
505 {
506 int addressFamily = addr.second->type() == IP::Protocol::IPv4 ? AF_INET : AF_INET6;
507 std::string destination = getNetworkID(
508 addressFamily,
509 addr.second->address(),
510 addr.second->prefixLength());
511
512 if (addr.second->gateway() != "0.0.0.0" &&
513 addr.second->gateway() != "" &&
514 destination != "0.0.0.0" &&
515 destination != "")
516 {
517 stream << "Gateway=" << addr.second->gateway() << "\n";
518 stream << "Destination=" << destination << "\n";
519 }
520
521 }
522 }
523
524 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +0530525}
526
527void EthernetInterface::writeDHCPSection(std::fstream& stream)
528{
529 using namespace std::string_literals;
530 stream << "DHCP=true\n";
531 // write the dhcp section
532 stream << "[DHCP]\n";
533
534 // Hardcoding the client identifier to mac, to address below issue
535 // https://github.com/openbmc/openbmc/issues/1280
536 stream << "ClientIdentifier=mac\n";
537 if (manager.getDHCPConf())
538 {
539 auto value = manager.getDHCPConf()->dNSEnabled() ? "true"s : "false"s;
540 stream << "UseDNS="s + value + "\n";
541
542 value = manager.getDHCPConf()->nTPEnabled() ? "true"s : "false"s;
543 stream << "UseNTP="s + value + "\n";
544
545 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
546 stream << "UseHostname="s + value + "\n";
547 }
548}
549
Ratan Guptabd303b12017-08-18 17:10:07 +0530550std::string EthernetInterface::mACAddress(std::string value)
551{
552 if (!mac_address::validate(value))
553 {
554 log<level::DEBUG>("MACAddress is not valid.",
555 entry("MAC=%s", value.c_str()));
556 return MacAddressIntf::mACAddress();
557 }
558
559 // check whether MAC is broadcast mac.
560 auto intMac = mac_address::internal::convertToInt(value);
561
562 if (!(intMac ^ mac_address::broadcastMac))
563 {
564 log<level::DEBUG>("MACAddress is a broadcast mac.",
565 entry("MAC=%s", value.c_str()));
566 return MacAddressIntf::mACAddress();
567 }
568
569 // Allow the mac to be set if one of the condition is true.
570 // 1) Incoming Mac is of local admin type.
571 // or
572 // 2) Incoming mac is same as eeprom Mac.
573
574 if (!(intMac & mac_address::localAdminMask))
575 {
576 try
577 {
578 auto inventoryMac = mac_address::getfromInventory(bus);
579 auto intInventoryMac = mac_address::internal::convertToInt(inventoryMac);
580
581 if (intInventoryMac != intMac)
582 {
583 log<level::DEBUG>("Given MAC address is neither a local Admin \
584 type nor is same as in inventory");
585 return MacAddressIntf::mACAddress();
586 }
587 }
588 catch(InternalFailure& e)
589 {
590 log<level::ERR>("Exception occured during getting of MAC \
591 address from Inventory");
592 return MacAddressIntf::mACAddress();
593 }
594 }
595 auto interface = interfaceName();
596 execute("/sbin/fw_setenv", "fw_setenv", "ethaddr", value.c_str());
597 //TODO: would replace below three calls
598 // with restarting of systemd-netwokd
599 // through https://github.com/systemd/systemd/issues/6696
600 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(), "down");
601 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(), "address",
602 value.c_str());
603
604 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(), "up");
605
606 auto mac = MacAddressIntf::mACAddress(std::move(value));
607 //update all the vlan interfaces
608 for(const auto& intf: vlanInterfaces)
609 {
610 intf.second->updateMacAddress();
611 }
Ratan Gupta677ae122017-09-18 16:28:50 +0530612
613 // restart the systemd networkd so that dhcp client gets the
614 // ip for the changed mac address.
615 if (dHCPEnabled())
616 {
617 restartSystemdUnit("systemd-networkd.service");
618 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530619 return mac;
620
621}
622
Ratan Guptae9c9b812017-09-22 17:15:37 +0530623void EthernetInterface::deleteAll()
624{
625 if(EthernetInterfaceIntf::dHCPEnabled())
626 {
627 log<level::INFO>("DHCP enabled on the interface"),
628 entry("INTERFACE=%s", interfaceName().c_str());
629
630 }
631
632 // clear all the ip on the interface
633 addrs.clear();
634 manager.writeToConfigurationFile();
635}
636
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530637}//namespace network
638}//namespace phosphor