blob: f65ebb01b69cbe64464acf8a52fb7d13d8722167 [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 III95530ec2022-08-19 01:44:39 -07009#include "util.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>
William A. Kennington III69f45542022-09-24 23:28:14 -070028#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053029#include <string>
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
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080050static stdplus::Fd& getIFSock()
51{
52 using namespace stdplus::fd;
53 static auto fd =
54 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
55 return fd;
56}
57
Patrick Williamsc38b0712022-07-22 19:26:54 -050058EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
Ratan Gupta91a99cc2017-04-14 16:32:09 +053059 const std::string& objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070060 const config::Parser& config,
William A. Kennington III0caf2212022-08-18 18:15:51 -070061 Manager& parent, bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -070062 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050063 Ifaces(bus, objPath.c_str(),
64 emitSignal ? Ifaces::action::defer_emit
65 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050066 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053067{
68 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053069 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053070 interfaceName(intfName);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070071 auto dhcpVal = getDHCPValue(config);
72 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
73 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070074 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070075 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070076 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
77 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050078 std::string defaultGateway;
79 std::string defaultGateway6;
80
William A. Kennington IIIe0564842021-10-23 16:02:22 -070081 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050082 {
83 if (gateway.first == intfName)
84 {
85 defaultGateway = gateway.second;
86 break;
87 }
88 }
89
William A. Kennington IIIe0564842021-10-23 16:02:22 -070090 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050091 {
92 if (gateway6.first == intfName)
93 {
94 defaultGateway6 = gateway6.second;
95 break;
96 }
97 }
98
99 EthernetInterfaceIntf::defaultGateway(defaultGateway);
100 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530101 // Don't get the mac address from the system as the mac address
102 // would be same as parent interface.
103 if (intfName.find(".") == std::string::npos)
104 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500105 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530106 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700107 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700108 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530109
110 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530111 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530112
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700113#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700114 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
115
116 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
117 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800118#endif
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530119
Ratan Gupta29b0e432017-05-25 12:51:40 +0530120 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530121 if (emitSignal)
122 {
123 this->emit_object_added();
124 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530125}
126
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700127static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800128{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700129 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800130 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700131 return IP::Protocol::IPv4;
132 }
133 else if (std::holds_alternative<in6_addr>(addr))
134 {
135 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800136 }
137
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700138 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800139}
140
William A. Kennington III24957b92021-12-03 13:59:19 -0800141bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800142{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700143 switch (family)
144 {
145 case IP::Protocol::IPv6:
146 return dhcp6();
147 case IP::Protocol::IPv4:
148 return dhcp4();
149 }
150 throw std::logic_error("Unreachable");
Johnathan Mantey817012a2020-01-30 15:07:39 -0800151}
152
Johnathan Mantey817012a2020-01-30 15:07:39 -0800153bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
154{
155 return (
156#ifdef LINK_LOCAL_AUTOCONFIGURATION
157 (origin == IP::AddressOrigin::Static)
158#else
159 (origin == IP::AddressOrigin::Static ||
160 origin == IP::AddressOrigin::LinkLocal)
161#endif
162
163 );
164}
165
Ratan Gupta87c13982017-06-15 09:27:27 +0530166void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530167{
Ratan Gupta87c13982017-06-15 09:27:27 +0530168 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530169
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700170 AddressFilter filter;
171 filter.interface = ifIndex();
172 auto currentAddrs = getCurrentAddresses(filter);
173 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530174 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700175 if (addr.flags & IFA_F_DEPRECATED)
176 {
177 continue;
178 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700179 auto address = toString(addr.address);
180 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800181 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800182 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530183 {
184 origin = IP::AddressOrigin::DHCP;
185 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700186 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530187 {
188 origin = IP::AddressOrigin::LinkLocal;
189 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700190 // Obsolete parameter
191 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530192
Gunnar Mills57d9c502018-09-14 14:42:34 -0500193 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700194 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530195
Lei YU7233c582021-04-08 14:39:43 +0800196 this->addrs.insert_or_assign(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700197 address, std::make_shared<phosphor::network::IPAddress>(
198 bus, ipAddressObjectPath.c_str(), *this, addressType,
199 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530200 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530201}
202
William A. Kennington III08505792019-01-30 16:00:04 -0800203void EthernetInterface::createStaticNeighborObjects()
204{
205 staticNeighbors.clear();
206
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700207 NeighborFilter filter;
208 filter.interface = ifIndex();
209 filter.state = NUD_PERMANENT;
210 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800211 for (const auto& neighbor : neighbors)
212 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700213 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800214 {
215 continue;
216 }
217 std::string ip = toString(neighbor.address);
218 std::string mac = mac_address::toString(*neighbor.mac);
219 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
220 staticNeighbors.emplace(ip,
221 std::make_shared<phosphor::network::Neighbor>(
222 bus, objectPath.c_str(), *this, ip, mac,
223 Neighbor::State::Permanent));
224 }
225}
226
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700227unsigned EthernetInterface::ifIndex() const
228{
229 unsigned idx = if_nametoindex(interfaceName().c_str());
230 if (idx == 0)
231 {
232 throw std::system_error(errno, std::generic_category(),
233 "if_nametoindex");
234 }
235 return idx;
236}
237
Patrick Williams6aef7692021-05-01 06:39:41 -0500238ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500239 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530240{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800241 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530242 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700243 log<level::INFO>("DHCP enabled on the interface, disabling"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500244 entry("INTERFACE=%s", interfaceName().c_str());
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700245 switch (protType)
246 {
247 case IP::Protocol::IPv4:
248 dhcp4(false);
249 break;
250 case IP::Protocol::IPv6:
251 dhcp6(false);
252 break;
253 }
Ravi Teja07450442022-07-07 04:30:57 -0500254 // Delete the IP address object and that reloads the networkd
255 // to allow the same IP address to be set as Static IP
256 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500257 }
258
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500259 IP::AddressOrigin origin = IP::AddressOrigin::Static;
260
261 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
262
263 if (!isValidIP(addressFamily, ipaddress))
264 {
265 log<level::ERR>("Not a valid IP address"),
266 entry("ADDRESS=%s", ipaddress.c_str());
267 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
268 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
269 }
270
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700271 // Gateway is an obsolete parameter
272 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500273
274 if (!isValidPrefix(addressFamily, prefixLength))
275 {
276 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700277 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500278 elog<InvalidArgument>(
279 Argument::ARGUMENT_NAME("prefixLength"),
280 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530281 }
282
Gunnar Mills57d9c502018-09-14 14:42:34 -0500283 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800284 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800285 this->addrs.insert_or_assign(ipaddress,
286 std::make_shared<phosphor::network::IPAddress>(
287 bus, objectPath.c_str(), *this, protType,
288 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530289
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700290 writeConfigurationFile();
291 manager.reloadConfigs();
292
raviteja-bce379562019-03-28 05:59:36 -0500293 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530294}
295
Patrick Williams6aef7692021-05-01 06:39:41 -0500296ObjectPath EthernetInterface::neighbor(std::string ipAddress,
297 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800298{
William A. Kennington IIIff12acb2022-10-07 19:06:56 -0700299 if (!isValidIP(ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800300 {
301 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500302 entry("ADDRESS=%s", ipAddress.c_str()));
303 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
304 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800305 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500306 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800307 {
308 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500309 entry("MACADDRESS=%s", ipAddress.c_str()));
310 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
311 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800312 }
313
314 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500315 generateStaticNeighborObjectPath(ipAddress, macAddress);
316 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800317 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500318 bus, objectPath.c_str(), *this, ipAddress,
319 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700320
321 writeConfigurationFile();
322 manager.reloadConfigs();
323
William A. Kennington III08505792019-01-30 16:00:04 -0800324 return objectPath;
325}
326
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700327#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530328/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800329 Enable this code if your NIC driver supports the ETHTOOL features.
330 Do this by adding the following to your phosphor-network*.bbappend file.
331 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
332 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530333*/
334InterfaceInfo EthernetInterface::getInterfaceInfo() const
335{
William A. Kennington III05368f12021-05-13 18:40:47 -0700336 ifreq ifr = {};
337 ethtool_cmd edata = {};
338 LinkSpeed speed = {};
339 Autoneg autoneg = {};
340 DuplexMode duplex = {};
341 LinkUp linkState = {};
342 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530343 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530344
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800345 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
346 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530347
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800348 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800349 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800350 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800351 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530352 speed = edata.speed;
353 duplex = edata.duplex;
354 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530355 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800356 catch (const std::exception& e)
357 {
358 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800359
William A. Kennington III96203312021-05-07 12:50:41 -0700360 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800361 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530362 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800363
Tejas Patil2c0fc562021-08-03 19:13:46 +0530364 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530365}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800366#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530367
368/** @brief get the mac address of the interface.
369 * @return macaddress on success
370 */
371
Gunnar Mills57d9c502018-09-14 14:42:34 -0500372std::string
373 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530374{
Patrick Williams6aef7692021-05-01 06:39:41 -0500375 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530376
William A. Kennington III05368f12021-05-13 18:40:47 -0700377 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800378 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800379 try
380 {
381 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
382 }
383 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530385 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800386 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700387 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530388 }
William A. Kennington III7c4c9a92022-10-07 19:08:09 -0700389 return mac_address::toString(
390 stdplus::raw::refFrom<ether_addr>(ifr.ifr_hwaddr.sa_data));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530391}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530392
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530393std::string EthernetInterface::generateId(const std::string& ipaddress,
394 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800395 const std::string& gateway,
396 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530397{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530398 std::stringstream hexId;
399 std::string hashString = ipaddress;
400 hashString += std::to_string(prefixLength);
401 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800402 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530403
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530404 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500405 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530406 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530407}
408
Patrick Williams6aef7692021-05-01 06:39:41 -0500409std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
410 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800411{
412 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500413 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800414
415 // Only want 8 hex digits.
416 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
417 return hexId.str();
418}
419
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530420void EthernetInterface::deleteObject(const std::string& ipaddress)
421{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530422 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530423 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530424 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530425 log<level::ERR>("DeleteObject:Unable to find the object.");
426 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530427 }
428 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700429
430 writeConfigurationFile();
431 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530432}
433
Patrick Williams6aef7692021-05-01 06:39:41 -0500434void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800435{
Patrick Williams6aef7692021-05-01 06:39:41 -0500436 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800437 if (it == staticNeighbors.end())
438 {
439 log<level::ERR>(
440 "DeleteStaticNeighborObject:Unable to find the object.");
441 return;
442 }
443 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700444
445 writeConfigurationFile();
446 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800447}
448
Ratan Guptae9c9b812017-09-22 17:15:37 +0530449void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530450{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700451 const auto& confDir = manager.getConfDir();
452 auto networkFile = config::pathForIntfConf(confDir, interface);
453 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530454
455 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700456 std::error_code ec;
William A. Kennington III95530ec2022-08-19 01:44:39 -0700457 std::filesystem::remove(networkFile, ec);
458 std::filesystem::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530459
460 // TODO systemd doesn't delete the virtual network interface
461 // even after deleting all the related configuartion.
462 // https://github.com/systemd/systemd/issues/6600
463 try
464 {
465 deleteInterface(interface);
466 }
Patrick Williams5758db32021-10-06 12:29:22 -0500467 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530468 {
469 commit<InternalFailure>();
470 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530471}
472
473void EthernetInterface::deleteVLANObject(const std::string& interface)
474{
475 auto it = vlanInterfaces.find(interface);
476 if (it == vlanInterfaces.end())
477 {
478 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500479 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530480 return;
481 }
482
483 deleteVLANFromSystem(interface);
484 // delete the interface
485 vlanInterfaces.erase(it);
486
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700487 writeConfigurationFile();
488 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530489}
490
Gunnar Mills57d9c502018-09-14 14:42:34 -0500491std::string EthernetInterface::generateObjectPath(
492 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800493 uint8_t prefixLength, const std::string& gateway,
494 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530495{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530496 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530497 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530498 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
499
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530500 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530501 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530502 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800503 objectPath /=
504 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530505 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530506}
507
William A. Kennington III08505792019-01-30 16:00:04 -0800508std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500509 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800510{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530511 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800512 objectPath /= objPath;
513 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500514 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800515 return objectPath.string();
516}
517
Patrick Williams6aef7692021-05-01 06:39:41 -0500518bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700519{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700520 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700521 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700522 writeConfigurationFile();
523 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700524 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700525 return value;
526}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700527
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700528bool EthernetInterface::dhcp4(bool value)
529{
530 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
531 {
532 writeConfigurationFile();
533 manager.reloadConfigs();
534 }
535 return value;
536}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700537
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700538bool EthernetInterface::dhcp6(bool value)
539{
540 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
541 {
542 writeConfigurationFile();
543 manager.reloadConfigs();
544 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700545 return value;
546}
547
Patrick Williams6aef7692021-05-01 06:39:41 -0500548EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530549{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700550 auto old4 = EthernetInterfaceIntf::dhcp4();
551 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
552 value == DHCPConf::v4v6stateless ||
553 value == DHCPConf::both);
554 auto old6 = EthernetInterfaceIntf::dhcp6();
555 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
556 value == DHCPConf::both);
557 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
558 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
559 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
560 value == DHCPConf::v6 || value == DHCPConf::both);
561
562 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530563 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700564 writeConfigurationFile();
565 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530566 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530567 return value;
568}
569
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700570EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
571{
572 if (dhcp6())
573 {
574 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
575 }
576 else if (dhcp4())
577 {
578 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
579 }
580 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
581}
582
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800583bool EthernetInterface::linkUp() const
584{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800585 bool value = EthernetInterfaceIntf::linkUp();
586
William A. Kennington III05368f12021-05-13 18:40:47 -0700587 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800588 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800589 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800590 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800591 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800592 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
593 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800594 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800595 {
596 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800597 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800598 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700599 return value;
600}
601
Tejas Patil2c0fc562021-08-03 19:13:46 +0530602size_t EthernetInterface::mtu() const
603{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530604 size_t value = EthernetInterfaceIntf::mtu();
605
Tejas Patil2c0fc562021-08-03 19:13:46 +0530606 ifreq ifr = {};
607 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800608 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530609 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800610 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530611 value = ifr.ifr_mtu;
612 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800613 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530614 {
615 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800616 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530617 }
618 return value;
619}
620
621size_t EthernetInterface::mtu(size_t value)
622{
623 if (value == EthernetInterfaceIntf::mtu())
624 {
625 return value;
626 }
627 else if (value == 0)
628 {
629 return EthernetInterfaceIntf::mtu();
630 }
631
Tejas Patil2c0fc562021-08-03 19:13:46 +0530632 ifreq ifr = {};
633 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
634 ifr.ifr_mtu = value;
635
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800636 try
637 {
638 getIFSock().ioctl(SIOCSIFMTU, &ifr);
639 }
640 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530641 {
642 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
643 entry("ERROR=%s", strerror(errno)));
644 return EthernetInterfaceIntf::mtu();
645 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530646
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800647 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530648 return value;
649}
650
William A. Kennington III26275a32021-07-13 20:32:42 -0700651bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700652{
William A. Kennington III26275a32021-07-13 20:32:42 -0700653 constexpr auto svc = "org.freedesktop.network1";
654 constexpr auto intf = "org.freedesktop.network1.Link";
655 constexpr auto prop = "AdministrativeState";
656 char* rpath;
657 sd_bus_path_encode("/org/freedesktop/network1/link",
658 std::to_string(ifIndex()).c_str(), &rpath);
659 std::string path(rpath);
660 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700661
William A. Kennington III26275a32021-07-13 20:32:42 -0700662 // Store / Parser for the AdministrativeState return value
663 std::optional<bool> ret;
664 auto cb = [&](const std::string& state) {
665 if (state != "initialized")
666 {
667 ret = state != "unmanaged";
668 }
669 };
670
671 // Build a matcher before making the property call to ensure we
672 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500673 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700674 bus,
675 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
676 "'PropertiesChanged',arg0='{}',",
677 svc, path, PROPERTY_INTERFACE, intf)
678 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500679 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700680 std::string intf;
681 std::unordered_map<std::string, std::variant<std::string>> values;
682 try
683 {
684 m.read(intf, values);
685 auto it = values.find(prop);
686 // Ignore properties that aren't AdministrativeState
687 if (it != values.end())
688 {
689 cb(std::get<std::string>(it->second));
690 }
691 }
692 catch (const std::exception& e)
693 {
694 log<level::ERR>(
695 fmt::format(
696 "AdministrativeState match parsing failed on {}: {}",
697 interfaceName(), e.what())
698 .c_str(),
699 entry("INTERFACE=%s", interfaceName().c_str()),
700 entry("ERROR=%s", e.what()));
701 }
702 });
703
704 // Actively call for the value in case the interface is already configured
705 auto method =
706 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
707 method.append(intf, prop);
708 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700709 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700710 auto reply = bus.call(method);
711 std::variant<std::string> state;
712 reply.read(state);
713 cb(std::get<std::string>(state));
714 }
715 catch (const std::exception& e)
716 {
717 log<level::ERR>(
718 fmt::format("Failed to get AdministrativeState on {}: {}",
719 interfaceName(), e.what())
720 .c_str(),
721 entry("INTERFACE=%s", interfaceName().c_str()),
722 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700723 }
724
William A. Kennington III26275a32021-07-13 20:32:42 -0700725 // The interface is not yet configured by systemd-networkd, wait until it
726 // signals us a valid state.
727 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700728 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700729 bus.wait();
730 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700731 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700732
733 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700734}
735
William A. Kennington III69f45542022-09-24 23:28:14 -0700736static void setNICAdminState(stdplus::const_zstring intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700737{
738 ifreq ifr = {};
William A. Kennington III69f45542022-09-24 23:28:14 -0700739 std::strncpy(ifr.ifr_name, intf.data(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800740 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700741
742 ifr.ifr_flags &= ~IFF_UP;
743 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800744 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700745}
746
Patrick Williams6aef7692021-05-01 06:39:41 -0500747bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700748{
Patrick Williams6aef7692021-05-01 06:39:41 -0500749 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700750 {
751 return value;
752 }
753
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800754 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700755 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800756 if (!value)
757 {
758 // We only need to bring down the interface, networkd will always bring
759 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700760 manager.addReloadPreHook(
761 [ifname = interfaceName()]() { setNICAdminState(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800762 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700763 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800764
765 return value;
766}
767
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530768ServerList EthernetInterface::staticNameServers(ServerList value)
769{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530770 for (const auto& nameserverip : value)
771 {
William A. Kennington IIIff12acb2022-10-07 19:06:56 -0700772 if (!isValidIP(nameserverip))
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530773 {
774 log<level::ERR>("Not a valid IP address"),
775 entry("ADDRESS=%s", nameserverip.c_str());
776 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530777 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530778 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
779 }
780 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530781 try
782 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530783 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700784
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530785 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700786 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530787 }
Patrick Williams5758db32021-10-06 12:29:22 -0500788 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530789 {
790 log<level::ERR>("Exception processing DNS entries");
791 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530792 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530793}
794
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700795void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530796{
797 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700798 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700799 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530800}
801
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530802ServerList EthernetInterface::getNameServerFromResolvd()
803{
804 ServerList servers;
805 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
806
807 /*
808 The DNS property under org.freedesktop.resolve1.Link interface contains
809 an array containing all DNS servers currently used by resolved. It
810 contains similar information as the DNS server data written to
811 /run/systemd/resolve/resolv.conf.
812
813 Each structure in the array consists of a numeric network interface index,
814 an address family, and a byte array containing the DNS server address
815 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
816 The array contains DNS servers configured system-wide, including those
817 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
818 /etc/systemd/resolved.conf, as well as per-interface DNS server
819 information either retrieved from systemd-networkd or configured by
820 external software via SetLinkDNS().
821 */
822
823 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
824 std::variant<type> name; // Variable to capture the DNS property
825 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
826 PROPERTY_INTERFACE, METHOD_GET);
827
828 method.append(RESOLVED_INTERFACE, "DNS");
829 auto reply = bus.call(method);
830
831 try
832 {
833 reply.read(name);
834 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500835 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530836 {
837 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
838 }
839 auto tupleVector = std::get_if<type>(&name);
840 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
841 {
Alexander Filippov983da552021-02-08 15:26:54 +0300842 int addressFamily = std::get<0>(*i);
843 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
844
845 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530846 {
Alexander Filippov983da552021-02-08 15:26:54 +0300847 case AF_INET:
848 if (ipaddress.size() == sizeof(struct in_addr))
849 {
850 servers.push_back(toString(
851 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
852 }
853 else
854 {
855 log<level::ERR>(
856 "Invalid data recived from Systemd-Resolved");
857 }
858 break;
859
860 case AF_INET6:
861 if (ipaddress.size() == sizeof(struct in6_addr))
862 {
863 servers.push_back(toString(
864 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
865 }
866 else
867 {
868 log<level::ERR>(
869 "Invalid data recived from Systemd-Resolved");
870 }
871 break;
872
873 default:
874 log<level::ERR>(
875 "Unsupported address family in DNS from Systemd-Resolved");
876 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530877 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530878 }
879 return servers;
880}
881
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700882std::string EthernetInterface::vlanIntfName(VlanId id) const
883{
884 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
885}
886
887std::string EthernetInterface::vlanObjPath(VlanId id) const
888{
889 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
890}
891
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530892void EthernetInterface::loadVLAN(VlanId id)
893{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700894 auto vlanInterfaceName = vlanIntfName(id);
895 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530896
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700897 config::Parser config(
898 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
899
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530900 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700901 bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
902 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530903
Gunnar Mills57d9c502018-09-14 14:42:34 -0500904 // Fetch the ip address from the system
905 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530906 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800907 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700908 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530909
910 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
911 std::move(vlanIntf));
912}
913
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700914ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530915{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700916 auto vlanInterfaceName = vlanIntfName(id);
917 if (this->vlanInterfaces.find(vlanInterfaceName) !=
918 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800919 {
920 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
921 elog<InvalidArgument>(
922 Argument::ARGUMENT_NAME("VLANId"),
923 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
924 }
925
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700926 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530927
Patrick Williams6aef7692021-05-01 06:39:41 -0500928 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530929 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530930 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700931 bus, path.c_str(), config::Parser(),
Patrick Williams6aef7692021-05-01 06:39:41 -0500932 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530933
934 // write the device file for the vlan interface.
935 vlanIntf->writeDeviceFile();
936
Gunnar Mills57d9c502018-09-14 14:42:34 -0500937 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700938
939 writeConfigurationFile();
940 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700941
942 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530943}
Ratan Gupta2b106532017-07-25 16:05:02 +0530944
Patrick Williams6aef7692021-05-01 06:39:41 -0500945ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530946{
Patrick Williams6aef7692021-05-01 06:39:41 -0500947 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530948
949 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700950 manager.reloadConfigs();
951
Ratan Gupta497c0c92017-08-22 19:15:59 +0530952 return ntpServers;
953}
Ratan Gupta2b106532017-07-25 16:05:02 +0530954// Need to merge the below function with the code which writes the
955// config file during factory reset.
956// TODO openbmc/openbmc#1751
957
958void EthernetInterface::writeConfigurationFile()
959{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500960 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530961 {
962 intf.second->writeConfigurationFile();
963 }
964
William A. Kennington III95a49a22022-08-18 17:50:05 -0700965 config::Parser config;
966 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530967 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700968 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800969#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700970 auto mac = MacAddressIntf::macAddress();
971 if (!mac.empty())
972 {
973 link["MACAddress"].emplace_back(mac);
974 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800975#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700976 if (!EthernetInterfaceIntf::nicEnabled())
977 {
978 link["Unmanaged"].emplace_back("yes");
979 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700980 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700981 {
982 auto& network = config.map["Network"].emplace_back();
983 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400984#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700985 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400986#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700987 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400988#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700989 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
990 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
991 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600992 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700993 auto& vlans = network["VLAN"];
994 for (const auto& intf : vlanInterfaces)
995 {
996 vlans.emplace_back(
997 intf.second->EthernetInterface::interfaceName());
998 }
999 }
1000 {
1001 auto& ntps = network["NTP"];
1002 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
1003 {
1004 ntps.emplace_back(ntp);
1005 }
1006 }
1007 {
1008 auto& dnss = network["DNS"];
1009 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1010 {
1011 dnss.emplace_back(dns);
1012 }
1013 }
1014 {
1015 auto& address = network["Address"];
1016 for (const auto& addr : getAddresses())
1017 {
1018 if (originIsManuallyAssigned(addr.second->origin()) &&
1019 !dhcpIsEnabled(addr.second->type()))
1020 {
1021 address.emplace_back(
1022 fmt::format("{}/{}", addr.second->address(),
1023 addr.second->prefixLength()));
1024 }
1025 }
1026 }
1027 {
1028 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001029 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001030 {
1031 auto gateway = EthernetInterfaceIntf::defaultGateway();
1032 if (!gateway.empty())
1033 {
1034 gateways.emplace_back(gateway);
1035 }
1036 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301037
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001038 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001039 {
1040 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1041 if (!gateway6.empty())
1042 {
1043 gateways.emplace_back(gateway6);
1044 }
1045 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001046 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001047 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001048 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001049 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001050 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001051 auto& neighbors = config.map["Neighbor"];
1052 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001053 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001054 auto& neighbor = neighbors.emplace_back();
1055 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1056 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001057 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001058 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001059 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001060 auto& dhcp = config.map["DHCP"].emplace_back();
1061 dhcp["ClientIdentifier"].emplace_back("mac");
1062 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001063 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001064 const auto& conf = *manager.getDHCPConf();
1065 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1066 dhcp["UseDNS"].emplace_back(dns_enabled);
1067 dhcp["UseDomains"].emplace_back(dns_enabled);
1068 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1069 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1070 : "false");
1071 dhcp["SendHostname"].emplace_back(
1072 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001073 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001074 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001075 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1076 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001077 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1078 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301079}
1080
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001081std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301082{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001083#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001084 ether_addr newMAC;
1085 try
1086 {
1087 newMAC = mac_address::fromString(value);
1088 }
Patrick Williams5758db32021-10-06 12:29:22 -05001089 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001090 {
1091 log<level::ERR>("MACAddress is not valid.",
1092 entry("MAC=%s", value.c_str()));
1093 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1094 Argument::ARGUMENT_VALUE(value.c_str()));
1095 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001096 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301097 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001098 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001099 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001100 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1101 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301102 }
1103
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001104 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001105 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001106
William A. Kennington III1137a972019-04-20 20:49:58 -07001107 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001108 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001109 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301110 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001111 // Update everything that depends on the MAC value
1112 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301113 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001114 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301115 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001116 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301117
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001118 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001119 manager.addReloadPreHook([interface]() {
1120 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III69f45542022-09-24 23:28:14 -07001121 setNICAdminState(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001122 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001123 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301124 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001125
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001126#ifdef HAVE_UBOOT_ENV
1127 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -07001128 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001129 if (envVar)
1130 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001131 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1132 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1133 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1134 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001135 }
1136#endif // HAVE_UBOOT_ENV
1137
William A. Kennington III1137a972019-04-20 20:49:58 -07001138 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001139#else
1140 elog<NotAllowed>(
1141 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1142#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301143}
1144
Ratan Guptae9c9b812017-09-22 17:15:37 +05301145void EthernetInterface::deleteAll()
1146{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301147 // clear all the ip on the interface
1148 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001149
1150 writeConfigurationFile();
1151 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301152}
1153
Ravi Tejaa5a09442020-07-17 00:57:33 -05001154std::string EthernetInterface::defaultGateway(std::string gateway)
1155{
1156 auto gw = EthernetInterfaceIntf::defaultGateway();
1157 if (gw == gateway)
1158 {
1159 return gw;
1160 }
1161
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001162 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001163 {
1164 log<level::ERR>("Not a valid v4 Gateway",
1165 entry("GATEWAY=%s", gateway.c_str()));
1166 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1167 Argument::ARGUMENT_VALUE(gateway.c_str()));
1168 }
1169 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001170
1171 writeConfigurationFile();
1172 manager.reloadConfigs();
1173
Ravi Tejaa5a09442020-07-17 00:57:33 -05001174 return gw;
1175}
1176
1177std::string EthernetInterface::defaultGateway6(std::string gateway)
1178{
1179 auto gw = EthernetInterfaceIntf::defaultGateway6();
1180 if (gw == gateway)
1181 {
1182 return gw;
1183 }
1184
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001185 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001186 {
1187 log<level::ERR>("Not a valid v6 Gateway",
1188 entry("GATEWAY=%s", gateway.c_str()));
1189 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1190 Argument::ARGUMENT_VALUE(gateway.c_str()));
1191 }
1192 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001193
1194 writeConfigurationFile();
1195 manager.reloadConfigs();
1196
Ravi Tejaa5a09442020-07-17 00:57:33 -05001197 return gw;
1198}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001199} // namespace network
1200} // namespace phosphor