blob: c3bac59c4486feada5688ac518ad31ffb0bfce5e [file] [log] [blame]
Ratan Gupta82549cc2017-04-21 08:45:23 +05301#include "config.h"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05302#include "ethernet_interface.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05303#include "ipaddress.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05304#include "network_manager.hpp"
Ratan Guptafc2c7242017-05-29 08:46:06 +05305#include "routing_table.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05306#include "vlan_interface.hpp"
7#include "xyz/openbmc_project/Common/error.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05308
Ratan Gupta2b106532017-07-25 16:05:02 +05309#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053010#include <phosphor-logging/log.hpp>
11
Ratan Gupta82549cc2017-04-21 08:45:23 +053012#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053013#include <linux/ethtool.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016#include <netinet/in.h>
17#include <sys/ioctl.h>
18#include <sys/socket.h>
19#include <unistd.h>
20
Ratan Gupta2b106532017-07-25 16:05:02 +053021
Ratan Gupta82549cc2017-04-21 08:45:23 +053022#include <algorithm>
23#include <experimental/filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <fstream>
25#include <sstream>
26#include <string>
Ratan Gupta82549cc2017-04-21 08:45:23 +053027
Ratan Gupta91a99cc2017-04-14 16:32:09 +053028namespace phosphor
29{
30namespace network
31{
32
33using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053034using namespace sdbusplus::xyz::openbmc_project::Common::Error;
35
Ratan Gupta91a99cc2017-04-14 16:32:09 +053036EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
37 const std::string& objPath,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053038 bool dhcpEnabled,
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053039 Manager& parent,
40 bool emitSignal) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053041 Ifaces(bus, objPath.c_str(), true),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053042 bus(bus),
Ratan Gupta47722dc2017-05-26 18:32:23 +053043 manager(parent),
44 objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053045{
46 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053047 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053048 interfaceName(intfName);
Ratan Guptac35481d2017-08-18 06:12:26 +053049 EthernetInterfaceIntf::dHCPEnabled(dhcpEnabled);
Ratan Guptabd303b12017-08-18 17:10:07 +053050 MacAddressIntf::mACAddress(getMACAddress(intfName));
Ratan Gupta5978dd12017-07-25 13:47:13 +053051
Ratan Gupta29b0e432017-05-25 12:51:40 +053052 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053053 if (emitSignal)
54 {
55 this->emit_object_added();
56 }
Ratan Gupta29b0e432017-05-25 12:51:40 +053057}
58
Ratan Gupta87c13982017-06-15 09:27:27 +053059void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +053060{
Ratan Gupta82549cc2017-04-21 08:45:23 +053061 std::string gateway;
Ratan Gupta87c13982017-06-15 09:27:27 +053062 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +053063
Ratan Gupta87c13982017-06-15 09:27:27 +053064 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +053065
Ratan Gupta82549cc2017-04-21 08:45:23 +053066 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053067 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Guptafc2c7242017-05-29 08:46:06 +053068 route::Table routingTable;
Ratan Gupta5978dd12017-07-25 13:47:13 +053069
Ratan Gupta6a387c12017-08-03 13:26:19 +053070 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +053071 {
72 if (addr.addrType == AF_INET6)
73 {
74 addressType = IP::Protocol::IPv6;
75 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053076 if (dHCPEnabled())
77 {
78 origin = IP::AddressOrigin::DHCP;
79 }
80 else if (isLinkLocal(addr.ipaddress))
81 {
82 origin = IP::AddressOrigin::LinkLocal;
83 }
84 gateway = routingTable.getGateway(addr.addrType, addr.ipaddress, addr.prefix);
Ratan Gupta82549cc2017-04-21 08:45:23 +053085
Ratan Gupta65e5abe2017-05-23 13:20:44 +053086 std::string ipAddressObjectPath = generateObjectPath(addressType,
87 addr.ipaddress,
88 addr.prefix,
89 gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +053090
Ratan Gupta82549cc2017-04-21 08:45:23 +053091 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +053092 std::move(addr.ipaddress),
93 std::make_shared<phosphor::network::IPAddress>(
Ratan Gupta719f83a2017-06-02 11:54:53 +053094 bus,
95 ipAddressObjectPath.c_str(),
96 *this,
97 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053098 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053099 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +0530100 addr.prefix,
Ratan Guptae578d562017-08-02 07:04:16 +0530101 gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530102 }
Ratan Guptafc2c7242017-05-29 08:46:06 +0530103
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530104}
105
Ratan Gupta82549cc2017-04-21 08:45:23 +0530106void EthernetInterface::iP(IP::Protocol protType,
107 std::string ipaddress,
108 uint8_t prefixLength,
109 std::string gateway)
110{
Ratan Guptafc2c7242017-05-29 08:46:06 +0530111
112 if (dHCPEnabled())
113 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530114 log<level::INFO>("DHCP enabled on the interface"),
Ratan Guptabd303b12017-08-18 17:10:07 +0530115 entry("INTERFACE=%s",interfaceName().c_str());
Ratan Guptafc2c7242017-05-29 08:46:06 +0530116 return;
117 }
118
Ratan Gupta29b0e432017-05-25 12:51:40 +0530119 IP::AddressOrigin origin = IP::AddressOrigin::Static;
120
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530121 std::string objectPath = generateObjectPath(protType,
122 ipaddress,
123 prefixLength,
124 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530125 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +0530126 std::move(ipaddress),
127 std::make_shared<phosphor::network::IPAddress>(
128 bus,
129 objectPath.c_str(),
130 *this,
131 protType,
132 ipaddress,
133 origin,
134 prefixLength,
135 gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530136
Ratan Guptae05083a2017-09-16 07:12:11 +0530137 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530138}
139
140
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530141/*
142Note: We don't have support for ethtool now
143will enable this code once we bring the ethtool
144in the image.
145TODO: https://github.com/openbmc/openbmc/issues/1484
146*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530147
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530148InterfaceInfo EthernetInterface::getInterfaceInfo() const
149{
150 int sock{-1};
151 struct ifreq ifr{0};
152 struct ethtool_cmd edata{0};
153 LinkSpeed speed {0};
154 Autoneg autoneg {0};
155 DuplexMode duplex {0};
156 do
157 {
158 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
159 if (sock < 0)
160 {
161 log<level::ERR>("socket creation failed:",
162 entry("ERROR=%s", strerror(errno)));
163 break;
164 }
165
166 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
167 ifr.ifr_data = reinterpret_cast<char*>(&edata);
168
169 edata.cmd = ETHTOOL_GSET;
170
171 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
172 {
173 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
174 entry("ERROR=%s", strerror(errno)));
175 break;
176
177 }
178 speed = edata.speed;
179 duplex = edata.duplex;
180 autoneg = edata.autoneg;
181 }
182 while (0);
183
184 if (sock)
185 {
186 close(sock);
187 }
188 return std::make_tuple(speed, duplex, autoneg);
189}
190
191/** @brief get the mac address of the interface.
192 * @return macaddress on success
193 */
194
Ratan Guptada7d3af2017-08-13 17:49:56 +0530195std::string EthernetInterface::getMACAddress(
196 const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530197{
Ratan Guptada7d3af2017-08-13 17:49:56 +0530198 struct ifreq ifr{};
Ratan Guptabd303b12017-08-18 17:10:07 +0530199 char macAddress[mac_address::size] {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530200
201 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
202 if (sock < 0)
203 {
204 log<level::ERR>("socket creation failed:",
205 entry("ERROR=%s", strerror(errno)));
206 return macAddress;
207 }
208
Ratan Guptada7d3af2017-08-13 17:49:56 +0530209 strcpy(ifr.ifr_name, interfaceName.c_str());
210 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530211 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530212 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
213 entry("ERROR=%s", strerror(errno)));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530214 return macAddress;
215 }
216
Ratan Guptabd303b12017-08-18 17:10:07 +0530217 snprintf(macAddress, mac_address::size, mac_address::format,
Ratan Guptada7d3af2017-08-13 17:49:56 +0530218 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
219 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
220 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530221
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530222 return macAddress;
223}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530224
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530225std::string EthernetInterface::generateId(const std::string& ipaddress,
226 uint8_t prefixLength,
227 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530228{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530229 std::stringstream hexId;
230 std::string hashString = ipaddress;
231 hashString += std::to_string(prefixLength);
232 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530233
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530234 // Only want 8 hex digits.
235 hexId << std::hex << ((std::hash<std::string> {}(
Ratan Guptafc2c7242017-05-29 08:46:06 +0530236 hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530237 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530238}
239
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530240void EthernetInterface::deleteObject(const std::string& ipaddress)
241{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530242 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530243 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530244 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530245 log<level::ERR>("DeleteObject:Unable to find the object.");
246 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530247 }
248 this->addrs.erase(it);
Ratan Guptae05083a2017-09-16 07:12:11 +0530249 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530250}
251
Ratan Guptae9c9b812017-09-22 17:15:37 +0530252void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530253{
Ratan Guptabc886292017-07-25 18:29:57 +0530254 auto confDir = manager.getConfDir();
255 fs::path networkFile = confDir;
256 networkFile /= systemd::config::networkFilePrefix + interface +
257 systemd::config::networkFileSuffix;
258
259 fs::path deviceFile = confDir;
260 deviceFile /= interface + systemd::config::deviceFileSuffix;
261
262 // delete the vlan network file
263 if (fs::is_regular_file(networkFile))
264 {
265 fs::remove(networkFile);
266 }
267
268 // delete the vlan device file
269 if (fs::is_regular_file(deviceFile))
270 {
271 fs::remove(deviceFile);
272 }
Ratan Guptabc886292017-07-25 18:29:57 +0530273
274 // TODO systemd doesn't delete the virtual network interface
275 // even after deleting all the related configuartion.
276 // https://github.com/systemd/systemd/issues/6600
277 try
278 {
279 deleteInterface(interface);
280 }
281 catch (InternalFailure& e)
282 {
283 commit<InternalFailure>();
284 }
Ratan Guptae05083a2017-09-16 07:12:11 +0530285
Ratan Guptae9c9b812017-09-22 17:15:37 +0530286}
287
288void EthernetInterface::deleteVLANObject(const std::string& interface)
289{
290 auto it = vlanInterfaces.find(interface);
291 if (it == vlanInterfaces.end())
292 {
293 log<level::ERR>("DeleteVLANObject:Unable to find the object",
294 entry("INTERFACE=%s",interface.c_str()));
295 return;
296 }
297
298 deleteVLANFromSystem(interface);
299 // delete the interface
300 vlanInterfaces.erase(it);
301
Ratan Guptae05083a2017-09-16 07:12:11 +0530302 manager.writeToConfigurationFile();
Ratan Guptabc886292017-07-25 18:29:57 +0530303}
304
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530305std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
306 const std::string& ipaddress,
307 uint8_t prefixLength,
308 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530309{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530310 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530311 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530312 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
313
314 std::experimental::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530315 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530316 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530317 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530318 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530319}
320
Ratan Gupta87c13982017-06-15 09:27:27 +0530321bool EthernetInterface::dHCPEnabled(bool value)
322{
Ratan Gupta5978dd12017-07-25 13:47:13 +0530323 if (value == EthernetInterfaceIntf::dHCPEnabled())
324 {
325 return value;
326 }
327
Ratan Gupta87c13982017-06-15 09:27:27 +0530328 EthernetInterfaceIntf::dHCPEnabled(value);
Ratan Guptae05083a2017-09-16 07:12:11 +0530329 manager.writeToConfigurationFile();
Ratan Gupta87c13982017-06-15 09:27:27 +0530330 return value;
331}
332
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530333void EthernetInterface::loadVLAN(VlanId id)
334{
335 std::string vlanInterfaceName = interfaceName() + "." +
336 std::to_string(id);
337 std::string path = objPath;
338 path += "_" + std::to_string(id);
339
Ratan Gupta6e8df632017-08-13 09:41:58 +0530340 auto dhcpEnabled = getDHCPValue(manager.getConfDir().string(),
341 vlanInterfaceName);
342
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530343 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
344 bus,
345 path.c_str(),
Ratan Gupta6e8df632017-08-13 09:41:58 +0530346 dhcpEnabled,
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530347 id,
348 *this,
349 manager);
350
351 // Fetch the ip address from the system
352 // and create the dbus object.
353 vlanIntf->createIPAddressObjects();
354
355 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
356 std::move(vlanIntf));
357}
358
Ratan Gupta5978dd12017-07-25 13:47:13 +0530359void EthernetInterface::createVLAN(VlanId id)
360{
361 std::string vlanInterfaceName = interfaceName() + "." +
362 std::to_string(id);
363 std::string path = objPath;
364 path += "_" + std::to_string(id);
365
366
367 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
368 bus,
369 path.c_str(),
Ratan Guptae05083a2017-09-16 07:12:11 +0530370 false,
Ratan Gupta5978dd12017-07-25 13:47:13 +0530371 id,
372 *this,
373 manager);
374
375 // write the device file for the vlan interface.
376 vlanIntf->writeDeviceFile();
377
Ratan Gupta6e8df632017-08-13 09:41:58 +0530378 this->vlanInterfaces.emplace(vlanInterfaceName,
Ratan Gupta5978dd12017-07-25 13:47:13 +0530379 std::move(vlanIntf));
380 // write the new vlan device entry to the configuration(network) file.
Ratan Guptae05083a2017-09-16 07:12:11 +0530381 manager.writeToConfigurationFile();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530382}
Ratan Gupta2b106532017-07-25 16:05:02 +0530383
384// Need to merge the below function with the code which writes the
385// config file during factory reset.
386// TODO openbmc/openbmc#1751
387
388void EthernetInterface::writeConfigurationFile()
389{
390 // write all the static ip address in the systemd-network conf file
391
392 using namespace std::string_literals;
393 using AddressOrigin =
394 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
395 namespace fs = std::experimental::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530396
397 // if there is vlan interafce then write the configuration file
398 // for vlan also.
399
400 for (const auto& intf: vlanInterfaces)
401 {
402 intf.second->writeConfigurationFile();
403 }
404
Ratan Gupta2b106532017-07-25 16:05:02 +0530405 fs::path confPath = manager.getConfDir();
406
Ratan Guptabc886292017-07-25 18:29:57 +0530407 std::string fileName = systemd::config::networkFilePrefix + interfaceName() +
408 systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +0530409 confPath /= fileName;
410 std::fstream stream;
411
412 stream.open(confPath.c_str(), std::fstream::out);
413 if (!stream.is_open())
414 {
415 log<level::ERR>("Unable to open the file",
416 entry("FILE=%s", confPath.c_str()));
417 elog<InternalFailure>();
418 }
419
420 // Write the device
421 stream << "[" << "Match" << "]\n";
422 stream << "Name=" << interfaceName() << "\n";
423
424 auto addrs = getAddresses();
425
426 // write the network section
427 stream << "[" << "Network" << "]\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +0530428
429 // Add the VLAN entry
430 for (const auto& intf: vlanInterfaces)
431 {
432 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
433 << "\n";
434 }
435
Ratan Gupta2b106532017-07-25 16:05:02 +0530436 // DHCP
437 if (dHCPEnabled() == true)
438 {
439 // write the dhcp section if interface is
440 // configured as dhcp.
441 writeDHCPSection(stream);
442 stream.close();
443 return;
444 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530445
446 // Static
447 for (const auto& addr : addrs)
448 {
449 if (addr.second->origin() == AddressOrigin::Static)
450 {
451 std::string address = addr.second->address() + "/" + std::to_string(
452 addr.second->prefixLength());
453
454 stream << "Address=" << address << "\n";
455 }
456 }
457
458 if (manager.getSystemConf())
459 {
460 stream << "Gateway=" << manager.getSystemConf()->defaultGateway()
461 << "\n";
462 }
463 // write the route section
464 stream << "[" << "Route" << "]\n";
465 for(const auto& addr : addrs)
466 {
467 if (addr.second->origin() == AddressOrigin::Static)
468 {
469 int addressFamily = addr.second->type() == IP::Protocol::IPv4 ? AF_INET : AF_INET6;
470 std::string destination = getNetworkID(
471 addressFamily,
472 addr.second->address(),
473 addr.second->prefixLength());
474
475 if (addr.second->gateway() != "0.0.0.0" &&
476 addr.second->gateway() != "" &&
477 destination != "0.0.0.0" &&
478 destination != "")
479 {
480 stream << "Gateway=" << addr.second->gateway() << "\n";
481 stream << "Destination=" << destination << "\n";
482 }
483
484 }
485 }
486
487 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +0530488}
489
490void EthernetInterface::writeDHCPSection(std::fstream& stream)
491{
492 using namespace std::string_literals;
493 stream << "DHCP=true\n";
494 // write the dhcp section
495 stream << "[DHCP]\n";
496
497 // Hardcoding the client identifier to mac, to address below issue
498 // https://github.com/openbmc/openbmc/issues/1280
499 stream << "ClientIdentifier=mac\n";
500 if (manager.getDHCPConf())
501 {
502 auto value = manager.getDHCPConf()->dNSEnabled() ? "true"s : "false"s;
503 stream << "UseDNS="s + value + "\n";
504
505 value = manager.getDHCPConf()->nTPEnabled() ? "true"s : "false"s;
506 stream << "UseNTP="s + value + "\n";
507
508 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
509 stream << "UseHostname="s + value + "\n";
510 }
511}
512
Ratan Guptabd303b12017-08-18 17:10:07 +0530513std::string EthernetInterface::mACAddress(std::string value)
514{
515 if (!mac_address::validate(value))
516 {
517 log<level::DEBUG>("MACAddress is not valid.",
518 entry("MAC=%s", value.c_str()));
519 return MacAddressIntf::mACAddress();
520 }
521
522 // check whether MAC is broadcast mac.
523 auto intMac = mac_address::internal::convertToInt(value);
524
525 if (!(intMac ^ mac_address::broadcastMac))
526 {
527 log<level::DEBUG>("MACAddress is a broadcast mac.",
528 entry("MAC=%s", value.c_str()));
529 return MacAddressIntf::mACAddress();
530 }
531
532 // Allow the mac to be set if one of the condition is true.
533 // 1) Incoming Mac is of local admin type.
534 // or
535 // 2) Incoming mac is same as eeprom Mac.
536
537 if (!(intMac & mac_address::localAdminMask))
538 {
539 try
540 {
541 auto inventoryMac = mac_address::getfromInventory(bus);
542 auto intInventoryMac = mac_address::internal::convertToInt(inventoryMac);
543
544 if (intInventoryMac != intMac)
545 {
546 log<level::DEBUG>("Given MAC address is neither a local Admin \
547 type nor is same as in inventory");
548 return MacAddressIntf::mACAddress();
549 }
550 }
551 catch(InternalFailure& e)
552 {
553 log<level::ERR>("Exception occured during getting of MAC \
554 address from Inventory");
555 return MacAddressIntf::mACAddress();
556 }
557 }
558 auto interface = interfaceName();
559 execute("/sbin/fw_setenv", "fw_setenv", "ethaddr", value.c_str());
560 //TODO: would replace below three calls
561 // with restarting of systemd-netwokd
562 // through https://github.com/systemd/systemd/issues/6696
563 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(), "down");
564 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(), "address",
565 value.c_str());
566
567 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(), "up");
568
569 auto mac = MacAddressIntf::mACAddress(std::move(value));
570 //update all the vlan interfaces
571 for(const auto& intf: vlanInterfaces)
572 {
573 intf.second->updateMacAddress();
574 }
Ratan Gupta677ae122017-09-18 16:28:50 +0530575
576 // restart the systemd networkd so that dhcp client gets the
577 // ip for the changed mac address.
578 if (dHCPEnabled())
579 {
580 restartSystemdUnit("systemd-networkd.service");
581 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530582 return mac;
583
584}
585
Ratan Guptae9c9b812017-09-22 17:15:37 +0530586void EthernetInterface::deleteAll()
587{
588 if(EthernetInterfaceIntf::dHCPEnabled())
589 {
590 log<level::INFO>("DHCP enabled on the interface"),
591 entry("INTERFACE=%s", interfaceName().c_str());
592
593 }
594
595 // clear all the ip on the interface
596 addrs.clear();
597 manager.writeToConfigurationFile();
598}
599
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530600}//namespace network
601}//namespace phosphor