blob: a98b176bc79eb7de8504812d211ce6dbe19ce9e4 [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"
Ravi Tejaa5a09442020-07-17 00:57:33 -05008#include "routing_table.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05309#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +053010
Ratan Gupta82549cc2017-04-21 08:45:23 +053011#include <arpa/inet.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070012#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053013#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070014#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053016#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053017#include <netinet/in.h>
18#include <sys/ioctl.h>
19#include <sys/socket.h>
20#include <unistd.h>
21
Ratan Gupta82549cc2017-04-21 08:45:23 +053022#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053023#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070025#include <phosphor-logging/elog-errors.hpp>
26#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070027#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053028#include <sstream>
William A. Kennington III12beaad2020-06-13 19:30:41 -070029#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053030#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070031#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070032#include <unordered_map>
33#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070034#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053035
Ratan Gupta91a99cc2017-04-14 16:32:09 +053036namespace phosphor
37{
38namespace network
39{
40
41using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053042using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053043using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
44using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050045using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053046constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
47constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
48constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
49constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
50constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053051
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080052struct EthernetIntfSocket
53{
54 EthernetIntfSocket(int domain, int type, int protocol)
55 {
56 if ((sock = socket(domain, type, protocol)) < 0)
57 {
58 log<level::ERR>("socket creation failed:",
59 entry("ERROR=%s", strerror(errno)));
60 }
61 }
62
63 ~EthernetIntfSocket()
64 {
65 if (sock >= 0)
66 {
67 close(sock);
68 }
69 }
70
71 int sock{-1};
72};
73
Johnathan Mantey817012a2020-01-30 15:07:39 -080074std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
75 {EthernetInterface::DHCPConf::both, "true"},
76 {EthernetInterface::DHCPConf::v4, "ipv4"},
77 {EthernetInterface::DHCPConf::v6, "ipv6"},
78 {EthernetInterface::DHCPConf::none, "false"}};
79
Ratan Gupta91a99cc2017-04-14 16:32:09 +053080EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
81 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080082 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070083 bool emitSignal,
84 std::optional<bool> enabled) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050085 Ifaces(bus, objPath.c_str(), true),
86 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053087{
88 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053089 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053090 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050091 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
92 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070093 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
Ravi Tejaa5a09442020-07-17 00:57:33 -050094 route::Table routingTable;
95 auto gatewayList = routingTable.getDefaultGateway();
96 auto gateway6List = routingTable.getDefaultGateway6();
97 std::string defaultGateway;
98 std::string defaultGateway6;
99
100 for (auto& gateway : gatewayList)
101 {
102 if (gateway.first == intfName)
103 {
104 defaultGateway = gateway.second;
105 break;
106 }
107 }
108
109 for (auto& gateway6 : gateway6List)
110 {
111 if (gateway6.first == intfName)
112 {
113 defaultGateway6 = gateway6.second;
114 break;
115 }
116 }
117
118 EthernetInterfaceIntf::defaultGateway(defaultGateway);
119 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530120 // Don't get the mac address from the system as the mac address
121 // would be same as parent interface.
122 if (intfName.find(".") == std::string::npos)
123 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500124 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530125 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500126 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
Ratan Gupta613a0122020-04-24 15:18:53 +0530127
128 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530129 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530130
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700131#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700132 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
133
134 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
135 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800136#endif
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530137
Ratan Gupta29b0e432017-05-25 12:51:40 +0530138 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530139 if (emitSignal)
140 {
141 this->emit_object_added();
142 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530143}
144
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800145static IP::Protocol convertFamily(int family)
146{
147 switch (family)
148 {
149 case AF_INET:
150 return IP::Protocol::IPv4;
151 case AF_INET6:
152 return IP::Protocol::IPv6;
153 }
154
155 throw std::invalid_argument("Bad address family");
156}
157
Johnathan Mantey817012a2020-01-30 15:07:39 -0800158void EthernetInterface::disableDHCP(IP::Protocol protocol)
159{
Patrick Williams6aef7692021-05-01 06:39:41 -0500160 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800161 if (dhcpState == EthernetInterface::DHCPConf::both)
162 {
163 if (protocol == IP::Protocol::IPv4)
164 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500165 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800166 }
167 else if (protocol == IP::Protocol::IPv6)
168 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500169 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800170 }
171 }
172 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
173 (protocol == IP::Protocol::IPv4))
174 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500175 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800176 }
177 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
178 (protocol == IP::Protocol::IPv6))
179 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500180 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800181 }
182}
183
184bool EthernetInterface::dhcpIsEnabled(IP::Protocol family, bool ignoreProtocol)
185{
Patrick Williams6aef7692021-05-01 06:39:41 -0500186 return ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800187 EthernetInterface::DHCPConf::both) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500188 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800189 EthernetInterface::DHCPConf::v6) &&
190 ((family == IP::Protocol::IPv6) || ignoreProtocol)) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500191 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800192 EthernetInterface::DHCPConf::v4) &&
193 ((family == IP::Protocol::IPv4) || ignoreProtocol)));
194}
195
196bool EthernetInterface::dhcpToBeEnabled(IP::Protocol family,
197 const std::string& nextDHCPState)
198{
199 return ((nextDHCPState == "true") ||
200 ((nextDHCPState == "ipv6") && (family == IP::Protocol::IPv6)) ||
201 ((nextDHCPState == "ipv4") && (family == IP::Protocol::IPv4)));
202}
203
204bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
205{
206 return (
207#ifdef LINK_LOCAL_AUTOCONFIGURATION
208 (origin == IP::AddressOrigin::Static)
209#else
210 (origin == IP::AddressOrigin::Static ||
211 origin == IP::AddressOrigin::LinkLocal)
212#endif
213
214 );
215}
216
Ratan Gupta87c13982017-06-15 09:27:27 +0530217void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530218{
Ratan Gupta87c13982017-06-15 09:27:27 +0530219 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530220
Ratan Gupta87c13982017-06-15 09:27:27 +0530221 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530222
Ratan Gupta6a387c12017-08-03 13:26:19 +0530223 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530224 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800225 IP::Protocol addressType = convertFamily(addr.addrType);
226 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800227 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530228 {
229 origin = IP::AddressOrigin::DHCP;
230 }
William A. Kennington III16893802019-01-30 16:01:01 -0800231 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530232 {
233 origin = IP::AddressOrigin::LinkLocal;
234 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700235 // Obsolete parameter
236 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530237
Gunnar Mills57d9c502018-09-14 14:42:34 -0500238 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800239 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530240
Lei YU7233c582021-04-08 14:39:43 +0800241 this->addrs.insert_or_assign(
242 addr.ipaddress,
243 std::make_shared<phosphor::network::IPAddress>(
244 bus, ipAddressObjectPath.c_str(), *this, addressType,
245 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530246 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530247}
248
William A. Kennington III08505792019-01-30 16:00:04 -0800249void EthernetInterface::createStaticNeighborObjects()
250{
251 staticNeighbors.clear();
252
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700253 NeighborFilter filter;
254 filter.interface = ifIndex();
255 filter.state = NUD_PERMANENT;
256 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800257 for (const auto& neighbor : neighbors)
258 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700259 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800260 {
261 continue;
262 }
263 std::string ip = toString(neighbor.address);
264 std::string mac = mac_address::toString(*neighbor.mac);
265 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
266 staticNeighbors.emplace(ip,
267 std::make_shared<phosphor::network::Neighbor>(
268 bus, objectPath.c_str(), *this, ip, mac,
269 Neighbor::State::Permanent));
270 }
271}
272
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700273unsigned EthernetInterface::ifIndex() const
274{
275 unsigned idx = if_nametoindex(interfaceName().c_str());
276 if (idx == 0)
277 {
278 throw std::system_error(errno, std::generic_category(),
279 "if_nametoindex");
280 }
281 return idx;
282}
283
Patrick Williams6aef7692021-05-01 06:39:41 -0500284ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500285 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530286{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800287 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530288 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530289 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500290 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800291 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500292 }
293
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500294 IP::AddressOrigin origin = IP::AddressOrigin::Static;
295
296 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
297
298 if (!isValidIP(addressFamily, ipaddress))
299 {
300 log<level::ERR>("Not a valid IP address"),
301 entry("ADDRESS=%s", ipaddress.c_str());
302 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
303 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
304 }
305
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700306 // Gateway is an obsolete parameter
307 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500308
309 if (!isValidPrefix(addressFamily, prefixLength))
310 {
311 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700312 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500313 elog<InvalidArgument>(
314 Argument::ARGUMENT_NAME("prefixLength"),
315 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530316 }
317
Gunnar Mills57d9c502018-09-14 14:42:34 -0500318 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800319 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800320 this->addrs.insert_or_assign(ipaddress,
321 std::make_shared<phosphor::network::IPAddress>(
322 bus, objectPath.c_str(), *this, protType,
323 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530324
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700325 writeConfigurationFile();
326 manager.reloadConfigs();
327
raviteja-bce379562019-03-28 05:59:36 -0500328 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530329}
330
Patrick Williams6aef7692021-05-01 06:39:41 -0500331ObjectPath EthernetInterface::neighbor(std::string ipAddress,
332 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800333{
Patrick Williams6aef7692021-05-01 06:39:41 -0500334 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800335 {
336 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500337 entry("ADDRESS=%s", ipAddress.c_str()));
338 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
339 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800340 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500341 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800342 {
343 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500344 entry("MACADDRESS=%s", ipAddress.c_str()));
345 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
346 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800347 }
348
349 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500350 generateStaticNeighborObjectPath(ipAddress, macAddress);
351 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800352 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500353 bus, objectPath.c_str(), *this, ipAddress,
354 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700355
356 writeConfigurationFile();
357 manager.reloadConfigs();
358
William A. Kennington III08505792019-01-30 16:00:04 -0800359 return objectPath;
360}
361
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700362#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530363/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800364 Enable this code if your NIC driver supports the ETHTOOL features.
365 Do this by adding the following to your phosphor-network*.bbappend file.
366 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
367 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530368*/
369InterfaceInfo EthernetInterface::getInterfaceInfo() const
370{
William A. Kennington III05368f12021-05-13 18:40:47 -0700371 ifreq ifr = {};
372 ethtool_cmd edata = {};
373 LinkSpeed speed = {};
374 Autoneg autoneg = {};
375 DuplexMode duplex = {};
376 LinkUp linkState = {};
377 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530378 MTU mtuSize = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800379 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
380
381 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530382 {
Tejas Patil2c0fc562021-08-03 19:13:46 +0530383 return std::make_tuple(speed, duplex, autoneg, linkState, enabled,
384 mtuSize);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800385 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530386
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800387 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
388 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530389
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800390 edata.cmd = ETHTOOL_GSET;
391 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
392 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530393 speed = edata.speed;
394 duplex = edata.duplex;
395 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530396 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800397
William A. Kennington III96203312021-05-07 12:50:41 -0700398 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800399 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530400 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800401
Tejas Patil2c0fc562021-08-03 19:13:46 +0530402 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530403}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800404#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530405
406/** @brief get the mac address of the interface.
407 * @return macaddress on success
408 */
409
Gunnar Mills57d9c502018-09-14 14:42:34 -0500410std::string
411 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530412{
Patrick Williams6aef7692021-05-01 06:39:41 -0500413 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800414 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
415
416 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530417 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800418 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530419 }
420
William A. Kennington III05368f12021-05-13 18:40:47 -0700421 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800422 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
423 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530424 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530425 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500426 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700427 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530428 }
429
William A. Kennington III1137a972019-04-20 20:49:58 -0700430 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
431 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
432 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700433 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530434}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530435
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530436std::string EthernetInterface::generateId(const std::string& ipaddress,
437 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800438 const std::string& gateway,
439 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530440{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530441 std::stringstream hexId;
442 std::string hashString = ipaddress;
443 hashString += std::to_string(prefixLength);
444 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800445 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530446
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530447 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500448 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530449 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530450}
451
Patrick Williams6aef7692021-05-01 06:39:41 -0500452std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
453 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800454{
455 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500456 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800457
458 // Only want 8 hex digits.
459 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
460 return hexId.str();
461}
462
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530463void EthernetInterface::deleteObject(const std::string& ipaddress)
464{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530465 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530466 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530467 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530468 log<level::ERR>("DeleteObject:Unable to find the object.");
469 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530470 }
471 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700472
473 writeConfigurationFile();
474 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530475}
476
Patrick Williams6aef7692021-05-01 06:39:41 -0500477void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800478{
Patrick Williams6aef7692021-05-01 06:39:41 -0500479 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800480 if (it == staticNeighbors.end())
481 {
482 log<level::ERR>(
483 "DeleteStaticNeighborObject:Unable to find the object.");
484 return;
485 }
486 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700487
488 writeConfigurationFile();
489 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800490}
491
Ratan Guptae9c9b812017-09-22 17:15:37 +0530492void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530493{
Ratan Guptabc886292017-07-25 18:29:57 +0530494 auto confDir = manager.getConfDir();
495 fs::path networkFile = confDir;
496 networkFile /= systemd::config::networkFilePrefix + interface +
497 systemd::config::networkFileSuffix;
498
499 fs::path deviceFile = confDir;
500 deviceFile /= interface + systemd::config::deviceFileSuffix;
501
502 // delete the vlan network file
503 if (fs::is_regular_file(networkFile))
504 {
505 fs::remove(networkFile);
506 }
507
508 // delete the vlan device file
509 if (fs::is_regular_file(deviceFile))
510 {
511 fs::remove(deviceFile);
512 }
Ratan Guptabc886292017-07-25 18:29:57 +0530513
514 // TODO systemd doesn't delete the virtual network interface
515 // even after deleting all the related configuartion.
516 // https://github.com/systemd/systemd/issues/6600
517 try
518 {
519 deleteInterface(interface);
520 }
Patrick Williams5758db32021-10-06 12:29:22 -0500521 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530522 {
523 commit<InternalFailure>();
524 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530525}
526
527void EthernetInterface::deleteVLANObject(const std::string& interface)
528{
529 auto it = vlanInterfaces.find(interface);
530 if (it == vlanInterfaces.end())
531 {
532 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500533 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530534 return;
535 }
536
537 deleteVLANFromSystem(interface);
538 // delete the interface
539 vlanInterfaces.erase(it);
540
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700541 writeConfigurationFile();
542 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530543}
544
Gunnar Mills57d9c502018-09-14 14:42:34 -0500545std::string EthernetInterface::generateObjectPath(
546 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800547 uint8_t prefixLength, const std::string& gateway,
548 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530549{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530550 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530551 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530552 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
553
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530554 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530555 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530556 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800557 objectPath /=
558 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530559 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530560}
561
William A. Kennington III08505792019-01-30 16:00:04 -0800562std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500563 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800564{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530565 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800566 objectPath /= objPath;
567 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500568 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800569 return objectPath.string();
570}
571
Patrick Williams6aef7692021-05-01 06:39:41 -0500572bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700573{
Patrick Williams6aef7692021-05-01 06:39:41 -0500574 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700575 {
576 return value;
577 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500578 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700579
580 writeConfigurationFile();
581 manager.reloadConfigs();
582
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700583 return value;
584}
585
Patrick Williams6aef7692021-05-01 06:39:41 -0500586EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530587{
Patrick Williams6aef7692021-05-01 06:39:41 -0500588 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530589 {
590 return value;
591 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500592 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700593
594 writeConfigurationFile();
595 manager.reloadConfigs();
596
Ratan Gupta87c13982017-06-15 09:27:27 +0530597 return value;
598}
599
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800600bool EthernetInterface::linkUp() const
601{
602 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
603 bool value = EthernetInterfaceIntf::linkUp();
604
605 if (eifSocket.sock < 0)
606 {
607 return value;
608 }
609
William A. Kennington III05368f12021-05-13 18:40:47 -0700610 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800611 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
612 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
613 {
614 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
615 }
616 else
617 {
618 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
619 entry("ERROR=%s", strerror(errno)));
620 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700621 return value;
622}
623
Tejas Patil2c0fc562021-08-03 19:13:46 +0530624size_t EthernetInterface::mtu() const
625{
626 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
627 size_t value = EthernetInterfaceIntf::mtu();
628
629 if (eifSocket.sock < 0)
630 {
631 return value;
632 }
633
634 ifreq ifr = {};
635 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
636 if (ioctl(eifSocket.sock, SIOCGIFMTU, &ifr) == 0)
637 {
638 value = ifr.ifr_mtu;
639 }
640 else
641 {
642 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
643 entry("ERROR=%s", strerror(errno)));
644 }
645 return value;
646}
647
648size_t EthernetInterface::mtu(size_t value)
649{
650 if (value == EthernetInterfaceIntf::mtu())
651 {
652 return value;
653 }
654 else if (value == 0)
655 {
656 return EthernetInterfaceIntf::mtu();
657 }
658
659 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
660 if (eifSocket.sock < 0)
661 {
662 return EthernetInterfaceIntf::mtu();
663 }
664
665 ifreq ifr = {};
666 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
667 ifr.ifr_mtu = value;
668
669 if (ioctl(eifSocket.sock, SIOCSIFMTU, &ifr) != 0)
670 {
671 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
672 entry("ERROR=%s", strerror(errno)));
673 return EthernetInterfaceIntf::mtu();
674 }
675 EthernetInterfaceIntf::mtu(value);
676
677 return value;
678}
679
William A. Kennington III26275a32021-07-13 20:32:42 -0700680bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700681{
William A. Kennington III26275a32021-07-13 20:32:42 -0700682 constexpr auto svc = "org.freedesktop.network1";
683 constexpr auto intf = "org.freedesktop.network1.Link";
684 constexpr auto prop = "AdministrativeState";
685 char* rpath;
686 sd_bus_path_encode("/org/freedesktop/network1/link",
687 std::to_string(ifIndex()).c_str(), &rpath);
688 std::string path(rpath);
689 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700690
William A. Kennington III26275a32021-07-13 20:32:42 -0700691 // Store / Parser for the AdministrativeState return value
692 std::optional<bool> ret;
693 auto cb = [&](const std::string& state) {
694 if (state != "initialized")
695 {
696 ret = state != "unmanaged";
697 }
698 };
699
700 // Build a matcher before making the property call to ensure we
701 // can eventually get the value.
702 sdbusplus::bus::match::match match(
703 bus,
704 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
705 "'PropertiesChanged',arg0='{}',",
706 svc, path, PROPERTY_INTERFACE, intf)
707 .c_str(),
708 [&](sdbusplus::message::message& m) {
709 std::string intf;
710 std::unordered_map<std::string, std::variant<std::string>> values;
711 try
712 {
713 m.read(intf, values);
714 auto it = values.find(prop);
715 // Ignore properties that aren't AdministrativeState
716 if (it != values.end())
717 {
718 cb(std::get<std::string>(it->second));
719 }
720 }
721 catch (const std::exception& e)
722 {
723 log<level::ERR>(
724 fmt::format(
725 "AdministrativeState match parsing failed on {}: {}",
726 interfaceName(), e.what())
727 .c_str(),
728 entry("INTERFACE=%s", interfaceName().c_str()),
729 entry("ERROR=%s", e.what()));
730 }
731 });
732
733 // Actively call for the value in case the interface is already configured
734 auto method =
735 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
736 method.append(intf, prop);
737 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700738 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700739 auto reply = bus.call(method);
740 std::variant<std::string> state;
741 reply.read(state);
742 cb(std::get<std::string>(state));
743 }
744 catch (const std::exception& e)
745 {
746 log<level::ERR>(
747 fmt::format("Failed to get AdministrativeState on {}: {}",
748 interfaceName(), e.what())
749 .c_str(),
750 entry("INTERFACE=%s", interfaceName().c_str()),
751 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700752 }
753
William A. Kennington III26275a32021-07-13 20:32:42 -0700754 // The interface is not yet configured by systemd-networkd, wait until it
755 // signals us a valid state.
756 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700757 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700758 bus.wait();
759 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700760 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700761
762 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700763}
764
Patrick Williams6aef7692021-05-01 06:39:41 -0500765bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700766{
Patrick Williams6aef7692021-05-01 06:39:41 -0500767 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700768 {
769 return value;
770 }
771
772 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
773 if (eifSocket.sock < 0)
774 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500775 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700776 }
777
William A. Kennington III05368f12021-05-13 18:40:47 -0700778 ifreq ifr = {};
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700779 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
780 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) != 0)
781 {
782 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
783 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500784 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700785 }
786
787 ifr.ifr_flags &= ~IFF_UP;
788 ifr.ifr_flags |= value ? IFF_UP : 0;
789
790 if (ioctl(eifSocket.sock, SIOCSIFFLAGS, &ifr) != 0)
791 {
792 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
793 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500794 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700795 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500796 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700797
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700798 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700799 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800800
801 return value;
802}
803
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530804ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530805{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530806 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
807 return EthernetInterfaceIntf::nameservers();
808}
809
810ServerList EthernetInterface::staticNameServers(ServerList value)
811{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530812 for (const auto& nameserverip : value)
813 {
814 if (!isValidIP(AF_INET, nameserverip) &&
815 !isValidIP(AF_INET6, nameserverip))
816 {
817 log<level::ERR>("Not a valid IP address"),
818 entry("ADDRESS=%s", nameserverip.c_str());
819 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530820 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530821 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
822 }
823 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530824 try
825 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530826 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700827
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530828 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700829 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530830 }
Patrick Williams5758db32021-10-06 12:29:22 -0500831 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530832 {
833 log<level::ERR>("Exception processing DNS entries");
834 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530835 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530836}
837
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530838void EthernetInterface::loadNameServers()
839{
840 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
841 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
842}
843
844ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530845{
846 fs::path confPath = manager.getConfDir();
847
848 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500849 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530850 confPath /= fileName;
851 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530852 config::Parser parser(confPath.string());
853 auto rc = config::ReturnCode::SUCCESS;
854
855 std::tie(rc, servers) = parser.getValues("Network", "DNS");
856 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530857 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530858 log<level::DEBUG>("Unable to get the value for network[DNS]",
859 entry("RC=%d", rc));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530860 }
861 return servers;
862}
863
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530864ServerList EthernetInterface::getNameServerFromResolvd()
865{
866 ServerList servers;
867 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
868
869 /*
870 The DNS property under org.freedesktop.resolve1.Link interface contains
871 an array containing all DNS servers currently used by resolved. It
872 contains similar information as the DNS server data written to
873 /run/systemd/resolve/resolv.conf.
874
875 Each structure in the array consists of a numeric network interface index,
876 an address family, and a byte array containing the DNS server address
877 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
878 The array contains DNS servers configured system-wide, including those
879 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
880 /etc/systemd/resolved.conf, as well as per-interface DNS server
881 information either retrieved from systemd-networkd or configured by
882 external software via SetLinkDNS().
883 */
884
885 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
886 std::variant<type> name; // Variable to capture the DNS property
887 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
888 PROPERTY_INTERFACE, METHOD_GET);
889
890 method.append(RESOLVED_INTERFACE, "DNS");
891 auto reply = bus.call(method);
892
893 try
894 {
895 reply.read(name);
896 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500897 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530898 {
899 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
900 }
901 auto tupleVector = std::get_if<type>(&name);
902 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
903 {
Alexander Filippov983da552021-02-08 15:26:54 +0300904 int addressFamily = std::get<0>(*i);
905 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
906
907 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530908 {
Alexander Filippov983da552021-02-08 15:26:54 +0300909 case AF_INET:
910 if (ipaddress.size() == sizeof(struct in_addr))
911 {
912 servers.push_back(toString(
913 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
914 }
915 else
916 {
917 log<level::ERR>(
918 "Invalid data recived from Systemd-Resolved");
919 }
920 break;
921
922 case AF_INET6:
923 if (ipaddress.size() == sizeof(struct in6_addr))
924 {
925 servers.push_back(toString(
926 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
927 }
928 else
929 {
930 log<level::ERR>(
931 "Invalid data recived from Systemd-Resolved");
932 }
933 break;
934
935 default:
936 log<level::ERR>(
937 "Unsupported address family in DNS from Systemd-Resolved");
938 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530939 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530940 }
941 return servers;
942}
943
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530944void EthernetInterface::loadVLAN(VlanId id)
945{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500946 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530947 std::string path = objPath;
948 path += "_" + std::to_string(id);
949
Johnathan Mantey817012a2020-01-30 15:07:39 -0800950 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500951 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530952 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500953 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800954 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530955
Gunnar Mills57d9c502018-09-14 14:42:34 -0500956 // Fetch the ip address from the system
957 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530958 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800959 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530960
961 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
962 std::move(vlanIntf));
963}
964
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700965ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530966{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500967 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530968 std::string path = objPath;
969 path += "_" + std::to_string(id);
970
Patrick Williams6aef7692021-05-01 06:39:41 -0500971 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530972 // VLAN interface can inherit.
973
Ratan Gupta5978dd12017-07-25 13:47:13 +0530974 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800975 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500976 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530977
978 // write the device file for the vlan interface.
979 vlanIntf->writeDeviceFile();
980
Gunnar Mills57d9c502018-09-14 14:42:34 -0500981 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700982
983 writeConfigurationFile();
984 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700985
986 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530987}
Ratan Gupta2b106532017-07-25 16:05:02 +0530988
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700989bool EthernetInterface::getIPv6AcceptRAFromConf()
990{
991 fs::path confPath = manager.getConfDir();
992
993 std::string fileName = systemd::config::networkFilePrefix +
994 interfaceName() + systemd::config::networkFileSuffix;
995 confPath /= fileName;
996 config::ValueList values;
997 config::Parser parser(confPath.string());
998 auto rc = config::ReturnCode::SUCCESS;
999 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
1000 if (rc != config::ReturnCode::SUCCESS)
1001 {
1002 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1003 entry("rc=%d", rc));
1004 return false;
1005 }
1006 return (values[0] == "true");
1007}
1008
Ratan Gupta497c0c92017-08-22 19:15:59 +05301009ServerList EthernetInterface::getNTPServersFromConf()
1010{
1011 fs::path confPath = manager.getConfDir();
1012
Gunnar Mills57d9c502018-09-14 14:42:34 -05001013 std::string fileName = systemd::config::networkFilePrefix +
1014 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301015 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301016
Ratan Gupta497c0c92017-08-22 19:15:59 +05301017 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301018 config::Parser parser(confPath.string());
1019 auto rc = config::ReturnCode::SUCCESS;
1020
1021 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1022 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301023 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301024 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1025 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301026 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301027
Ratan Gupta497c0c92017-08-22 19:15:59 +05301028 return servers;
1029}
1030
Patrick Williams6aef7692021-05-01 06:39:41 -05001031ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301032{
Patrick Williams6aef7692021-05-01 06:39:41 -05001033 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301034
1035 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001036 manager.reloadConfigs();
1037
Ratan Gupta497c0c92017-08-22 19:15:59 +05301038 return ntpServers;
1039}
Ratan Gupta2b106532017-07-25 16:05:02 +05301040// Need to merge the below function with the code which writes the
1041// config file during factory reset.
1042// TODO openbmc/openbmc#1751
1043
1044void EthernetInterface::writeConfigurationFile()
1045{
1046 // write all the static ip address in the systemd-network conf file
1047
1048 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301049 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301050
1051 // if there is vlan interafce then write the configuration file
1052 // for vlan also.
1053
Gunnar Mills57d9c502018-09-14 14:42:34 -05001054 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301055 {
1056 intf.second->writeConfigurationFile();
1057 }
1058
Ratan Gupta2b106532017-07-25 16:05:02 +05301059 fs::path confPath = manager.getConfDir();
1060
Gunnar Mills57d9c502018-09-14 14:42:34 -05001061 std::string fileName = systemd::config::networkFilePrefix +
1062 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301063 confPath /= fileName;
1064 std::fstream stream;
1065
1066 stream.open(confPath.c_str(), std::fstream::out);
1067 if (!stream.is_open())
1068 {
1069 log<level::ERR>("Unable to open the file",
1070 entry("FILE=%s", confPath.c_str()));
1071 elog<InternalFailure>();
1072 }
1073
1074 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001075 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301076 stream << "Name=" << interfaceName() << "\n";
1077
1078 auto addrs = getAddresses();
1079
William A. Kennington III15787212019-04-23 19:18:01 -07001080 // Write the link section
1081 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001082 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001083 if (!mac.empty())
1084 {
1085 stream << "MACAddress=" << mac << "\n";
1086 }
1087
Patrick Williams6aef7692021-05-01 06:39:41 -05001088 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001089 {
1090 stream << "Unmanaged=yes\n";
1091 }
1092
Ratan Gupta2b106532017-07-25 16:05:02 +05301093 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001094 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001095#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001096 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001097#else
1098 stream << "LinkLocalAddressing=no\n";
1099#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001100 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001101 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301102
1103 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001104 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301105 {
1106 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001107 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301108 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301109 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001110 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301111 {
1112 stream << "NTP=" << ntp << "\n";
1113 }
1114
1115 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301116 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301117 {
1118 stream << "DNS=" << dns << "\n";
1119 }
1120
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001121 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001122 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001123 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001124
Johnathan Mantey817012a2020-01-30 15:07:39 -08001125 // Static IP addresses
1126 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301127 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001128 if (originIsManuallyAssigned(addr.second->origin()) &&
1129 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001130 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001131 // Process all static addresses
1132 std::string address = addr.second->address() + "/" +
1133 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301134
Johnathan Mantey817012a2020-01-30 15:07:39 -08001135 // build the address entries. Do not use [Network] shortcuts to
1136 // insert address entries.
1137 stream << "[Address]\n";
1138 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001139 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001140 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001141
Lei YUcb2d4082021-08-12 15:26:49 +08001142 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001143 {
Lei YUcb2d4082021-08-12 15:26:49 +08001144 auto gateway = EthernetInterfaceIntf::defaultGateway();
1145 if (!gateway.empty())
1146 {
1147 stream << "[Route]\n";
1148 stream << "Gateway=" << gateway << "\n";
1149 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001150 }
1151
Lei YUcb2d4082021-08-12 15:26:49 +08001152 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001153 {
Lei YUcb2d4082021-08-12 15:26:49 +08001154 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1155 if (!gateway6.empty())
1156 {
1157 stream << "[Route]\n";
1158 stream << "Gateway=" << gateway6 << "\n";
1159 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001160 }
1161
William A. Kennington III08505792019-01-30 16:00:04 -08001162 // Write the neighbor sections
1163 for (const auto& neighbor : staticNeighbors)
1164 {
1165 stream << "[Neighbor]"
1166 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001167 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1168 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001169 }
1170
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001171 // Write the dhcp section irrespective of whether DHCP is enabled or not
1172 writeDHCPSection(stream);
1173
Ratan Gupta2b106532017-07-25 16:05:02 +05301174 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301175}
1176
1177void EthernetInterface::writeDHCPSection(std::fstream& stream)
1178{
1179 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301180 // write the dhcp section
1181 stream << "[DHCP]\n";
1182
1183 // Hardcoding the client identifier to mac, to address below issue
1184 // https://github.com/openbmc/openbmc/issues/1280
1185 stream << "ClientIdentifier=mac\n";
1186 if (manager.getDHCPConf())
1187 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001188 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301189 stream << "UseDNS="s + value + "\n";
1190
Patrick Williams6aef7692021-05-01 06:39:41 -05001191 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301192 stream << "UseNTP="s + value + "\n";
1193
1194 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1195 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001196
1197 value =
1198 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1199 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301200 }
1201}
1202
Patrick Williams6aef7692021-05-01 06:39:41 -05001203std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301204{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001205 ether_addr newMAC;
1206 try
1207 {
1208 newMAC = mac_address::fromString(value);
1209 }
Patrick Williams5758db32021-10-06 12:29:22 -05001210 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001211 {
1212 log<level::ERR>("MACAddress is not valid.",
1213 entry("MAC=%s", value.c_str()));
1214 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1215 Argument::ARGUMENT_VALUE(value.c_str()));
1216 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001217 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301218 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001219 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001220 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001221 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1222 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301223 }
1224
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001225 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001226 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001227
William A. Kennington III1137a972019-04-20 20:49:58 -07001228 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001229 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001230 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301231 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001232 // Update everything that depends on the MAC value
1233 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301234 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001235 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301236 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001237 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301238
William A. Kennington III15787212019-04-23 19:18:01 -07001239 // TODO: would remove the call below and
1240 // just restart systemd-netwokd
William A. Kennington III1137a972019-04-20 20:49:58 -07001241 // through https://github.com/systemd/systemd/issues/6696
1242 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(),
1243 "down");
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001244 writeConfigurationFile();
1245 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301246 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001247
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001248#ifdef HAVE_UBOOT_ENV
1249 // Ensure that the valid address is stored in the u-boot-env
1250 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1251 if (envVar)
1252 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001253 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1254 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1255 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1256 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001257 }
1258#endif // HAVE_UBOOT_ENV
1259
William A. Kennington III1137a972019-04-20 20:49:58 -07001260 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301261}
1262
Ratan Guptae9c9b812017-09-22 17:15:37 +05301263void EthernetInterface::deleteAll()
1264{
Johnathan Mantey817012a2020-01-30 15:07:39 -08001265 if (dhcpIsEnabled(IP::Protocol::IPv4, true))
Ratan Guptae9c9b812017-09-22 17:15:37 +05301266 {
1267 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -05001268 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +05301269 }
1270
1271 // clear all the ip on the interface
1272 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001273
1274 writeConfigurationFile();
1275 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301276}
1277
Ravi Tejaa5a09442020-07-17 00:57:33 -05001278std::string EthernetInterface::defaultGateway(std::string gateway)
1279{
1280 auto gw = EthernetInterfaceIntf::defaultGateway();
1281 if (gw == gateway)
1282 {
1283 return gw;
1284 }
1285
1286 if (!isValidIP(AF_INET, gateway))
1287 {
1288 log<level::ERR>("Not a valid v4 Gateway",
1289 entry("GATEWAY=%s", gateway.c_str()));
1290 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1291 Argument::ARGUMENT_VALUE(gateway.c_str()));
1292 }
1293 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001294
1295 writeConfigurationFile();
1296 manager.reloadConfigs();
1297
Ravi Tejaa5a09442020-07-17 00:57:33 -05001298 return gw;
1299}
1300
1301std::string EthernetInterface::defaultGateway6(std::string gateway)
1302{
1303 auto gw = EthernetInterfaceIntf::defaultGateway6();
1304 if (gw == gateway)
1305 {
1306 return gw;
1307 }
1308
1309 if (!isValidIP(AF_INET6, gateway))
1310 {
1311 log<level::ERR>("Not a valid v6 Gateway",
1312 entry("GATEWAY=%s", gateway.c_str()));
1313 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1314 Argument::ARGUMENT_VALUE(gateway.c_str()));
1315 }
1316 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001317
1318 writeConfigurationFile();
1319 manager.reloadConfigs();
1320
Ravi Tejaa5a09442020-07-17 00:57:33 -05001321 return gw;
1322}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001323} // namespace network
1324} // namespace phosphor