blob: 87c660d2b29f99446ba9f3931a2e60387422398a [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 III1137a972019-04-20 20:49:58 -070030#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070031#include <unordered_map>
32#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070033#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053034
Ratan Gupta91a99cc2017-04-14 16:32:09 +053035namespace phosphor
36{
37namespace network
38{
39
40using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053041using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053042using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
43using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050044using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053045constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
46constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
47constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
48constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
49constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053050
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080051static stdplus::Fd& getIFSock()
52{
53 using namespace stdplus::fd;
54 static auto fd =
55 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
56 return fd;
57}
58
Patrick Williamsc38b0712022-07-22 19:26:54 -050059EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
Ratan Gupta91a99cc2017-04-14 16:32:09 +053060 const std::string& objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070061 const config::Parser& config,
William A. Kennington III0caf2212022-08-18 18:15:51 -070062 Manager& parent, bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -070063 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050064 Ifaces(bus, objPath.c_str(),
65 emitSignal ? Ifaces::action::defer_emit
66 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050067 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053068{
69 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053070 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053071 interfaceName(intfName);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070072 auto dhcpVal = getDHCPValue(config);
73 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
74 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070075 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070076 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070077 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
78 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050079 std::string defaultGateway;
80 std::string defaultGateway6;
81
William A. Kennington IIIe0564842021-10-23 16:02:22 -070082 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050083 {
84 if (gateway.first == intfName)
85 {
86 defaultGateway = gateway.second;
87 break;
88 }
89 }
90
William A. Kennington IIIe0564842021-10-23 16:02:22 -070091 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050092 {
93 if (gateway6.first == intfName)
94 {
95 defaultGateway6 = gateway6.second;
96 break;
97 }
98 }
99
100 EthernetInterfaceIntf::defaultGateway(defaultGateway);
101 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530102 // Don't get the mac address from the system as the mac address
103 // would be same as parent interface.
104 if (intfName.find(".") == std::string::npos)
105 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500106 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530107 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700108 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700109 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530110
111 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530112 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530113
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700114#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700115 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
116
117 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
118 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800119#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530120
Ratan Gupta29b0e432017-05-25 12:51:40 +0530121 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530122 if (emitSignal)
123 {
124 this->emit_object_added();
125 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530126}
127
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700128static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800129{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700130 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800131 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700132 return IP::Protocol::IPv4;
133 }
134 else if (std::holds_alternative<in6_addr>(addr))
135 {
136 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800137 }
138
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700139 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800140}
141
William A. Kennington III24957b92021-12-03 13:59:19 -0800142bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800143{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700144 switch (family)
145 {
146 case IP::Protocol::IPv6:
147 return dhcp6();
148 case IP::Protocol::IPv4:
149 return dhcp4();
150 }
151 throw std::logic_error("Unreachable");
Johnathan Mantey817012a2020-01-30 15:07:39 -0800152}
153
Johnathan Mantey817012a2020-01-30 15:07:39 -0800154bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
155{
156 return (
157#ifdef LINK_LOCAL_AUTOCONFIGURATION
158 (origin == IP::AddressOrigin::Static)
159#else
160 (origin == IP::AddressOrigin::Static ||
161 origin == IP::AddressOrigin::LinkLocal)
162#endif
163
164 );
165}
166
Ratan Gupta87c13982017-06-15 09:27:27 +0530167void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530168{
Ratan Gupta87c13982017-06-15 09:27:27 +0530169 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530170
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700171 AddressFilter filter;
172 filter.interface = ifIndex();
173 auto currentAddrs = getCurrentAddresses(filter);
174 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530175 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700176 if (addr.flags & IFA_F_DEPRECATED)
177 {
178 continue;
179 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700180 auto address = toString(addr.address);
181 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800182 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800183 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530184 {
185 origin = IP::AddressOrigin::DHCP;
186 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700187 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530188 {
189 origin = IP::AddressOrigin::LinkLocal;
190 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700191 // Obsolete parameter
192 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530193
Gunnar Mills57d9c502018-09-14 14:42:34 -0500194 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700195 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530196
Lei YU7233c582021-04-08 14:39:43 +0800197 this->addrs.insert_or_assign(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700198 address, std::make_shared<phosphor::network::IPAddress>(
199 bus, ipAddressObjectPath.c_str(), *this, addressType,
200 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530201 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530202}
203
William A. Kennington III08505792019-01-30 16:00:04 -0800204void EthernetInterface::createStaticNeighborObjects()
205{
206 staticNeighbors.clear();
207
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700208 NeighborFilter filter;
209 filter.interface = ifIndex();
210 filter.state = NUD_PERMANENT;
211 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800212 for (const auto& neighbor : neighbors)
213 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700214 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800215 {
216 continue;
217 }
218 std::string ip = toString(neighbor.address);
219 std::string mac = mac_address::toString(*neighbor.mac);
220 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
221 staticNeighbors.emplace(ip,
222 std::make_shared<phosphor::network::Neighbor>(
223 bus, objectPath.c_str(), *this, ip, mac,
224 Neighbor::State::Permanent));
225 }
226}
227
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700228unsigned EthernetInterface::ifIndex() const
229{
230 unsigned idx = if_nametoindex(interfaceName().c_str());
231 if (idx == 0)
232 {
233 throw std::system_error(errno, std::generic_category(),
234 "if_nametoindex");
235 }
236 return idx;
237}
238
Patrick Williams6aef7692021-05-01 06:39:41 -0500239ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500240 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530241{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800242 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530243 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700244 log<level::INFO>("DHCP enabled on the interface, disabling"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500245 entry("INTERFACE=%s", interfaceName().c_str());
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700246 switch (protType)
247 {
248 case IP::Protocol::IPv4:
249 dhcp4(false);
250 break;
251 case IP::Protocol::IPv6:
252 dhcp6(false);
253 break;
254 }
Ravi Teja07450442022-07-07 04:30:57 -0500255 // Delete the IP address object and that reloads the networkd
256 // to allow the same IP address to be set as Static IP
257 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500258 }
259
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500260 IP::AddressOrigin origin = IP::AddressOrigin::Static;
261
262 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
263
264 if (!isValidIP(addressFamily, ipaddress))
265 {
266 log<level::ERR>("Not a valid IP address"),
267 entry("ADDRESS=%s", ipaddress.c_str());
268 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
269 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
270 }
271
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700272 // Gateway is an obsolete parameter
273 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500274
275 if (!isValidPrefix(addressFamily, prefixLength))
276 {
277 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700278 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500279 elog<InvalidArgument>(
280 Argument::ARGUMENT_NAME("prefixLength"),
281 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530282 }
283
Gunnar Mills57d9c502018-09-14 14:42:34 -0500284 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800285 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800286 this->addrs.insert_or_assign(ipaddress,
287 std::make_shared<phosphor::network::IPAddress>(
288 bus, objectPath.c_str(), *this, protType,
289 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530290
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700291 writeConfigurationFile();
292 manager.reloadConfigs();
293
raviteja-bce379562019-03-28 05:59:36 -0500294 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530295}
296
Patrick Williams6aef7692021-05-01 06:39:41 -0500297ObjectPath EthernetInterface::neighbor(std::string ipAddress,
298 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800299{
Patrick Williams6aef7692021-05-01 06:39:41 -0500300 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800301 {
302 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500303 entry("ADDRESS=%s", ipAddress.c_str()));
304 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
305 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800306 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500307 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800308 {
309 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500310 entry("MACADDRESS=%s", ipAddress.c_str()));
311 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
312 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800313 }
314
315 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500316 generateStaticNeighborObjectPath(ipAddress, macAddress);
317 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800318 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500319 bus, objectPath.c_str(), *this, ipAddress,
320 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700321
322 writeConfigurationFile();
323 manager.reloadConfigs();
324
William A. Kennington III08505792019-01-30 16:00:04 -0800325 return objectPath;
326}
327
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700328#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530329/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800330 Enable this code if your NIC driver supports the ETHTOOL features.
331 Do this by adding the following to your phosphor-network*.bbappend file.
332 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
333 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530334*/
335InterfaceInfo EthernetInterface::getInterfaceInfo() const
336{
William A. Kennington III05368f12021-05-13 18:40:47 -0700337 ifreq ifr = {};
338 ethtool_cmd edata = {};
339 LinkSpeed speed = {};
340 Autoneg autoneg = {};
341 DuplexMode duplex = {};
342 LinkUp linkState = {};
343 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530344 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530345
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800346 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
347 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530348
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800349 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800350 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800351 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800352 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530353 speed = edata.speed;
354 duplex = edata.duplex;
355 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530356 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800357 catch (const std::exception& e)
358 {
359 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800360
William A. Kennington III96203312021-05-07 12:50:41 -0700361 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800362 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530363 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800364
Tejas Patil2c0fc562021-08-03 19:13:46 +0530365 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530366}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800367#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530368
369/** @brief get the mac address of the interface.
370 * @return macaddress on success
371 */
372
Gunnar Mills57d9c502018-09-14 14:42:34 -0500373std::string
374 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530375{
Patrick Williams6aef7692021-05-01 06:39:41 -0500376 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530377
William A. Kennington III05368f12021-05-13 18:40:47 -0700378 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800379 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800380 try
381 {
382 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
383 }
384 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530385 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530386 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800387 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700388 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530389 }
390
William A. Kennington III1137a972019-04-20 20:49:58 -0700391 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
392 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
393 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700394 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530395}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530396
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530397std::string EthernetInterface::generateId(const std::string& ipaddress,
398 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800399 const std::string& gateway,
400 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530401{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530402 std::stringstream hexId;
403 std::string hashString = ipaddress;
404 hashString += std::to_string(prefixLength);
405 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800406 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530407
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530408 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500409 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530410 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530411}
412
Patrick Williams6aef7692021-05-01 06:39:41 -0500413std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
414 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800415{
416 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500417 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800418
419 // Only want 8 hex digits.
420 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
421 return hexId.str();
422}
423
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530424void EthernetInterface::deleteObject(const std::string& ipaddress)
425{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530426 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530427 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530428 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530429 log<level::ERR>("DeleteObject:Unable to find the object.");
430 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530431 }
432 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700433
434 writeConfigurationFile();
435 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530436}
437
Patrick Williams6aef7692021-05-01 06:39:41 -0500438void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800439{
Patrick Williams6aef7692021-05-01 06:39:41 -0500440 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800441 if (it == staticNeighbors.end())
442 {
443 log<level::ERR>(
444 "DeleteStaticNeighborObject:Unable to find the object.");
445 return;
446 }
447 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700448
449 writeConfigurationFile();
450 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800451}
452
Ratan Guptae9c9b812017-09-22 17:15:37 +0530453void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530454{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700455 const auto& confDir = manager.getConfDir();
456 auto networkFile = config::pathForIntfConf(confDir, interface);
457 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530458
459 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700460 std::error_code ec;
William A. Kennington III95530ec2022-08-19 01:44:39 -0700461 std::filesystem::remove(networkFile, ec);
462 std::filesystem::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530463
464 // TODO systemd doesn't delete the virtual network interface
465 // even after deleting all the related configuartion.
466 // https://github.com/systemd/systemd/issues/6600
467 try
468 {
469 deleteInterface(interface);
470 }
Patrick Williams5758db32021-10-06 12:29:22 -0500471 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530472 {
473 commit<InternalFailure>();
474 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530475}
476
477void EthernetInterface::deleteVLANObject(const std::string& interface)
478{
479 auto it = vlanInterfaces.find(interface);
480 if (it == vlanInterfaces.end())
481 {
482 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500483 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530484 return;
485 }
486
487 deleteVLANFromSystem(interface);
488 // delete the interface
489 vlanInterfaces.erase(it);
490
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700491 writeConfigurationFile();
492 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530493}
494
Gunnar Mills57d9c502018-09-14 14:42:34 -0500495std::string EthernetInterface::generateObjectPath(
496 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800497 uint8_t prefixLength, const std::string& gateway,
498 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530499{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530500 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530501 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530502 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
503
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530504 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530505 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530506 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800507 objectPath /=
508 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530509 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530510}
511
William A. Kennington III08505792019-01-30 16:00:04 -0800512std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500513 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800514{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530515 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800516 objectPath /= objPath;
517 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500518 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800519 return objectPath.string();
520}
521
Patrick Williams6aef7692021-05-01 06:39:41 -0500522bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700523{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700524 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700525 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700526 writeConfigurationFile();
527 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700528 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700529 return value;
530}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700531
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700532bool EthernetInterface::dhcp4(bool value)
533{
534 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
535 {
536 writeConfigurationFile();
537 manager.reloadConfigs();
538 }
539 return value;
540}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700541
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700542bool EthernetInterface::dhcp6(bool value)
543{
544 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
545 {
546 writeConfigurationFile();
547 manager.reloadConfigs();
548 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700549 return value;
550}
551
Patrick Williams6aef7692021-05-01 06:39:41 -0500552EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530553{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700554 auto old4 = EthernetInterfaceIntf::dhcp4();
555 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
556 value == DHCPConf::v4v6stateless ||
557 value == DHCPConf::both);
558 auto old6 = EthernetInterfaceIntf::dhcp6();
559 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
560 value == DHCPConf::both);
561 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
562 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
563 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
564 value == DHCPConf::v6 || value == DHCPConf::both);
565
566 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530567 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700568 writeConfigurationFile();
569 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530570 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530571 return value;
572}
573
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700574EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
575{
576 if (dhcp6())
577 {
578 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
579 }
580 else if (dhcp4())
581 {
582 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
583 }
584 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
585}
586
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800587bool EthernetInterface::linkUp() const
588{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800589 bool value = EthernetInterfaceIntf::linkUp();
590
William A. Kennington III05368f12021-05-13 18:40:47 -0700591 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800592 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800593 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800594 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800595 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800596 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
597 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800598 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800599 {
600 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800601 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800602 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700603 return value;
604}
605
Tejas Patil2c0fc562021-08-03 19:13:46 +0530606size_t EthernetInterface::mtu() const
607{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530608 size_t value = EthernetInterfaceIntf::mtu();
609
Tejas Patil2c0fc562021-08-03 19:13:46 +0530610 ifreq ifr = {};
611 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800612 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530613 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800614 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530615 value = ifr.ifr_mtu;
616 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800617 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530618 {
619 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800620 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530621 }
622 return value;
623}
624
625size_t EthernetInterface::mtu(size_t value)
626{
627 if (value == EthernetInterfaceIntf::mtu())
628 {
629 return value;
630 }
631 else if (value == 0)
632 {
633 return EthernetInterfaceIntf::mtu();
634 }
635
Tejas Patil2c0fc562021-08-03 19:13:46 +0530636 ifreq ifr = {};
637 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
638 ifr.ifr_mtu = value;
639
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800640 try
641 {
642 getIFSock().ioctl(SIOCSIFMTU, &ifr);
643 }
644 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530645 {
646 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
647 entry("ERROR=%s", strerror(errno)));
648 return EthernetInterfaceIntf::mtu();
649 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530650
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800651 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530652 return value;
653}
654
William A. Kennington III26275a32021-07-13 20:32:42 -0700655bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700656{
William A. Kennington III26275a32021-07-13 20:32:42 -0700657 constexpr auto svc = "org.freedesktop.network1";
658 constexpr auto intf = "org.freedesktop.network1.Link";
659 constexpr auto prop = "AdministrativeState";
660 char* rpath;
661 sd_bus_path_encode("/org/freedesktop/network1/link",
662 std::to_string(ifIndex()).c_str(), &rpath);
663 std::string path(rpath);
664 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700665
William A. Kennington III26275a32021-07-13 20:32:42 -0700666 // Store / Parser for the AdministrativeState return value
667 std::optional<bool> ret;
668 auto cb = [&](const std::string& state) {
669 if (state != "initialized")
670 {
671 ret = state != "unmanaged";
672 }
673 };
674
675 // Build a matcher before making the property call to ensure we
676 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500677 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700678 bus,
679 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
680 "'PropertiesChanged',arg0='{}',",
681 svc, path, PROPERTY_INTERFACE, intf)
682 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500683 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700684 std::string intf;
685 std::unordered_map<std::string, std::variant<std::string>> values;
686 try
687 {
688 m.read(intf, values);
689 auto it = values.find(prop);
690 // Ignore properties that aren't AdministrativeState
691 if (it != values.end())
692 {
693 cb(std::get<std::string>(it->second));
694 }
695 }
696 catch (const std::exception& e)
697 {
698 log<level::ERR>(
699 fmt::format(
700 "AdministrativeState match parsing failed on {}: {}",
701 interfaceName(), e.what())
702 .c_str(),
703 entry("INTERFACE=%s", interfaceName().c_str()),
704 entry("ERROR=%s", e.what()));
705 }
706 });
707
708 // Actively call for the value in case the interface is already configured
709 auto method =
710 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
711 method.append(intf, prop);
712 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700713 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700714 auto reply = bus.call(method);
715 std::variant<std::string> state;
716 reply.read(state);
717 cb(std::get<std::string>(state));
718 }
719 catch (const std::exception& e)
720 {
721 log<level::ERR>(
722 fmt::format("Failed to get AdministrativeState on {}: {}",
723 interfaceName(), e.what())
724 .c_str(),
725 entry("INTERFACE=%s", interfaceName().c_str()),
726 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700727 }
728
William A. Kennington III26275a32021-07-13 20:32:42 -0700729 // The interface is not yet configured by systemd-networkd, wait until it
730 // signals us a valid state.
731 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700732 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700733 bus.wait();
734 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700735 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700736
737 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700738}
739
William A. Kennington III69f45542022-09-24 23:28:14 -0700740static void setNICAdminState(stdplus::const_zstring intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700741{
742 ifreq ifr = {};
William A. Kennington III69f45542022-09-24 23:28:14 -0700743 std::strncpy(ifr.ifr_name, intf.data(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800744 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700745
746 ifr.ifr_flags &= ~IFF_UP;
747 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800748 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700749}
750
Patrick Williams6aef7692021-05-01 06:39:41 -0500751bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700752{
Patrick Williams6aef7692021-05-01 06:39:41 -0500753 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700754 {
755 return value;
756 }
757
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800758 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700759 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800760 if (!value)
761 {
762 // We only need to bring down the interface, networkd will always bring
763 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700764 manager.addReloadPreHook(
765 [ifname = interfaceName()]() { setNICAdminState(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800766 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700767 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800768
769 return value;
770}
771
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530772ServerList EthernetInterface::staticNameServers(ServerList value)
773{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530774 for (const auto& nameserverip : value)
775 {
776 if (!isValidIP(AF_INET, nameserverip) &&
777 !isValidIP(AF_INET6, nameserverip))
778 {
779 log<level::ERR>("Not a valid IP address"),
780 entry("ADDRESS=%s", nameserverip.c_str());
781 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530782 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530783 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
784 }
785 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530786 try
787 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530788 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700789
Ratan Gupta6dec3902017-08-20 15:28:12 +0530790 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700791 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530792 }
Patrick Williams5758db32021-10-06 12:29:22 -0500793 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530794 {
795 log<level::ERR>("Exception processing DNS entries");
796 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530797 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530798}
799
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700800void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530801{
802 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700803 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700804 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530805}
806
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530807ServerList EthernetInterface::getNameServerFromResolvd()
808{
809 ServerList servers;
810 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
811
812 /*
813 The DNS property under org.freedesktop.resolve1.Link interface contains
814 an array containing all DNS servers currently used by resolved. It
815 contains similar information as the DNS server data written to
816 /run/systemd/resolve/resolv.conf.
817
818 Each structure in the array consists of a numeric network interface index,
819 an address family, and a byte array containing the DNS server address
820 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
821 The array contains DNS servers configured system-wide, including those
822 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
823 /etc/systemd/resolved.conf, as well as per-interface DNS server
824 information either retrieved from systemd-networkd or configured by
825 external software via SetLinkDNS().
826 */
827
828 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
829 std::variant<type> name; // Variable to capture the DNS property
830 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
831 PROPERTY_INTERFACE, METHOD_GET);
832
833 method.append(RESOLVED_INTERFACE, "DNS");
834 auto reply = bus.call(method);
835
836 try
837 {
838 reply.read(name);
839 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500840 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530841 {
842 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
843 }
844 auto tupleVector = std::get_if<type>(&name);
845 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
846 {
Alexander Filippov983da552021-02-08 15:26:54 +0300847 int addressFamily = std::get<0>(*i);
848 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
849
850 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530851 {
Alexander Filippov983da552021-02-08 15:26:54 +0300852 case AF_INET:
853 if (ipaddress.size() == sizeof(struct in_addr))
854 {
855 servers.push_back(toString(
856 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
857 }
858 else
859 {
860 log<level::ERR>(
861 "Invalid data recived from Systemd-Resolved");
862 }
863 break;
864
865 case AF_INET6:
866 if (ipaddress.size() == sizeof(struct in6_addr))
867 {
868 servers.push_back(toString(
869 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
870 }
871 else
872 {
873 log<level::ERR>(
874 "Invalid data recived from Systemd-Resolved");
875 }
876 break;
877
878 default:
879 log<level::ERR>(
880 "Unsupported address family in DNS from Systemd-Resolved");
881 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530882 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530883 }
884 return servers;
885}
886
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700887std::string EthernetInterface::vlanIntfName(VlanId id) const
888{
889 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
890}
891
892std::string EthernetInterface::vlanObjPath(VlanId id) const
893{
894 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
895}
896
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530897void EthernetInterface::loadVLAN(VlanId id)
898{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700899 auto vlanInterfaceName = vlanIntfName(id);
900 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530901
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700902 config::Parser config(
903 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
904
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530905 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700906 bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
907 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530908
Gunnar Mills57d9c502018-09-14 14:42:34 -0500909 // Fetch the ip address from the system
910 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530911 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800912 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700913 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530914
915 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
916 std::move(vlanIntf));
917}
918
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700919ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530920{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700921 auto vlanInterfaceName = vlanIntfName(id);
922 if (this->vlanInterfaces.find(vlanInterfaceName) !=
923 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800924 {
925 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
926 elog<InvalidArgument>(
927 Argument::ARGUMENT_NAME("VLANId"),
928 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
929 }
930
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700931 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530932
Patrick Williams6aef7692021-05-01 06:39:41 -0500933 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530934 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530935 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700936 bus, path.c_str(), config::Parser(),
Patrick Williams6aef7692021-05-01 06:39:41 -0500937 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530938
939 // write the device file for the vlan interface.
940 vlanIntf->writeDeviceFile();
941
Gunnar Mills57d9c502018-09-14 14:42:34 -0500942 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700943
944 writeConfigurationFile();
945 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700946
947 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530948}
Ratan Gupta2b106532017-07-25 16:05:02 +0530949
Patrick Williams6aef7692021-05-01 06:39:41 -0500950ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530951{
Patrick Williams6aef7692021-05-01 06:39:41 -0500952 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530953
954 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700955 manager.reloadConfigs();
956
Ratan Gupta497c0c92017-08-22 19:15:59 +0530957 return ntpServers;
958}
Ratan Gupta2b106532017-07-25 16:05:02 +0530959// Need to merge the below function with the code which writes the
960// config file during factory reset.
961// TODO openbmc/openbmc#1751
962
963void EthernetInterface::writeConfigurationFile()
964{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500965 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530966 {
967 intf.second->writeConfigurationFile();
968 }
969
William A. Kennington III95a49a22022-08-18 17:50:05 -0700970 config::Parser config;
971 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530972 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700973 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800974#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700975 auto mac = MacAddressIntf::macAddress();
976 if (!mac.empty())
977 {
978 link["MACAddress"].emplace_back(mac);
979 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800980#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700981 if (!EthernetInterfaceIntf::nicEnabled())
982 {
983 link["Unmanaged"].emplace_back("yes");
984 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700985 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700986 {
987 auto& network = config.map["Network"].emplace_back();
988 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400989#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700990 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400991#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700992 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400993#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700994 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
995 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
996 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600997 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700998 auto& vlans = network["VLAN"];
999 for (const auto& intf : vlanInterfaces)
1000 {
1001 vlans.emplace_back(
1002 intf.second->EthernetInterface::interfaceName());
1003 }
1004 }
1005 {
1006 auto& ntps = network["NTP"];
1007 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
1008 {
1009 ntps.emplace_back(ntp);
1010 }
1011 }
1012 {
1013 auto& dnss = network["DNS"];
1014 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1015 {
1016 dnss.emplace_back(dns);
1017 }
1018 }
1019 {
1020 auto& address = network["Address"];
1021 for (const auto& addr : getAddresses())
1022 {
1023 if (originIsManuallyAssigned(addr.second->origin()) &&
1024 !dhcpIsEnabled(addr.second->type()))
1025 {
1026 address.emplace_back(
1027 fmt::format("{}/{}", addr.second->address(),
1028 addr.second->prefixLength()));
1029 }
1030 }
1031 }
1032 {
1033 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001034 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001035 {
1036 auto gateway = EthernetInterfaceIntf::defaultGateway();
1037 if (!gateway.empty())
1038 {
1039 gateways.emplace_back(gateway);
1040 }
1041 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301042
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001043 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001044 {
1045 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1046 if (!gateway6.empty())
1047 {
1048 gateways.emplace_back(gateway6);
1049 }
1050 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001051 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001052 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001053 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001054 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001055 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001056 auto& neighbors = config.map["Neighbor"];
1057 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001058 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001059 auto& neighbor = neighbors.emplace_back();
1060 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1061 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001062 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001063 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001064 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001065 auto& dhcp = config.map["DHCP"].emplace_back();
1066 dhcp["ClientIdentifier"].emplace_back("mac");
1067 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001068 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001069 const auto& conf = *manager.getDHCPConf();
1070 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1071 dhcp["UseDNS"].emplace_back(dns_enabled);
1072 dhcp["UseDomains"].emplace_back(dns_enabled);
1073 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1074 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1075 : "false");
1076 dhcp["SendHostname"].emplace_back(
1077 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001078 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001079 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001080 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1081 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001082 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1083 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301084}
1085
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001086std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301087{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001088#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001089 ether_addr newMAC;
1090 try
1091 {
1092 newMAC = mac_address::fromString(value);
1093 }
Patrick Williams5758db32021-10-06 12:29:22 -05001094 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001095 {
1096 log<level::ERR>("MACAddress is not valid.",
1097 entry("MAC=%s", value.c_str()));
1098 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1099 Argument::ARGUMENT_VALUE(value.c_str()));
1100 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001101 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301102 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001103 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001104 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001105 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1106 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301107 }
1108
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001109 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001110 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001111
William A. Kennington III1137a972019-04-20 20:49:58 -07001112 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001113 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001114 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301115 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001116 // Update everything that depends on the MAC value
1117 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301118 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001119 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301120 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001121 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301122
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001123 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001124 manager.addReloadPreHook([interface]() {
1125 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III69f45542022-09-24 23:28:14 -07001126 setNICAdminState(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001127 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001128 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301129 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001130
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001131#ifdef HAVE_UBOOT_ENV
1132 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -07001133 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001134 if (envVar)
1135 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001136 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1137 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1138 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1139 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001140 }
1141#endif // HAVE_UBOOT_ENV
1142
William A. Kennington III1137a972019-04-20 20:49:58 -07001143 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001144#else
1145 elog<NotAllowed>(
1146 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1147#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301148}
1149
Ratan Guptae9c9b812017-09-22 17:15:37 +05301150void EthernetInterface::deleteAll()
1151{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301152 // clear all the ip on the interface
1153 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001154
1155 writeConfigurationFile();
1156 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301157}
1158
Ravi Tejaa5a09442020-07-17 00:57:33 -05001159std::string EthernetInterface::defaultGateway(std::string gateway)
1160{
1161 auto gw = EthernetInterfaceIntf::defaultGateway();
1162 if (gw == gateway)
1163 {
1164 return gw;
1165 }
1166
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001167 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001168 {
1169 log<level::ERR>("Not a valid v4 Gateway",
1170 entry("GATEWAY=%s", gateway.c_str()));
1171 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1172 Argument::ARGUMENT_VALUE(gateway.c_str()));
1173 }
1174 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001175
1176 writeConfigurationFile();
1177 manager.reloadConfigs();
1178
Ravi Tejaa5a09442020-07-17 00:57:33 -05001179 return gw;
1180}
1181
1182std::string EthernetInterface::defaultGateway6(std::string gateway)
1183{
1184 auto gw = EthernetInterfaceIntf::defaultGateway6();
1185 if (gw == gateway)
1186 {
1187 return gw;
1188 }
1189
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001190 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001191 {
1192 log<level::ERR>("Not a valid v6 Gateway",
1193 entry("GATEWAY=%s", gateway.c_str()));
1194 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1195 Argument::ARGUMENT_VALUE(gateway.c_str()));
1196 }
1197 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001198
1199 writeConfigurationFile();
1200 manager.reloadConfigs();
1201
Ravi Tejaa5a09442020-07-17 00:57:33 -05001202 return gw;
1203}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001204} // namespace network
1205} // namespace phosphor