blob: 3afe48c4e340ec3d196ab4a79e7da36e656e5fed [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 IIIc2e5e0e2019-04-22 01:26:06 -07006#include "ipaddress.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08007#include "neighbor.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05308#include "network_manager.hpp"
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -07009#include "types.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +053010#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +053011
Ratan Gupta82549cc2017-04-21 08:45:23 +053012#include <arpa/inet.h>
William A. Kennington IIIa520a392022-08-08 12:17:34 -070013#include <fmt/compile.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070014#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070016#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053017#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053018#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053019
Ratan Gupta82549cc2017-04-21 08:45:23 +053020#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053021#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070022#include <phosphor-logging/elog-errors.hpp>
23#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070024#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053025#include <sstream>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080026#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070027#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053028#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070029#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070030#include <unordered_map>
31#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070032#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053033
Ratan Gupta91a99cc2017-04-14 16:32:09 +053034namespace phosphor
35{
36namespace network
37{
38
39using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053040using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053041using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
42using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050043using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053044constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
45constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
46constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
47constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
48constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053049
Johnathan Mantey817012a2020-01-30 15:07:39 -080050std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
51 {EthernetInterface::DHCPConf::both, "true"},
52 {EthernetInterface::DHCPConf::v4, "ipv4"},
53 {EthernetInterface::DHCPConf::v6, "ipv6"},
54 {EthernetInterface::DHCPConf::none, "false"}};
55
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080056static stdplus::Fd& getIFSock()
57{
58 using namespace stdplus::fd;
59 static auto fd =
60 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
61 return fd;
62}
63
Patrick Williamsc38b0712022-07-22 19:26:54 -050064EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
Ratan Gupta91a99cc2017-04-14 16:32:09 +053065 const std::string& objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070066 const config::Parser& config,
Johnathan Mantey817012a2020-01-30 15:07:39 -080067 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070068 bool emitSignal,
69 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050070 Ifaces(bus, objPath.c_str(),
71 emitSignal ? Ifaces::action::defer_emit
72 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050073 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053074{
75 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053076 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053077 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050078 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070079 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070080 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070081 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
82 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050083 std::string defaultGateway;
84 std::string defaultGateway6;
85
William A. Kennington IIIe0564842021-10-23 16:02:22 -070086 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050087 {
88 if (gateway.first == intfName)
89 {
90 defaultGateway = gateway.second;
91 break;
92 }
93 }
94
William A. Kennington IIIe0564842021-10-23 16:02:22 -070095 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050096 {
97 if (gateway6.first == intfName)
98 {
99 defaultGateway6 = gateway6.second;
100 break;
101 }
102 }
103
104 EthernetInterfaceIntf::defaultGateway(defaultGateway);
105 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530106 // Don't get the mac address from the system as the mac address
107 // would be same as parent interface.
108 if (intfName.find(".") == std::string::npos)
109 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500110 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530111 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700112 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700113 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530114
115 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530116 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530117
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700118#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700119 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
120
121 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
122 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800123#endif
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530124
Ratan Gupta29b0e432017-05-25 12:51:40 +0530125 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530126 if (emitSignal)
127 {
128 this->emit_object_added();
129 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530130}
131
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700132static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800133{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700134 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800135 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700136 return IP::Protocol::IPv4;
137 }
138 else if (std::holds_alternative<in6_addr>(addr))
139 {
140 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800141 }
142
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700143 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800144}
145
Johnathan Mantey817012a2020-01-30 15:07:39 -0800146void EthernetInterface::disableDHCP(IP::Protocol protocol)
147{
Patrick Williams6aef7692021-05-01 06:39:41 -0500148 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800149 if (dhcpState == EthernetInterface::DHCPConf::both)
150 {
151 if (protocol == IP::Protocol::IPv4)
152 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500153 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800154 }
155 else if (protocol == IP::Protocol::IPv6)
156 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500157 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800158 }
159 }
160 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
161 (protocol == IP::Protocol::IPv4))
162 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500163 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800164 }
165 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
166 (protocol == IP::Protocol::IPv6))
167 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500168 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800169 }
170}
171
William A. Kennington III24957b92021-12-03 13:59:19 -0800172bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800173{
William A. Kennington III24957b92021-12-03 13:59:19 -0800174 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
175 return cur == EthernetInterface::DHCPConf::both ||
176 (family == IP::Protocol::IPv6 &&
177 cur == EthernetInterface::DHCPConf::v6) ||
178 (family == IP::Protocol::IPv4 &&
179 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800180}
181
Johnathan Mantey817012a2020-01-30 15:07:39 -0800182bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
183{
184 return (
185#ifdef LINK_LOCAL_AUTOCONFIGURATION
186 (origin == IP::AddressOrigin::Static)
187#else
188 (origin == IP::AddressOrigin::Static ||
189 origin == IP::AddressOrigin::LinkLocal)
190#endif
191
192 );
193}
194
Ratan Gupta87c13982017-06-15 09:27:27 +0530195void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530196{
Ratan Gupta87c13982017-06-15 09:27:27 +0530197 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530198
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700199 AddressFilter filter;
200 filter.interface = ifIndex();
201 auto currentAddrs = getCurrentAddresses(filter);
202 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530203 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700204 if (addr.flags & IFA_F_DEPRECATED)
205 {
206 continue;
207 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700208 auto address = toString(addr.address);
209 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800210 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800211 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530212 {
213 origin = IP::AddressOrigin::DHCP;
214 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700215 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530216 {
217 origin = IP::AddressOrigin::LinkLocal;
218 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700219 // Obsolete parameter
220 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530221
Gunnar Mills57d9c502018-09-14 14:42:34 -0500222 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700223 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530224
Lei YU7233c582021-04-08 14:39:43 +0800225 this->addrs.insert_or_assign(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700226 address, std::make_shared<phosphor::network::IPAddress>(
227 bus, ipAddressObjectPath.c_str(), *this, addressType,
228 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530229 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530230}
231
William A. Kennington III08505792019-01-30 16:00:04 -0800232void EthernetInterface::createStaticNeighborObjects()
233{
234 staticNeighbors.clear();
235
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700236 NeighborFilter filter;
237 filter.interface = ifIndex();
238 filter.state = NUD_PERMANENT;
239 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800240 for (const auto& neighbor : neighbors)
241 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700242 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800243 {
244 continue;
245 }
246 std::string ip = toString(neighbor.address);
247 std::string mac = mac_address::toString(*neighbor.mac);
248 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
249 staticNeighbors.emplace(ip,
250 std::make_shared<phosphor::network::Neighbor>(
251 bus, objectPath.c_str(), *this, ip, mac,
252 Neighbor::State::Permanent));
253 }
254}
255
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700256unsigned EthernetInterface::ifIndex() const
257{
258 unsigned idx = if_nametoindex(interfaceName().c_str());
259 if (idx == 0)
260 {
261 throw std::system_error(errno, std::generic_category(),
262 "if_nametoindex");
263 }
264 return idx;
265}
266
Patrick Williams6aef7692021-05-01 06:39:41 -0500267ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500268 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530269{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800270 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530271 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530272 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500273 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800274 disableDHCP(protType);
Ravi Teja07450442022-07-07 04:30:57 -0500275 // Delete the IP address object and that reloads the networkd
276 // to allow the same IP address to be set as Static IP
277 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500278 }
279
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500280 IP::AddressOrigin origin = IP::AddressOrigin::Static;
281
282 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
283
284 if (!isValidIP(addressFamily, ipaddress))
285 {
286 log<level::ERR>("Not a valid IP address"),
287 entry("ADDRESS=%s", ipaddress.c_str());
288 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
289 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
290 }
291
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700292 // Gateway is an obsolete parameter
293 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500294
295 if (!isValidPrefix(addressFamily, prefixLength))
296 {
297 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700298 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500299 elog<InvalidArgument>(
300 Argument::ARGUMENT_NAME("prefixLength"),
301 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530302 }
303
Gunnar Mills57d9c502018-09-14 14:42:34 -0500304 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800305 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800306 this->addrs.insert_or_assign(ipaddress,
307 std::make_shared<phosphor::network::IPAddress>(
308 bus, objectPath.c_str(), *this, protType,
309 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530310
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700311 writeConfigurationFile();
312 manager.reloadConfigs();
313
raviteja-bce379562019-03-28 05:59:36 -0500314 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530315}
316
Patrick Williams6aef7692021-05-01 06:39:41 -0500317ObjectPath EthernetInterface::neighbor(std::string ipAddress,
318 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800319{
Patrick Williams6aef7692021-05-01 06:39:41 -0500320 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800321 {
322 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500323 entry("ADDRESS=%s", ipAddress.c_str()));
324 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
325 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800326 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500327 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800328 {
329 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500330 entry("MACADDRESS=%s", ipAddress.c_str()));
331 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
332 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800333 }
334
335 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500336 generateStaticNeighborObjectPath(ipAddress, macAddress);
337 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800338 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500339 bus, objectPath.c_str(), *this, ipAddress,
340 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700341
342 writeConfigurationFile();
343 manager.reloadConfigs();
344
William A. Kennington III08505792019-01-30 16:00:04 -0800345 return objectPath;
346}
347
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700348#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530349/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800350 Enable this code if your NIC driver supports the ETHTOOL features.
351 Do this by adding the following to your phosphor-network*.bbappend file.
352 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
353 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530354*/
355InterfaceInfo EthernetInterface::getInterfaceInfo() const
356{
William A. Kennington III05368f12021-05-13 18:40:47 -0700357 ifreq ifr = {};
358 ethtool_cmd edata = {};
359 LinkSpeed speed = {};
360 Autoneg autoneg = {};
361 DuplexMode duplex = {};
362 LinkUp linkState = {};
363 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530364 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530365
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800366 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
367 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530368
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800369 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800370 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800371 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800372 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530373 speed = edata.speed;
374 duplex = edata.duplex;
375 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530376 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800377 catch (const std::exception& e)
378 {
379 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800380
William A. Kennington III96203312021-05-07 12:50:41 -0700381 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800382 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530383 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800384
Tejas Patil2c0fc562021-08-03 19:13:46 +0530385 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530386}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800387#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530388
389/** @brief get the mac address of the interface.
390 * @return macaddress on success
391 */
392
Gunnar Mills57d9c502018-09-14 14:42:34 -0500393std::string
394 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530395{
Patrick Williams6aef7692021-05-01 06:39:41 -0500396 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530397
William A. Kennington III05368f12021-05-13 18:40:47 -0700398 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800399 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800400 try
401 {
402 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
403 }
404 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530405 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530406 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800407 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700408 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530409 }
410
William A. Kennington III1137a972019-04-20 20:49:58 -0700411 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
412 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
413 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700414 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530415}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530416
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530417std::string EthernetInterface::generateId(const std::string& ipaddress,
418 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800419 const std::string& gateway,
420 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530421{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530422 std::stringstream hexId;
423 std::string hashString = ipaddress;
424 hashString += std::to_string(prefixLength);
425 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800426 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530427
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530428 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500429 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530430 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530431}
432
Patrick Williams6aef7692021-05-01 06:39:41 -0500433std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
434 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800435{
436 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500437 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800438
439 // Only want 8 hex digits.
440 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
441 return hexId.str();
442}
443
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530444void EthernetInterface::deleteObject(const std::string& ipaddress)
445{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530446 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530447 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530448 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530449 log<level::ERR>("DeleteObject:Unable to find the object.");
450 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530451 }
452 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700453
454 writeConfigurationFile();
455 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530456}
457
Patrick Williams6aef7692021-05-01 06:39:41 -0500458void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800459{
Patrick Williams6aef7692021-05-01 06:39:41 -0500460 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800461 if (it == staticNeighbors.end())
462 {
463 log<level::ERR>(
464 "DeleteStaticNeighborObject:Unable to find the object.");
465 return;
466 }
467 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700468
469 writeConfigurationFile();
470 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800471}
472
Ratan Guptae9c9b812017-09-22 17:15:37 +0530473void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530474{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700475 const auto& confDir = manager.getConfDir();
476 auto networkFile = config::pathForIntfConf(confDir, interface);
477 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530478
479 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700480 std::error_code ec;
481 fs::remove(networkFile, ec);
482 fs::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530483
484 // TODO systemd doesn't delete the virtual network interface
485 // even after deleting all the related configuartion.
486 // https://github.com/systemd/systemd/issues/6600
487 try
488 {
489 deleteInterface(interface);
490 }
Patrick Williams5758db32021-10-06 12:29:22 -0500491 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530492 {
493 commit<InternalFailure>();
494 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530495}
496
497void EthernetInterface::deleteVLANObject(const std::string& interface)
498{
499 auto it = vlanInterfaces.find(interface);
500 if (it == vlanInterfaces.end())
501 {
502 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500503 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530504 return;
505 }
506
507 deleteVLANFromSystem(interface);
508 // delete the interface
509 vlanInterfaces.erase(it);
510
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700511 writeConfigurationFile();
512 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530513}
514
Gunnar Mills57d9c502018-09-14 14:42:34 -0500515std::string EthernetInterface::generateObjectPath(
516 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800517 uint8_t prefixLength, const std::string& gateway,
518 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530519{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530520 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530521 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530522 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
523
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530524 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530525 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530526 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800527 objectPath /=
528 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530529 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530530}
531
William A. Kennington III08505792019-01-30 16:00:04 -0800532std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500533 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800534{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530535 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800536 objectPath /= objPath;
537 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500538 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800539 return objectPath.string();
540}
541
Patrick Williams6aef7692021-05-01 06:39:41 -0500542bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700543{
Patrick Williams6aef7692021-05-01 06:39:41 -0500544 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700545 {
546 return value;
547 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500548 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700549
550 writeConfigurationFile();
551 manager.reloadConfigs();
552
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700553 return value;
554}
555
Patrick Williams6aef7692021-05-01 06:39:41 -0500556EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530557{
Patrick Williams6aef7692021-05-01 06:39:41 -0500558 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530559 {
560 return value;
561 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500562 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700563
564 writeConfigurationFile();
565 manager.reloadConfigs();
566
Ratan Gupta87c13982017-06-15 09:27:27 +0530567 return value;
568}
569
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800570bool EthernetInterface::linkUp() const
571{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800572 bool value = EthernetInterfaceIntf::linkUp();
573
William A. Kennington III05368f12021-05-13 18:40:47 -0700574 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800575 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800576 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800577 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800578 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800579 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
580 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800581 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800582 {
583 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800584 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800585 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700586 return value;
587}
588
Tejas Patil2c0fc562021-08-03 19:13:46 +0530589size_t EthernetInterface::mtu() const
590{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530591 size_t value = EthernetInterfaceIntf::mtu();
592
Tejas Patil2c0fc562021-08-03 19:13:46 +0530593 ifreq ifr = {};
594 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800595 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530596 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800597 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530598 value = ifr.ifr_mtu;
599 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800600 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530601 {
602 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800603 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530604 }
605 return value;
606}
607
608size_t EthernetInterface::mtu(size_t value)
609{
610 if (value == EthernetInterfaceIntf::mtu())
611 {
612 return value;
613 }
614 else if (value == 0)
615 {
616 return EthernetInterfaceIntf::mtu();
617 }
618
Tejas Patil2c0fc562021-08-03 19:13:46 +0530619 ifreq ifr = {};
620 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
621 ifr.ifr_mtu = value;
622
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800623 try
624 {
625 getIFSock().ioctl(SIOCSIFMTU, &ifr);
626 }
627 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530628 {
629 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
630 entry("ERROR=%s", strerror(errno)));
631 return EthernetInterfaceIntf::mtu();
632 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530633
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800634 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530635 return value;
636}
637
William A. Kennington III26275a32021-07-13 20:32:42 -0700638bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700639{
William A. Kennington III26275a32021-07-13 20:32:42 -0700640 constexpr auto svc = "org.freedesktop.network1";
641 constexpr auto intf = "org.freedesktop.network1.Link";
642 constexpr auto prop = "AdministrativeState";
643 char* rpath;
644 sd_bus_path_encode("/org/freedesktop/network1/link",
645 std::to_string(ifIndex()).c_str(), &rpath);
646 std::string path(rpath);
647 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700648
William A. Kennington III26275a32021-07-13 20:32:42 -0700649 // Store / Parser for the AdministrativeState return value
650 std::optional<bool> ret;
651 auto cb = [&](const std::string& state) {
652 if (state != "initialized")
653 {
654 ret = state != "unmanaged";
655 }
656 };
657
658 // Build a matcher before making the property call to ensure we
659 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500660 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700661 bus,
662 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
663 "'PropertiesChanged',arg0='{}',",
664 svc, path, PROPERTY_INTERFACE, intf)
665 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500666 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700667 std::string intf;
668 std::unordered_map<std::string, std::variant<std::string>> values;
669 try
670 {
671 m.read(intf, values);
672 auto it = values.find(prop);
673 // Ignore properties that aren't AdministrativeState
674 if (it != values.end())
675 {
676 cb(std::get<std::string>(it->second));
677 }
678 }
679 catch (const std::exception& e)
680 {
681 log<level::ERR>(
682 fmt::format(
683 "AdministrativeState match parsing failed on {}: {}",
684 interfaceName(), e.what())
685 .c_str(),
686 entry("INTERFACE=%s", interfaceName().c_str()),
687 entry("ERROR=%s", e.what()));
688 }
689 });
690
691 // Actively call for the value in case the interface is already configured
692 auto method =
693 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
694 method.append(intf, prop);
695 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700696 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700697 auto reply = bus.call(method);
698 std::variant<std::string> state;
699 reply.read(state);
700 cb(std::get<std::string>(state));
701 }
702 catch (const std::exception& e)
703 {
704 log<level::ERR>(
705 fmt::format("Failed to get AdministrativeState on {}: {}",
706 interfaceName(), e.what())
707 .c_str(),
708 entry("INTERFACE=%s", interfaceName().c_str()),
709 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700710 }
711
William A. Kennington III26275a32021-07-13 20:32:42 -0700712 // The interface is not yet configured by systemd-networkd, wait until it
713 // signals us a valid state.
714 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700715 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700716 bus.wait();
717 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700718 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700719
720 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700721}
722
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800723static void setNICAdminState(const char* intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700724{
725 ifreq ifr = {};
726 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800727 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700728
729 ifr.ifr_flags &= ~IFF_UP;
730 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800731 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700732}
733
Patrick Williams6aef7692021-05-01 06:39:41 -0500734bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700735{
Patrick Williams6aef7692021-05-01 06:39:41 -0500736 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700737 {
738 return value;
739 }
740
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800741 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700742 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800743 if (!value)
744 {
745 // We only need to bring down the interface, networkd will always bring
746 // up managed interfaces
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800747 manager.addReloadPreHook([ifname = interfaceName()]() {
748 setNICAdminState(ifname.c_str(), false);
749 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800750 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700751 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800752
753 return value;
754}
755
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530756ServerList EthernetInterface::staticNameServers(ServerList value)
757{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530758 for (const auto& nameserverip : value)
759 {
760 if (!isValidIP(AF_INET, nameserverip) &&
761 !isValidIP(AF_INET6, nameserverip))
762 {
763 log<level::ERR>("Not a valid IP address"),
764 entry("ADDRESS=%s", nameserverip.c_str());
765 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530766 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530767 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
768 }
769 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530770 try
771 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530772 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700773
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530774 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700775 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530776 }
Patrick Williams5758db32021-10-06 12:29:22 -0500777 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530778 {
779 log<level::ERR>("Exception processing DNS entries");
780 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530781 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530782}
783
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700784void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530785{
786 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700787 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700788 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530789}
790
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530791ServerList EthernetInterface::getNameServerFromResolvd()
792{
793 ServerList servers;
794 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
795
796 /*
797 The DNS property under org.freedesktop.resolve1.Link interface contains
798 an array containing all DNS servers currently used by resolved. It
799 contains similar information as the DNS server data written to
800 /run/systemd/resolve/resolv.conf.
801
802 Each structure in the array consists of a numeric network interface index,
803 an address family, and a byte array containing the DNS server address
804 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
805 The array contains DNS servers configured system-wide, including those
806 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
807 /etc/systemd/resolved.conf, as well as per-interface DNS server
808 information either retrieved from systemd-networkd or configured by
809 external software via SetLinkDNS().
810 */
811
812 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
813 std::variant<type> name; // Variable to capture the DNS property
814 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
815 PROPERTY_INTERFACE, METHOD_GET);
816
817 method.append(RESOLVED_INTERFACE, "DNS");
818 auto reply = bus.call(method);
819
820 try
821 {
822 reply.read(name);
823 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500824 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530825 {
826 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
827 }
828 auto tupleVector = std::get_if<type>(&name);
829 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
830 {
Alexander Filippov983da552021-02-08 15:26:54 +0300831 int addressFamily = std::get<0>(*i);
832 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
833
834 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530835 {
Alexander Filippov983da552021-02-08 15:26:54 +0300836 case AF_INET:
837 if (ipaddress.size() == sizeof(struct in_addr))
838 {
839 servers.push_back(toString(
840 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
841 }
842 else
843 {
844 log<level::ERR>(
845 "Invalid data recived from Systemd-Resolved");
846 }
847 break;
848
849 case AF_INET6:
850 if (ipaddress.size() == sizeof(struct in6_addr))
851 {
852 servers.push_back(toString(
853 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
854 }
855 else
856 {
857 log<level::ERR>(
858 "Invalid data recived from Systemd-Resolved");
859 }
860 break;
861
862 default:
863 log<level::ERR>(
864 "Unsupported address family in DNS from Systemd-Resolved");
865 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530866 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530867 }
868 return servers;
869}
870
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700871std::string EthernetInterface::vlanIntfName(VlanId id) const
872{
873 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
874}
875
876std::string EthernetInterface::vlanObjPath(VlanId id) const
877{
878 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
879}
880
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530881void EthernetInterface::loadVLAN(VlanId id)
882{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700883 auto vlanInterfaceName = vlanIntfName(id);
884 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530885
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700886 config::Parser config(
887 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
888
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530889 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700890 bus, path.c_str(), config, getDHCPValue(config),
891 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530892
Gunnar Mills57d9c502018-09-14 14:42:34 -0500893 // Fetch the ip address from the system
894 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530895 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800896 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700897 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530898
899 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
900 std::move(vlanIntf));
901}
902
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700903ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530904{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700905 auto vlanInterfaceName = vlanIntfName(id);
906 if (this->vlanInterfaces.find(vlanInterfaceName) !=
907 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800908 {
909 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
910 elog<InvalidArgument>(
911 Argument::ARGUMENT_NAME("VLANId"),
912 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
913 }
914
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700915 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530916
Patrick Williams6aef7692021-05-01 06:39:41 -0500917 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530918 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530919 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700920 bus, path.c_str(), config::Parser(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500921 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530922
923 // write the device file for the vlan interface.
924 vlanIntf->writeDeviceFile();
925
Gunnar Mills57d9c502018-09-14 14:42:34 -0500926 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700927
928 writeConfigurationFile();
929 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700930
931 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530932}
Ratan Gupta2b106532017-07-25 16:05:02 +0530933
Patrick Williams6aef7692021-05-01 06:39:41 -0500934ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530935{
Patrick Williams6aef7692021-05-01 06:39:41 -0500936 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530937
938 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700939 manager.reloadConfigs();
940
Ratan Gupta497c0c92017-08-22 19:15:59 +0530941 return ntpServers;
942}
Ratan Gupta2b106532017-07-25 16:05:02 +0530943// Need to merge the below function with the code which writes the
944// config file during factory reset.
945// TODO openbmc/openbmc#1751
946
947void EthernetInterface::writeConfigurationFile()
948{
949 // write all the static ip address in the systemd-network conf file
950
951 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530952 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530953
954 // if there is vlan interafce then write the configuration file
955 // for vlan also.
956
Gunnar Mills57d9c502018-09-14 14:42:34 -0500957 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530958 {
959 intf.second->writeConfigurationFile();
960 }
961
William A. Kennington III95a49a22022-08-18 17:50:05 -0700962 config::Parser config;
963 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530964 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700965 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800966#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700967 auto mac = MacAddressIntf::macAddress();
968 if (!mac.empty())
969 {
970 link["MACAddress"].emplace_back(mac);
971 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800972#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700973 if (!EthernetInterfaceIntf::nicEnabled())
974 {
975 link["Unmanaged"].emplace_back("yes");
976 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700977 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700978 {
979 auto& network = config.map["Network"].emplace_back();
980 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400981#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700982 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400983#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700984 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400985#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700986 network["IPv6AcceptRA"].emplace_back(
987 EthernetInterfaceIntf::ipv6AcceptRA() ? "true" : "false");
988 network["DHCP"].emplace_back(
989 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()]);
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600990 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700991 auto& vlans = network["VLAN"];
992 for (const auto& intf : vlanInterfaces)
993 {
994 vlans.emplace_back(
995 intf.second->EthernetInterface::interfaceName());
996 }
997 }
998 {
999 auto& ntps = network["NTP"];
1000 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
1001 {
1002 ntps.emplace_back(ntp);
1003 }
1004 }
1005 {
1006 auto& dnss = network["DNS"];
1007 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1008 {
1009 dnss.emplace_back(dns);
1010 }
1011 }
1012 {
1013 auto& address = network["Address"];
1014 for (const auto& addr : getAddresses())
1015 {
1016 if (originIsManuallyAssigned(addr.second->origin()) &&
1017 !dhcpIsEnabled(addr.second->type()))
1018 {
1019 address.emplace_back(
1020 fmt::format("{}/{}", addr.second->address(),
1021 addr.second->prefixLength()));
1022 }
1023 }
1024 }
1025 {
1026 auto& gateways = network["Gateway"];
1027 if (!dhcpIsEnabled(IP::Protocol::IPv4))
1028 {
1029 auto gateway = EthernetInterfaceIntf::defaultGateway();
1030 if (!gateway.empty())
1031 {
1032 gateways.emplace_back(gateway);
1033 }
1034 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301035
William A. Kennington III95a49a22022-08-18 17:50:05 -07001036 if (!dhcpIsEnabled(IP::Protocol::IPv6))
1037 {
1038 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1039 if (!gateway6.empty())
1040 {
1041 gateways.emplace_back(gateway6);
1042 }
1043 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001044 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001045 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001046 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
1047 dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001048 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001049 auto& neighbors = config.map["Neighbor"];
1050 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001051 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001052 auto& neighbor = neighbors.emplace_back();
1053 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1054 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001055 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001056 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001057 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001058 auto& dhcp = config.map["DHCP"].emplace_back();
1059 dhcp["ClientIdentifier"].emplace_back("mac");
1060 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001061 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001062 const auto& conf = *manager.getDHCPConf();
1063 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1064 dhcp["UseDNS"].emplace_back(dns_enabled);
1065 dhcp["UseDomains"].emplace_back(dns_enabled);
1066 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1067 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1068 : "false");
1069 dhcp["SendHostname"].emplace_back(
1070 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001071 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001072 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001073 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1074 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001075 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1076 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301077}
1078
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001079std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301080{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001081#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001082 ether_addr newMAC;
1083 try
1084 {
1085 newMAC = mac_address::fromString(value);
1086 }
Patrick Williams5758db32021-10-06 12:29:22 -05001087 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001088 {
1089 log<level::ERR>("MACAddress is not valid.",
1090 entry("MAC=%s", value.c_str()));
1091 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1092 Argument::ARGUMENT_VALUE(value.c_str()));
1093 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001094 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301095 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001096 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001097 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001098 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1099 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301100 }
1101
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001102 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001103 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001104
William A. Kennington III1137a972019-04-20 20:49:58 -07001105 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001106 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001107 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301108 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001109 // Update everything that depends on the MAC value
1110 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301111 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001112 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301113 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001114 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301115
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001116 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001117 manager.addReloadPreHook([interface]() {
1118 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001119 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001120 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001121 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301122 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001123
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001124#ifdef HAVE_UBOOT_ENV
1125 // Ensure that the valid address is stored in the u-boot-env
1126 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1127 if (envVar)
1128 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001129 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1130 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1131 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1132 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001133 }
1134#endif // HAVE_UBOOT_ENV
1135
William A. Kennington III1137a972019-04-20 20:49:58 -07001136 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001137#else
1138 elog<NotAllowed>(
1139 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1140#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301141}
1142
Ratan Guptae9c9b812017-09-22 17:15:37 +05301143void EthernetInterface::deleteAll()
1144{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301145 // clear all the ip on the interface
1146 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001147
1148 writeConfigurationFile();
1149 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301150}
1151
Ravi Tejaa5a09442020-07-17 00:57:33 -05001152std::string EthernetInterface::defaultGateway(std::string gateway)
1153{
1154 auto gw = EthernetInterfaceIntf::defaultGateway();
1155 if (gw == gateway)
1156 {
1157 return gw;
1158 }
1159
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001160 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001161 {
1162 log<level::ERR>("Not a valid v4 Gateway",
1163 entry("GATEWAY=%s", gateway.c_str()));
1164 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1165 Argument::ARGUMENT_VALUE(gateway.c_str()));
1166 }
1167 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001168
1169 writeConfigurationFile();
1170 manager.reloadConfigs();
1171
Ravi Tejaa5a09442020-07-17 00:57:33 -05001172 return gw;
1173}
1174
1175std::string EthernetInterface::defaultGateway6(std::string gateway)
1176{
1177 auto gw = EthernetInterfaceIntf::defaultGateway6();
1178 if (gw == gateway)
1179 {
1180 return gw;
1181 }
1182
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001183 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001184 {
1185 log<level::ERR>("Not a valid v6 Gateway",
1186 entry("GATEWAY=%s", gateway.c_str()));
1187 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1188 Argument::ARGUMENT_VALUE(gateway.c_str()));
1189 }
1190 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001191
1192 writeConfigurationFile();
1193 manager.reloadConfigs();
1194
Ravi Tejaa5a09442020-07-17 00:57:33 -05001195 return gw;
1196}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001197} // namespace network
1198} // namespace phosphor