blob: c222af1c52372b70d41eedb1f1ac9dd619ade650 [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,
William A. Kennington III0caf2212022-08-18 18:15:51 -070067 Manager& parent, bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -070068 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050069 Ifaces(bus, objPath.c_str(),
70 emitSignal ? Ifaces::action::defer_emit
71 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050072 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053073{
74 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053075 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053076 interfaceName(intfName);
William A. Kennington III0caf2212022-08-18 18:15:51 -070077 EthernetInterfaceIntf::dhcpEnabled(getDHCPValue(config));
William A. Kennington IIIa520a392022-08-08 12:17:34 -070078 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070079 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070080 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
81 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050082 std::string defaultGateway;
83 std::string defaultGateway6;
84
William A. Kennington IIIe0564842021-10-23 16:02:22 -070085 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050086 {
87 if (gateway.first == intfName)
88 {
89 defaultGateway = gateway.second;
90 break;
91 }
92 }
93
William A. Kennington IIIe0564842021-10-23 16:02:22 -070094 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050095 {
96 if (gateway6.first == intfName)
97 {
98 defaultGateway6 = gateway6.second;
99 break;
100 }
101 }
102
103 EthernetInterfaceIntf::defaultGateway(defaultGateway);
104 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530105 // Don't get the mac address from the system as the mac address
106 // would be same as parent interface.
107 if (intfName.find(".") == std::string::npos)
108 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500109 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530110 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700111 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700112 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530113
114 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530115 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530116
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700117#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700118 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
119
120 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
121 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800122#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530123
Ratan Gupta29b0e432017-05-25 12:51:40 +0530124 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530125 if (emitSignal)
126 {
127 this->emit_object_added();
128 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530129}
130
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700131static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800132{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700133 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800134 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700135 return IP::Protocol::IPv4;
136 }
137 else if (std::holds_alternative<in6_addr>(addr))
138 {
139 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800140 }
141
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700142 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800143}
144
Johnathan Mantey817012a2020-01-30 15:07:39 -0800145void EthernetInterface::disableDHCP(IP::Protocol protocol)
146{
Patrick Williams6aef7692021-05-01 06:39:41 -0500147 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800148 if (dhcpState == EthernetInterface::DHCPConf::both)
149 {
150 if (protocol == IP::Protocol::IPv4)
151 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500152 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800153 }
154 else if (protocol == IP::Protocol::IPv6)
155 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500156 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800157 }
158 }
159 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
160 (protocol == IP::Protocol::IPv4))
161 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500162 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800163 }
164 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
165 (protocol == IP::Protocol::IPv6))
166 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500167 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800168 }
169}
170
William A. Kennington III24957b92021-12-03 13:59:19 -0800171bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800172{
William A. Kennington III24957b92021-12-03 13:59:19 -0800173 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
174 return cur == EthernetInterface::DHCPConf::both ||
175 (family == IP::Protocol::IPv6 &&
176 cur == EthernetInterface::DHCPConf::v6) ||
177 (family == IP::Protocol::IPv4 &&
178 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800179}
180
Johnathan Mantey817012a2020-01-30 15:07:39 -0800181bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
182{
183 return (
184#ifdef LINK_LOCAL_AUTOCONFIGURATION
185 (origin == IP::AddressOrigin::Static)
186#else
187 (origin == IP::AddressOrigin::Static ||
188 origin == IP::AddressOrigin::LinkLocal)
189#endif
190
191 );
192}
193
Ratan Gupta87c13982017-06-15 09:27:27 +0530194void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530195{
Ratan Gupta87c13982017-06-15 09:27:27 +0530196 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530197
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700198 AddressFilter filter;
199 filter.interface = ifIndex();
200 auto currentAddrs = getCurrentAddresses(filter);
201 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530202 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700203 if (addr.flags & IFA_F_DEPRECATED)
204 {
205 continue;
206 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700207 auto address = toString(addr.address);
208 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800209 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800210 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530211 {
212 origin = IP::AddressOrigin::DHCP;
213 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700214 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530215 {
216 origin = IP::AddressOrigin::LinkLocal;
217 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700218 // Obsolete parameter
219 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530220
Gunnar Mills57d9c502018-09-14 14:42:34 -0500221 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700222 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530223
Lei YU7233c582021-04-08 14:39:43 +0800224 this->addrs.insert_or_assign(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700225 address, std::make_shared<phosphor::network::IPAddress>(
226 bus, ipAddressObjectPath.c_str(), *this, addressType,
227 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530228 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530229}
230
William A. Kennington III08505792019-01-30 16:00:04 -0800231void EthernetInterface::createStaticNeighborObjects()
232{
233 staticNeighbors.clear();
234
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700235 NeighborFilter filter;
236 filter.interface = ifIndex();
237 filter.state = NUD_PERMANENT;
238 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800239 for (const auto& neighbor : neighbors)
240 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700241 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800242 {
243 continue;
244 }
245 std::string ip = toString(neighbor.address);
246 std::string mac = mac_address::toString(*neighbor.mac);
247 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
248 staticNeighbors.emplace(ip,
249 std::make_shared<phosphor::network::Neighbor>(
250 bus, objectPath.c_str(), *this, ip, mac,
251 Neighbor::State::Permanent));
252 }
253}
254
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700255unsigned EthernetInterface::ifIndex() const
256{
257 unsigned idx = if_nametoindex(interfaceName().c_str());
258 if (idx == 0)
259 {
260 throw std::system_error(errno, std::generic_category(),
261 "if_nametoindex");
262 }
263 return idx;
264}
265
Patrick Williams6aef7692021-05-01 06:39:41 -0500266ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500267 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530268{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800269 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530270 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530271 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500272 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800273 disableDHCP(protType);
Ravi Teja07450442022-07-07 04:30:57 -0500274 // Delete the IP address object and that reloads the networkd
275 // to allow the same IP address to be set as Static IP
276 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500277 }
278
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500279 IP::AddressOrigin origin = IP::AddressOrigin::Static;
280
281 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
282
283 if (!isValidIP(addressFamily, ipaddress))
284 {
285 log<level::ERR>("Not a valid IP address"),
286 entry("ADDRESS=%s", ipaddress.c_str());
287 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
288 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
289 }
290
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700291 // Gateway is an obsolete parameter
292 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500293
294 if (!isValidPrefix(addressFamily, prefixLength))
295 {
296 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700297 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500298 elog<InvalidArgument>(
299 Argument::ARGUMENT_NAME("prefixLength"),
300 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530301 }
302
Gunnar Mills57d9c502018-09-14 14:42:34 -0500303 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800304 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800305 this->addrs.insert_or_assign(ipaddress,
306 std::make_shared<phosphor::network::IPAddress>(
307 bus, objectPath.c_str(), *this, protType,
308 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530309
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700310 writeConfigurationFile();
311 manager.reloadConfigs();
312
raviteja-bce379562019-03-28 05:59:36 -0500313 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530314}
315
Patrick Williams6aef7692021-05-01 06:39:41 -0500316ObjectPath EthernetInterface::neighbor(std::string ipAddress,
317 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800318{
Patrick Williams6aef7692021-05-01 06:39:41 -0500319 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800320 {
321 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500322 entry("ADDRESS=%s", ipAddress.c_str()));
323 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
324 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800325 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500326 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800327 {
328 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500329 entry("MACADDRESS=%s", ipAddress.c_str()));
330 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
331 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800332 }
333
334 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500335 generateStaticNeighborObjectPath(ipAddress, macAddress);
336 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800337 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500338 bus, objectPath.c_str(), *this, ipAddress,
339 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700340
341 writeConfigurationFile();
342 manager.reloadConfigs();
343
William A. Kennington III08505792019-01-30 16:00:04 -0800344 return objectPath;
345}
346
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700347#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530348/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800349 Enable this code if your NIC driver supports the ETHTOOL features.
350 Do this by adding the following to your phosphor-network*.bbappend file.
351 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
352 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530353*/
354InterfaceInfo EthernetInterface::getInterfaceInfo() const
355{
William A. Kennington III05368f12021-05-13 18:40:47 -0700356 ifreq ifr = {};
357 ethtool_cmd edata = {};
358 LinkSpeed speed = {};
359 Autoneg autoneg = {};
360 DuplexMode duplex = {};
361 LinkUp linkState = {};
362 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530363 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530364
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800365 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
366 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530367
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800368 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800369 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800370 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800371 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530372 speed = edata.speed;
373 duplex = edata.duplex;
374 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530375 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800376 catch (const std::exception& e)
377 {
378 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800379
William A. Kennington III96203312021-05-07 12:50:41 -0700380 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800381 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530382 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800383
Tejas Patil2c0fc562021-08-03 19:13:46 +0530384 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530385}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800386#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530387
388/** @brief get the mac address of the interface.
389 * @return macaddress on success
390 */
391
Gunnar Mills57d9c502018-09-14 14:42:34 -0500392std::string
393 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530394{
Patrick Williams6aef7692021-05-01 06:39:41 -0500395 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530396
William A. Kennington III05368f12021-05-13 18:40:47 -0700397 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800398 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800399 try
400 {
401 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
402 }
403 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530404 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530405 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800406 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700407 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530408 }
409
William A. Kennington III1137a972019-04-20 20:49:58 -0700410 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
411 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
412 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700413 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530414}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530415
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530416std::string EthernetInterface::generateId(const std::string& ipaddress,
417 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800418 const std::string& gateway,
419 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530420{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530421 std::stringstream hexId;
422 std::string hashString = ipaddress;
423 hashString += std::to_string(prefixLength);
424 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800425 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530426
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530427 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500428 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530429 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530430}
431
Patrick Williams6aef7692021-05-01 06:39:41 -0500432std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
433 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800434{
435 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500436 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800437
438 // Only want 8 hex digits.
439 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
440 return hexId.str();
441}
442
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530443void EthernetInterface::deleteObject(const std::string& ipaddress)
444{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530445 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530446 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530447 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530448 log<level::ERR>("DeleteObject:Unable to find the object.");
449 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530450 }
451 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700452
453 writeConfigurationFile();
454 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530455}
456
Patrick Williams6aef7692021-05-01 06:39:41 -0500457void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800458{
Patrick Williams6aef7692021-05-01 06:39:41 -0500459 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800460 if (it == staticNeighbors.end())
461 {
462 log<level::ERR>(
463 "DeleteStaticNeighborObject:Unable to find the object.");
464 return;
465 }
466 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700467
468 writeConfigurationFile();
469 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800470}
471
Ratan Guptae9c9b812017-09-22 17:15:37 +0530472void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530473{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700474 const auto& confDir = manager.getConfDir();
475 auto networkFile = config::pathForIntfConf(confDir, interface);
476 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530477
478 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700479 std::error_code ec;
480 fs::remove(networkFile, ec);
481 fs::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530482
483 // TODO systemd doesn't delete the virtual network interface
484 // even after deleting all the related configuartion.
485 // https://github.com/systemd/systemd/issues/6600
486 try
487 {
488 deleteInterface(interface);
489 }
Patrick Williams5758db32021-10-06 12:29:22 -0500490 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530491 {
492 commit<InternalFailure>();
493 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530494}
495
496void EthernetInterface::deleteVLANObject(const std::string& interface)
497{
498 auto it = vlanInterfaces.find(interface);
499 if (it == vlanInterfaces.end())
500 {
501 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500502 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530503 return;
504 }
505
506 deleteVLANFromSystem(interface);
507 // delete the interface
508 vlanInterfaces.erase(it);
509
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700510 writeConfigurationFile();
511 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530512}
513
Gunnar Mills57d9c502018-09-14 14:42:34 -0500514std::string EthernetInterface::generateObjectPath(
515 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800516 uint8_t prefixLength, const std::string& gateway,
517 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530518{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530519 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530520 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530521 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
522
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530523 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530524 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530525 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800526 objectPath /=
527 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530528 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530529}
530
William A. Kennington III08505792019-01-30 16:00:04 -0800531std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500532 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800533{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530534 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800535 objectPath /= objPath;
536 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500537 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800538 return objectPath.string();
539}
540
Patrick Williams6aef7692021-05-01 06:39:41 -0500541bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700542{
Patrick Williams6aef7692021-05-01 06:39:41 -0500543 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700544 {
545 return value;
546 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500547 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700548
549 writeConfigurationFile();
550 manager.reloadConfigs();
551
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700552 return value;
553}
554
Patrick Williams6aef7692021-05-01 06:39:41 -0500555EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530556{
Patrick Williams6aef7692021-05-01 06:39:41 -0500557 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530558 {
559 return value;
560 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500561 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700562
563 writeConfigurationFile();
564 manager.reloadConfigs();
565
Ratan Gupta87c13982017-06-15 09:27:27 +0530566 return value;
567}
568
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800569bool EthernetInterface::linkUp() const
570{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800571 bool value = EthernetInterfaceIntf::linkUp();
572
William A. Kennington III05368f12021-05-13 18:40:47 -0700573 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800574 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800575 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800576 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800577 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800578 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
579 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800580 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800581 {
582 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800583 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800584 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700585 return value;
586}
587
Tejas Patil2c0fc562021-08-03 19:13:46 +0530588size_t EthernetInterface::mtu() const
589{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530590 size_t value = EthernetInterfaceIntf::mtu();
591
Tejas Patil2c0fc562021-08-03 19:13:46 +0530592 ifreq ifr = {};
593 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800594 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530595 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800596 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530597 value = ifr.ifr_mtu;
598 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800599 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530600 {
601 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800602 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530603 }
604 return value;
605}
606
607size_t EthernetInterface::mtu(size_t value)
608{
609 if (value == EthernetInterfaceIntf::mtu())
610 {
611 return value;
612 }
613 else if (value == 0)
614 {
615 return EthernetInterfaceIntf::mtu();
616 }
617
Tejas Patil2c0fc562021-08-03 19:13:46 +0530618 ifreq ifr = {};
619 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
620 ifr.ifr_mtu = value;
621
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800622 try
623 {
624 getIFSock().ioctl(SIOCSIFMTU, &ifr);
625 }
626 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530627 {
628 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
629 entry("ERROR=%s", strerror(errno)));
630 return EthernetInterfaceIntf::mtu();
631 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530632
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800633 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530634 return value;
635}
636
William A. Kennington III26275a32021-07-13 20:32:42 -0700637bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700638{
William A. Kennington III26275a32021-07-13 20:32:42 -0700639 constexpr auto svc = "org.freedesktop.network1";
640 constexpr auto intf = "org.freedesktop.network1.Link";
641 constexpr auto prop = "AdministrativeState";
642 char* rpath;
643 sd_bus_path_encode("/org/freedesktop/network1/link",
644 std::to_string(ifIndex()).c_str(), &rpath);
645 std::string path(rpath);
646 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700647
William A. Kennington III26275a32021-07-13 20:32:42 -0700648 // Store / Parser for the AdministrativeState return value
649 std::optional<bool> ret;
650 auto cb = [&](const std::string& state) {
651 if (state != "initialized")
652 {
653 ret = state != "unmanaged";
654 }
655 };
656
657 // Build a matcher before making the property call to ensure we
658 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500659 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700660 bus,
661 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
662 "'PropertiesChanged',arg0='{}',",
663 svc, path, PROPERTY_INTERFACE, intf)
664 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500665 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700666 std::string intf;
667 std::unordered_map<std::string, std::variant<std::string>> values;
668 try
669 {
670 m.read(intf, values);
671 auto it = values.find(prop);
672 // Ignore properties that aren't AdministrativeState
673 if (it != values.end())
674 {
675 cb(std::get<std::string>(it->second));
676 }
677 }
678 catch (const std::exception& e)
679 {
680 log<level::ERR>(
681 fmt::format(
682 "AdministrativeState match parsing failed on {}: {}",
683 interfaceName(), e.what())
684 .c_str(),
685 entry("INTERFACE=%s", interfaceName().c_str()),
686 entry("ERROR=%s", e.what()));
687 }
688 });
689
690 // Actively call for the value in case the interface is already configured
691 auto method =
692 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
693 method.append(intf, prop);
694 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700695 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700696 auto reply = bus.call(method);
697 std::variant<std::string> state;
698 reply.read(state);
699 cb(std::get<std::string>(state));
700 }
701 catch (const std::exception& e)
702 {
703 log<level::ERR>(
704 fmt::format("Failed to get AdministrativeState on {}: {}",
705 interfaceName(), e.what())
706 .c_str(),
707 entry("INTERFACE=%s", interfaceName().c_str()),
708 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700709 }
710
William A. Kennington III26275a32021-07-13 20:32:42 -0700711 // The interface is not yet configured by systemd-networkd, wait until it
712 // signals us a valid state.
713 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700714 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700715 bus.wait();
716 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700717 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700718
719 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700720}
721
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800722static void setNICAdminState(const char* intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700723{
724 ifreq ifr = {};
725 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800726 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700727
728 ifr.ifr_flags &= ~IFF_UP;
729 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800730 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700731}
732
Patrick Williams6aef7692021-05-01 06:39:41 -0500733bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700734{
Patrick Williams6aef7692021-05-01 06:39:41 -0500735 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700736 {
737 return value;
738 }
739
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800740 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700741 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800742 if (!value)
743 {
744 // We only need to bring down the interface, networkd will always bring
745 // up managed interfaces
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800746 manager.addReloadPreHook([ifname = interfaceName()]() {
747 setNICAdminState(ifname.c_str(), false);
748 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800749 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700750 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800751
752 return value;
753}
754
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530755ServerList EthernetInterface::staticNameServers(ServerList value)
756{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530757 for (const auto& nameserverip : value)
758 {
759 if (!isValidIP(AF_INET, nameserverip) &&
760 !isValidIP(AF_INET6, nameserverip))
761 {
762 log<level::ERR>("Not a valid IP address"),
763 entry("ADDRESS=%s", nameserverip.c_str());
764 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530765 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530766 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
767 }
768 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530769 try
770 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530771 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700772
Ratan Gupta6dec3902017-08-20 15:28:12 +0530773 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700774 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530775 }
Patrick Williams5758db32021-10-06 12:29:22 -0500776 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530777 {
778 log<level::ERR>("Exception processing DNS entries");
779 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530780 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530781}
782
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700783void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530784{
785 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700786 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700787 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530788}
789
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530790ServerList EthernetInterface::getNameServerFromResolvd()
791{
792 ServerList servers;
793 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
794
795 /*
796 The DNS property under org.freedesktop.resolve1.Link interface contains
797 an array containing all DNS servers currently used by resolved. It
798 contains similar information as the DNS server data written to
799 /run/systemd/resolve/resolv.conf.
800
801 Each structure in the array consists of a numeric network interface index,
802 an address family, and a byte array containing the DNS server address
803 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
804 The array contains DNS servers configured system-wide, including those
805 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
806 /etc/systemd/resolved.conf, as well as per-interface DNS server
807 information either retrieved from systemd-networkd or configured by
808 external software via SetLinkDNS().
809 */
810
811 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
812 std::variant<type> name; // Variable to capture the DNS property
813 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
814 PROPERTY_INTERFACE, METHOD_GET);
815
816 method.append(RESOLVED_INTERFACE, "DNS");
817 auto reply = bus.call(method);
818
819 try
820 {
821 reply.read(name);
822 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500823 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530824 {
825 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
826 }
827 auto tupleVector = std::get_if<type>(&name);
828 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
829 {
Alexander Filippov983da552021-02-08 15:26:54 +0300830 int addressFamily = std::get<0>(*i);
831 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
832
833 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530834 {
Alexander Filippov983da552021-02-08 15:26:54 +0300835 case AF_INET:
836 if (ipaddress.size() == sizeof(struct in_addr))
837 {
838 servers.push_back(toString(
839 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
840 }
841 else
842 {
843 log<level::ERR>(
844 "Invalid data recived from Systemd-Resolved");
845 }
846 break;
847
848 case AF_INET6:
849 if (ipaddress.size() == sizeof(struct in6_addr))
850 {
851 servers.push_back(toString(
852 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
853 }
854 else
855 {
856 log<level::ERR>(
857 "Invalid data recived from Systemd-Resolved");
858 }
859 break;
860
861 default:
862 log<level::ERR>(
863 "Unsupported address family in DNS from Systemd-Resolved");
864 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530865 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530866 }
867 return servers;
868}
869
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700870std::string EthernetInterface::vlanIntfName(VlanId id) const
871{
872 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
873}
874
875std::string EthernetInterface::vlanObjPath(VlanId id) const
876{
877 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
878}
879
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530880void EthernetInterface::loadVLAN(VlanId id)
881{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700882 auto vlanInterfaceName = vlanIntfName(id);
883 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530884
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700885 config::Parser config(
886 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
887
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530888 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700889 bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
890 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530891
Gunnar Mills57d9c502018-09-14 14:42:34 -0500892 // Fetch the ip address from the system
893 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530894 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800895 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700896 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530897
898 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
899 std::move(vlanIntf));
900}
901
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700902ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530903{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700904 auto vlanInterfaceName = vlanIntfName(id);
905 if (this->vlanInterfaces.find(vlanInterfaceName) !=
906 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800907 {
908 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
909 elog<InvalidArgument>(
910 Argument::ARGUMENT_NAME("VLANId"),
911 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
912 }
913
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700914 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530915
Patrick Williams6aef7692021-05-01 06:39:41 -0500916 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530917 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530918 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700919 bus, path.c_str(), config::Parser(),
Patrick Williams6aef7692021-05-01 06:39:41 -0500920 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530921
922 // write the device file for the vlan interface.
923 vlanIntf->writeDeviceFile();
924
Gunnar Mills57d9c502018-09-14 14:42:34 -0500925 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700926
927 writeConfigurationFile();
928 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700929
930 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530931}
Ratan Gupta2b106532017-07-25 16:05:02 +0530932
Patrick Williams6aef7692021-05-01 06:39:41 -0500933ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530934{
Patrick Williams6aef7692021-05-01 06:39:41 -0500935 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530936
937 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700938 manager.reloadConfigs();
939
Ratan Gupta497c0c92017-08-22 19:15:59 +0530940 return ntpServers;
941}
Ratan Gupta2b106532017-07-25 16:05:02 +0530942// Need to merge the below function with the code which writes the
943// config file during factory reset.
944// TODO openbmc/openbmc#1751
945
946void EthernetInterface::writeConfigurationFile()
947{
948 // write all the static ip address in the systemd-network conf file
949
950 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530951 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530952
953 // if there is vlan interafce then write the configuration file
954 // for vlan also.
955
Gunnar Mills57d9c502018-09-14 14:42:34 -0500956 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530957 {
958 intf.second->writeConfigurationFile();
959 }
960
William A. Kennington III95a49a22022-08-18 17:50:05 -0700961 config::Parser config;
962 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530963 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700964 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800965#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700966 auto mac = MacAddressIntf::macAddress();
967 if (!mac.empty())
968 {
969 link["MACAddress"].emplace_back(mac);
970 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800971#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700972 if (!EthernetInterfaceIntf::nicEnabled())
973 {
974 link["Unmanaged"].emplace_back("yes");
975 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700976 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700977 {
978 auto& network = config.map["Network"].emplace_back();
979 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400980#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700981 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400982#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700983 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400984#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700985 network["IPv6AcceptRA"].emplace_back(
986 EthernetInterfaceIntf::ipv6AcceptRA() ? "true" : "false");
987 network["DHCP"].emplace_back(
988 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()]);
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600989 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700990 auto& vlans = network["VLAN"];
991 for (const auto& intf : vlanInterfaces)
992 {
993 vlans.emplace_back(
994 intf.second->EthernetInterface::interfaceName());
995 }
996 }
997 {
998 auto& ntps = network["NTP"];
999 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
1000 {
1001 ntps.emplace_back(ntp);
1002 }
1003 }
1004 {
1005 auto& dnss = network["DNS"];
1006 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1007 {
1008 dnss.emplace_back(dns);
1009 }
1010 }
1011 {
1012 auto& address = network["Address"];
1013 for (const auto& addr : getAddresses())
1014 {
1015 if (originIsManuallyAssigned(addr.second->origin()) &&
1016 !dhcpIsEnabled(addr.second->type()))
1017 {
1018 address.emplace_back(
1019 fmt::format("{}/{}", addr.second->address(),
1020 addr.second->prefixLength()));
1021 }
1022 }
1023 }
1024 {
1025 auto& gateways = network["Gateway"];
1026 if (!dhcpIsEnabled(IP::Protocol::IPv4))
1027 {
1028 auto gateway = EthernetInterfaceIntf::defaultGateway();
1029 if (!gateway.empty())
1030 {
1031 gateways.emplace_back(gateway);
1032 }
1033 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301034
William A. Kennington III95a49a22022-08-18 17:50:05 -07001035 if (!dhcpIsEnabled(IP::Protocol::IPv6))
1036 {
1037 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1038 if (!gateway6.empty())
1039 {
1040 gateways.emplace_back(gateway6);
1041 }
1042 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001043 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001044 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001045 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
1046 dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001047 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001048 auto& neighbors = config.map["Neighbor"];
1049 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001050 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001051 auto& neighbor = neighbors.emplace_back();
1052 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1053 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001054 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001055 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001056 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001057 auto& dhcp = config.map["DHCP"].emplace_back();
1058 dhcp["ClientIdentifier"].emplace_back("mac");
1059 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001060 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001061 const auto& conf = *manager.getDHCPConf();
1062 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1063 dhcp["UseDNS"].emplace_back(dns_enabled);
1064 dhcp["UseDomains"].emplace_back(dns_enabled);
1065 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1066 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1067 : "false");
1068 dhcp["SendHostname"].emplace_back(
1069 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001070 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001071 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001072 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1073 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001074 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1075 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301076}
1077
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001078std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301079{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001080#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001081 ether_addr newMAC;
1082 try
1083 {
1084 newMAC = mac_address::fromString(value);
1085 }
Patrick Williams5758db32021-10-06 12:29:22 -05001086 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001087 {
1088 log<level::ERR>("MACAddress is not valid.",
1089 entry("MAC=%s", value.c_str()));
1090 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1091 Argument::ARGUMENT_VALUE(value.c_str()));
1092 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001093 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301094 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001095 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001096 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001097 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1098 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301099 }
1100
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001101 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001102 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001103
William A. Kennington III1137a972019-04-20 20:49:58 -07001104 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001105 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001106 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301107 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001108 // Update everything that depends on the MAC value
1109 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301110 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001111 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301112 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001113 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301114
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001115 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001116 manager.addReloadPreHook([interface]() {
1117 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001118 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001119 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001120 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301121 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001122
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001123#ifdef HAVE_UBOOT_ENV
1124 // Ensure that the valid address is stored in the u-boot-env
1125 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1126 if (envVar)
1127 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001128 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1129 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1130 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1131 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001132 }
1133#endif // HAVE_UBOOT_ENV
1134
William A. Kennington III1137a972019-04-20 20:49:58 -07001135 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001136#else
1137 elog<NotAllowed>(
1138 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1139#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301140}
1141
Ratan Guptae9c9b812017-09-22 17:15:37 +05301142void EthernetInterface::deleteAll()
1143{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301144 // clear all the ip on the interface
1145 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001146
1147 writeConfigurationFile();
1148 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301149}
1150
Ravi Tejaa5a09442020-07-17 00:57:33 -05001151std::string EthernetInterface::defaultGateway(std::string gateway)
1152{
1153 auto gw = EthernetInterfaceIntf::defaultGateway();
1154 if (gw == gateway)
1155 {
1156 return gw;
1157 }
1158
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001159 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001160 {
1161 log<level::ERR>("Not a valid v4 Gateway",
1162 entry("GATEWAY=%s", gateway.c_str()));
1163 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1164 Argument::ARGUMENT_VALUE(gateway.c_str()));
1165 }
1166 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001167
1168 writeConfigurationFile();
1169 manager.reloadConfigs();
1170
Ravi Tejaa5a09442020-07-17 00:57:33 -05001171 return gw;
1172}
1173
1174std::string EthernetInterface::defaultGateway6(std::string gateway)
1175{
1176 auto gw = EthernetInterfaceIntf::defaultGateway6();
1177 if (gw == gateway)
1178 {
1179 return gw;
1180 }
1181
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001182 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001183 {
1184 log<level::ERR>("Not a valid v6 Gateway",
1185 entry("GATEWAY=%s", gateway.c_str()));
1186 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1187 Argument::ARGUMENT_VALUE(gateway.c_str()));
1188 }
1189 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001190
1191 writeConfigurationFile();
1192 manager.reloadConfigs();
1193
Ravi Tejaa5a09442020-07-17 00:57:33 -05001194 return gw;
1195}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001196} // namespace network
1197} // namespace phosphor