blob: 3cca478e454ed463881f89e79175a7e052ec6708 [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
Johnathan Mantey817012a2020-01-30 15:07:39 -0800192bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
193{
194 return (
195#ifdef LINK_LOCAL_AUTOCONFIGURATION
196 (origin == IP::AddressOrigin::Static)
197#else
198 (origin == IP::AddressOrigin::Static ||
199 origin == IP::AddressOrigin::LinkLocal)
200#endif
201
202 );
203}
204
Ratan Gupta87c13982017-06-15 09:27:27 +0530205void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530206{
Ratan Gupta87c13982017-06-15 09:27:27 +0530207 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530208
Ratan Gupta87c13982017-06-15 09:27:27 +0530209 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530210
Ratan Gupta6a387c12017-08-03 13:26:19 +0530211 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530212 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800213 IP::Protocol addressType = convertFamily(addr.addrType);
214 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800215 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530216 {
217 origin = IP::AddressOrigin::DHCP;
218 }
William A. Kennington III16893802019-01-30 16:01:01 -0800219 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530220 {
221 origin = IP::AddressOrigin::LinkLocal;
222 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700223 // Obsolete parameter
224 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530225
Gunnar Mills57d9c502018-09-14 14:42:34 -0500226 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800227 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530228
Lei YU7233c582021-04-08 14:39:43 +0800229 this->addrs.insert_or_assign(
230 addr.ipaddress,
231 std::make_shared<phosphor::network::IPAddress>(
232 bus, ipAddressObjectPath.c_str(), *this, addressType,
233 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530234 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530235}
236
William A. Kennington III08505792019-01-30 16:00:04 -0800237void EthernetInterface::createStaticNeighborObjects()
238{
239 staticNeighbors.clear();
240
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700241 NeighborFilter filter;
242 filter.interface = ifIndex();
243 filter.state = NUD_PERMANENT;
244 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800245 for (const auto& neighbor : neighbors)
246 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700247 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800248 {
249 continue;
250 }
251 std::string ip = toString(neighbor.address);
252 std::string mac = mac_address::toString(*neighbor.mac);
253 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
254 staticNeighbors.emplace(ip,
255 std::make_shared<phosphor::network::Neighbor>(
256 bus, objectPath.c_str(), *this, ip, mac,
257 Neighbor::State::Permanent));
258 }
259}
260
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700261unsigned EthernetInterface::ifIndex() const
262{
263 unsigned idx = if_nametoindex(interfaceName().c_str());
264 if (idx == 0)
265 {
266 throw std::system_error(errno, std::generic_category(),
267 "if_nametoindex");
268 }
269 return idx;
270}
271
Patrick Williams6aef7692021-05-01 06:39:41 -0500272ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500273 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530274{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800275 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530276 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530277 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500278 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800279 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500280 }
281
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500282 IP::AddressOrigin origin = IP::AddressOrigin::Static;
283
284 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
285
286 if (!isValidIP(addressFamily, ipaddress))
287 {
288 log<level::ERR>("Not a valid IP address"),
289 entry("ADDRESS=%s", ipaddress.c_str());
290 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
291 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
292 }
293
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700294 // Gateway is an obsolete parameter
295 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500296
297 if (!isValidPrefix(addressFamily, prefixLength))
298 {
299 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700300 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500301 elog<InvalidArgument>(
302 Argument::ARGUMENT_NAME("prefixLength"),
303 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530304 }
305
Gunnar Mills57d9c502018-09-14 14:42:34 -0500306 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800307 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800308 this->addrs.insert_or_assign(ipaddress,
309 std::make_shared<phosphor::network::IPAddress>(
310 bus, objectPath.c_str(), *this, protType,
311 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530312
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700313 writeConfigurationFile();
314 manager.reloadConfigs();
315
raviteja-bce379562019-03-28 05:59:36 -0500316 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530317}
318
Patrick Williams6aef7692021-05-01 06:39:41 -0500319ObjectPath EthernetInterface::neighbor(std::string ipAddress,
320 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800321{
Patrick Williams6aef7692021-05-01 06:39:41 -0500322 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800323 {
324 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500325 entry("ADDRESS=%s", ipAddress.c_str()));
326 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
327 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800328 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500329 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800330 {
331 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500332 entry("MACADDRESS=%s", ipAddress.c_str()));
333 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
334 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800335 }
336
337 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500338 generateStaticNeighborObjectPath(ipAddress, macAddress);
339 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800340 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500341 bus, objectPath.c_str(), *this, ipAddress,
342 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700343
344 writeConfigurationFile();
345 manager.reloadConfigs();
346
William A. Kennington III08505792019-01-30 16:00:04 -0800347 return objectPath;
348}
349
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700350#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530351/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800352 Enable this code if your NIC driver supports the ETHTOOL features.
353 Do this by adding the following to your phosphor-network*.bbappend file.
354 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
355 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530356*/
357InterfaceInfo EthernetInterface::getInterfaceInfo() const
358{
William A. Kennington III05368f12021-05-13 18:40:47 -0700359 ifreq ifr = {};
360 ethtool_cmd edata = {};
361 LinkSpeed speed = {};
362 Autoneg autoneg = {};
363 DuplexMode duplex = {};
364 LinkUp linkState = {};
365 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530366 MTU mtuSize = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800367 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
368
369 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530370 {
Tejas Patil2c0fc562021-08-03 19:13:46 +0530371 return std::make_tuple(speed, duplex, autoneg, linkState, enabled,
372 mtuSize);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800373 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530374
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800375 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
376 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530377
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800378 edata.cmd = ETHTOOL_GSET;
379 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
380 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530381 speed = edata.speed;
382 duplex = edata.duplex;
383 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800385
William A. Kennington III96203312021-05-07 12:50:41 -0700386 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800387 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530388 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800389
Tejas Patil2c0fc562021-08-03 19:13:46 +0530390 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530391}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800392#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530393
394/** @brief get the mac address of the interface.
395 * @return macaddress on success
396 */
397
Gunnar Mills57d9c502018-09-14 14:42:34 -0500398std::string
399 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530400{
Patrick Williams6aef7692021-05-01 06:39:41 -0500401 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800402 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
403
404 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530405 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800406 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530407 }
408
William A. Kennington III05368f12021-05-13 18:40:47 -0700409 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800410 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
411 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530412 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530413 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500414 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700415 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530416 }
417
William A. Kennington III1137a972019-04-20 20:49:58 -0700418 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
419 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
420 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700421 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530422}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530423
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530424std::string EthernetInterface::generateId(const std::string& ipaddress,
425 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800426 const std::string& gateway,
427 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530428{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530429 std::stringstream hexId;
430 std::string hashString = ipaddress;
431 hashString += std::to_string(prefixLength);
432 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800433 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530434
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530435 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500436 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530437 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530438}
439
Patrick Williams6aef7692021-05-01 06:39:41 -0500440std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
441 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800442{
443 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500444 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800445
446 // Only want 8 hex digits.
447 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
448 return hexId.str();
449}
450
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530451void EthernetInterface::deleteObject(const std::string& ipaddress)
452{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530453 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530454 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530455 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530456 log<level::ERR>("DeleteObject:Unable to find the object.");
457 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530458 }
459 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700460
461 writeConfigurationFile();
462 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530463}
464
Patrick Williams6aef7692021-05-01 06:39:41 -0500465void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800466{
Patrick Williams6aef7692021-05-01 06:39:41 -0500467 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800468 if (it == staticNeighbors.end())
469 {
470 log<level::ERR>(
471 "DeleteStaticNeighborObject:Unable to find the object.");
472 return;
473 }
474 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700475
476 writeConfigurationFile();
477 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800478}
479
Ratan Guptae9c9b812017-09-22 17:15:37 +0530480void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530481{
Ratan Guptabc886292017-07-25 18:29:57 +0530482 auto confDir = manager.getConfDir();
483 fs::path networkFile = confDir;
484 networkFile /= systemd::config::networkFilePrefix + interface +
485 systemd::config::networkFileSuffix;
486
487 fs::path deviceFile = confDir;
488 deviceFile /= interface + systemd::config::deviceFileSuffix;
489
490 // delete the vlan network file
491 if (fs::is_regular_file(networkFile))
492 {
493 fs::remove(networkFile);
494 }
495
496 // delete the vlan device file
497 if (fs::is_regular_file(deviceFile))
498 {
499 fs::remove(deviceFile);
500 }
Ratan Guptabc886292017-07-25 18:29:57 +0530501
502 // TODO systemd doesn't delete the virtual network interface
503 // even after deleting all the related configuartion.
504 // https://github.com/systemd/systemd/issues/6600
505 try
506 {
507 deleteInterface(interface);
508 }
Patrick Williams5758db32021-10-06 12:29:22 -0500509 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530510 {
511 commit<InternalFailure>();
512 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530513}
514
515void EthernetInterface::deleteVLANObject(const std::string& interface)
516{
517 auto it = vlanInterfaces.find(interface);
518 if (it == vlanInterfaces.end())
519 {
520 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500521 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530522 return;
523 }
524
525 deleteVLANFromSystem(interface);
526 // delete the interface
527 vlanInterfaces.erase(it);
528
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700529 writeConfigurationFile();
530 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530531}
532
Gunnar Mills57d9c502018-09-14 14:42:34 -0500533std::string EthernetInterface::generateObjectPath(
534 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800535 uint8_t prefixLength, const std::string& gateway,
536 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530537{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530538 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530539 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530540 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
541
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530542 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530543 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530544 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800545 objectPath /=
546 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530547 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530548}
549
William A. Kennington III08505792019-01-30 16:00:04 -0800550std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500551 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800552{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530553 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800554 objectPath /= objPath;
555 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500556 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800557 return objectPath.string();
558}
559
Patrick Williams6aef7692021-05-01 06:39:41 -0500560bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700561{
Patrick Williams6aef7692021-05-01 06:39:41 -0500562 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700563 {
564 return value;
565 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500566 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700567
568 writeConfigurationFile();
569 manager.reloadConfigs();
570
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700571 return value;
572}
573
Patrick Williams6aef7692021-05-01 06:39:41 -0500574EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530575{
Patrick Williams6aef7692021-05-01 06:39:41 -0500576 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530577 {
578 return value;
579 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500580 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700581
582 writeConfigurationFile();
583 manager.reloadConfigs();
584
Ratan Gupta87c13982017-06-15 09:27:27 +0530585 return value;
586}
587
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800588bool EthernetInterface::linkUp() const
589{
590 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
591 bool value = EthernetInterfaceIntf::linkUp();
592
593 if (eifSocket.sock < 0)
594 {
595 return value;
596 }
597
William A. Kennington III05368f12021-05-13 18:40:47 -0700598 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800599 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
600 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
601 {
602 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
603 }
604 else
605 {
606 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
607 entry("ERROR=%s", strerror(errno)));
608 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700609 return value;
610}
611
Tejas Patil2c0fc562021-08-03 19:13:46 +0530612size_t EthernetInterface::mtu() const
613{
614 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
615 size_t value = EthernetInterfaceIntf::mtu();
616
617 if (eifSocket.sock < 0)
618 {
619 return value;
620 }
621
622 ifreq ifr = {};
623 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
624 if (ioctl(eifSocket.sock, SIOCGIFMTU, &ifr) == 0)
625 {
626 value = ifr.ifr_mtu;
627 }
628 else
629 {
630 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
631 entry("ERROR=%s", strerror(errno)));
632 }
633 return value;
634}
635
636size_t EthernetInterface::mtu(size_t value)
637{
638 if (value == EthernetInterfaceIntf::mtu())
639 {
640 return value;
641 }
642 else if (value == 0)
643 {
644 return EthernetInterfaceIntf::mtu();
645 }
646
647 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
648 if (eifSocket.sock < 0)
649 {
650 return EthernetInterfaceIntf::mtu();
651 }
652
653 ifreq ifr = {};
654 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
655 ifr.ifr_mtu = value;
656
657 if (ioctl(eifSocket.sock, SIOCSIFMTU, &ifr) != 0)
658 {
659 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
660 entry("ERROR=%s", strerror(errno)));
661 return EthernetInterfaceIntf::mtu();
662 }
663 EthernetInterfaceIntf::mtu(value);
664
665 return value;
666}
667
William A. Kennington III26275a32021-07-13 20:32:42 -0700668bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700669{
William A. Kennington III26275a32021-07-13 20:32:42 -0700670 constexpr auto svc = "org.freedesktop.network1";
671 constexpr auto intf = "org.freedesktop.network1.Link";
672 constexpr auto prop = "AdministrativeState";
673 char* rpath;
674 sd_bus_path_encode("/org/freedesktop/network1/link",
675 std::to_string(ifIndex()).c_str(), &rpath);
676 std::string path(rpath);
677 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700678
William A. Kennington III26275a32021-07-13 20:32:42 -0700679 // Store / Parser for the AdministrativeState return value
680 std::optional<bool> ret;
681 auto cb = [&](const std::string& state) {
682 if (state != "initialized")
683 {
684 ret = state != "unmanaged";
685 }
686 };
687
688 // Build a matcher before making the property call to ensure we
689 // can eventually get the value.
690 sdbusplus::bus::match::match match(
691 bus,
692 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
693 "'PropertiesChanged',arg0='{}',",
694 svc, path, PROPERTY_INTERFACE, intf)
695 .c_str(),
696 [&](sdbusplus::message::message& m) {
697 std::string intf;
698 std::unordered_map<std::string, std::variant<std::string>> values;
699 try
700 {
701 m.read(intf, values);
702 auto it = values.find(prop);
703 // Ignore properties that aren't AdministrativeState
704 if (it != values.end())
705 {
706 cb(std::get<std::string>(it->second));
707 }
708 }
709 catch (const std::exception& e)
710 {
711 log<level::ERR>(
712 fmt::format(
713 "AdministrativeState match parsing failed on {}: {}",
714 interfaceName(), e.what())
715 .c_str(),
716 entry("INTERFACE=%s", interfaceName().c_str()),
717 entry("ERROR=%s", e.what()));
718 }
719 });
720
721 // Actively call for the value in case the interface is already configured
722 auto method =
723 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
724 method.append(intf, prop);
725 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700726 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700727 auto reply = bus.call(method);
728 std::variant<std::string> state;
729 reply.read(state);
730 cb(std::get<std::string>(state));
731 }
732 catch (const std::exception& e)
733 {
734 log<level::ERR>(
735 fmt::format("Failed to get AdministrativeState on {}: {}",
736 interfaceName(), e.what())
737 .c_str(),
738 entry("INTERFACE=%s", interfaceName().c_str()),
739 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700740 }
741
William A. Kennington III26275a32021-07-13 20:32:42 -0700742 // The interface is not yet configured by systemd-networkd, wait until it
743 // signals us a valid state.
744 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700745 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700746 bus.wait();
747 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700748 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700749
750 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700751}
752
William A. Kennington III4209cee2021-10-23 18:14:21 -0700753static void setNICAdminState(int fd, const char* intf, bool up)
754{
755 ifreq ifr = {};
756 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
757 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0)
758 {
759 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
760 entry("ERROR=%s", strerror(errno)));
761 elog<InternalFailure>();
762 }
763
764 ifr.ifr_flags &= ~IFF_UP;
765 ifr.ifr_flags |= up ? IFF_UP : 0;
766
767 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
768 {
769 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
770 entry("ERROR=%s", strerror(errno)));
771 elog<InternalFailure>();
772 }
773}
774
Patrick Williams6aef7692021-05-01 06:39:41 -0500775bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700776{
Patrick Williams6aef7692021-05-01 06:39:41 -0500777 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700778 {
779 return value;
780 }
781
782 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
783 if (eifSocket.sock < 0)
784 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500785 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700786 }
William A. Kennington III4209cee2021-10-23 18:14:21 -0700787 auto ifname = interfaceName();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700788
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700789 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800790 if (!value)
791 {
792 // We only need to bring down the interface, networkd will always bring
793 // up managed interfaces
794 manager.addReloadPreHook(
795 [ifname = std::move(ifname), eifSocket = std::move(eifSocket)]() {
796 setNICAdminState(eifSocket.sock, ifname.c_str(), false);
797 });
798 }
799 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700800 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800801
802 return value;
803}
804
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530805ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530806{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530807 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
808 return EthernetInterfaceIntf::nameservers();
809}
810
811ServerList EthernetInterface::staticNameServers(ServerList value)
812{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530813 for (const auto& nameserverip : value)
814 {
815 if (!isValidIP(AF_INET, nameserverip) &&
816 !isValidIP(AF_INET6, nameserverip))
817 {
818 log<level::ERR>("Not a valid IP address"),
819 entry("ADDRESS=%s", nameserverip.c_str());
820 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530821 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530822 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
823 }
824 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530825 try
826 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530827 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700828
Ratan Gupta6dec3902017-08-20 15:28:12 +0530829 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700830 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530831 }
Patrick Williams5758db32021-10-06 12:29:22 -0500832 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530833 {
834 log<level::ERR>("Exception processing DNS entries");
835 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530836 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530837}
838
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530839void EthernetInterface::loadNameServers()
840{
841 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
842 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
843}
844
845ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec3902017-08-20 15:28:12 +0530846{
847 fs::path confPath = manager.getConfDir();
848
849 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500850 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530851 confPath /= fileName;
852 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530853 config::Parser parser(confPath.string());
854 auto rc = config::ReturnCode::SUCCESS;
855
856 std::tie(rc, servers) = parser.getValues("Network", "DNS");
857 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530858 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530859 log<level::DEBUG>("Unable to get the value for network[DNS]",
860 entry("RC=%d", rc));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530861 }
862 return servers;
863}
864
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530865ServerList EthernetInterface::getNameServerFromResolvd()
866{
867 ServerList servers;
868 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
869
870 /*
871 The DNS property under org.freedesktop.resolve1.Link interface contains
872 an array containing all DNS servers currently used by resolved. It
873 contains similar information as the DNS server data written to
874 /run/systemd/resolve/resolv.conf.
875
876 Each structure in the array consists of a numeric network interface index,
877 an address family, and a byte array containing the DNS server address
878 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
879 The array contains DNS servers configured system-wide, including those
880 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
881 /etc/systemd/resolved.conf, as well as per-interface DNS server
882 information either retrieved from systemd-networkd or configured by
883 external software via SetLinkDNS().
884 */
885
886 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
887 std::variant<type> name; // Variable to capture the DNS property
888 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
889 PROPERTY_INTERFACE, METHOD_GET);
890
891 method.append(RESOLVED_INTERFACE, "DNS");
892 auto reply = bus.call(method);
893
894 try
895 {
896 reply.read(name);
897 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500898 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530899 {
900 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
901 }
902 auto tupleVector = std::get_if<type>(&name);
903 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
904 {
Alexander Filippov983da552021-02-08 15:26:54 +0300905 int addressFamily = std::get<0>(*i);
906 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
907
908 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530909 {
Alexander Filippov983da552021-02-08 15:26:54 +0300910 case AF_INET:
911 if (ipaddress.size() == sizeof(struct in_addr))
912 {
913 servers.push_back(toString(
914 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
915 }
916 else
917 {
918 log<level::ERR>(
919 "Invalid data recived from Systemd-Resolved");
920 }
921 break;
922
923 case AF_INET6:
924 if (ipaddress.size() == sizeof(struct in6_addr))
925 {
926 servers.push_back(toString(
927 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
928 }
929 else
930 {
931 log<level::ERR>(
932 "Invalid data recived from Systemd-Resolved");
933 }
934 break;
935
936 default:
937 log<level::ERR>(
938 "Unsupported address family in DNS from Systemd-Resolved");
939 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530940 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530941 }
942 return servers;
943}
944
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530945void EthernetInterface::loadVLAN(VlanId id)
946{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500947 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530948 std::string path = objPath;
949 path += "_" + std::to_string(id);
950
Johnathan Mantey817012a2020-01-30 15:07:39 -0800951 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500952 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530953 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500954 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800955 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530956
Gunnar Mills57d9c502018-09-14 14:42:34 -0500957 // Fetch the ip address from the system
958 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530959 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800960 vlanIntf->createStaticNeighborObjects();
Jiaqing Zhaocc5a6702021-12-31 14:58:55 +0800961 vlanIntf->loadNameServers();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530962
963 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
964 std::move(vlanIntf));
965}
966
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700967ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530968{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500969 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530970 std::string path = objPath;
971 path += "_" + std::to_string(id);
972
Patrick Williams6aef7692021-05-01 06:39:41 -0500973 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530974 // VLAN interface can inherit.
975
Ratan Gupta5978dd12017-07-25 13:47:13 +0530976 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800977 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500978 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530979
980 // write the device file for the vlan interface.
981 vlanIntf->writeDeviceFile();
982
Gunnar Mills57d9c502018-09-14 14:42:34 -0500983 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700984
985 writeConfigurationFile();
986 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700987
988 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530989}
Ratan Gupta2b106532017-07-25 16:05:02 +0530990
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700991bool EthernetInterface::getIPv6AcceptRAFromConf()
992{
993 fs::path confPath = manager.getConfDir();
994
995 std::string fileName = systemd::config::networkFilePrefix +
996 interfaceName() + systemd::config::networkFileSuffix;
997 confPath /= fileName;
998 config::ValueList values;
999 config::Parser parser(confPath.string());
1000 auto rc = config::ReturnCode::SUCCESS;
1001 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
1002 if (rc != config::ReturnCode::SUCCESS)
1003 {
1004 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1005 entry("rc=%d", rc));
1006 return false;
1007 }
1008 return (values[0] == "true");
1009}
1010
Ratan Gupta497c0c92017-08-22 19:15:59 +05301011ServerList EthernetInterface::getNTPServersFromConf()
1012{
1013 fs::path confPath = manager.getConfDir();
1014
Gunnar Mills57d9c502018-09-14 14:42:34 -05001015 std::string fileName = systemd::config::networkFilePrefix +
1016 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301017 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301018
Ratan Gupta497c0c92017-08-22 19:15:59 +05301019 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301020 config::Parser parser(confPath.string());
1021 auto rc = config::ReturnCode::SUCCESS;
1022
1023 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1024 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301025 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301026 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1027 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301028 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301029
Ratan Gupta497c0c92017-08-22 19:15:59 +05301030 return servers;
1031}
1032
Patrick Williams6aef7692021-05-01 06:39:41 -05001033ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301034{
Patrick Williams6aef7692021-05-01 06:39:41 -05001035 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301036
1037 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001038 manager.reloadConfigs();
1039
Ratan Gupta497c0c92017-08-22 19:15:59 +05301040 return ntpServers;
1041}
Ratan Gupta2b106532017-07-25 16:05:02 +05301042// Need to merge the below function with the code which writes the
1043// config file during factory reset.
1044// TODO openbmc/openbmc#1751
1045
1046void EthernetInterface::writeConfigurationFile()
1047{
1048 // write all the static ip address in the systemd-network conf file
1049
1050 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301051 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301052
1053 // if there is vlan interafce then write the configuration file
1054 // for vlan also.
1055
Gunnar Mills57d9c502018-09-14 14:42:34 -05001056 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301057 {
1058 intf.second->writeConfigurationFile();
1059 }
1060
Ratan Gupta2b106532017-07-25 16:05:02 +05301061 fs::path confPath = manager.getConfDir();
1062
Gunnar Mills57d9c502018-09-14 14:42:34 -05001063 std::string fileName = systemd::config::networkFilePrefix +
1064 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301065 confPath /= fileName;
1066 std::fstream stream;
1067
1068 stream.open(confPath.c_str(), std::fstream::out);
1069 if (!stream.is_open())
1070 {
1071 log<level::ERR>("Unable to open the file",
1072 entry("FILE=%s", confPath.c_str()));
1073 elog<InternalFailure>();
1074 }
1075
1076 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001077 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301078 stream << "Name=" << interfaceName() << "\n";
1079
1080 auto addrs = getAddresses();
1081
William A. Kennington III15787212019-04-23 19:18:01 -07001082 // Write the link section
1083 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001084 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001085 if (!mac.empty())
1086 {
1087 stream << "MACAddress=" << mac << "\n";
1088 }
1089
Patrick Williams6aef7692021-05-01 06:39:41 -05001090 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001091 {
1092 stream << "Unmanaged=yes\n";
1093 }
1094
Ratan Gupta2b106532017-07-25 16:05:02 +05301095 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001096 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001097#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001098 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001099#else
1100 stream << "LinkLocalAddressing=no\n";
1101#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001102 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001103 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301104
1105 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001106 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301107 {
1108 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001109 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301110 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301111 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001112 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301113 {
1114 stream << "NTP=" << ntp << "\n";
1115 }
1116
1117 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301118 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301119 {
1120 stream << "DNS=" << dns << "\n";
1121 }
1122
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001123 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001124 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001125 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001126
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001127 stream << "[IPv6AcceptRA]\n";
1128 stream << "DHCPv6Client=";
1129 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Johnathan Manteyb353ba02021-12-09 12:27:32 -08001130 stream << "\n";
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001131
Johnathan Mantey817012a2020-01-30 15:07:39 -08001132 // Static IP addresses
1133 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301134 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001135 if (originIsManuallyAssigned(addr.second->origin()) &&
1136 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001137 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001138 // Process all static addresses
1139 std::string address = addr.second->address() + "/" +
1140 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301141
Johnathan Mantey817012a2020-01-30 15:07:39 -08001142 // build the address entries. Do not use [Network] shortcuts to
1143 // insert address entries.
1144 stream << "[Address]\n";
1145 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001146 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001147 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001148
Lei YUcb2d4082021-08-12 15:26:49 +08001149 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001150 {
Lei YUcb2d4082021-08-12 15:26:49 +08001151 auto gateway = EthernetInterfaceIntf::defaultGateway();
1152 if (!gateway.empty())
1153 {
1154 stream << "[Route]\n";
1155 stream << "Gateway=" << gateway << "\n";
1156 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001157 }
1158
Lei YUcb2d4082021-08-12 15:26:49 +08001159 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001160 {
Lei YUcb2d4082021-08-12 15:26:49 +08001161 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1162 if (!gateway6.empty())
1163 {
1164 stream << "[Route]\n";
1165 stream << "Gateway=" << gateway6 << "\n";
1166 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001167 }
1168
William A. Kennington III08505792019-01-30 16:00:04 -08001169 // Write the neighbor sections
1170 for (const auto& neighbor : staticNeighbors)
1171 {
1172 stream << "[Neighbor]"
1173 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001174 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1175 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001176 }
1177
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001178 // Write the dhcp section irrespective of whether DHCP is enabled or not
1179 writeDHCPSection(stream);
1180
Ratan Gupta2b106532017-07-25 16:05:02 +05301181 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301182}
1183
1184void EthernetInterface::writeDHCPSection(std::fstream& stream)
1185{
1186 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301187 // write the dhcp section
1188 stream << "[DHCP]\n";
1189
1190 // Hardcoding the client identifier to mac, to address below issue
1191 // https://github.com/openbmc/openbmc/issues/1280
1192 stream << "ClientIdentifier=mac\n";
1193 if (manager.getDHCPConf())
1194 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001195 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301196 stream << "UseDNS="s + value + "\n";
1197
Patrick Williams6aef7692021-05-01 06:39:41 -05001198 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301199 stream << "UseNTP="s + value + "\n";
1200
1201 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1202 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001203
1204 value =
1205 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1206 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301207 }
1208}
1209
Patrick Williams6aef7692021-05-01 06:39:41 -05001210std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301211{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001212 ether_addr newMAC;
1213 try
1214 {
1215 newMAC = mac_address::fromString(value);
1216 }
Patrick Williams5758db32021-10-06 12:29:22 -05001217 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001218 {
1219 log<level::ERR>("MACAddress is not valid.",
1220 entry("MAC=%s", value.c_str()));
1221 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1222 Argument::ARGUMENT_VALUE(value.c_str()));
1223 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001224 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301225 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001226 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001227 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001228 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1229 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301230 }
1231
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001232 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001233 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001234
William A. Kennington III1137a972019-04-20 20:49:58 -07001235 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001236 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001237 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301238 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001239 // Update everything that depends on the MAC value
1240 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301241 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001242 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301243 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001244 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301245
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001246 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001247 manager.addReloadPreHook([interface]() {
1248 // The MAC and LLADDRs will only update if the NIC is already down
1249 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1250 setNICAdminState(eifSocket.sock, interface.c_str(), false);
1251 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001252 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301253 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001254
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001255#ifdef HAVE_UBOOT_ENV
1256 // Ensure that the valid address is stored in the u-boot-env
1257 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1258 if (envVar)
1259 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001260 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1261 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1262 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1263 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001264 }
1265#endif // HAVE_UBOOT_ENV
1266
William A. Kennington III1137a972019-04-20 20:49:58 -07001267 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301268}
1269
Ratan Guptae9c9b812017-09-22 17:15:37 +05301270void EthernetInterface::deleteAll()
1271{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301272 // clear all the ip on the interface
1273 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001274
1275 writeConfigurationFile();
1276 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301277}
1278
Ravi Tejaa5a09442020-07-17 00:57:33 -05001279std::string EthernetInterface::defaultGateway(std::string gateway)
1280{
1281 auto gw = EthernetInterfaceIntf::defaultGateway();
1282 if (gw == gateway)
1283 {
1284 return gw;
1285 }
1286
1287 if (!isValidIP(AF_INET, gateway))
1288 {
1289 log<level::ERR>("Not a valid v4 Gateway",
1290 entry("GATEWAY=%s", gateway.c_str()));
1291 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1292 Argument::ARGUMENT_VALUE(gateway.c_str()));
1293 }
1294 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001295
1296 writeConfigurationFile();
1297 manager.reloadConfigs();
1298
Ravi Tejaa5a09442020-07-17 00:57:33 -05001299 return gw;
1300}
1301
1302std::string EthernetInterface::defaultGateway6(std::string gateway)
1303{
1304 auto gw = EthernetInterfaceIntf::defaultGateway6();
1305 if (gw == gateway)
1306 {
1307 return gw;
1308 }
1309
1310 if (!isValidIP(AF_INET6, gateway))
1311 {
1312 log<level::ERR>("Not a valid v6 Gateway",
1313 entry("GATEWAY=%s", gateway.c_str()));
1314 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1315 Argument::ARGUMENT_VALUE(gateway.c_str()));
1316 }
1317 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001318
1319 writeConfigurationFile();
1320 manager.reloadConfigs();
1321
Ravi Tejaa5a09442020-07-17 00:57:33 -05001322 return gw;
1323}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001324} // namespace network
1325} // namespace phosphor