blob: 711e3b50e8f1fb496c4d5ad399d56363a92722df [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#include <netinet/in.h>
17#include <sys/ioctl.h>
18#include <sys/socket.h>
19#include <unistd.h>
20
Ratan Gupta82549cc2017-04-21 08:45:23 +053021#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053022#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070024#include <phosphor-logging/elog-errors.hpp>
25#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070026#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053027#include <sstream>
William A. Kennington III12beaad2020-06-13 19:30:41 -070028#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053029#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070030#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070031#include <unordered_map>
32#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070033#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053034
Ratan Gupta91a99cc2017-04-14 16:32:09 +053035namespace phosphor
36{
37namespace network
38{
39
40using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053041using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053042using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
43using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050044using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053045constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
46constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
47constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
48constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
49constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053050
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080051struct EthernetIntfSocket
52{
53 EthernetIntfSocket(int domain, int type, int protocol)
54 {
55 if ((sock = socket(domain, type, protocol)) < 0)
56 {
57 log<level::ERR>("socket creation failed:",
58 entry("ERROR=%s", strerror(errno)));
59 }
60 }
61
62 ~EthernetIntfSocket()
63 {
64 if (sock >= 0)
65 {
66 close(sock);
67 }
68 }
69
70 int sock{-1};
71};
72
Johnathan Mantey817012a2020-01-30 15:07:39 -080073std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
74 {EthernetInterface::DHCPConf::both, "true"},
75 {EthernetInterface::DHCPConf::v4, "ipv4"},
76 {EthernetInterface::DHCPConf::v6, "ipv6"},
77 {EthernetInterface::DHCPConf::none, "false"}};
78
Ratan Gupta91a99cc2017-04-14 16:32:09 +053079EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
80 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080081 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070082 bool emitSignal,
83 std::optional<bool> enabled) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050084 Ifaces(bus, objPath.c_str(), true),
85 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053086{
87 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053088 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053089 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050090 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
91 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070092 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070093 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
94 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050095 std::string defaultGateway;
96 std::string defaultGateway6;
97
William A. Kennington IIIe0564842021-10-23 16:02:22 -070098 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050099 {
100 if (gateway.first == intfName)
101 {
102 defaultGateway = gateway.second;
103 break;
104 }
105 }
106
William A. Kennington IIIe0564842021-10-23 16:02:22 -0700107 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500108 {
109 if (gateway6.first == intfName)
110 {
111 defaultGateway6 = gateway6.second;
112 break;
113 }
114 }
115
116 EthernetInterfaceIntf::defaultGateway(defaultGateway);
117 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530118 // Don't get the mac address from the system as the mac address
119 // would be same as parent interface.
120 if (intfName.find(".") == std::string::npos)
121 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500122 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530123 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500124 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
Ratan Gupta613a0122020-04-24 15:18:53 +0530125
126 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530127 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530128
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700129#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700130 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
131
132 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
133 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800134#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530135
Ratan Gupta29b0e432017-05-25 12:51:40 +0530136 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530137 if (emitSignal)
138 {
139 this->emit_object_added();
140 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530141}
142
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800143static IP::Protocol convertFamily(int family)
144{
145 switch (family)
146 {
147 case AF_INET:
148 return IP::Protocol::IPv4;
149 case AF_INET6:
150 return IP::Protocol::IPv6;
151 }
152
153 throw std::invalid_argument("Bad address family");
154}
155
Johnathan Mantey817012a2020-01-30 15:07:39 -0800156void EthernetInterface::disableDHCP(IP::Protocol protocol)
157{
Patrick Williams6aef7692021-05-01 06:39:41 -0500158 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800159 if (dhcpState == EthernetInterface::DHCPConf::both)
160 {
161 if (protocol == IP::Protocol::IPv4)
162 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500163 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800164 }
165 else if (protocol == IP::Protocol::IPv6)
166 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500167 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800168 }
169 }
170 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
171 (protocol == IP::Protocol::IPv4))
172 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500173 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800174 }
175 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
176 (protocol == IP::Protocol::IPv6))
177 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500178 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800179 }
180}
181
William A. Kennington III24957b92021-12-03 13:59:19 -0800182bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800183{
William A. Kennington III24957b92021-12-03 13:59:19 -0800184 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
185 return cur == EthernetInterface::DHCPConf::both ||
186 (family == IP::Protocol::IPv6 &&
187 cur == EthernetInterface::DHCPConf::v6) ||
188 (family == IP::Protocol::IPv4 &&
189 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800190}
191
192bool EthernetInterface::dhcpToBeEnabled(IP::Protocol family,
193 const std::string& nextDHCPState)
194{
195 return ((nextDHCPState == "true") ||
196 ((nextDHCPState == "ipv6") && (family == IP::Protocol::IPv6)) ||
197 ((nextDHCPState == "ipv4") && (family == IP::Protocol::IPv4)));
198}
199
200bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
201{
202 return (
203#ifdef LINK_LOCAL_AUTOCONFIGURATION
204 (origin == IP::AddressOrigin::Static)
205#else
206 (origin == IP::AddressOrigin::Static ||
207 origin == IP::AddressOrigin::LinkLocal)
208#endif
209
210 );
211}
212
Ratan Gupta87c13982017-06-15 09:27:27 +0530213void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530214{
Ratan Gupta87c13982017-06-15 09:27:27 +0530215 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530216
Ratan Gupta87c13982017-06-15 09:27:27 +0530217 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530218
Ratan Gupta6a387c12017-08-03 13:26:19 +0530219 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530220 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800221 IP::Protocol addressType = convertFamily(addr.addrType);
222 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800223 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530224 {
225 origin = IP::AddressOrigin::DHCP;
226 }
William A. Kennington III16893802019-01-30 16:01:01 -0800227 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530228 {
229 origin = IP::AddressOrigin::LinkLocal;
230 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700231 // Obsolete parameter
232 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530233
Gunnar Mills57d9c502018-09-14 14:42:34 -0500234 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800235 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530236
Lei YU7233c582021-04-08 14:39:43 +0800237 this->addrs.insert_or_assign(
238 addr.ipaddress,
239 std::make_shared<phosphor::network::IPAddress>(
240 bus, ipAddressObjectPath.c_str(), *this, addressType,
241 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530242 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530243}
244
William A. Kennington III08505792019-01-30 16:00:04 -0800245void EthernetInterface::createStaticNeighborObjects()
246{
247 staticNeighbors.clear();
248
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700249 NeighborFilter filter;
250 filter.interface = ifIndex();
251 filter.state = NUD_PERMANENT;
252 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800253 for (const auto& neighbor : neighbors)
254 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700255 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800256 {
257 continue;
258 }
259 std::string ip = toString(neighbor.address);
260 std::string mac = mac_address::toString(*neighbor.mac);
261 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
262 staticNeighbors.emplace(ip,
263 std::make_shared<phosphor::network::Neighbor>(
264 bus, objectPath.c_str(), *this, ip, mac,
265 Neighbor::State::Permanent));
266 }
267}
268
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700269unsigned EthernetInterface::ifIndex() const
270{
271 unsigned idx = if_nametoindex(interfaceName().c_str());
272 if (idx == 0)
273 {
274 throw std::system_error(errno, std::generic_category(),
275 "if_nametoindex");
276 }
277 return idx;
278}
279
Patrick Williams6aef7692021-05-01 06:39:41 -0500280ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500281 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530282{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800283 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530284 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530285 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500286 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800287 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500288 }
289
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500290 IP::AddressOrigin origin = IP::AddressOrigin::Static;
291
292 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
293
294 if (!isValidIP(addressFamily, ipaddress))
295 {
296 log<level::ERR>("Not a valid IP address"),
297 entry("ADDRESS=%s", ipaddress.c_str());
298 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
299 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
300 }
301
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700302 // Gateway is an obsolete parameter
303 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500304
305 if (!isValidPrefix(addressFamily, prefixLength))
306 {
307 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700308 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500309 elog<InvalidArgument>(
310 Argument::ARGUMENT_NAME("prefixLength"),
311 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530312 }
313
Gunnar Mills57d9c502018-09-14 14:42:34 -0500314 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800315 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800316 this->addrs.insert_or_assign(ipaddress,
317 std::make_shared<phosphor::network::IPAddress>(
318 bus, objectPath.c_str(), *this, protType,
319 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530320
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700321 writeConfigurationFile();
322 manager.reloadConfigs();
323
raviteja-bce379562019-03-28 05:59:36 -0500324 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530325}
326
Patrick Williams6aef7692021-05-01 06:39:41 -0500327ObjectPath EthernetInterface::neighbor(std::string ipAddress,
328 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800329{
Patrick Williams6aef7692021-05-01 06:39:41 -0500330 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800331 {
332 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500333 entry("ADDRESS=%s", ipAddress.c_str()));
334 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
335 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800336 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500337 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800338 {
339 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500340 entry("MACADDRESS=%s", ipAddress.c_str()));
341 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
342 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800343 }
344
345 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500346 generateStaticNeighborObjectPath(ipAddress, macAddress);
347 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800348 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500349 bus, objectPath.c_str(), *this, ipAddress,
350 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700351
352 writeConfigurationFile();
353 manager.reloadConfigs();
354
William A. Kennington III08505792019-01-30 16:00:04 -0800355 return objectPath;
356}
357
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700358#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530359/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800360 Enable this code if your NIC driver supports the ETHTOOL features.
361 Do this by adding the following to your phosphor-network*.bbappend file.
362 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
363 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530364*/
365InterfaceInfo EthernetInterface::getInterfaceInfo() const
366{
William A. Kennington III05368f12021-05-13 18:40:47 -0700367 ifreq ifr = {};
368 ethtool_cmd edata = {};
369 LinkSpeed speed = {};
370 Autoneg autoneg = {};
371 DuplexMode duplex = {};
372 LinkUp linkState = {};
373 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530374 MTU mtuSize = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800375 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
376
377 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530378 {
Tejas Patil2c0fc562021-08-03 19:13:46 +0530379 return std::make_tuple(speed, duplex, autoneg, linkState, enabled,
380 mtuSize);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800381 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530382
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800383 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
384 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530385
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800386 edata.cmd = ETHTOOL_GSET;
387 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
388 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530389 speed = edata.speed;
390 duplex = edata.duplex;
391 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530392 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800393
William A. Kennington III96203312021-05-07 12:50:41 -0700394 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800395 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530396 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800397
Tejas Patil2c0fc562021-08-03 19:13:46 +0530398 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530399}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800400#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530401
402/** @brief get the mac address of the interface.
403 * @return macaddress on success
404 */
405
Gunnar Mills57d9c502018-09-14 14:42:34 -0500406std::string
407 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530408{
Patrick Williams6aef7692021-05-01 06:39:41 -0500409 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800410 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
411
412 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530413 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800414 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530415 }
416
William A. Kennington III05368f12021-05-13 18:40:47 -0700417 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800418 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
419 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530420 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530421 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500422 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700423 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530424 }
425
William A. Kennington III1137a972019-04-20 20:49:58 -0700426 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
427 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
428 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700429 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530430}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530431
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530432std::string EthernetInterface::generateId(const std::string& ipaddress,
433 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800434 const std::string& gateway,
435 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530436{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530437 std::stringstream hexId;
438 std::string hashString = ipaddress;
439 hashString += std::to_string(prefixLength);
440 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800441 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530442
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530443 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500444 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530445 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530446}
447
Patrick Williams6aef7692021-05-01 06:39:41 -0500448std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
449 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800450{
451 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500452 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800453
454 // Only want 8 hex digits.
455 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
456 return hexId.str();
457}
458
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530459void EthernetInterface::deleteObject(const std::string& ipaddress)
460{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530461 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530462 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530463 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530464 log<level::ERR>("DeleteObject:Unable to find the object.");
465 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530466 }
467 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700468
469 writeConfigurationFile();
470 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530471}
472
Patrick Williams6aef7692021-05-01 06:39:41 -0500473void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800474{
Patrick Williams6aef7692021-05-01 06:39:41 -0500475 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800476 if (it == staticNeighbors.end())
477 {
478 log<level::ERR>(
479 "DeleteStaticNeighborObject:Unable to find the object.");
480 return;
481 }
482 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700483
484 writeConfigurationFile();
485 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800486}
487
Ratan Guptae9c9b812017-09-22 17:15:37 +0530488void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530489{
Ratan Guptabc886292017-07-25 18:29:57 +0530490 auto confDir = manager.getConfDir();
491 fs::path networkFile = confDir;
492 networkFile /= systemd::config::networkFilePrefix + interface +
493 systemd::config::networkFileSuffix;
494
495 fs::path deviceFile = confDir;
496 deviceFile /= interface + systemd::config::deviceFileSuffix;
497
498 // delete the vlan network file
499 if (fs::is_regular_file(networkFile))
500 {
501 fs::remove(networkFile);
502 }
503
504 // delete the vlan device file
505 if (fs::is_regular_file(deviceFile))
506 {
507 fs::remove(deviceFile);
508 }
Ratan Guptabc886292017-07-25 18:29:57 +0530509
510 // TODO systemd doesn't delete the virtual network interface
511 // even after deleting all the related configuartion.
512 // https://github.com/systemd/systemd/issues/6600
513 try
514 {
515 deleteInterface(interface);
516 }
Patrick Williams5758db32021-10-06 12:29:22 -0500517 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530518 {
519 commit<InternalFailure>();
520 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530521}
522
523void EthernetInterface::deleteVLANObject(const std::string& interface)
524{
525 auto it = vlanInterfaces.find(interface);
526 if (it == vlanInterfaces.end())
527 {
528 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500529 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530530 return;
531 }
532
533 deleteVLANFromSystem(interface);
534 // delete the interface
535 vlanInterfaces.erase(it);
536
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700537 writeConfigurationFile();
538 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530539}
540
Gunnar Mills57d9c502018-09-14 14:42:34 -0500541std::string EthernetInterface::generateObjectPath(
542 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800543 uint8_t prefixLength, const std::string& gateway,
544 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530545{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530546 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530547 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530548 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
549
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530550 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530551 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530552 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800553 objectPath /=
554 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530555 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530556}
557
William A. Kennington III08505792019-01-30 16:00:04 -0800558std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500559 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800560{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530561 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800562 objectPath /= objPath;
563 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500564 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800565 return objectPath.string();
566}
567
Patrick Williams6aef7692021-05-01 06:39:41 -0500568bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700569{
Patrick Williams6aef7692021-05-01 06:39:41 -0500570 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700571 {
572 return value;
573 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500574 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700575
576 writeConfigurationFile();
577 manager.reloadConfigs();
578
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700579 return value;
580}
581
Patrick Williams6aef7692021-05-01 06:39:41 -0500582EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530583{
Patrick Williams6aef7692021-05-01 06:39:41 -0500584 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530585 {
586 return value;
587 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500588 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700589
590 writeConfigurationFile();
591 manager.reloadConfigs();
592
Ratan Gupta87c13982017-06-15 09:27:27 +0530593 return value;
594}
595
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800596bool EthernetInterface::linkUp() const
597{
598 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
599 bool value = EthernetInterfaceIntf::linkUp();
600
601 if (eifSocket.sock < 0)
602 {
603 return value;
604 }
605
William A. Kennington III05368f12021-05-13 18:40:47 -0700606 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800607 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
608 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
609 {
610 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
611 }
612 else
613 {
614 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
615 entry("ERROR=%s", strerror(errno)));
616 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700617 return value;
618}
619
Tejas Patil2c0fc562021-08-03 19:13:46 +0530620size_t EthernetInterface::mtu() const
621{
622 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
623 size_t value = EthernetInterfaceIntf::mtu();
624
625 if (eifSocket.sock < 0)
626 {
627 return value;
628 }
629
630 ifreq ifr = {};
631 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
632 if (ioctl(eifSocket.sock, SIOCGIFMTU, &ifr) == 0)
633 {
634 value = ifr.ifr_mtu;
635 }
636 else
637 {
638 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
639 entry("ERROR=%s", strerror(errno)));
640 }
641 return value;
642}
643
644size_t EthernetInterface::mtu(size_t value)
645{
646 if (value == EthernetInterfaceIntf::mtu())
647 {
648 return value;
649 }
650 else if (value == 0)
651 {
652 return EthernetInterfaceIntf::mtu();
653 }
654
655 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
656 if (eifSocket.sock < 0)
657 {
658 return EthernetInterfaceIntf::mtu();
659 }
660
661 ifreq ifr = {};
662 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
663 ifr.ifr_mtu = value;
664
665 if (ioctl(eifSocket.sock, SIOCSIFMTU, &ifr) != 0)
666 {
667 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
668 entry("ERROR=%s", strerror(errno)));
669 return EthernetInterfaceIntf::mtu();
670 }
671 EthernetInterfaceIntf::mtu(value);
672
673 return value;
674}
675
William A. Kennington III26275a32021-07-13 20:32:42 -0700676bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700677{
William A. Kennington III26275a32021-07-13 20:32:42 -0700678 constexpr auto svc = "org.freedesktop.network1";
679 constexpr auto intf = "org.freedesktop.network1.Link";
680 constexpr auto prop = "AdministrativeState";
681 char* rpath;
682 sd_bus_path_encode("/org/freedesktop/network1/link",
683 std::to_string(ifIndex()).c_str(), &rpath);
684 std::string path(rpath);
685 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700686
William A. Kennington III26275a32021-07-13 20:32:42 -0700687 // Store / Parser for the AdministrativeState return value
688 std::optional<bool> ret;
689 auto cb = [&](const std::string& state) {
690 if (state != "initialized")
691 {
692 ret = state != "unmanaged";
693 }
694 };
695
696 // Build a matcher before making the property call to ensure we
697 // can eventually get the value.
698 sdbusplus::bus::match::match match(
699 bus,
700 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
701 "'PropertiesChanged',arg0='{}',",
702 svc, path, PROPERTY_INTERFACE, intf)
703 .c_str(),
704 [&](sdbusplus::message::message& m) {
705 std::string intf;
706 std::unordered_map<std::string, std::variant<std::string>> values;
707 try
708 {
709 m.read(intf, values);
710 auto it = values.find(prop);
711 // Ignore properties that aren't AdministrativeState
712 if (it != values.end())
713 {
714 cb(std::get<std::string>(it->second));
715 }
716 }
717 catch (const std::exception& e)
718 {
719 log<level::ERR>(
720 fmt::format(
721 "AdministrativeState match parsing failed on {}: {}",
722 interfaceName(), e.what())
723 .c_str(),
724 entry("INTERFACE=%s", interfaceName().c_str()),
725 entry("ERROR=%s", e.what()));
726 }
727 });
728
729 // Actively call for the value in case the interface is already configured
730 auto method =
731 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
732 method.append(intf, prop);
733 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700734 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700735 auto reply = bus.call(method);
736 std::variant<std::string> state;
737 reply.read(state);
738 cb(std::get<std::string>(state));
739 }
740 catch (const std::exception& e)
741 {
742 log<level::ERR>(
743 fmt::format("Failed to get AdministrativeState on {}: {}",
744 interfaceName(), e.what())
745 .c_str(),
746 entry("INTERFACE=%s", interfaceName().c_str()),
747 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700748 }
749
William A. Kennington III26275a32021-07-13 20:32:42 -0700750 // The interface is not yet configured by systemd-networkd, wait until it
751 // signals us a valid state.
752 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700753 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700754 bus.wait();
755 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700756 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700757
758 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700759}
760
William A. Kennington III4209cee2021-10-23 18:14:21 -0700761static void setNICAdminState(int fd, const char* intf, bool up)
762{
763 ifreq ifr = {};
764 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
765 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0)
766 {
767 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
768 entry("ERROR=%s", strerror(errno)));
769 elog<InternalFailure>();
770 }
771
772 ifr.ifr_flags &= ~IFF_UP;
773 ifr.ifr_flags |= up ? IFF_UP : 0;
774
775 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
776 {
777 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
778 entry("ERROR=%s", strerror(errno)));
779 elog<InternalFailure>();
780 }
781}
782
Patrick Williams6aef7692021-05-01 06:39:41 -0500783bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700784{
Patrick Williams6aef7692021-05-01 06:39:41 -0500785 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700786 {
787 return value;
788 }
789
790 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
791 if (eifSocket.sock < 0)
792 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500793 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700794 }
William A. Kennington III4209cee2021-10-23 18:14:21 -0700795 auto ifname = interfaceName();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700796
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700797 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800798 if (!value)
799 {
800 // We only need to bring down the interface, networkd will always bring
801 // up managed interfaces
802 manager.addReloadPreHook(
803 [ifname = std::move(ifname), eifSocket = std::move(eifSocket)]() {
804 setNICAdminState(eifSocket.sock, ifname.c_str(), false);
805 });
806 }
807 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700808 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800809
810 return value;
811}
812
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530813ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530814{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530815 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
816 return EthernetInterfaceIntf::nameservers();
817}
818
819ServerList EthernetInterface::staticNameServers(ServerList value)
820{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530821 for (const auto& nameserverip : value)
822 {
823 if (!isValidIP(AF_INET, nameserverip) &&
824 !isValidIP(AF_INET6, nameserverip))
825 {
826 log<level::ERR>("Not a valid IP address"),
827 entry("ADDRESS=%s", nameserverip.c_str());
828 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530829 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530830 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
831 }
832 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530833 try
834 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530835 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700836
Ratan Gupta6dec3902017-08-20 15:28:12 +0530837 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700838 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530839 }
Patrick Williams5758db32021-10-06 12:29:22 -0500840 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530841 {
842 log<level::ERR>("Exception processing DNS entries");
843 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530844 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530845}
846
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530847void EthernetInterface::loadNameServers()
848{
849 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
850 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
851}
852
853ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec3902017-08-20 15:28:12 +0530854{
855 fs::path confPath = manager.getConfDir();
856
857 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500858 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530859 confPath /= fileName;
860 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530861 config::Parser parser(confPath.string());
862 auto rc = config::ReturnCode::SUCCESS;
863
864 std::tie(rc, servers) = parser.getValues("Network", "DNS");
865 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530866 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530867 log<level::DEBUG>("Unable to get the value for network[DNS]",
868 entry("RC=%d", rc));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530869 }
870 return servers;
871}
872
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530873ServerList EthernetInterface::getNameServerFromResolvd()
874{
875 ServerList servers;
876 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
877
878 /*
879 The DNS property under org.freedesktop.resolve1.Link interface contains
880 an array containing all DNS servers currently used by resolved. It
881 contains similar information as the DNS server data written to
882 /run/systemd/resolve/resolv.conf.
883
884 Each structure in the array consists of a numeric network interface index,
885 an address family, and a byte array containing the DNS server address
886 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
887 The array contains DNS servers configured system-wide, including those
888 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
889 /etc/systemd/resolved.conf, as well as per-interface DNS server
890 information either retrieved from systemd-networkd or configured by
891 external software via SetLinkDNS().
892 */
893
894 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
895 std::variant<type> name; // Variable to capture the DNS property
896 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
897 PROPERTY_INTERFACE, METHOD_GET);
898
899 method.append(RESOLVED_INTERFACE, "DNS");
900 auto reply = bus.call(method);
901
902 try
903 {
904 reply.read(name);
905 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500906 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530907 {
908 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
909 }
910 auto tupleVector = std::get_if<type>(&name);
911 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
912 {
Alexander Filippov983da552021-02-08 15:26:54 +0300913 int addressFamily = std::get<0>(*i);
914 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
915
916 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530917 {
Alexander Filippov983da552021-02-08 15:26:54 +0300918 case AF_INET:
919 if (ipaddress.size() == sizeof(struct in_addr))
920 {
921 servers.push_back(toString(
922 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
923 }
924 else
925 {
926 log<level::ERR>(
927 "Invalid data recived from Systemd-Resolved");
928 }
929 break;
930
931 case AF_INET6:
932 if (ipaddress.size() == sizeof(struct in6_addr))
933 {
934 servers.push_back(toString(
935 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
936 }
937 else
938 {
939 log<level::ERR>(
940 "Invalid data recived from Systemd-Resolved");
941 }
942 break;
943
944 default:
945 log<level::ERR>(
946 "Unsupported address family in DNS from Systemd-Resolved");
947 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530948 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530949 }
950 return servers;
951}
952
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530953void EthernetInterface::loadVLAN(VlanId id)
954{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500955 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530956 std::string path = objPath;
957 path += "_" + std::to_string(id);
958
Johnathan Mantey817012a2020-01-30 15:07:39 -0800959 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500960 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530961 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500962 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800963 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530964
Gunnar Mills57d9c502018-09-14 14:42:34 -0500965 // Fetch the ip address from the system
966 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530967 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800968 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530969
970 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
971 std::move(vlanIntf));
972}
973
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700974ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530975{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500976 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530977 std::string path = objPath;
978 path += "_" + std::to_string(id);
979
Patrick Williams6aef7692021-05-01 06:39:41 -0500980 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530981 // VLAN interface can inherit.
982
Ratan Gupta5978dd12017-07-25 13:47:13 +0530983 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800984 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500985 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530986
987 // write the device file for the vlan interface.
988 vlanIntf->writeDeviceFile();
989
Gunnar Mills57d9c502018-09-14 14:42:34 -0500990 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700991
992 writeConfigurationFile();
993 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700994
995 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530996}
Ratan Gupta2b106532017-07-25 16:05:02 +0530997
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700998bool EthernetInterface::getIPv6AcceptRAFromConf()
999{
1000 fs::path confPath = manager.getConfDir();
1001
1002 std::string fileName = systemd::config::networkFilePrefix +
1003 interfaceName() + systemd::config::networkFileSuffix;
1004 confPath /= fileName;
1005 config::ValueList values;
1006 config::Parser parser(confPath.string());
1007 auto rc = config::ReturnCode::SUCCESS;
1008 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
1009 if (rc != config::ReturnCode::SUCCESS)
1010 {
1011 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1012 entry("rc=%d", rc));
1013 return false;
1014 }
1015 return (values[0] == "true");
1016}
1017
Ratan Gupta497c0c92017-08-22 19:15:59 +05301018ServerList EthernetInterface::getNTPServersFromConf()
1019{
1020 fs::path confPath = manager.getConfDir();
1021
Gunnar Mills57d9c502018-09-14 14:42:34 -05001022 std::string fileName = systemd::config::networkFilePrefix +
1023 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301024 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301025
Ratan Gupta497c0c92017-08-22 19:15:59 +05301026 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301027 config::Parser parser(confPath.string());
1028 auto rc = config::ReturnCode::SUCCESS;
1029
1030 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1031 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301032 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301033 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1034 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301035 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301036
Ratan Gupta497c0c92017-08-22 19:15:59 +05301037 return servers;
1038}
1039
Patrick Williams6aef7692021-05-01 06:39:41 -05001040ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301041{
Patrick Williams6aef7692021-05-01 06:39:41 -05001042 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301043
1044 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001045 manager.reloadConfigs();
1046
Ratan Gupta497c0c92017-08-22 19:15:59 +05301047 return ntpServers;
1048}
Ratan Gupta2b106532017-07-25 16:05:02 +05301049// Need to merge the below function with the code which writes the
1050// config file during factory reset.
1051// TODO openbmc/openbmc#1751
1052
1053void EthernetInterface::writeConfigurationFile()
1054{
1055 // write all the static ip address in the systemd-network conf file
1056
1057 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301058 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301059
1060 // if there is vlan interafce then write the configuration file
1061 // for vlan also.
1062
Gunnar Mills57d9c502018-09-14 14:42:34 -05001063 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301064 {
1065 intf.second->writeConfigurationFile();
1066 }
1067
Ratan Gupta2b106532017-07-25 16:05:02 +05301068 fs::path confPath = manager.getConfDir();
1069
Gunnar Mills57d9c502018-09-14 14:42:34 -05001070 std::string fileName = systemd::config::networkFilePrefix +
1071 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301072 confPath /= fileName;
1073 std::fstream stream;
1074
1075 stream.open(confPath.c_str(), std::fstream::out);
1076 if (!stream.is_open())
1077 {
1078 log<level::ERR>("Unable to open the file",
1079 entry("FILE=%s", confPath.c_str()));
1080 elog<InternalFailure>();
1081 }
1082
1083 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001084 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301085 stream << "Name=" << interfaceName() << "\n";
1086
1087 auto addrs = getAddresses();
1088
William A. Kennington III15787212019-04-23 19:18:01 -07001089 // Write the link section
1090 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001091 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001092 if (!mac.empty())
1093 {
1094 stream << "MACAddress=" << mac << "\n";
1095 }
1096
Patrick Williams6aef7692021-05-01 06:39:41 -05001097 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001098 {
1099 stream << "Unmanaged=yes\n";
1100 }
1101
Ratan Gupta2b106532017-07-25 16:05:02 +05301102 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001103 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001104#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001105 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001106#else
1107 stream << "LinkLocalAddressing=no\n";
1108#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001109 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001110 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301111
1112 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001113 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301114 {
1115 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001116 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301117 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301118 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001119 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301120 {
1121 stream << "NTP=" << ntp << "\n";
1122 }
1123
1124 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301125 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301126 {
1127 stream << "DNS=" << dns << "\n";
1128 }
1129
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001130 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001131 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001132 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001133
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001134 stream << "[IPv6AcceptRA]\n";
1135 stream << "DHCPv6Client=";
1136 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
1137
Johnathan Mantey817012a2020-01-30 15:07:39 -08001138 // Static IP addresses
1139 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301140 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001141 if (originIsManuallyAssigned(addr.second->origin()) &&
1142 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001143 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001144 // Process all static addresses
1145 std::string address = addr.second->address() + "/" +
1146 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301147
Johnathan Mantey817012a2020-01-30 15:07:39 -08001148 // build the address entries. Do not use [Network] shortcuts to
1149 // insert address entries.
1150 stream << "[Address]\n";
1151 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001152 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001153 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001154
Lei YUcb2d4082021-08-12 15:26:49 +08001155 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001156 {
Lei YUcb2d4082021-08-12 15:26:49 +08001157 auto gateway = EthernetInterfaceIntf::defaultGateway();
1158 if (!gateway.empty())
1159 {
1160 stream << "[Route]\n";
1161 stream << "Gateway=" << gateway << "\n";
1162 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001163 }
1164
Lei YUcb2d4082021-08-12 15:26:49 +08001165 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001166 {
Lei YUcb2d4082021-08-12 15:26:49 +08001167 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1168 if (!gateway6.empty())
1169 {
1170 stream << "[Route]\n";
1171 stream << "Gateway=" << gateway6 << "\n";
1172 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001173 }
1174
William A. Kennington III08505792019-01-30 16:00:04 -08001175 // Write the neighbor sections
1176 for (const auto& neighbor : staticNeighbors)
1177 {
1178 stream << "[Neighbor]"
1179 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001180 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1181 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001182 }
1183
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001184 // Write the dhcp section irrespective of whether DHCP is enabled or not
1185 writeDHCPSection(stream);
1186
Ratan Gupta2b106532017-07-25 16:05:02 +05301187 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301188}
1189
1190void EthernetInterface::writeDHCPSection(std::fstream& stream)
1191{
1192 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301193 // write the dhcp section
1194 stream << "[DHCP]\n";
1195
1196 // Hardcoding the client identifier to mac, to address below issue
1197 // https://github.com/openbmc/openbmc/issues/1280
1198 stream << "ClientIdentifier=mac\n";
1199 if (manager.getDHCPConf())
1200 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001201 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301202 stream << "UseDNS="s + value + "\n";
1203
Patrick Williams6aef7692021-05-01 06:39:41 -05001204 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301205 stream << "UseNTP="s + value + "\n";
1206
1207 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1208 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001209
1210 value =
1211 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1212 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301213 }
1214}
1215
Patrick Williams6aef7692021-05-01 06:39:41 -05001216std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301217{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001218 ether_addr newMAC;
1219 try
1220 {
1221 newMAC = mac_address::fromString(value);
1222 }
Patrick Williams5758db32021-10-06 12:29:22 -05001223 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001224 {
1225 log<level::ERR>("MACAddress is not valid.",
1226 entry("MAC=%s", value.c_str()));
1227 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1228 Argument::ARGUMENT_VALUE(value.c_str()));
1229 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001230 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301231 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001232 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001233 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001234 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1235 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301236 }
1237
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001238 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001239 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001240
William A. Kennington III1137a972019-04-20 20:49:58 -07001241 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001242 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001243 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301244 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001245 // Update everything that depends on the MAC value
1246 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301247 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001248 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301249 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001250 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301251
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001252 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001253 manager.addReloadPreHook([interface]() {
1254 // The MAC and LLADDRs will only update if the NIC is already down
1255 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1256 setNICAdminState(eifSocket.sock, interface.c_str(), false);
1257 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001258 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301259 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001260
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001261#ifdef HAVE_UBOOT_ENV
1262 // Ensure that the valid address is stored in the u-boot-env
1263 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1264 if (envVar)
1265 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001266 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1267 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1268 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1269 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001270 }
1271#endif // HAVE_UBOOT_ENV
1272
William A. Kennington III1137a972019-04-20 20:49:58 -07001273 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301274}
1275
Ratan Guptae9c9b812017-09-22 17:15:37 +05301276void EthernetInterface::deleteAll()
1277{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301278 // clear all the ip on the interface
1279 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001280
1281 writeConfigurationFile();
1282 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301283}
1284
Ravi Tejaa5a09442020-07-17 00:57:33 -05001285std::string EthernetInterface::defaultGateway(std::string gateway)
1286{
1287 auto gw = EthernetInterfaceIntf::defaultGateway();
1288 if (gw == gateway)
1289 {
1290 return gw;
1291 }
1292
1293 if (!isValidIP(AF_INET, gateway))
1294 {
1295 log<level::ERR>("Not a valid v4 Gateway",
1296 entry("GATEWAY=%s", gateway.c_str()));
1297 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1298 Argument::ARGUMENT_VALUE(gateway.c_str()));
1299 }
1300 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001301
1302 writeConfigurationFile();
1303 manager.reloadConfigs();
1304
Ravi Tejaa5a09442020-07-17 00:57:33 -05001305 return gw;
1306}
1307
1308std::string EthernetInterface::defaultGateway6(std::string gateway)
1309{
1310 auto gw = EthernetInterfaceIntf::defaultGateway6();
1311 if (gw == gateway)
1312 {
1313 return gw;
1314 }
1315
1316 if (!isValidIP(AF_INET6, gateway))
1317 {
1318 log<level::ERR>("Not a valid v6 Gateway",
1319 entry("GATEWAY=%s", gateway.c_str()));
1320 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1321 Argument::ARGUMENT_VALUE(gateway.c_str()));
1322 }
1323 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001324
1325 writeConfigurationFile();
1326 manager.reloadConfigs();
1327
Ravi Tejaa5a09442020-07-17 00:57:33 -05001328 return gw;
1329}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001330} // namespace network
1331} // namespace phosphor