blob: 3da9a57f9bd157a10974fb9e8e8298318d1c0ea2 [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"
Ratan Gupta2b106532017-07-25 16:05:02 +05308#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309
Ratan Gupta82549cc2017-04-21 08:45:23 +053010#include <arpa/inet.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070011#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053012#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070013#include <linux/rtnetlink.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
Ratan Gupta82549cc2017-04-21 08:45:23 +053017#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053018#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053019#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070020#include <phosphor-logging/elog-errors.hpp>
21#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070022#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <sstream>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080024#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070025#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053026#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070027#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070028#include <unordered_map>
29#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070030#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053031
Ratan Gupta91a99cc2017-04-14 16:32:09 +053032namespace phosphor
33{
34namespace network
35{
36
37using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053038using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053039using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
40using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050041using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053042constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
43constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
44constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
45constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
46constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053047
Johnathan Mantey817012a2020-01-30 15:07:39 -080048std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
49 {EthernetInterface::DHCPConf::both, "true"},
50 {EthernetInterface::DHCPConf::v4, "ipv4"},
51 {EthernetInterface::DHCPConf::v6, "ipv6"},
52 {EthernetInterface::DHCPConf::none, "false"}};
53
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080054static stdplus::Fd& getIFSock()
55{
56 using namespace stdplus::fd;
57 static auto fd =
58 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
59 return fd;
60}
61
Ratan Gupta91a99cc2017-04-14 16:32:09 +053062EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
63 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080064 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070065 bool emitSignal,
66 std::optional<bool> enabled) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050067 Ifaces(bus, objPath.c_str(), true),
68 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053069{
70 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053071 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053072 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050073 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
74 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070075 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070076 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
77 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050078 std::string defaultGateway;
79 std::string defaultGateway6;
80
William A. Kennington IIIe0564842021-10-23 16:02:22 -070081 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050082 {
83 if (gateway.first == intfName)
84 {
85 defaultGateway = gateway.second;
86 break;
87 }
88 }
89
William A. Kennington IIIe0564842021-10-23 16:02:22 -070090 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050091 {
92 if (gateway6.first == intfName)
93 {
94 defaultGateway6 = gateway6.second;
95 break;
96 }
97 }
98
99 EthernetInterfaceIntf::defaultGateway(defaultGateway);
100 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530101 // Don't get the mac address from the system as the mac address
102 // would be same as parent interface.
103 if (intfName.find(".") == std::string::npos)
104 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500105 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530106 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500107 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
Ratan Gupta613a0122020-04-24 15:18:53 +0530108
109 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530110 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530111
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700112#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700113 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
114
115 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
116 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800117#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530118
Ratan Gupta29b0e432017-05-25 12:51:40 +0530119 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530120 if (emitSignal)
121 {
122 this->emit_object_added();
123 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530124}
125
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800126static IP::Protocol convertFamily(int family)
127{
128 switch (family)
129 {
130 case AF_INET:
131 return IP::Protocol::IPv4;
132 case AF_INET6:
133 return IP::Protocol::IPv6;
134 }
135
136 throw std::invalid_argument("Bad address family");
137}
138
Johnathan Mantey817012a2020-01-30 15:07:39 -0800139void EthernetInterface::disableDHCP(IP::Protocol protocol)
140{
Patrick Williams6aef7692021-05-01 06:39:41 -0500141 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800142 if (dhcpState == EthernetInterface::DHCPConf::both)
143 {
144 if (protocol == IP::Protocol::IPv4)
145 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500146 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800147 }
148 else if (protocol == IP::Protocol::IPv6)
149 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500150 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800151 }
152 }
153 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
154 (protocol == IP::Protocol::IPv4))
155 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500156 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800157 }
158 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
159 (protocol == IP::Protocol::IPv6))
160 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500161 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800162 }
163}
164
William A. Kennington III24957b92021-12-03 13:59:19 -0800165bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800166{
William A. Kennington III24957b92021-12-03 13:59:19 -0800167 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
168 return cur == EthernetInterface::DHCPConf::both ||
169 (family == IP::Protocol::IPv6 &&
170 cur == EthernetInterface::DHCPConf::v6) ||
171 (family == IP::Protocol::IPv4 &&
172 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800173}
174
Johnathan Mantey817012a2020-01-30 15:07:39 -0800175bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
176{
177 return (
178#ifdef LINK_LOCAL_AUTOCONFIGURATION
179 (origin == IP::AddressOrigin::Static)
180#else
181 (origin == IP::AddressOrigin::Static ||
182 origin == IP::AddressOrigin::LinkLocal)
183#endif
184
185 );
186}
187
Ratan Gupta87c13982017-06-15 09:27:27 +0530188void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530189{
Ratan Gupta87c13982017-06-15 09:27:27 +0530190 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530191
Ratan Gupta87c13982017-06-15 09:27:27 +0530192 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530193
Ratan Gupta6a387c12017-08-03 13:26:19 +0530194 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530195 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800196 IP::Protocol addressType = convertFamily(addr.addrType);
197 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800198 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530199 {
200 origin = IP::AddressOrigin::DHCP;
201 }
William A. Kennington III16893802019-01-30 16:01:01 -0800202 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530203 {
204 origin = IP::AddressOrigin::LinkLocal;
205 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700206 // Obsolete parameter
207 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530208
Gunnar Mills57d9c502018-09-14 14:42:34 -0500209 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800210 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530211
Lei YU7233c582021-04-08 14:39:43 +0800212 this->addrs.insert_or_assign(
213 addr.ipaddress,
214 std::make_shared<phosphor::network::IPAddress>(
215 bus, ipAddressObjectPath.c_str(), *this, addressType,
216 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530217 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530218}
219
William A. Kennington III08505792019-01-30 16:00:04 -0800220void EthernetInterface::createStaticNeighborObjects()
221{
222 staticNeighbors.clear();
223
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700224 NeighborFilter filter;
225 filter.interface = ifIndex();
226 filter.state = NUD_PERMANENT;
227 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800228 for (const auto& neighbor : neighbors)
229 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700230 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800231 {
232 continue;
233 }
234 std::string ip = toString(neighbor.address);
235 std::string mac = mac_address::toString(*neighbor.mac);
236 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
237 staticNeighbors.emplace(ip,
238 std::make_shared<phosphor::network::Neighbor>(
239 bus, objectPath.c_str(), *this, ip, mac,
240 Neighbor::State::Permanent));
241 }
242}
243
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700244unsigned EthernetInterface::ifIndex() const
245{
246 unsigned idx = if_nametoindex(interfaceName().c_str());
247 if (idx == 0)
248 {
249 throw std::system_error(errno, std::generic_category(),
250 "if_nametoindex");
251 }
252 return idx;
253}
254
Patrick Williams6aef7692021-05-01 06:39:41 -0500255ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500256 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530257{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800258 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530259 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530260 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500261 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800262 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500263 }
264
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 IP::AddressOrigin origin = IP::AddressOrigin::Static;
266
267 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
268
269 if (!isValidIP(addressFamily, ipaddress))
270 {
271 log<level::ERR>("Not a valid IP address"),
272 entry("ADDRESS=%s", ipaddress.c_str());
273 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
274 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
275 }
276
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700277 // Gateway is an obsolete parameter
278 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500279
280 if (!isValidPrefix(addressFamily, prefixLength))
281 {
282 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700283 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500284 elog<InvalidArgument>(
285 Argument::ARGUMENT_NAME("prefixLength"),
286 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530287 }
288
Gunnar Mills57d9c502018-09-14 14:42:34 -0500289 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800290 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800291 this->addrs.insert_or_assign(ipaddress,
292 std::make_shared<phosphor::network::IPAddress>(
293 bus, objectPath.c_str(), *this, protType,
294 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530295
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700296 writeConfigurationFile();
297 manager.reloadConfigs();
298
raviteja-bce379562019-03-28 05:59:36 -0500299 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530300}
301
Patrick Williams6aef7692021-05-01 06:39:41 -0500302ObjectPath EthernetInterface::neighbor(std::string ipAddress,
303 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800304{
Patrick Williams6aef7692021-05-01 06:39:41 -0500305 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800306 {
307 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500308 entry("ADDRESS=%s", ipAddress.c_str()));
309 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
310 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800311 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500312 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800313 {
314 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500315 entry("MACADDRESS=%s", ipAddress.c_str()));
316 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
317 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800318 }
319
320 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500321 generateStaticNeighborObjectPath(ipAddress, macAddress);
322 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800323 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500324 bus, objectPath.c_str(), *this, ipAddress,
325 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700326
327 writeConfigurationFile();
328 manager.reloadConfigs();
329
William A. Kennington III08505792019-01-30 16:00:04 -0800330 return objectPath;
331}
332
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700333#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530334/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800335 Enable this code if your NIC driver supports the ETHTOOL features.
336 Do this by adding the following to your phosphor-network*.bbappend file.
337 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
338 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530339*/
340InterfaceInfo EthernetInterface::getInterfaceInfo() const
341{
William A. Kennington III05368f12021-05-13 18:40:47 -0700342 ifreq ifr = {};
343 ethtool_cmd edata = {};
344 LinkSpeed speed = {};
345 Autoneg autoneg = {};
346 DuplexMode duplex = {};
347 LinkUp linkState = {};
348 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530349 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530350
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800351 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
352 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530353
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800354 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800355 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800356 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800357 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530358 speed = edata.speed;
359 duplex = edata.duplex;
360 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530361 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800362 catch (const std::exception& e)
363 {
364 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800365
William A. Kennington III96203312021-05-07 12:50:41 -0700366 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800367 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530368 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800369
Tejas Patil2c0fc562021-08-03 19:13:46 +0530370 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530371}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800372#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530373
374/** @brief get the mac address of the interface.
375 * @return macaddress on success
376 */
377
Gunnar Mills57d9c502018-09-14 14:42:34 -0500378std::string
379 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530380{
Patrick Williams6aef7692021-05-01 06:39:41 -0500381 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530382
William A. Kennington III05368f12021-05-13 18:40:47 -0700383 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800384 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800385 try
386 {
387 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
388 }
389 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530390 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530391 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800392 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700393 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530394 }
395
William A. Kennington III1137a972019-04-20 20:49:58 -0700396 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
397 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
398 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700399 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530400}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530401
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530402std::string EthernetInterface::generateId(const std::string& ipaddress,
403 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800404 const std::string& gateway,
405 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530406{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530407 std::stringstream hexId;
408 std::string hashString = ipaddress;
409 hashString += std::to_string(prefixLength);
410 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800411 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530412
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530413 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500414 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530415 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530416}
417
Patrick Williams6aef7692021-05-01 06:39:41 -0500418std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
419 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800420{
421 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500422 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800423
424 // Only want 8 hex digits.
425 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
426 return hexId.str();
427}
428
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530429void EthernetInterface::deleteObject(const std::string& ipaddress)
430{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530431 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530432 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530433 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530434 log<level::ERR>("DeleteObject:Unable to find the object.");
435 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530436 }
437 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700438
439 writeConfigurationFile();
440 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530441}
442
Patrick Williams6aef7692021-05-01 06:39:41 -0500443void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800444{
Patrick Williams6aef7692021-05-01 06:39:41 -0500445 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800446 if (it == staticNeighbors.end())
447 {
448 log<level::ERR>(
449 "DeleteStaticNeighborObject:Unable to find the object.");
450 return;
451 }
452 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700453
454 writeConfigurationFile();
455 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800456}
457
Ratan Guptae9c9b812017-09-22 17:15:37 +0530458void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530459{
Ratan Guptabc886292017-07-25 18:29:57 +0530460 auto confDir = manager.getConfDir();
461 fs::path networkFile = confDir;
462 networkFile /= systemd::config::networkFilePrefix + interface +
463 systemd::config::networkFileSuffix;
464
465 fs::path deviceFile = confDir;
466 deviceFile /= interface + systemd::config::deviceFileSuffix;
467
468 // delete the vlan network file
469 if (fs::is_regular_file(networkFile))
470 {
471 fs::remove(networkFile);
472 }
473
474 // delete the vlan device file
475 if (fs::is_regular_file(deviceFile))
476 {
477 fs::remove(deviceFile);
478 }
Ratan Guptabc886292017-07-25 18:29:57 +0530479
480 // TODO systemd doesn't delete the virtual network interface
481 // even after deleting all the related configuartion.
482 // https://github.com/systemd/systemd/issues/6600
483 try
484 {
485 deleteInterface(interface);
486 }
Patrick Williams5758db32021-10-06 12:29:22 -0500487 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530488 {
489 commit<InternalFailure>();
490 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530491}
492
493void EthernetInterface::deleteVLANObject(const std::string& interface)
494{
495 auto it = vlanInterfaces.find(interface);
496 if (it == vlanInterfaces.end())
497 {
498 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500499 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530500 return;
501 }
502
503 deleteVLANFromSystem(interface);
504 // delete the interface
505 vlanInterfaces.erase(it);
506
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700507 writeConfigurationFile();
508 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530509}
510
Gunnar Mills57d9c502018-09-14 14:42:34 -0500511std::string EthernetInterface::generateObjectPath(
512 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800513 uint8_t prefixLength, const std::string& gateway,
514 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530515{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530516 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530517 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530518 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
519
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530520 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530521 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530522 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800523 objectPath /=
524 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530525 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530526}
527
William A. Kennington III08505792019-01-30 16:00:04 -0800528std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500529 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800530{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530531 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800532 objectPath /= objPath;
533 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500534 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800535 return objectPath.string();
536}
537
Patrick Williams6aef7692021-05-01 06:39:41 -0500538bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700539{
Patrick Williams6aef7692021-05-01 06:39:41 -0500540 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700541 {
542 return value;
543 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500544 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700545
546 writeConfigurationFile();
547 manager.reloadConfigs();
548
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700549 return value;
550}
551
Patrick Williams6aef7692021-05-01 06:39:41 -0500552EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530553{
Patrick Williams6aef7692021-05-01 06:39:41 -0500554 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530555 {
556 return value;
557 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500558 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700559
560 writeConfigurationFile();
561 manager.reloadConfigs();
562
Ratan Gupta87c13982017-06-15 09:27:27 +0530563 return value;
564}
565
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800566bool EthernetInterface::linkUp() const
567{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800568 bool value = EthernetInterfaceIntf::linkUp();
569
William A. Kennington III05368f12021-05-13 18:40:47 -0700570 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800571 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800572 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800573 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800574 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800575 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
576 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800577 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800578 {
579 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800580 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800581 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700582 return value;
583}
584
Tejas Patil2c0fc562021-08-03 19:13:46 +0530585size_t EthernetInterface::mtu() const
586{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530587 size_t value = EthernetInterfaceIntf::mtu();
588
Tejas Patil2c0fc562021-08-03 19:13:46 +0530589 ifreq ifr = {};
590 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800591 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530592 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800593 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530594 value = ifr.ifr_mtu;
595 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800596 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530597 {
598 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800599 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530600 }
601 return value;
602}
603
604size_t EthernetInterface::mtu(size_t value)
605{
606 if (value == EthernetInterfaceIntf::mtu())
607 {
608 return value;
609 }
610 else if (value == 0)
611 {
612 return EthernetInterfaceIntf::mtu();
613 }
614
Tejas Patil2c0fc562021-08-03 19:13:46 +0530615 ifreq ifr = {};
616 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
617 ifr.ifr_mtu = value;
618
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800619 try
620 {
621 getIFSock().ioctl(SIOCSIFMTU, &ifr);
622 }
623 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530624 {
625 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
626 entry("ERROR=%s", strerror(errno)));
627 return EthernetInterfaceIntf::mtu();
628 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530629
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800630 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530631 return value;
632}
633
William A. Kennington III26275a32021-07-13 20:32:42 -0700634bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700635{
William A. Kennington III26275a32021-07-13 20:32:42 -0700636 constexpr auto svc = "org.freedesktop.network1";
637 constexpr auto intf = "org.freedesktop.network1.Link";
638 constexpr auto prop = "AdministrativeState";
639 char* rpath;
640 sd_bus_path_encode("/org/freedesktop/network1/link",
641 std::to_string(ifIndex()).c_str(), &rpath);
642 std::string path(rpath);
643 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700644
William A. Kennington III26275a32021-07-13 20:32:42 -0700645 // Store / Parser for the AdministrativeState return value
646 std::optional<bool> ret;
647 auto cb = [&](const std::string& state) {
648 if (state != "initialized")
649 {
650 ret = state != "unmanaged";
651 }
652 };
653
654 // Build a matcher before making the property call to ensure we
655 // can eventually get the value.
656 sdbusplus::bus::match::match match(
657 bus,
658 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
659 "'PropertiesChanged',arg0='{}',",
660 svc, path, PROPERTY_INTERFACE, intf)
661 .c_str(),
662 [&](sdbusplus::message::message& m) {
663 std::string intf;
664 std::unordered_map<std::string, std::variant<std::string>> values;
665 try
666 {
667 m.read(intf, values);
668 auto it = values.find(prop);
669 // Ignore properties that aren't AdministrativeState
670 if (it != values.end())
671 {
672 cb(std::get<std::string>(it->second));
673 }
674 }
675 catch (const std::exception& e)
676 {
677 log<level::ERR>(
678 fmt::format(
679 "AdministrativeState match parsing failed on {}: {}",
680 interfaceName(), e.what())
681 .c_str(),
682 entry("INTERFACE=%s", interfaceName().c_str()),
683 entry("ERROR=%s", e.what()));
684 }
685 });
686
687 // Actively call for the value in case the interface is already configured
688 auto method =
689 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
690 method.append(intf, prop);
691 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700692 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700693 auto reply = bus.call(method);
694 std::variant<std::string> state;
695 reply.read(state);
696 cb(std::get<std::string>(state));
697 }
698 catch (const std::exception& e)
699 {
700 log<level::ERR>(
701 fmt::format("Failed to get AdministrativeState on {}: {}",
702 interfaceName(), e.what())
703 .c_str(),
704 entry("INTERFACE=%s", interfaceName().c_str()),
705 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700706 }
707
William A. Kennington III26275a32021-07-13 20:32:42 -0700708 // The interface is not yet configured by systemd-networkd, wait until it
709 // signals us a valid state.
710 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700711 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700712 bus.wait();
713 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700714 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700715
716 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700717}
718
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800719static void setNICAdminState(const char* intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700720{
721 ifreq ifr = {};
722 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800723 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700724
725 ifr.ifr_flags &= ~IFF_UP;
726 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800727 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700728}
729
Patrick Williams6aef7692021-05-01 06:39:41 -0500730bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700731{
Patrick Williams6aef7692021-05-01 06:39:41 -0500732 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700733 {
734 return value;
735 }
736
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800737 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700738 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800739 if (!value)
740 {
741 // We only need to bring down the interface, networkd will always bring
742 // up managed interfaces
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800743 manager.addReloadPreHook([ifname = interfaceName()]() {
744 setNICAdminState(ifname.c_str(), false);
745 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800746 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700747 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800748
749 return value;
750}
751
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530752ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530753{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530754 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
755 return EthernetInterfaceIntf::nameservers();
756}
757
758ServerList EthernetInterface::staticNameServers(ServerList value)
759{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530760 for (const auto& nameserverip : value)
761 {
762 if (!isValidIP(AF_INET, nameserverip) &&
763 !isValidIP(AF_INET6, nameserverip))
764 {
765 log<level::ERR>("Not a valid IP address"),
766 entry("ADDRESS=%s", nameserverip.c_str());
767 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530768 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530769 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
770 }
771 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530772 try
773 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530774 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700775
Ratan Gupta6dec3902017-08-20 15:28:12 +0530776 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700777 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530778 }
Patrick Williams5758db32021-10-06 12:29:22 -0500779 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530780 {
781 log<level::ERR>("Exception processing DNS entries");
782 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530783 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530784}
785
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530786void EthernetInterface::loadNameServers()
787{
788 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
789 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
790}
791
792ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec3902017-08-20 15:28:12 +0530793{
794 fs::path confPath = manager.getConfDir();
795
796 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500797 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530798 confPath /= fileName;
799 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530800 config::Parser parser(confPath.string());
801 auto rc = config::ReturnCode::SUCCESS;
802
803 std::tie(rc, servers) = parser.getValues("Network", "DNS");
804 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530805 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530806 log<level::DEBUG>("Unable to get the value for network[DNS]",
807 entry("RC=%d", rc));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530808 }
809 return servers;
810}
811
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530812ServerList EthernetInterface::getNameServerFromResolvd()
813{
814 ServerList servers;
815 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
816
817 /*
818 The DNS property under org.freedesktop.resolve1.Link interface contains
819 an array containing all DNS servers currently used by resolved. It
820 contains similar information as the DNS server data written to
821 /run/systemd/resolve/resolv.conf.
822
823 Each structure in the array consists of a numeric network interface index,
824 an address family, and a byte array containing the DNS server address
825 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
826 The array contains DNS servers configured system-wide, including those
827 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
828 /etc/systemd/resolved.conf, as well as per-interface DNS server
829 information either retrieved from systemd-networkd or configured by
830 external software via SetLinkDNS().
831 */
832
833 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
834 std::variant<type> name; // Variable to capture the DNS property
835 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
836 PROPERTY_INTERFACE, METHOD_GET);
837
838 method.append(RESOLVED_INTERFACE, "DNS");
839 auto reply = bus.call(method);
840
841 try
842 {
843 reply.read(name);
844 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500845 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530846 {
847 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
848 }
849 auto tupleVector = std::get_if<type>(&name);
850 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
851 {
Alexander Filippov983da552021-02-08 15:26:54 +0300852 int addressFamily = std::get<0>(*i);
853 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
854
855 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530856 {
Alexander Filippov983da552021-02-08 15:26:54 +0300857 case AF_INET:
858 if (ipaddress.size() == sizeof(struct in_addr))
859 {
860 servers.push_back(toString(
861 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
862 }
863 else
864 {
865 log<level::ERR>(
866 "Invalid data recived from Systemd-Resolved");
867 }
868 break;
869
870 case AF_INET6:
871 if (ipaddress.size() == sizeof(struct in6_addr))
872 {
873 servers.push_back(toString(
874 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
875 }
876 else
877 {
878 log<level::ERR>(
879 "Invalid data recived from Systemd-Resolved");
880 }
881 break;
882
883 default:
884 log<level::ERR>(
885 "Unsupported address family in DNS from Systemd-Resolved");
886 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530887 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530888 }
889 return servers;
890}
891
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530892void EthernetInterface::loadVLAN(VlanId id)
893{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500894 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530895 std::string path = objPath;
896 path += "_" + std::to_string(id);
897
Johnathan Mantey817012a2020-01-30 15:07:39 -0800898 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500899 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530900 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500901 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800902 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530903
Gunnar Mills57d9c502018-09-14 14:42:34 -0500904 // Fetch the ip address from the system
905 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530906 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800907 vlanIntf->createStaticNeighborObjects();
Jiaqing Zhaocc5a6702021-12-31 14:58:55 +0800908 vlanIntf->loadNameServers();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530909
910 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
911 std::move(vlanIntf));
912}
913
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700914ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530915{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500916 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530917 std::string path = objPath;
918 path += "_" + std::to_string(id);
919
Patrick Williams6aef7692021-05-01 06:39:41 -0500920 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530921 // VLAN interface can inherit.
922
Ratan Gupta5978dd12017-07-25 13:47:13 +0530923 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800924 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500925 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530926
927 // write the device file for the vlan interface.
928 vlanIntf->writeDeviceFile();
929
Gunnar Mills57d9c502018-09-14 14:42:34 -0500930 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700931
932 writeConfigurationFile();
933 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700934
935 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530936}
Ratan Gupta2b106532017-07-25 16:05:02 +0530937
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700938bool EthernetInterface::getIPv6AcceptRAFromConf()
939{
940 fs::path confPath = manager.getConfDir();
941
942 std::string fileName = systemd::config::networkFilePrefix +
943 interfaceName() + systemd::config::networkFileSuffix;
944 confPath /= fileName;
945 config::ValueList values;
946 config::Parser parser(confPath.string());
947 auto rc = config::ReturnCode::SUCCESS;
948 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
949 if (rc != config::ReturnCode::SUCCESS)
950 {
951 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
952 entry("rc=%d", rc));
953 return false;
954 }
955 return (values[0] == "true");
956}
957
Ratan Gupta497c0c92017-08-22 19:15:59 +0530958ServerList EthernetInterface::getNTPServersFromConf()
959{
960 fs::path confPath = manager.getConfDir();
961
Gunnar Mills57d9c502018-09-14 14:42:34 -0500962 std::string fileName = systemd::config::networkFilePrefix +
963 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +0530964 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +0530965
Ratan Gupta497c0c92017-08-22 19:15:59 +0530966 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530967 config::Parser parser(confPath.string());
968 auto rc = config::ReturnCode::SUCCESS;
969
970 std::tie(rc, servers) = parser.getValues("Network", "NTP");
971 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530972 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530973 log<level::DEBUG>("Unable to get the value for Network[NTP]",
974 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530975 }
Ratan Guptac27170a2017-11-22 15:44:42 +0530976
Ratan Gupta497c0c92017-08-22 19:15:59 +0530977 return servers;
978}
979
Patrick Williams6aef7692021-05-01 06:39:41 -0500980ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530981{
Patrick Williams6aef7692021-05-01 06:39:41 -0500982 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530983
984 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700985 manager.reloadConfigs();
986
Ratan Gupta497c0c92017-08-22 19:15:59 +0530987 return ntpServers;
988}
Ratan Gupta2b106532017-07-25 16:05:02 +0530989// Need to merge the below function with the code which writes the
990// config file during factory reset.
991// TODO openbmc/openbmc#1751
992
993void EthernetInterface::writeConfigurationFile()
994{
995 // write all the static ip address in the systemd-network conf file
996
997 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530998 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530999
1000 // if there is vlan interafce then write the configuration file
1001 // for vlan also.
1002
Gunnar Mills57d9c502018-09-14 14:42:34 -05001003 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301004 {
1005 intf.second->writeConfigurationFile();
1006 }
1007
Ratan Gupta2b106532017-07-25 16:05:02 +05301008 fs::path confPath = manager.getConfDir();
1009
Gunnar Mills57d9c502018-09-14 14:42:34 -05001010 std::string fileName = systemd::config::networkFilePrefix +
1011 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301012 confPath /= fileName;
1013 std::fstream stream;
1014
1015 stream.open(confPath.c_str(), std::fstream::out);
1016 if (!stream.is_open())
1017 {
1018 log<level::ERR>("Unable to open the file",
1019 entry("FILE=%s", confPath.c_str()));
1020 elog<InternalFailure>();
1021 }
1022
1023 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001024 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301025 stream << "Name=" << interfaceName() << "\n";
1026
1027 auto addrs = getAddresses();
1028
William A. Kennington III15787212019-04-23 19:18:01 -07001029 // Write the link section
1030 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001031 auto mac = MacAddressIntf::macAddress();
Johnathan Mantey609c12d2022-02-03 09:23:09 -08001032#ifdef PERSIST_MAC
William A. Kennington III15787212019-04-23 19:18:01 -07001033 if (!mac.empty())
1034 {
1035 stream << "MACAddress=" << mac << "\n";
1036 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -08001037#endif
William A. Kennington III15787212019-04-23 19:18:01 -07001038
Patrick Williams6aef7692021-05-01 06:39:41 -05001039 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001040 {
1041 stream << "Unmanaged=yes\n";
1042 }
1043
Ratan Gupta2b106532017-07-25 16:05:02 +05301044 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001045 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001046#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001047 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001048#else
1049 stream << "LinkLocalAddressing=no\n";
1050#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001051 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001052 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301053
1054 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001055 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301056 {
1057 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001058 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301059 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301060 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001061 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301062 {
1063 stream << "NTP=" << ntp << "\n";
1064 }
1065
1066 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301067 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301068 {
1069 stream << "DNS=" << dns << "\n";
1070 }
1071
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001072 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001073 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001074 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001075
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001076 stream << "[IPv6AcceptRA]\n";
1077 stream << "DHCPv6Client=";
1078 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Johnathan Manteyb353ba02021-12-09 12:27:32 -08001079 stream << "\n";
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001080
Johnathan Mantey817012a2020-01-30 15:07:39 -08001081 // Static IP addresses
1082 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301083 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001084 if (originIsManuallyAssigned(addr.second->origin()) &&
1085 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001086 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001087 // Process all static addresses
1088 std::string address = addr.second->address() + "/" +
1089 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301090
Johnathan Mantey817012a2020-01-30 15:07:39 -08001091 // build the address entries. Do not use [Network] shortcuts to
1092 // insert address entries.
1093 stream << "[Address]\n";
1094 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001095 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001096 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001097
Lei YUcb2d4082021-08-12 15:26:49 +08001098 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001099 {
Lei YUcb2d4082021-08-12 15:26:49 +08001100 auto gateway = EthernetInterfaceIntf::defaultGateway();
1101 if (!gateway.empty())
1102 {
1103 stream << "[Route]\n";
1104 stream << "Gateway=" << gateway << "\n";
1105 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001106 }
1107
Lei YUcb2d4082021-08-12 15:26:49 +08001108 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001109 {
Lei YUcb2d4082021-08-12 15:26:49 +08001110 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1111 if (!gateway6.empty())
1112 {
1113 stream << "[Route]\n";
1114 stream << "Gateway=" << gateway6 << "\n";
1115 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001116 }
1117
William A. Kennington III08505792019-01-30 16:00:04 -08001118 // Write the neighbor sections
1119 for (const auto& neighbor : staticNeighbors)
1120 {
1121 stream << "[Neighbor]"
1122 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001123 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1124 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001125 }
1126
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001127 // Write the dhcp section irrespective of whether DHCP is enabled or not
1128 writeDHCPSection(stream);
1129
Ratan Gupta2b106532017-07-25 16:05:02 +05301130 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301131}
1132
1133void EthernetInterface::writeDHCPSection(std::fstream& stream)
1134{
1135 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301136 // write the dhcp section
1137 stream << "[DHCP]\n";
1138
1139 // Hardcoding the client identifier to mac, to address below issue
1140 // https://github.com/openbmc/openbmc/issues/1280
1141 stream << "ClientIdentifier=mac\n";
1142 if (manager.getDHCPConf())
1143 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001144 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301145 stream << "UseDNS="s + value + "\n";
1146
Patrick Williams6aef7692021-05-01 06:39:41 -05001147 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301148 stream << "UseNTP="s + value + "\n";
1149
1150 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1151 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001152
1153 value =
1154 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1155 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301156 }
1157}
1158
Patrick Williams6aef7692021-05-01 06:39:41 -05001159std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301160{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001161 ether_addr newMAC;
1162 try
1163 {
1164 newMAC = mac_address::fromString(value);
1165 }
Patrick Williams5758db32021-10-06 12:29:22 -05001166 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001167 {
1168 log<level::ERR>("MACAddress is not valid.",
1169 entry("MAC=%s", value.c_str()));
1170 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1171 Argument::ARGUMENT_VALUE(value.c_str()));
1172 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001173 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301174 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001175 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001176 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001177 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1178 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301179 }
1180
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001181 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001182 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001183
William A. Kennington III1137a972019-04-20 20:49:58 -07001184 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001185 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001186 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301187 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001188 // Update everything that depends on the MAC value
1189 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301190 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001191 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301192 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001193 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301194
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001195 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001196 manager.addReloadPreHook([interface]() {
1197 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001198 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001199 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001200 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301201 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001202
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001203#ifdef HAVE_UBOOT_ENV
1204 // Ensure that the valid address is stored in the u-boot-env
1205 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1206 if (envVar)
1207 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001208 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1209 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1210 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1211 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001212 }
1213#endif // HAVE_UBOOT_ENV
1214
William A. Kennington III1137a972019-04-20 20:49:58 -07001215 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301216}
1217
Ratan Guptae9c9b812017-09-22 17:15:37 +05301218void EthernetInterface::deleteAll()
1219{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301220 // clear all the ip on the interface
1221 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001222
1223 writeConfigurationFile();
1224 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301225}
1226
Ravi Tejaa5a09442020-07-17 00:57:33 -05001227std::string EthernetInterface::defaultGateway(std::string gateway)
1228{
1229 auto gw = EthernetInterfaceIntf::defaultGateway();
1230 if (gw == gateway)
1231 {
1232 return gw;
1233 }
1234
1235 if (!isValidIP(AF_INET, gateway))
1236 {
1237 log<level::ERR>("Not a valid v4 Gateway",
1238 entry("GATEWAY=%s", gateway.c_str()));
1239 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1240 Argument::ARGUMENT_VALUE(gateway.c_str()));
1241 }
1242 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001243
1244 writeConfigurationFile();
1245 manager.reloadConfigs();
1246
Ravi Tejaa5a09442020-07-17 00:57:33 -05001247 return gw;
1248}
1249
1250std::string EthernetInterface::defaultGateway6(std::string gateway)
1251{
1252 auto gw = EthernetInterfaceIntf::defaultGateway6();
1253 if (gw == gateway)
1254 {
1255 return gw;
1256 }
1257
1258 if (!isValidIP(AF_INET6, gateway))
1259 {
1260 log<level::ERR>("Not a valid v6 Gateway",
1261 entry("GATEWAY=%s", gateway.c_str()));
1262 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1263 Argument::ARGUMENT_VALUE(gateway.c_str()));
1264 }
1265 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001266
1267 writeConfigurationFile();
1268 manager.reloadConfigs();
1269
Ravi Tejaa5a09442020-07-17 00:57:33 -05001270 return gw;
1271}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001272} // namespace network
1273} // namespace phosphor