blob: 52f68d1a9f9b5a7c18fd42b7288dd46a99545494 [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 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 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 Gupta6dec3902017-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 Gupta6dec3902017-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 Gupta6dec3902017-08-20 15:28:12 +0530778 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700779 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530780 }
Patrick Williams5758db32021-10-06 12:29:22 -0500781 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-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 Gupta6dec3902017-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 Gupta6dec3902017-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 Gupta6dec3902017-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 Gupta6dec3902017-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 Gupta6dec3902017-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);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530919 std::string path = objPath;
920 path += "_" + std::to_string(id);
921
Patrick Williams6aef7692021-05-01 06:39:41 -0500922 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530923 // VLAN interface can inherit.
924
Ratan Gupta5978dd12017-07-25 13:47:13 +0530925 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800926 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500927 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530928
929 // write the device file for the vlan interface.
930 vlanIntf->writeDeviceFile();
931
Gunnar Mills57d9c502018-09-14 14:42:34 -0500932 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700933
934 writeConfigurationFile();
935 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700936
937 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530938}
Ratan Gupta2b106532017-07-25 16:05:02 +0530939
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700940bool EthernetInterface::getIPv6AcceptRAFromConf()
941{
942 fs::path confPath = manager.getConfDir();
943
944 std::string fileName = systemd::config::networkFilePrefix +
945 interfaceName() + systemd::config::networkFileSuffix;
946 confPath /= fileName;
947 config::ValueList values;
948 config::Parser parser(confPath.string());
949 auto rc = config::ReturnCode::SUCCESS;
950 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
951 if (rc != config::ReturnCode::SUCCESS)
952 {
953 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
954 entry("rc=%d", rc));
955 return false;
956 }
957 return (values[0] == "true");
958}
959
Ratan Gupta497c0c92017-08-22 19:15:59 +0530960ServerList EthernetInterface::getNTPServersFromConf()
961{
962 fs::path confPath = manager.getConfDir();
963
Gunnar Mills57d9c502018-09-14 14:42:34 -0500964 std::string fileName = systemd::config::networkFilePrefix +
965 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +0530966 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +0530967
Ratan Gupta497c0c92017-08-22 19:15:59 +0530968 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530969 config::Parser parser(confPath.string());
970 auto rc = config::ReturnCode::SUCCESS;
971
972 std::tie(rc, servers) = parser.getValues("Network", "NTP");
973 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530974 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530975 log<level::DEBUG>("Unable to get the value for Network[NTP]",
976 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530977 }
Ratan Guptac27170a2017-11-22 15:44:42 +0530978
Ratan Gupta497c0c92017-08-22 19:15:59 +0530979 return servers;
980}
981
Patrick Williams6aef7692021-05-01 06:39:41 -0500982ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530983{
Patrick Williams6aef7692021-05-01 06:39:41 -0500984 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530985
986 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700987 manager.reloadConfigs();
988
Ratan Gupta497c0c92017-08-22 19:15:59 +0530989 return ntpServers;
990}
Ratan Gupta2b106532017-07-25 16:05:02 +0530991// Need to merge the below function with the code which writes the
992// config file during factory reset.
993// TODO openbmc/openbmc#1751
994
995void EthernetInterface::writeConfigurationFile()
996{
997 // write all the static ip address in the systemd-network conf file
998
999 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301000 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301001
1002 // if there is vlan interafce then write the configuration file
1003 // for vlan also.
1004
Gunnar Mills57d9c502018-09-14 14:42:34 -05001005 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301006 {
1007 intf.second->writeConfigurationFile();
1008 }
1009
Ratan Gupta2b106532017-07-25 16:05:02 +05301010 fs::path confPath = manager.getConfDir();
1011
Gunnar Mills57d9c502018-09-14 14:42:34 -05001012 std::string fileName = systemd::config::networkFilePrefix +
1013 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301014 confPath /= fileName;
1015 std::fstream stream;
1016
1017 stream.open(confPath.c_str(), std::fstream::out);
1018 if (!stream.is_open())
1019 {
1020 log<level::ERR>("Unable to open the file",
1021 entry("FILE=%s", confPath.c_str()));
1022 elog<InternalFailure>();
1023 }
1024
1025 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001026 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301027 stream << "Name=" << interfaceName() << "\n";
1028
1029 auto addrs = getAddresses();
1030
William A. Kennington III15787212019-04-23 19:18:01 -07001031 // Write the link section
1032 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001033 auto mac = MacAddressIntf::macAddress();
Johnathan Mantey609c12d2022-02-03 09:23:09 -08001034#ifdef PERSIST_MAC
William A. Kennington III15787212019-04-23 19:18:01 -07001035 if (!mac.empty())
1036 {
1037 stream << "MACAddress=" << mac << "\n";
1038 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -08001039#endif
William A. Kennington III15787212019-04-23 19:18:01 -07001040
Patrick Williams6aef7692021-05-01 06:39:41 -05001041 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001042 {
1043 stream << "Unmanaged=yes\n";
1044 }
1045
Ratan Gupta2b106532017-07-25 16:05:02 +05301046 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001047 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001048#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001049 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001050#else
1051 stream << "LinkLocalAddressing=no\n";
1052#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001053 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001054 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301055
1056 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001057 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301058 {
1059 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001060 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301061 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301062 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001063 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301064 {
1065 stream << "NTP=" << ntp << "\n";
1066 }
1067
1068 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301069 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301070 {
1071 stream << "DNS=" << dns << "\n";
1072 }
1073
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001074 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001075 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001076 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001077
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001078 stream << "[IPv6AcceptRA]\n";
1079 stream << "DHCPv6Client=";
1080 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Johnathan Manteyb353ba02021-12-09 12:27:32 -08001081 stream << "\n";
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001082
Johnathan Mantey817012a2020-01-30 15:07:39 -08001083 // Static IP addresses
1084 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301085 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001086 if (originIsManuallyAssigned(addr.second->origin()) &&
1087 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001088 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001089 // Process all static addresses
1090 std::string address = addr.second->address() + "/" +
1091 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301092
Johnathan Mantey817012a2020-01-30 15:07:39 -08001093 // build the address entries. Do not use [Network] shortcuts to
1094 // insert address entries.
1095 stream << "[Address]\n";
1096 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001097 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001098 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001099
Lei YUcb2d4082021-08-12 15:26:49 +08001100 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001101 {
Lei YUcb2d4082021-08-12 15:26:49 +08001102 auto gateway = EthernetInterfaceIntf::defaultGateway();
1103 if (!gateway.empty())
1104 {
1105 stream << "[Route]\n";
1106 stream << "Gateway=" << gateway << "\n";
1107 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001108 }
1109
Lei YUcb2d4082021-08-12 15:26:49 +08001110 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001111 {
Lei YUcb2d4082021-08-12 15:26:49 +08001112 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1113 if (!gateway6.empty())
1114 {
1115 stream << "[Route]\n";
1116 stream << "Gateway=" << gateway6 << "\n";
1117 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001118 }
1119
William A. Kennington III08505792019-01-30 16:00:04 -08001120 // Write the neighbor sections
1121 for (const auto& neighbor : staticNeighbors)
1122 {
1123 stream << "[Neighbor]"
1124 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001125 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1126 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001127 }
1128
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001129 // Write the dhcp section irrespective of whether DHCP is enabled or not
1130 writeDHCPSection(stream);
1131
Ratan Gupta2b106532017-07-25 16:05:02 +05301132 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301133}
1134
1135void EthernetInterface::writeDHCPSection(std::fstream& stream)
1136{
1137 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301138 // write the dhcp section
1139 stream << "[DHCP]\n";
1140
1141 // Hardcoding the client identifier to mac, to address below issue
1142 // https://github.com/openbmc/openbmc/issues/1280
1143 stream << "ClientIdentifier=mac\n";
1144 if (manager.getDHCPConf())
1145 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001146 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301147 stream << "UseDNS="s + value + "\n";
1148
Patrick Williams6aef7692021-05-01 06:39:41 -05001149 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301150 stream << "UseNTP="s + value + "\n";
1151
1152 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1153 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001154
1155 value =
1156 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1157 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301158 }
1159}
1160
Patrick Williams6aef7692021-05-01 06:39:41 -05001161std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301162{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001163 ether_addr newMAC;
1164 try
1165 {
1166 newMAC = mac_address::fromString(value);
1167 }
Patrick Williams5758db32021-10-06 12:29:22 -05001168 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001169 {
1170 log<level::ERR>("MACAddress is not valid.",
1171 entry("MAC=%s", value.c_str()));
1172 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1173 Argument::ARGUMENT_VALUE(value.c_str()));
1174 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001175 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301176 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001177 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001178 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001179 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1180 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301181 }
1182
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001183 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001184 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001185
William A. Kennington III1137a972019-04-20 20:49:58 -07001186 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001187 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001188 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301189 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001190 // Update everything that depends on the MAC value
1191 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301192 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001193 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301194 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001195 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301196
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001197 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001198 manager.addReloadPreHook([interface]() {
1199 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001200 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001201 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001202 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301203 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001204
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001205#ifdef HAVE_UBOOT_ENV
1206 // Ensure that the valid address is stored in the u-boot-env
1207 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1208 if (envVar)
1209 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001210 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1211 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1212 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1213 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001214 }
1215#endif // HAVE_UBOOT_ENV
1216
William A. Kennington III1137a972019-04-20 20:49:58 -07001217 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301218}
1219
Ratan Guptae9c9b812017-09-22 17:15:37 +05301220void EthernetInterface::deleteAll()
1221{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301222 // clear all the ip on the interface
1223 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001224
1225 writeConfigurationFile();
1226 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301227}
1228
Ravi Tejaa5a09442020-07-17 00:57:33 -05001229std::string EthernetInterface::defaultGateway(std::string gateway)
1230{
1231 auto gw = EthernetInterfaceIntf::defaultGateway();
1232 if (gw == gateway)
1233 {
1234 return gw;
1235 }
1236
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001237 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001238 {
1239 log<level::ERR>("Not a valid v4 Gateway",
1240 entry("GATEWAY=%s", gateway.c_str()));
1241 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1242 Argument::ARGUMENT_VALUE(gateway.c_str()));
1243 }
1244 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001245
1246 writeConfigurationFile();
1247 manager.reloadConfigs();
1248
Ravi Tejaa5a09442020-07-17 00:57:33 -05001249 return gw;
1250}
1251
1252std::string EthernetInterface::defaultGateway6(std::string gateway)
1253{
1254 auto gw = EthernetInterfaceIntf::defaultGateway6();
1255 if (gw == gateway)
1256 {
1257 return gw;
1258 }
1259
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001260 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001261 {
1262 log<level::ERR>("Not a valid v6 Gateway",
1263 entry("GATEWAY=%s", gateway.c_str()));
1264 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1265 Argument::ARGUMENT_VALUE(gateway.c_str()));
1266 }
1267 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001268
1269 writeConfigurationFile();
1270 manager.reloadConfigs();
1271
Ravi Tejaa5a09442020-07-17 00:57:33 -05001272 return gw;
1273}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001274} // namespace network
1275} // namespace phosphor