blob: 504090f865d3494fe308650b26a0e41ef914543f [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include "config.h"
2
Patrick Venture189d44e2018-07-09 12:30:59 -07003#include "ethernet_interface.hpp"
4
Ratan Gupta497c0c92017-08-22 19:15:59 +05305#include "config_parser.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08006#include "neighbor.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05307#include "network_manager.hpp"
Ravi Tejaa5a09442020-07-17 00:57:33 -05008#include "routing_table.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05309#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +053010
Ratan Gupta82549cc2017-04-21 08:45:23 +053011#include <arpa/inet.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070012#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053013#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070014#include <linux/rtnetlink.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 Gupta82549cc2017-04-21 08:45:23 +053022#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053023#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070025#include <phosphor-logging/elog-errors.hpp>
26#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070027#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053028#include <sstream>
William A. Kennington III12beaad2020-06-13 19:30:41 -070029#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053030#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070031#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070032#include <unordered_map>
33#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070034#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053035
Ratan Gupta91a99cc2017-04-14 16:32:09 +053036namespace phosphor
37{
38namespace network
39{
40
41using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053042using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053043using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
44using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050045using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053046constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
47constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
48constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
49constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
50constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053051
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080052struct EthernetIntfSocket
53{
54 EthernetIntfSocket(int domain, int type, int protocol)
55 {
56 if ((sock = socket(domain, type, protocol)) < 0)
57 {
58 log<level::ERR>("socket creation failed:",
59 entry("ERROR=%s", strerror(errno)));
60 }
61 }
62
63 ~EthernetIntfSocket()
64 {
65 if (sock >= 0)
66 {
67 close(sock);
68 }
69 }
70
71 int sock{-1};
72};
73
Johnathan Mantey817012a2020-01-30 15:07:39 -080074std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
75 {EthernetInterface::DHCPConf::both, "true"},
76 {EthernetInterface::DHCPConf::v4, "ipv4"},
77 {EthernetInterface::DHCPConf::v6, "ipv6"},
78 {EthernetInterface::DHCPConf::none, "false"}};
79
Ratan Gupta91a99cc2017-04-14 16:32:09 +053080EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
81 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080082 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070083 bool emitSignal,
84 std::optional<bool> enabled) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050085 Ifaces(bus, objPath.c_str(), true),
86 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053087{
88 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053089 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053090 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050091 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
92 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070093 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
Ravi Tejaa5a09442020-07-17 00:57:33 -050094 route::Table routingTable;
95 auto gatewayList = routingTable.getDefaultGateway();
96 auto gateway6List = routingTable.getDefaultGateway6();
97 std::string defaultGateway;
98 std::string defaultGateway6;
99
100 for (auto& gateway : gatewayList)
101 {
102 if (gateway.first == intfName)
103 {
104 defaultGateway = gateway.second;
105 break;
106 }
107 }
108
109 for (auto& gateway6 : gateway6List)
110 {
111 if (gateway6.first == intfName)
112 {
113 defaultGateway6 = gateway6.second;
114 break;
115 }
116 }
117
118 EthernetInterfaceIntf::defaultGateway(defaultGateway);
119 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530120 // Don't get the mac address from the system as the mac address
121 // would be same as parent interface.
122 if (intfName.find(".") == std::string::npos)
123 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500124 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530125 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500126 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
Ratan Gupta613a0122020-04-24 15:18:53 +0530127
128 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530129 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530130
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700131#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700132 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
133
134 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
135 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800136#endif
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530137
Ratan Gupta29b0e432017-05-25 12:51:40 +0530138 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530139 if (emitSignal)
140 {
141 this->emit_object_added();
142 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530143}
144
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800145static IP::Protocol convertFamily(int family)
146{
147 switch (family)
148 {
149 case AF_INET:
150 return IP::Protocol::IPv4;
151 case AF_INET6:
152 return IP::Protocol::IPv6;
153 }
154
155 throw std::invalid_argument("Bad address family");
156}
157
Johnathan Mantey817012a2020-01-30 15:07:39 -0800158void EthernetInterface::disableDHCP(IP::Protocol protocol)
159{
Patrick Williams6aef7692021-05-01 06:39:41 -0500160 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800161 if (dhcpState == EthernetInterface::DHCPConf::both)
162 {
163 if (protocol == IP::Protocol::IPv4)
164 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500165 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800166 }
167 else if (protocol == IP::Protocol::IPv6)
168 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500169 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800170 }
171 }
172 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
173 (protocol == IP::Protocol::IPv4))
174 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500175 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800176 }
177 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
178 (protocol == IP::Protocol::IPv6))
179 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500180 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800181 }
182}
183
184bool EthernetInterface::dhcpIsEnabled(IP::Protocol family, bool ignoreProtocol)
185{
Patrick Williams6aef7692021-05-01 06:39:41 -0500186 return ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800187 EthernetInterface::DHCPConf::both) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500188 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800189 EthernetInterface::DHCPConf::v6) &&
190 ((family == IP::Protocol::IPv6) || ignoreProtocol)) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500191 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800192 EthernetInterface::DHCPConf::v4) &&
193 ((family == IP::Protocol::IPv4) || ignoreProtocol)));
194}
195
196bool EthernetInterface::dhcpToBeEnabled(IP::Protocol family,
197 const std::string& nextDHCPState)
198{
199 return ((nextDHCPState == "true") ||
200 ((nextDHCPState == "ipv6") && (family == IP::Protocol::IPv6)) ||
201 ((nextDHCPState == "ipv4") && (family == IP::Protocol::IPv4)));
202}
203
204bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
205{
206 return (
207#ifdef LINK_LOCAL_AUTOCONFIGURATION
208 (origin == IP::AddressOrigin::Static)
209#else
210 (origin == IP::AddressOrigin::Static ||
211 origin == IP::AddressOrigin::LinkLocal)
212#endif
213
214 );
215}
216
Ratan Gupta87c13982017-06-15 09:27:27 +0530217void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530218{
Ratan Gupta87c13982017-06-15 09:27:27 +0530219 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530220
Ratan Gupta87c13982017-06-15 09:27:27 +0530221 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530222
Ratan Gupta6a387c12017-08-03 13:26:19 +0530223 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530224 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800225 IP::Protocol addressType = convertFamily(addr.addrType);
226 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800227 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530228 {
229 origin = IP::AddressOrigin::DHCP;
230 }
William A. Kennington III16893802019-01-30 16:01:01 -0800231 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530232 {
233 origin = IP::AddressOrigin::LinkLocal;
234 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700235 // Obsolete parameter
236 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530237
Gunnar Mills57d9c502018-09-14 14:42:34 -0500238 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800239 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530240
Lei YU7233c582021-04-08 14:39:43 +0800241 this->addrs.insert_or_assign(
242 addr.ipaddress,
243 std::make_shared<phosphor::network::IPAddress>(
244 bus, ipAddressObjectPath.c_str(), *this, addressType,
245 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530246 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530247}
248
William A. Kennington III08505792019-01-30 16:00:04 -0800249void EthernetInterface::createStaticNeighborObjects()
250{
251 staticNeighbors.clear();
252
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700253 NeighborFilter filter;
254 filter.interface = ifIndex();
255 filter.state = NUD_PERMANENT;
256 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800257 for (const auto& neighbor : neighbors)
258 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700259 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800260 {
261 continue;
262 }
263 std::string ip = toString(neighbor.address);
264 std::string mac = mac_address::toString(*neighbor.mac);
265 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
266 staticNeighbors.emplace(ip,
267 std::make_shared<phosphor::network::Neighbor>(
268 bus, objectPath.c_str(), *this, ip, mac,
269 Neighbor::State::Permanent));
270 }
271}
272
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700273unsigned EthernetInterface::ifIndex() const
274{
275 unsigned idx = if_nametoindex(interfaceName().c_str());
276 if (idx == 0)
277 {
278 throw std::system_error(errno, std::generic_category(),
279 "if_nametoindex");
280 }
281 return idx;
282}
283
Patrick Williams6aef7692021-05-01 06:39:41 -0500284ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500285 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530286{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800287 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530288 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530289 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500290 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800291 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500292 }
293
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500294 IP::AddressOrigin origin = IP::AddressOrigin::Static;
295
296 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
297
298 if (!isValidIP(addressFamily, ipaddress))
299 {
300 log<level::ERR>("Not a valid IP address"),
301 entry("ADDRESS=%s", ipaddress.c_str());
302 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
303 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
304 }
305
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700306 // Gateway is an obsolete parameter
307 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500308
309 if (!isValidPrefix(addressFamily, prefixLength))
310 {
311 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700312 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500313 elog<InvalidArgument>(
314 Argument::ARGUMENT_NAME("prefixLength"),
315 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530316 }
317
Gunnar Mills57d9c502018-09-14 14:42:34 -0500318 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800319 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800320 this->addrs.insert_or_assign(ipaddress,
321 std::make_shared<phosphor::network::IPAddress>(
322 bus, objectPath.c_str(), *this, protType,
323 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530324
Ratan Guptae05083a2017-09-16 07:12:11 +0530325 manager.writeToConfigurationFile();
raviteja-bce379562019-03-28 05:59:36 -0500326 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530327}
328
Patrick Williams6aef7692021-05-01 06:39:41 -0500329ObjectPath EthernetInterface::neighbor(std::string ipAddress,
330 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800331{
Patrick Williams6aef7692021-05-01 06:39:41 -0500332 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800333 {
334 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500335 entry("ADDRESS=%s", ipAddress.c_str()));
336 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
337 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800338 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500339 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800340 {
341 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500342 entry("MACADDRESS=%s", ipAddress.c_str()));
343 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
344 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800345 }
346
347 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500348 generateStaticNeighborObjectPath(ipAddress, macAddress);
349 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800350 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500351 bus, objectPath.c_str(), *this, ipAddress,
352 macAddress, Neighbor::State::Permanent));
William A. Kennington III08505792019-01-30 16:00:04 -0800353 manager.writeToConfigurationFile();
354 return objectPath;
355}
356
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700357#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530358/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800359 Enable this code if your NIC driver supports the ETHTOOL features.
360 Do this by adding the following to your phosphor-network*.bbappend file.
361 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
362 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530363*/
364InterfaceInfo EthernetInterface::getInterfaceInfo() const
365{
William A. Kennington III05368f12021-05-13 18:40:47 -0700366 ifreq ifr = {};
367 ethtool_cmd edata = {};
368 LinkSpeed speed = {};
369 Autoneg autoneg = {};
370 DuplexMode duplex = {};
371 LinkUp linkState = {};
372 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530373 MTU mtuSize = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800374 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
375
376 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530377 {
Tejas Patil2c0fc562021-08-03 19:13:46 +0530378 return std::make_tuple(speed, duplex, autoneg, linkState, enabled,
379 mtuSize);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800380 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530381
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800382 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
383 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800385 edata.cmd = ETHTOOL_GSET;
386 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
387 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530388 speed = edata.speed;
389 duplex = edata.duplex;
390 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530391 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800392
William A. Kennington III96203312021-05-07 12:50:41 -0700393 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800394 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530395 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800396
Tejas Patil2c0fc562021-08-03 19:13:46 +0530397 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530398}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800399#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530400
401/** @brief get the mac address of the interface.
402 * @return macaddress on success
403 */
404
Gunnar Mills57d9c502018-09-14 14:42:34 -0500405std::string
406 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530407{
Patrick Williams6aef7692021-05-01 06:39:41 -0500408 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800409 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
410
411 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530412 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800413 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530414 }
415
William A. Kennington III05368f12021-05-13 18:40:47 -0700416 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800417 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
418 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530419 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530420 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500421 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700422 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530423 }
424
William A. Kennington III1137a972019-04-20 20:49:58 -0700425 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
426 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
427 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700428 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530429}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530430
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530431std::string EthernetInterface::generateId(const std::string& ipaddress,
432 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800433 const std::string& gateway,
434 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530435{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530436 std::stringstream hexId;
437 std::string hashString = ipaddress;
438 hashString += std::to_string(prefixLength);
439 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800440 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530441
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530442 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500443 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530444 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530445}
446
Patrick Williams6aef7692021-05-01 06:39:41 -0500447std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
448 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800449{
450 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500451 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800452
453 // Only want 8 hex digits.
454 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
455 return hexId.str();
456}
457
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530458void EthernetInterface::deleteObject(const std::string& ipaddress)
459{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530460 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530461 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530462 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530463 log<level::ERR>("DeleteObject:Unable to find the object.");
464 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530465 }
466 this->addrs.erase(it);
Ratan Guptae05083a2017-09-16 07:12:11 +0530467 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530468}
469
Patrick Williams6aef7692021-05-01 06:39:41 -0500470void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800471{
Patrick Williams6aef7692021-05-01 06:39:41 -0500472 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800473 if (it == staticNeighbors.end())
474 {
475 log<level::ERR>(
476 "DeleteStaticNeighborObject:Unable to find the object.");
477 return;
478 }
479 staticNeighbors.erase(it);
480 manager.writeToConfigurationFile();
481}
482
Ratan Guptae9c9b812017-09-22 17:15:37 +0530483void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530484{
Ratan Guptabc886292017-07-25 18:29:57 +0530485 auto confDir = manager.getConfDir();
486 fs::path networkFile = confDir;
487 networkFile /= systemd::config::networkFilePrefix + interface +
488 systemd::config::networkFileSuffix;
489
490 fs::path deviceFile = confDir;
491 deviceFile /= interface + systemd::config::deviceFileSuffix;
492
493 // delete the vlan network file
494 if (fs::is_regular_file(networkFile))
495 {
496 fs::remove(networkFile);
497 }
498
499 // delete the vlan device file
500 if (fs::is_regular_file(deviceFile))
501 {
502 fs::remove(deviceFile);
503 }
Ratan Guptabc886292017-07-25 18:29:57 +0530504
505 // TODO systemd doesn't delete the virtual network interface
506 // even after deleting all the related configuartion.
507 // https://github.com/systemd/systemd/issues/6600
508 try
509 {
510 deleteInterface(interface);
511 }
512 catch (InternalFailure& e)
513 {
514 commit<InternalFailure>();
515 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530516}
517
518void EthernetInterface::deleteVLANObject(const std::string& interface)
519{
520 auto it = vlanInterfaces.find(interface);
521 if (it == vlanInterfaces.end())
522 {
523 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500524 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530525 return;
526 }
527
528 deleteVLANFromSystem(interface);
529 // delete the interface
530 vlanInterfaces.erase(it);
531
Ratan Guptae05083a2017-09-16 07:12:11 +0530532 manager.writeToConfigurationFile();
Ratan Guptabc886292017-07-25 18:29:57 +0530533}
534
Gunnar Mills57d9c502018-09-14 14:42:34 -0500535std::string EthernetInterface::generateObjectPath(
536 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800537 uint8_t prefixLength, const std::string& gateway,
538 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530539{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530540 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530541 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530542 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
543
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530544 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530545 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530546 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800547 objectPath /=
548 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530549 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530550}
551
William A. Kennington III08505792019-01-30 16:00:04 -0800552std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500553 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800554{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530555 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800556 objectPath /= objPath;
557 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500558 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800559 return objectPath.string();
560}
561
Patrick Williams6aef7692021-05-01 06:39:41 -0500562bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700563{
Patrick Williams6aef7692021-05-01 06:39:41 -0500564 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700565 {
566 return value;
567 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500568 EthernetInterfaceIntf::ipv6AcceptRA(value);
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700569 manager.writeToConfigurationFile();
570 return value;
571}
572
Patrick Williams6aef7692021-05-01 06:39:41 -0500573EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530574{
Patrick Williams6aef7692021-05-01 06:39:41 -0500575 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530576 {
577 return value;
578 }
579
Patrick Williams6aef7692021-05-01 06:39:41 -0500580 EthernetInterfaceIntf::dhcpEnabled(value);
Ratan Guptae05083a2017-09-16 07:12:11 +0530581 manager.writeToConfigurationFile();
Ratan Gupta87c13982017-06-15 09:27:27 +0530582 return value;
583}
584
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800585bool EthernetInterface::linkUp() const
586{
587 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
588 bool value = EthernetInterfaceIntf::linkUp();
589
590 if (eifSocket.sock < 0)
591 {
592 return value;
593 }
594
William A. Kennington III05368f12021-05-13 18:40:47 -0700595 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800596 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
597 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
598 {
599 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
600 }
601 else
602 {
603 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
604 entry("ERROR=%s", strerror(errno)));
605 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700606 return value;
607}
608
Tejas Patil2c0fc562021-08-03 19:13:46 +0530609size_t EthernetInterface::mtu() const
610{
611 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
612 size_t value = EthernetInterfaceIntf::mtu();
613
614 if (eifSocket.sock < 0)
615 {
616 return value;
617 }
618
619 ifreq ifr = {};
620 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
621 if (ioctl(eifSocket.sock, SIOCGIFMTU, &ifr) == 0)
622 {
623 value = ifr.ifr_mtu;
624 }
625 else
626 {
627 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
628 entry("ERROR=%s", strerror(errno)));
629 }
630 return value;
631}
632
633size_t EthernetInterface::mtu(size_t value)
634{
635 if (value == EthernetInterfaceIntf::mtu())
636 {
637 return value;
638 }
639 else if (value == 0)
640 {
641 return EthernetInterfaceIntf::mtu();
642 }
643
644 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
645 if (eifSocket.sock < 0)
646 {
647 return EthernetInterfaceIntf::mtu();
648 }
649
650 ifreq ifr = {};
651 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
652 ifr.ifr_mtu = value;
653
654 if (ioctl(eifSocket.sock, SIOCSIFMTU, &ifr) != 0)
655 {
656 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
657 entry("ERROR=%s", strerror(errno)));
658 return EthernetInterfaceIntf::mtu();
659 }
660 EthernetInterfaceIntf::mtu(value);
661
662 return value;
663}
664
William A. Kennington III26275a32021-07-13 20:32:42 -0700665bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700666{
William A. Kennington III26275a32021-07-13 20:32:42 -0700667 constexpr auto svc = "org.freedesktop.network1";
668 constexpr auto intf = "org.freedesktop.network1.Link";
669 constexpr auto prop = "AdministrativeState";
670 char* rpath;
671 sd_bus_path_encode("/org/freedesktop/network1/link",
672 std::to_string(ifIndex()).c_str(), &rpath);
673 std::string path(rpath);
674 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700675
William A. Kennington III26275a32021-07-13 20:32:42 -0700676 // Store / Parser for the AdministrativeState return value
677 std::optional<bool> ret;
678 auto cb = [&](const std::string& state) {
679 if (state != "initialized")
680 {
681 ret = state != "unmanaged";
682 }
683 };
684
685 // Build a matcher before making the property call to ensure we
686 // can eventually get the value.
687 sdbusplus::bus::match::match match(
688 bus,
689 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
690 "'PropertiesChanged',arg0='{}',",
691 svc, path, PROPERTY_INTERFACE, intf)
692 .c_str(),
693 [&](sdbusplus::message::message& m) {
694 std::string intf;
695 std::unordered_map<std::string, std::variant<std::string>> values;
696 try
697 {
698 m.read(intf, values);
699 auto it = values.find(prop);
700 // Ignore properties that aren't AdministrativeState
701 if (it != values.end())
702 {
703 cb(std::get<std::string>(it->second));
704 }
705 }
706 catch (const std::exception& e)
707 {
708 log<level::ERR>(
709 fmt::format(
710 "AdministrativeState match parsing failed on {}: {}",
711 interfaceName(), e.what())
712 .c_str(),
713 entry("INTERFACE=%s", interfaceName().c_str()),
714 entry("ERROR=%s", e.what()));
715 }
716 });
717
718 // Actively call for the value in case the interface is already configured
719 auto method =
720 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
721 method.append(intf, prop);
722 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700723 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700724 auto reply = bus.call(method);
725 std::variant<std::string> state;
726 reply.read(state);
727 cb(std::get<std::string>(state));
728 }
729 catch (const std::exception& e)
730 {
731 log<level::ERR>(
732 fmt::format("Failed to get AdministrativeState on {}: {}",
733 interfaceName(), e.what())
734 .c_str(),
735 entry("INTERFACE=%s", interfaceName().c_str()),
736 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700737 }
738
William A. Kennington III26275a32021-07-13 20:32:42 -0700739 // The interface is not yet configured by systemd-networkd, wait until it
740 // signals us a valid state.
741 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700742 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700743 bus.wait();
744 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700745 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700746
747 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700748}
749
Patrick Williams6aef7692021-05-01 06:39:41 -0500750bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700751{
Patrick Williams6aef7692021-05-01 06:39:41 -0500752 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700753 {
754 return value;
755 }
756
757 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
758 if (eifSocket.sock < 0)
759 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500760 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700761 }
762
William A. Kennington III05368f12021-05-13 18:40:47 -0700763 ifreq ifr = {};
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700764 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
765 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) != 0)
766 {
767 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
768 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500769 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700770 }
771
772 ifr.ifr_flags &= ~IFF_UP;
773 ifr.ifr_flags |= value ? IFF_UP : 0;
774
775 if (ioctl(eifSocket.sock, SIOCSIFFLAGS, &ifr) != 0)
776 {
777 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
778 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500779 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700780 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500781 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700782 writeConfigurationFile();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800783
784 return value;
785}
786
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530787ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530788{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530789 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
790 return EthernetInterfaceIntf::nameservers();
791}
792
793ServerList EthernetInterface::staticNameServers(ServerList value)
794{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530795 for (const auto& nameserverip : value)
796 {
797 if (!isValidIP(AF_INET, nameserverip) &&
798 !isValidIP(AF_INET6, nameserverip))
799 {
800 log<level::ERR>("Not a valid IP address"),
801 entry("ADDRESS=%s", nameserverip.c_str());
802 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530803 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530804 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
805 }
806 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530807 try
808 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530809 EthernetInterfaceIntf::staticNameServers(value);
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530810 writeConfigurationFile();
Ratan Guptab4005972019-09-19 06:19:16 +0530811 // resolved reads the DNS server configuration from the
812 // network file.
813 manager.restartSystemdUnit(networkdService);
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530814 }
815 catch (InternalFailure& e)
816 {
817 log<level::ERR>("Exception processing DNS entries");
818 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530819 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530820}
821
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530822void EthernetInterface::loadNameServers()
823{
824 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
825 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
826}
827
828ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530829{
830 fs::path confPath = manager.getConfDir();
831
832 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500833 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530834 confPath /= fileName;
835 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530836 config::Parser parser(confPath.string());
837 auto rc = config::ReturnCode::SUCCESS;
838
839 std::tie(rc, servers) = parser.getValues("Network", "DNS");
840 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530841 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530842 log<level::DEBUG>("Unable to get the value for network[DNS]",
843 entry("RC=%d", rc));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530844 }
845 return servers;
846}
847
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530848ServerList EthernetInterface::getNameServerFromResolvd()
849{
850 ServerList servers;
851 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
852
853 /*
854 The DNS property under org.freedesktop.resolve1.Link interface contains
855 an array containing all DNS servers currently used by resolved. It
856 contains similar information as the DNS server data written to
857 /run/systemd/resolve/resolv.conf.
858
859 Each structure in the array consists of a numeric network interface index,
860 an address family, and a byte array containing the DNS server address
861 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
862 The array contains DNS servers configured system-wide, including those
863 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
864 /etc/systemd/resolved.conf, as well as per-interface DNS server
865 information either retrieved from systemd-networkd or configured by
866 external software via SetLinkDNS().
867 */
868
869 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
870 std::variant<type> name; // Variable to capture the DNS property
871 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
872 PROPERTY_INTERFACE, METHOD_GET);
873
874 method.append(RESOLVED_INTERFACE, "DNS");
875 auto reply = bus.call(method);
876
877 try
878 {
879 reply.read(name);
880 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500881 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530882 {
883 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
884 }
885 auto tupleVector = std::get_if<type>(&name);
886 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
887 {
Alexander Filippov983da552021-02-08 15:26:54 +0300888 int addressFamily = std::get<0>(*i);
889 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
890
891 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530892 {
Alexander Filippov983da552021-02-08 15:26:54 +0300893 case AF_INET:
894 if (ipaddress.size() == sizeof(struct in_addr))
895 {
896 servers.push_back(toString(
897 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
898 }
899 else
900 {
901 log<level::ERR>(
902 "Invalid data recived from Systemd-Resolved");
903 }
904 break;
905
906 case AF_INET6:
907 if (ipaddress.size() == sizeof(struct in6_addr))
908 {
909 servers.push_back(toString(
910 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
911 }
912 else
913 {
914 log<level::ERR>(
915 "Invalid data recived from Systemd-Resolved");
916 }
917 break;
918
919 default:
920 log<level::ERR>(
921 "Unsupported address family in DNS from Systemd-Resolved");
922 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530923 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530924 }
925 return servers;
926}
927
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530928void EthernetInterface::loadVLAN(VlanId id)
929{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500930 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530931 std::string path = objPath;
932 path += "_" + std::to_string(id);
933
Johnathan Mantey817012a2020-01-30 15:07:39 -0800934 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500935 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530936 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500937 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800938 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530939
Gunnar Mills57d9c502018-09-14 14:42:34 -0500940 // Fetch the ip address from the system
941 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530942 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800943 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530944
945 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
946 std::move(vlanIntf));
947}
948
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700949ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530950{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500951 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530952 std::string path = objPath;
953 path += "_" + std::to_string(id);
954
Patrick Williams6aef7692021-05-01 06:39:41 -0500955 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530956 // VLAN interface can inherit.
957
Ratan Gupta5978dd12017-07-25 13:47:13 +0530958 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800959 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500960 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530961
962 // write the device file for the vlan interface.
963 vlanIntf->writeDeviceFile();
964
Gunnar Mills57d9c502018-09-14 14:42:34 -0500965 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530966 // write the new vlan device entry to the configuration(network) file.
Ratan Guptae05083a2017-09-16 07:12:11 +0530967 manager.writeToConfigurationFile();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700968
969 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530970}
Ratan Gupta2b106532017-07-25 16:05:02 +0530971
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700972bool EthernetInterface::getIPv6AcceptRAFromConf()
973{
974 fs::path confPath = manager.getConfDir();
975
976 std::string fileName = systemd::config::networkFilePrefix +
977 interfaceName() + systemd::config::networkFileSuffix;
978 confPath /= fileName;
979 config::ValueList values;
980 config::Parser parser(confPath.string());
981 auto rc = config::ReturnCode::SUCCESS;
982 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
983 if (rc != config::ReturnCode::SUCCESS)
984 {
985 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
986 entry("rc=%d", rc));
987 return false;
988 }
989 return (values[0] == "true");
990}
991
Ratan Gupta497c0c92017-08-22 19:15:59 +0530992ServerList EthernetInterface::getNTPServersFromConf()
993{
994 fs::path confPath = manager.getConfDir();
995
Gunnar Mills57d9c502018-09-14 14:42:34 -0500996 std::string fileName = systemd::config::networkFilePrefix +
997 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +0530998 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +0530999
Ratan Gupta497c0c92017-08-22 19:15:59 +05301000 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301001 config::Parser parser(confPath.string());
1002 auto rc = config::ReturnCode::SUCCESS;
1003
1004 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1005 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301006 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301007 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1008 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301009 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301010
Ratan Gupta497c0c92017-08-22 19:15:59 +05301011 return servers;
1012}
1013
Patrick Williams6aef7692021-05-01 06:39:41 -05001014ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301015{
Patrick Williams6aef7692021-05-01 06:39:41 -05001016 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301017
1018 writeConfigurationFile();
1019 // timesynchd reads the NTP server configuration from the
1020 // network file.
Ratan Gupta895f9e52018-11-26 20:57:34 +05301021 manager.restartSystemdUnit(networkdService);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301022 return ntpServers;
1023}
Ratan Gupta2b106532017-07-25 16:05:02 +05301024// Need to merge the below function with the code which writes the
1025// config file during factory reset.
1026// TODO openbmc/openbmc#1751
1027
1028void EthernetInterface::writeConfigurationFile()
1029{
1030 // write all the static ip address in the systemd-network conf file
1031
1032 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301033 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301034
1035 // if there is vlan interafce then write the configuration file
1036 // for vlan also.
1037
Gunnar Mills57d9c502018-09-14 14:42:34 -05001038 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301039 {
1040 intf.second->writeConfigurationFile();
1041 }
1042
Ratan Gupta2b106532017-07-25 16:05:02 +05301043 fs::path confPath = manager.getConfDir();
1044
Gunnar Mills57d9c502018-09-14 14:42:34 -05001045 std::string fileName = systemd::config::networkFilePrefix +
1046 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301047 confPath /= fileName;
1048 std::fstream stream;
1049
1050 stream.open(confPath.c_str(), std::fstream::out);
1051 if (!stream.is_open())
1052 {
1053 log<level::ERR>("Unable to open the file",
1054 entry("FILE=%s", confPath.c_str()));
1055 elog<InternalFailure>();
1056 }
1057
1058 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001059 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301060 stream << "Name=" << interfaceName() << "\n";
1061
1062 auto addrs = getAddresses();
1063
William A. Kennington III15787212019-04-23 19:18:01 -07001064 // Write the link section
1065 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001066 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001067 if (!mac.empty())
1068 {
1069 stream << "MACAddress=" << mac << "\n";
1070 }
1071
Patrick Williams6aef7692021-05-01 06:39:41 -05001072 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001073 {
1074 stream << "Unmanaged=yes\n";
1075 }
1076
Ratan Gupta2b106532017-07-25 16:05:02 +05301077 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001078 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001079#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001080 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001081#else
1082 stream << "LinkLocalAddressing=no\n";
1083#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001084 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001085 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301086
1087 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001088 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301089 {
1090 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001091 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301092 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301093 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001094 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301095 {
1096 stream << "NTP=" << ntp << "\n";
1097 }
1098
1099 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301100 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301101 {
1102 stream << "DNS=" << dns << "\n";
1103 }
1104
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001105 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001106 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001107 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001108
Johnathan Mantey817012a2020-01-30 15:07:39 -08001109 // Static IP addresses
1110 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301111 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001112 if (originIsManuallyAssigned(addr.second->origin()) &&
1113 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001114 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001115 // Process all static addresses
1116 std::string address = addr.second->address() + "/" +
1117 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301118
Johnathan Mantey817012a2020-01-30 15:07:39 -08001119 // build the address entries. Do not use [Network] shortcuts to
1120 // insert address entries.
1121 stream << "[Address]\n";
1122 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001123 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001124 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001125
Lei YUcb2d4082021-08-12 15:26:49 +08001126 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001127 {
Lei YUcb2d4082021-08-12 15:26:49 +08001128 auto gateway = EthernetInterfaceIntf::defaultGateway();
1129 if (!gateway.empty())
1130 {
1131 stream << "[Route]\n";
1132 stream << "Gateway=" << gateway << "\n";
1133 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001134 }
1135
Lei YUcb2d4082021-08-12 15:26:49 +08001136 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001137 {
Lei YUcb2d4082021-08-12 15:26:49 +08001138 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1139 if (!gateway6.empty())
1140 {
1141 stream << "[Route]\n";
1142 stream << "Gateway=" << gateway6 << "\n";
1143 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001144 }
1145
William A. Kennington III08505792019-01-30 16:00:04 -08001146 // Write the neighbor sections
1147 for (const auto& neighbor : staticNeighbors)
1148 {
1149 stream << "[Neighbor]"
1150 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001151 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1152 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001153 }
1154
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001155 // Write the dhcp section irrespective of whether DHCP is enabled or not
1156 writeDHCPSection(stream);
1157
Ratan Gupta2b106532017-07-25 16:05:02 +05301158 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301159}
1160
1161void EthernetInterface::writeDHCPSection(std::fstream& stream)
1162{
1163 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301164 // write the dhcp section
1165 stream << "[DHCP]\n";
1166
1167 // Hardcoding the client identifier to mac, to address below issue
1168 // https://github.com/openbmc/openbmc/issues/1280
1169 stream << "ClientIdentifier=mac\n";
1170 if (manager.getDHCPConf())
1171 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001172 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301173 stream << "UseDNS="s + value + "\n";
1174
Patrick Williams6aef7692021-05-01 06:39:41 -05001175 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301176 stream << "UseNTP="s + value + "\n";
1177
1178 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1179 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001180
1181 value =
1182 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1183 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301184 }
1185}
1186
Patrick Williams6aef7692021-05-01 06:39:41 -05001187std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301188{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001189 ether_addr newMAC;
1190 try
1191 {
1192 newMAC = mac_address::fromString(value);
1193 }
1194 catch (std::invalid_argument&)
1195 {
1196 log<level::ERR>("MACAddress is not valid.",
1197 entry("MAC=%s", value.c_str()));
1198 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1199 Argument::ARGUMENT_VALUE(value.c_str()));
1200 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001201 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301202 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001203 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001204 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001205 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1206 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301207 }
1208
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001209 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001210 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001211
William A. Kennington III1137a972019-04-20 20:49:58 -07001212 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001213 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001214 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301215 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001216 // Update everything that depends on the MAC value
1217 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301218 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001219 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301220 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001221 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301222
William A. Kennington III15787212019-04-23 19:18:01 -07001223 // TODO: would remove the call below and
1224 // just restart systemd-netwokd
William A. Kennington III1137a972019-04-20 20:49:58 -07001225 // through https://github.com/systemd/systemd/issues/6696
1226 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(),
1227 "down");
William A. Kennington III15787212019-04-23 19:18:01 -07001228 manager.writeToConfigurationFile();
Ratan Gupta677ae122017-09-18 16:28:50 +05301229 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001230
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001231#ifdef HAVE_UBOOT_ENV
1232 // Ensure that the valid address is stored in the u-boot-env
1233 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1234 if (envVar)
1235 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001236 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1237 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1238 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1239 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001240 }
1241#endif // HAVE_UBOOT_ENV
1242
William A. Kennington III1137a972019-04-20 20:49:58 -07001243 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301244}
1245
Ratan Guptae9c9b812017-09-22 17:15:37 +05301246void EthernetInterface::deleteAll()
1247{
Johnathan Mantey817012a2020-01-30 15:07:39 -08001248 if (dhcpIsEnabled(IP::Protocol::IPv4, true))
Ratan Guptae9c9b812017-09-22 17:15:37 +05301249 {
1250 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -05001251 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +05301252 }
1253
1254 // clear all the ip on the interface
1255 addrs.clear();
1256 manager.writeToConfigurationFile();
1257}
1258
Ravi Tejaa5a09442020-07-17 00:57:33 -05001259std::string EthernetInterface::defaultGateway(std::string gateway)
1260{
1261 auto gw = EthernetInterfaceIntf::defaultGateway();
1262 if (gw == gateway)
1263 {
1264 return gw;
1265 }
1266
1267 if (!isValidIP(AF_INET, gateway))
1268 {
1269 log<level::ERR>("Not a valid v4 Gateway",
1270 entry("GATEWAY=%s", gateway.c_str()));
1271 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1272 Argument::ARGUMENT_VALUE(gateway.c_str()));
1273 }
1274 gw = EthernetInterfaceIntf::defaultGateway(gateway);
1275 manager.writeToConfigurationFile();
1276 return gw;
1277}
1278
1279std::string EthernetInterface::defaultGateway6(std::string gateway)
1280{
1281 auto gw = EthernetInterfaceIntf::defaultGateway6();
1282 if (gw == gateway)
1283 {
1284 return gw;
1285 }
1286
1287 if (!isValidIP(AF_INET6, gateway))
1288 {
1289 log<level::ERR>("Not a valid v6 Gateway",
1290 entry("GATEWAY=%s", gateway.c_str()));
1291 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1292 Argument::ARGUMENT_VALUE(gateway.c_str()));
1293 }
1294 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
1295 manager.writeToConfigurationFile();
1296 return gw;
1297}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001298} // namespace network
1299} // namespace phosphor