blob: 610ec79c894cd9a7dbf7d44563ec6ece7d1da4db [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include "config.h"
2
Patrick Venture189d44e2018-07-09 12:30:59 -07003#include "ethernet_interface.hpp"
4
Ratan Gupta497c0c92017-08-22 19:15:59 +05305#include "config_parser.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08006#include "neighbor.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05307#include "network_manager.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05308#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309
Ratan Gupta82549cc2017-04-21 08:45:23 +053010#include <arpa/inet.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070011#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053012#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070013#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016
Ratan Gupta82549cc2017-04-21 08:45:23 +053017#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053018#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053019#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070020#include <phosphor-logging/elog-errors.hpp>
21#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070022#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <sstream>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080024#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070025#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053026#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070027#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070028#include <unordered_map>
29#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070030#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053031
Ratan Gupta91a99cc2017-04-14 16:32:09 +053032namespace phosphor
33{
34namespace network
35{
36
37using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053038using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053039using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
40using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050041using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053042constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
43constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
44constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
45constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
46constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053047
Johnathan Mantey817012a2020-01-30 15:07:39 -080048std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
49 {EthernetInterface::DHCPConf::both, "true"},
50 {EthernetInterface::DHCPConf::v4, "ipv4"},
51 {EthernetInterface::DHCPConf::v6, "ipv6"},
52 {EthernetInterface::DHCPConf::none, "false"}};
53
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080054static stdplus::Fd& getIFSock()
55{
56 using namespace stdplus::fd;
57 static auto fd =
58 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
59 return fd;
60}
61
Ratan Gupta91a99cc2017-04-14 16:32:09 +053062EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
63 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080064 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070065 bool emitSignal,
66 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050067 Ifaces(bus, objPath.c_str(),
68 emitSignal ? Ifaces::action::defer_emit
69 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050070 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053071{
72 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053073 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053074 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050075 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
76 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070077 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070078 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
79 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050080 std::string defaultGateway;
81 std::string defaultGateway6;
82
William A. Kennington IIIe0564842021-10-23 16:02:22 -070083 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050084 {
85 if (gateway.first == intfName)
86 {
87 defaultGateway = gateway.second;
88 break;
89 }
90 }
91
William A. Kennington IIIe0564842021-10-23 16:02:22 -070092 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050093 {
94 if (gateway6.first == intfName)
95 {
96 defaultGateway6 = gateway6.second;
97 break;
98 }
99 }
100
101 EthernetInterfaceIntf::defaultGateway(defaultGateway);
102 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530103 // Don't get the mac address from the system as the mac address
104 // would be same as parent interface.
105 if (intfName.find(".") == std::string::npos)
106 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500107 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530108 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500109 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
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 Gupta6dec390f2017-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 IIIfbafa252018-11-30 16:53:52 -0800128static IP::Protocol convertFamily(int family)
129{
130 switch (family)
131 {
132 case AF_INET:
133 return IP::Protocol::IPv4;
134 case AF_INET6:
135 return IP::Protocol::IPv6;
136 }
137
138 throw std::invalid_argument("Bad address family");
139}
140
Johnathan Mantey817012a2020-01-30 15:07:39 -0800141void EthernetInterface::disableDHCP(IP::Protocol protocol)
142{
Patrick Williams6aef7692021-05-01 06:39:41 -0500143 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800144 if (dhcpState == EthernetInterface::DHCPConf::both)
145 {
146 if (protocol == IP::Protocol::IPv4)
147 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500148 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800149 }
150 else if (protocol == IP::Protocol::IPv6)
151 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500152 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800153 }
154 }
155 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
156 (protocol == IP::Protocol::IPv4))
157 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500158 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800159 }
160 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
161 (protocol == IP::Protocol::IPv6))
162 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500163 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800164 }
165}
166
William A. Kennington III24957b92021-12-03 13:59:19 -0800167bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800168{
William A. Kennington III24957b92021-12-03 13:59:19 -0800169 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
170 return cur == EthernetInterface::DHCPConf::both ||
171 (family == IP::Protocol::IPv6 &&
172 cur == EthernetInterface::DHCPConf::v6) ||
173 (family == IP::Protocol::IPv4 &&
174 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800175}
176
Johnathan Mantey817012a2020-01-30 15:07:39 -0800177bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
178{
179 return (
180#ifdef LINK_LOCAL_AUTOCONFIGURATION
181 (origin == IP::AddressOrigin::Static)
182#else
183 (origin == IP::AddressOrigin::Static ||
184 origin == IP::AddressOrigin::LinkLocal)
185#endif
186
187 );
188}
189
Ratan Gupta87c13982017-06-15 09:27:27 +0530190void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530191{
Ratan Gupta87c13982017-06-15 09:27:27 +0530192 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530193
Ratan Gupta87c13982017-06-15 09:27:27 +0530194 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530195
Ratan Gupta6a387c12017-08-03 13:26:19 +0530196 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530197 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800198 IP::Protocol addressType = convertFamily(addr.addrType);
199 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800200 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530201 {
202 origin = IP::AddressOrigin::DHCP;
203 }
William A. Kennington III16893802019-01-30 16:01:01 -0800204 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530205 {
206 origin = IP::AddressOrigin::LinkLocal;
207 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700208 // Obsolete parameter
209 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530210
Gunnar Mills57d9c502018-09-14 14:42:34 -0500211 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800212 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530213
Lei YU7233c582021-04-08 14:39:43 +0800214 this->addrs.insert_or_assign(
215 addr.ipaddress,
216 std::make_shared<phosphor::network::IPAddress>(
217 bus, ipAddressObjectPath.c_str(), *this, addressType,
218 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530219 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530220}
221
William A. Kennington III08505792019-01-30 16:00:04 -0800222void EthernetInterface::createStaticNeighborObjects()
223{
224 staticNeighbors.clear();
225
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700226 NeighborFilter filter;
227 filter.interface = ifIndex();
228 filter.state = NUD_PERMANENT;
229 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800230 for (const auto& neighbor : neighbors)
231 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700232 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800233 {
234 continue;
235 }
236 std::string ip = toString(neighbor.address);
237 std::string mac = mac_address::toString(*neighbor.mac);
238 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
239 staticNeighbors.emplace(ip,
240 std::make_shared<phosphor::network::Neighbor>(
241 bus, objectPath.c_str(), *this, ip, mac,
242 Neighbor::State::Permanent));
243 }
244}
245
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700246unsigned EthernetInterface::ifIndex() const
247{
248 unsigned idx = if_nametoindex(interfaceName().c_str());
249 if (idx == 0)
250 {
251 throw std::system_error(errno, std::generic_category(),
252 "if_nametoindex");
253 }
254 return idx;
255}
256
Patrick Williams6aef7692021-05-01 06:39:41 -0500257ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500258 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530259{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800260 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530261 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530262 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500263 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800264 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 }
266
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500267 IP::AddressOrigin origin = IP::AddressOrigin::Static;
268
269 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
270
271 if (!isValidIP(addressFamily, ipaddress))
272 {
273 log<level::ERR>("Not a valid IP address"),
274 entry("ADDRESS=%s", ipaddress.c_str());
275 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
276 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
277 }
278
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700279 // Gateway is an obsolete parameter
280 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500281
282 if (!isValidPrefix(addressFamily, prefixLength))
283 {
284 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700285 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500286 elog<InvalidArgument>(
287 Argument::ARGUMENT_NAME("prefixLength"),
288 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530289 }
290
Gunnar Mills57d9c502018-09-14 14:42:34 -0500291 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800292 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800293 this->addrs.insert_or_assign(ipaddress,
294 std::make_shared<phosphor::network::IPAddress>(
295 bus, objectPath.c_str(), *this, protType,
296 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530297
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700298 writeConfigurationFile();
299 manager.reloadConfigs();
300
raviteja-bce379562019-03-28 05:59:36 -0500301 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530302}
303
Patrick Williams6aef7692021-05-01 06:39:41 -0500304ObjectPath EthernetInterface::neighbor(std::string ipAddress,
305 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800306{
Patrick Williams6aef7692021-05-01 06:39:41 -0500307 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800308 {
309 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500310 entry("ADDRESS=%s", ipAddress.c_str()));
311 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
312 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800313 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500314 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800315 {
316 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500317 entry("MACADDRESS=%s", ipAddress.c_str()));
318 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
319 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800320 }
321
322 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500323 generateStaticNeighborObjectPath(ipAddress, macAddress);
324 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800325 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500326 bus, objectPath.c_str(), *this, ipAddress,
327 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700328
329 writeConfigurationFile();
330 manager.reloadConfigs();
331
William A. Kennington III08505792019-01-30 16:00:04 -0800332 return objectPath;
333}
334
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700335#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530336/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800337 Enable this code if your NIC driver supports the ETHTOOL features.
338 Do this by adding the following to your phosphor-network*.bbappend file.
339 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
340 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530341*/
342InterfaceInfo EthernetInterface::getInterfaceInfo() const
343{
William A. Kennington III05368f12021-05-13 18:40:47 -0700344 ifreq ifr = {};
345 ethtool_cmd edata = {};
346 LinkSpeed speed = {};
347 Autoneg autoneg = {};
348 DuplexMode duplex = {};
349 LinkUp linkState = {};
350 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530351 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530352
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800353 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
354 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530355
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800356 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800357 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800358 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800359 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530360 speed = edata.speed;
361 duplex = edata.duplex;
362 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530363 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800364 catch (const std::exception& e)
365 {
366 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800367
William A. Kennington III96203312021-05-07 12:50:41 -0700368 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800369 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530370 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800371
Tejas Patil2c0fc562021-08-03 19:13:46 +0530372 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530373}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800374#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530375
376/** @brief get the mac address of the interface.
377 * @return macaddress on success
378 */
379
Gunnar Mills57d9c502018-09-14 14:42:34 -0500380std::string
381 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530382{
Patrick Williams6aef7692021-05-01 06:39:41 -0500383 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384
William A. Kennington III05368f12021-05-13 18:40:47 -0700385 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800386 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800387 try
388 {
389 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
390 }
391 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530392 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530393 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800394 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700395 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530396 }
397
William A. Kennington III1137a972019-04-20 20:49:58 -0700398 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
399 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
400 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700401 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530402}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530403
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530404std::string EthernetInterface::generateId(const std::string& ipaddress,
405 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800406 const std::string& gateway,
407 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530408{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530409 std::stringstream hexId;
410 std::string hashString = ipaddress;
411 hashString += std::to_string(prefixLength);
412 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800413 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530414
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530415 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500416 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530417 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530418}
419
Patrick Williams6aef7692021-05-01 06:39:41 -0500420std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
421 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800422{
423 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500424 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800425
426 // Only want 8 hex digits.
427 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
428 return hexId.str();
429}
430
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530431void EthernetInterface::deleteObject(const std::string& ipaddress)
432{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530433 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530434 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530435 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530436 log<level::ERR>("DeleteObject:Unable to find the object.");
437 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530438 }
439 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700440
441 writeConfigurationFile();
442 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530443}
444
Patrick Williams6aef7692021-05-01 06:39:41 -0500445void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800446{
Patrick Williams6aef7692021-05-01 06:39:41 -0500447 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800448 if (it == staticNeighbors.end())
449 {
450 log<level::ERR>(
451 "DeleteStaticNeighborObject:Unable to find the object.");
452 return;
453 }
454 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700455
456 writeConfigurationFile();
457 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800458}
459
Ratan Guptae9c9b812017-09-22 17:15:37 +0530460void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530461{
Ratan Guptabc886292017-07-25 18:29:57 +0530462 auto confDir = manager.getConfDir();
463 fs::path networkFile = confDir;
464 networkFile /= systemd::config::networkFilePrefix + interface +
465 systemd::config::networkFileSuffix;
466
467 fs::path deviceFile = confDir;
468 deviceFile /= interface + systemd::config::deviceFileSuffix;
469
470 // delete the vlan network file
471 if (fs::is_regular_file(networkFile))
472 {
473 fs::remove(networkFile);
474 }
475
476 // delete the vlan device file
477 if (fs::is_regular_file(deviceFile))
478 {
479 fs::remove(deviceFile);
480 }
Ratan Guptabc886292017-07-25 18:29:57 +0530481
482 // TODO systemd doesn't delete the virtual network interface
483 // even after deleting all the related configuartion.
484 // https://github.com/systemd/systemd/issues/6600
485 try
486 {
487 deleteInterface(interface);
488 }
Patrick Williams5758db32021-10-06 12:29:22 -0500489 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530490 {
491 commit<InternalFailure>();
492 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530493}
494
495void EthernetInterface::deleteVLANObject(const std::string& interface)
496{
497 auto it = vlanInterfaces.find(interface);
498 if (it == vlanInterfaces.end())
499 {
500 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500501 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530502 return;
503 }
504
505 deleteVLANFromSystem(interface);
506 // delete the interface
507 vlanInterfaces.erase(it);
508
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700509 writeConfigurationFile();
510 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530511}
512
Gunnar Mills57d9c502018-09-14 14:42:34 -0500513std::string EthernetInterface::generateObjectPath(
514 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800515 uint8_t prefixLength, const std::string& gateway,
516 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530517{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530518 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530519 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530520 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
521
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530522 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530523 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530524 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800525 objectPath /=
526 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530527 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530528}
529
William A. Kennington III08505792019-01-30 16:00:04 -0800530std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500531 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800532{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530533 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800534 objectPath /= objPath;
535 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500536 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800537 return objectPath.string();
538}
539
Patrick Williams6aef7692021-05-01 06:39:41 -0500540bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700541{
Patrick Williams6aef7692021-05-01 06:39:41 -0500542 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700543 {
544 return value;
545 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500546 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700547
548 writeConfigurationFile();
549 manager.reloadConfigs();
550
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700551 return value;
552}
553
Patrick Williams6aef7692021-05-01 06:39:41 -0500554EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530555{
Patrick Williams6aef7692021-05-01 06:39:41 -0500556 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530557 {
558 return value;
559 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500560 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700561
562 writeConfigurationFile();
563 manager.reloadConfigs();
564
Ratan Gupta87c13982017-06-15 09:27:27 +0530565 return value;
566}
567
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800568bool EthernetInterface::linkUp() const
569{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800570 bool value = EthernetInterfaceIntf::linkUp();
571
William A. Kennington III05368f12021-05-13 18:40:47 -0700572 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800573 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800574 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800575 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800576 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800577 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
578 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800579 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800580 {
581 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800582 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800583 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700584 return value;
585}
586
Tejas Patil2c0fc562021-08-03 19:13:46 +0530587size_t EthernetInterface::mtu() const
588{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530589 size_t value = EthernetInterfaceIntf::mtu();
590
Tejas Patil2c0fc562021-08-03 19:13:46 +0530591 ifreq ifr = {};
592 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800593 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530594 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800595 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530596 value = ifr.ifr_mtu;
597 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800598 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530599 {
600 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800601 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530602 }
603 return value;
604}
605
606size_t EthernetInterface::mtu(size_t value)
607{
608 if (value == EthernetInterfaceIntf::mtu())
609 {
610 return value;
611 }
612 else if (value == 0)
613 {
614 return EthernetInterfaceIntf::mtu();
615 }
616
Tejas Patil2c0fc562021-08-03 19:13:46 +0530617 ifreq ifr = {};
618 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
619 ifr.ifr_mtu = value;
620
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800621 try
622 {
623 getIFSock().ioctl(SIOCSIFMTU, &ifr);
624 }
625 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530626 {
627 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
628 entry("ERROR=%s", strerror(errno)));
629 return EthernetInterfaceIntf::mtu();
630 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530631
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800632 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530633 return value;
634}
635
William A. Kennington III26275a32021-07-13 20:32:42 -0700636bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700637{
William A. Kennington III26275a32021-07-13 20:32:42 -0700638 constexpr auto svc = "org.freedesktop.network1";
639 constexpr auto intf = "org.freedesktop.network1.Link";
640 constexpr auto prop = "AdministrativeState";
641 char* rpath;
642 sd_bus_path_encode("/org/freedesktop/network1/link",
643 std::to_string(ifIndex()).c_str(), &rpath);
644 std::string path(rpath);
645 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700646
William A. Kennington III26275a32021-07-13 20:32:42 -0700647 // Store / Parser for the AdministrativeState return value
648 std::optional<bool> ret;
649 auto cb = [&](const std::string& state) {
650 if (state != "initialized")
651 {
652 ret = state != "unmanaged";
653 }
654 };
655
656 // Build a matcher before making the property call to ensure we
657 // can eventually get the value.
658 sdbusplus::bus::match::match match(
659 bus,
660 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
661 "'PropertiesChanged',arg0='{}',",
662 svc, path, PROPERTY_INTERFACE, intf)
663 .c_str(),
664 [&](sdbusplus::message::message& m) {
665 std::string intf;
666 std::unordered_map<std::string, std::variant<std::string>> values;
667 try
668 {
669 m.read(intf, values);
670 auto it = values.find(prop);
671 // Ignore properties that aren't AdministrativeState
672 if (it != values.end())
673 {
674 cb(std::get<std::string>(it->second));
675 }
676 }
677 catch (const std::exception& e)
678 {
679 log<level::ERR>(
680 fmt::format(
681 "AdministrativeState match parsing failed on {}: {}",
682 interfaceName(), e.what())
683 .c_str(),
684 entry("INTERFACE=%s", interfaceName().c_str()),
685 entry("ERROR=%s", e.what()));
686 }
687 });
688
689 // Actively call for the value in case the interface is already configured
690 auto method =
691 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
692 method.append(intf, prop);
693 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700694 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700695 auto reply = bus.call(method);
696 std::variant<std::string> state;
697 reply.read(state);
698 cb(std::get<std::string>(state));
699 }
700 catch (const std::exception& e)
701 {
702 log<level::ERR>(
703 fmt::format("Failed to get AdministrativeState on {}: {}",
704 interfaceName(), e.what())
705 .c_str(),
706 entry("INTERFACE=%s", interfaceName().c_str()),
707 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700708 }
709
William A. Kennington III26275a32021-07-13 20:32:42 -0700710 // The interface is not yet configured by systemd-networkd, wait until it
711 // signals us a valid state.
712 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700713 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700714 bus.wait();
715 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700716 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700717
718 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700719}
720
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800721static void setNICAdminState(const char* intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700722{
723 ifreq ifr = {};
724 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800725 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700726
727 ifr.ifr_flags &= ~IFF_UP;
728 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800729 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700730}
731
Patrick Williams6aef7692021-05-01 06:39:41 -0500732bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700733{
Patrick Williams6aef7692021-05-01 06:39:41 -0500734 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700735 {
736 return value;
737 }
738
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800739 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700740 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800741 if (!value)
742 {
743 // We only need to bring down the interface, networkd will always bring
744 // up managed interfaces
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800745 manager.addReloadPreHook([ifname = interfaceName()]() {
746 setNICAdminState(ifname.c_str(), false);
747 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800748 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700749 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800750
751 return value;
752}
753
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530754ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530755{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530756 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
757 return EthernetInterfaceIntf::nameservers();
758}
759
760ServerList EthernetInterface::staticNameServers(ServerList value)
761{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530762 for (const auto& nameserverip : value)
763 {
764 if (!isValidIP(AF_INET, nameserverip) &&
765 !isValidIP(AF_INET6, nameserverip))
766 {
767 log<level::ERR>("Not a valid IP address"),
768 entry("ADDRESS=%s", nameserverip.c_str());
769 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530770 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530771 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
772 }
773 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530774 try
775 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530776 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700777
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530778 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700779 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530780 }
Patrick Williams5758db32021-10-06 12:29:22 -0500781 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530782 {
783 log<level::ERR>("Exception processing DNS entries");
784 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530785 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530786}
787
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530788void EthernetInterface::loadNameServers()
789{
790 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
791 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
792}
793
794ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530795{
796 fs::path confPath = manager.getConfDir();
797
798 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500799 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530800 confPath /= fileName;
801 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530802 config::Parser parser(confPath.string());
803 auto rc = config::ReturnCode::SUCCESS;
804
805 std::tie(rc, servers) = parser.getValues("Network", "DNS");
806 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530807 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530808 log<level::DEBUG>("Unable to get the value for network[DNS]",
809 entry("RC=%d", rc));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530810 }
811 return servers;
812}
813
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530814ServerList EthernetInterface::getNameServerFromResolvd()
815{
816 ServerList servers;
817 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
818
819 /*
820 The DNS property under org.freedesktop.resolve1.Link interface contains
821 an array containing all DNS servers currently used by resolved. It
822 contains similar information as the DNS server data written to
823 /run/systemd/resolve/resolv.conf.
824
825 Each structure in the array consists of a numeric network interface index,
826 an address family, and a byte array containing the DNS server address
827 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
828 The array contains DNS servers configured system-wide, including those
829 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
830 /etc/systemd/resolved.conf, as well as per-interface DNS server
831 information either retrieved from systemd-networkd or configured by
832 external software via SetLinkDNS().
833 */
834
835 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
836 std::variant<type> name; // Variable to capture the DNS property
837 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
838 PROPERTY_INTERFACE, METHOD_GET);
839
840 method.append(RESOLVED_INTERFACE, "DNS");
841 auto reply = bus.call(method);
842
843 try
844 {
845 reply.read(name);
846 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500847 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530848 {
849 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
850 }
851 auto tupleVector = std::get_if<type>(&name);
852 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
853 {
Alexander Filippov983da552021-02-08 15:26:54 +0300854 int addressFamily = std::get<0>(*i);
855 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
856
857 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530858 {
Alexander Filippov983da552021-02-08 15:26:54 +0300859 case AF_INET:
860 if (ipaddress.size() == sizeof(struct in_addr))
861 {
862 servers.push_back(toString(
863 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
864 }
865 else
866 {
867 log<level::ERR>(
868 "Invalid data recived from Systemd-Resolved");
869 }
870 break;
871
872 case AF_INET6:
873 if (ipaddress.size() == sizeof(struct in6_addr))
874 {
875 servers.push_back(toString(
876 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
877 }
878 else
879 {
880 log<level::ERR>(
881 "Invalid data recived from Systemd-Resolved");
882 }
883 break;
884
885 default:
886 log<level::ERR>(
887 "Unsupported address family in DNS from Systemd-Resolved");
888 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530889 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530890 }
891 return servers;
892}
893
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530894void EthernetInterface::loadVLAN(VlanId id)
895{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500896 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530897 std::string path = objPath;
898 path += "_" + std::to_string(id);
899
Johnathan Mantey817012a2020-01-30 15:07:39 -0800900 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500901 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530902 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500903 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800904 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530905
Gunnar Mills57d9c502018-09-14 14:42:34 -0500906 // Fetch the ip address from the system
907 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530908 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800909 vlanIntf->createStaticNeighborObjects();
Jiaqing Zhaocc5a6702021-12-31 14:58:55 +0800910 vlanIntf->loadNameServers();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530911
912 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
913 std::move(vlanIntf));
914}
915
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700916ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530917{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500918 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800919
920 if (this->vlanInterfaces.count(vlanInterfaceName))
921 {
922 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
923 elog<InvalidArgument>(
924 Argument::ARGUMENT_NAME("VLANId"),
925 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
926 }
927
Ratan Gupta5978dd12017-07-25 13:47:13 +0530928 std::string path = objPath;
929 path += "_" + std::to_string(id);
930
Patrick Williams6aef7692021-05-01 06:39:41 -0500931 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530932 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530933 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800934 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500935 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530936
937 // write the device file for the vlan interface.
938 vlanIntf->writeDeviceFile();
939
Gunnar Mills57d9c502018-09-14 14:42:34 -0500940 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700941
942 writeConfigurationFile();
943 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700944
945 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530946}
Ratan Gupta2b106532017-07-25 16:05:02 +0530947
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700948bool EthernetInterface::getIPv6AcceptRAFromConf()
949{
950 fs::path confPath = manager.getConfDir();
951
952 std::string fileName = systemd::config::networkFilePrefix +
953 interfaceName() + systemd::config::networkFileSuffix;
954 confPath /= fileName;
955 config::ValueList values;
956 config::Parser parser(confPath.string());
957 auto rc = config::ReturnCode::SUCCESS;
958 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
959 if (rc != config::ReturnCode::SUCCESS)
960 {
961 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
962 entry("rc=%d", rc));
963 return false;
964 }
965 return (values[0] == "true");
966}
967
Ratan Gupta497c0c92017-08-22 19:15:59 +0530968ServerList EthernetInterface::getNTPServersFromConf()
969{
970 fs::path confPath = manager.getConfDir();
971
Gunnar Mills57d9c502018-09-14 14:42:34 -0500972 std::string fileName = systemd::config::networkFilePrefix +
973 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +0530974 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +0530975
Ratan Gupta497c0c92017-08-22 19:15:59 +0530976 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530977 config::Parser parser(confPath.string());
978 auto rc = config::ReturnCode::SUCCESS;
979
980 std::tie(rc, servers) = parser.getValues("Network", "NTP");
981 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530982 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530983 log<level::DEBUG>("Unable to get the value for Network[NTP]",
984 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530985 }
Ratan Guptac27170a2017-11-22 15:44:42 +0530986
Ratan Gupta497c0c92017-08-22 19:15:59 +0530987 return servers;
988}
989
Patrick Williams6aef7692021-05-01 06:39:41 -0500990ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530991{
Patrick Williams6aef7692021-05-01 06:39:41 -0500992 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530993
994 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700995 manager.reloadConfigs();
996
Ratan Gupta497c0c92017-08-22 19:15:59 +0530997 return ntpServers;
998}
Ratan Gupta2b106532017-07-25 16:05:02 +0530999// Need to merge the below function with the code which writes the
1000// config file during factory reset.
1001// TODO openbmc/openbmc#1751
1002
1003void EthernetInterface::writeConfigurationFile()
1004{
1005 // write all the static ip address in the systemd-network conf file
1006
1007 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301008 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301009
1010 // if there is vlan interafce then write the configuration file
1011 // for vlan also.
1012
Gunnar Mills57d9c502018-09-14 14:42:34 -05001013 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301014 {
1015 intf.second->writeConfigurationFile();
1016 }
1017
Ratan Gupta2b106532017-07-25 16:05:02 +05301018 fs::path confPath = manager.getConfDir();
1019
Gunnar Mills57d9c502018-09-14 14:42:34 -05001020 std::string fileName = systemd::config::networkFilePrefix +
1021 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301022 confPath /= fileName;
1023 std::fstream stream;
1024
1025 stream.open(confPath.c_str(), std::fstream::out);
1026 if (!stream.is_open())
1027 {
1028 log<level::ERR>("Unable to open the file",
1029 entry("FILE=%s", confPath.c_str()));
1030 elog<InternalFailure>();
1031 }
1032
1033 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001034 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301035 stream << "Name=" << interfaceName() << "\n";
1036
1037 auto addrs = getAddresses();
1038
William A. Kennington III15787212019-04-23 19:18:01 -07001039 // Write the link section
1040 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001041 auto mac = MacAddressIntf::macAddress();
Johnathan Mantey609c12d2022-02-03 09:23:09 -08001042#ifdef PERSIST_MAC
William A. Kennington III15787212019-04-23 19:18:01 -07001043 if (!mac.empty())
1044 {
1045 stream << "MACAddress=" << mac << "\n";
1046 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -08001047#endif
William A. Kennington III15787212019-04-23 19:18:01 -07001048
Patrick Williams6aef7692021-05-01 06:39:41 -05001049 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001050 {
1051 stream << "Unmanaged=yes\n";
1052 }
1053
Ratan Gupta2b106532017-07-25 16:05:02 +05301054 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001055 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001056#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001057 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001058#else
1059 stream << "LinkLocalAddressing=no\n";
1060#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001061 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001062 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301063
1064 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001065 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301066 {
1067 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001068 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301069 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301070 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001071 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301072 {
1073 stream << "NTP=" << ntp << "\n";
1074 }
1075
1076 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301077 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301078 {
1079 stream << "DNS=" << dns << "\n";
1080 }
1081
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001082 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001083 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001084 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001085
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001086 stream << "[IPv6AcceptRA]\n";
1087 stream << "DHCPv6Client=";
1088 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Johnathan Manteyb353ba02021-12-09 12:27:32 -08001089 stream << "\n";
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001090
Johnathan Mantey817012a2020-01-30 15:07:39 -08001091 // Static IP addresses
1092 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301093 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001094 if (originIsManuallyAssigned(addr.second->origin()) &&
1095 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001096 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001097 // Process all static addresses
1098 std::string address = addr.second->address() + "/" +
1099 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301100
Johnathan Mantey817012a2020-01-30 15:07:39 -08001101 // build the address entries. Do not use [Network] shortcuts to
1102 // insert address entries.
1103 stream << "[Address]\n";
1104 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001105 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001106 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001107
Lei YUcb2d4082021-08-12 15:26:49 +08001108 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001109 {
Lei YUcb2d4082021-08-12 15:26:49 +08001110 auto gateway = EthernetInterfaceIntf::defaultGateway();
1111 if (!gateway.empty())
1112 {
1113 stream << "[Route]\n";
1114 stream << "Gateway=" << gateway << "\n";
1115 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001116 }
1117
Lei YUcb2d4082021-08-12 15:26:49 +08001118 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001119 {
Lei YUcb2d4082021-08-12 15:26:49 +08001120 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1121 if (!gateway6.empty())
1122 {
1123 stream << "[Route]\n";
1124 stream << "Gateway=" << gateway6 << "\n";
1125 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001126 }
1127
William A. Kennington III08505792019-01-30 16:00:04 -08001128 // Write the neighbor sections
1129 for (const auto& neighbor : staticNeighbors)
1130 {
1131 stream << "[Neighbor]"
1132 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001133 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1134 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001135 }
1136
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001137 // Write the dhcp section irrespective of whether DHCP is enabled or not
1138 writeDHCPSection(stream);
1139
Ratan Gupta2b106532017-07-25 16:05:02 +05301140 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301141}
1142
1143void EthernetInterface::writeDHCPSection(std::fstream& stream)
1144{
1145 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301146 // write the dhcp section
1147 stream << "[DHCP]\n";
1148
1149 // Hardcoding the client identifier to mac, to address below issue
1150 // https://github.com/openbmc/openbmc/issues/1280
1151 stream << "ClientIdentifier=mac\n";
1152 if (manager.getDHCPConf())
1153 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001154 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301155 stream << "UseDNS="s + value + "\n";
sunharisdd1e5922022-03-31 01:49:21 -05001156 stream << "UseDomains="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301157
Patrick Williams6aef7692021-05-01 06:39:41 -05001158 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301159 stream << "UseNTP="s + value + "\n";
1160
1161 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1162 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001163
1164 value =
1165 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1166 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301167 }
1168}
1169
Patrick Williams6aef7692021-05-01 06:39:41 -05001170std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301171{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001172 ether_addr newMAC;
1173 try
1174 {
1175 newMAC = mac_address::fromString(value);
1176 }
Patrick Williams5758db32021-10-06 12:29:22 -05001177 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001178 {
1179 log<level::ERR>("MACAddress is not valid.",
1180 entry("MAC=%s", value.c_str()));
1181 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1182 Argument::ARGUMENT_VALUE(value.c_str()));
1183 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001184 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301185 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001186 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001187 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001188 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1189 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301190 }
1191
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001192 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001193 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001194
William A. Kennington III1137a972019-04-20 20:49:58 -07001195 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001196 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001197 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301198 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001199 // Update everything that depends on the MAC value
1200 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301201 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001202 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301203 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001204 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301205
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001206 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001207 manager.addReloadPreHook([interface]() {
1208 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001209 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001210 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001211 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301212 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001213
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001214#ifdef HAVE_UBOOT_ENV
1215 // Ensure that the valid address is stored in the u-boot-env
1216 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1217 if (envVar)
1218 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001219 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1220 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1221 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1222 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001223 }
1224#endif // HAVE_UBOOT_ENV
1225
William A. Kennington III1137a972019-04-20 20:49:58 -07001226 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301227}
1228
Ratan Guptae9c9b812017-09-22 17:15:37 +05301229void EthernetInterface::deleteAll()
1230{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301231 // clear all the ip on the interface
1232 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001233
1234 writeConfigurationFile();
1235 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301236}
1237
Ravi Tejaa5a09442020-07-17 00:57:33 -05001238std::string EthernetInterface::defaultGateway(std::string gateway)
1239{
1240 auto gw = EthernetInterfaceIntf::defaultGateway();
1241 if (gw == gateway)
1242 {
1243 return gw;
1244 }
1245
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001246 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001247 {
1248 log<level::ERR>("Not a valid v4 Gateway",
1249 entry("GATEWAY=%s", gateway.c_str()));
1250 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1251 Argument::ARGUMENT_VALUE(gateway.c_str()));
1252 }
1253 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001254
1255 writeConfigurationFile();
1256 manager.reloadConfigs();
1257
Ravi Tejaa5a09442020-07-17 00:57:33 -05001258 return gw;
1259}
1260
1261std::string EthernetInterface::defaultGateway6(std::string gateway)
1262{
1263 auto gw = EthernetInterfaceIntf::defaultGateway6();
1264 if (gw == gateway)
1265 {
1266 return gw;
1267 }
1268
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001269 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001270 {
1271 log<level::ERR>("Not a valid v6 Gateway",
1272 entry("GATEWAY=%s", gateway.c_str()));
1273 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1274 Argument::ARGUMENT_VALUE(gateway.c_str()));
1275 }
1276 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001277
1278 writeConfigurationFile();
1279 manager.reloadConfigs();
1280
Ravi Tejaa5a09442020-07-17 00:57:33 -05001281 return gw;
1282}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001283} // namespace network
1284} // namespace phosphor