blob: baf530f2df19596a28c153c6b51ec4582be3a9fb [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 Gupta6dec390f2017-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
182bool EthernetInterface::dhcpIsEnabled(IP::Protocol family, bool ignoreProtocol)
183{
Patrick Williams6aef7692021-05-01 06:39:41 -0500184 return ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800185 EthernetInterface::DHCPConf::both) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500186 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800187 EthernetInterface::DHCPConf::v6) &&
188 ((family == IP::Protocol::IPv6) || ignoreProtocol)) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500189 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800190 EthernetInterface::DHCPConf::v4) &&
191 ((family == IP::Protocol::IPv4) || ignoreProtocol)));
192}
193
194bool EthernetInterface::dhcpToBeEnabled(IP::Protocol family,
195 const std::string& nextDHCPState)
196{
197 return ((nextDHCPState == "true") ||
198 ((nextDHCPState == "ipv6") && (family == IP::Protocol::IPv6)) ||
199 ((nextDHCPState == "ipv4") && (family == IP::Protocol::IPv4)));
200}
201
202bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
203{
204 return (
205#ifdef LINK_LOCAL_AUTOCONFIGURATION
206 (origin == IP::AddressOrigin::Static)
207#else
208 (origin == IP::AddressOrigin::Static ||
209 origin == IP::AddressOrigin::LinkLocal)
210#endif
211
212 );
213}
214
Ratan Gupta87c13982017-06-15 09:27:27 +0530215void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530216{
Ratan Gupta87c13982017-06-15 09:27:27 +0530217 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530218
Ratan Gupta87c13982017-06-15 09:27:27 +0530219 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530220
Ratan Gupta6a387c12017-08-03 13:26:19 +0530221 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530222 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800223 IP::Protocol addressType = convertFamily(addr.addrType);
224 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800225 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530226 {
227 origin = IP::AddressOrigin::DHCP;
228 }
William A. Kennington III16893802019-01-30 16:01:01 -0800229 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530230 {
231 origin = IP::AddressOrigin::LinkLocal;
232 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700233 // Obsolete parameter
234 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530235
Gunnar Mills57d9c502018-09-14 14:42:34 -0500236 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800237 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530238
Lei YU7233c582021-04-08 14:39:43 +0800239 this->addrs.insert_or_assign(
240 addr.ipaddress,
241 std::make_shared<phosphor::network::IPAddress>(
242 bus, ipAddressObjectPath.c_str(), *this, addressType,
243 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530244 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530245}
246
William A. Kennington III08505792019-01-30 16:00:04 -0800247void EthernetInterface::createStaticNeighborObjects()
248{
249 staticNeighbors.clear();
250
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700251 NeighborFilter filter;
252 filter.interface = ifIndex();
253 filter.state = NUD_PERMANENT;
254 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800255 for (const auto& neighbor : neighbors)
256 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700257 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800258 {
259 continue;
260 }
261 std::string ip = toString(neighbor.address);
262 std::string mac = mac_address::toString(*neighbor.mac);
263 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
264 staticNeighbors.emplace(ip,
265 std::make_shared<phosphor::network::Neighbor>(
266 bus, objectPath.c_str(), *this, ip, mac,
267 Neighbor::State::Permanent));
268 }
269}
270
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700271unsigned EthernetInterface::ifIndex() const
272{
273 unsigned idx = if_nametoindex(interfaceName().c_str());
274 if (idx == 0)
275 {
276 throw std::system_error(errno, std::generic_category(),
277 "if_nametoindex");
278 }
279 return idx;
280}
281
Patrick Williams6aef7692021-05-01 06:39:41 -0500282ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500283 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530284{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800285 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530286 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530287 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500288 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800289 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500290 }
291
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500292 IP::AddressOrigin origin = IP::AddressOrigin::Static;
293
294 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
295
296 if (!isValidIP(addressFamily, ipaddress))
297 {
298 log<level::ERR>("Not a valid IP address"),
299 entry("ADDRESS=%s", ipaddress.c_str());
300 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
301 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
302 }
303
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700304 // Gateway is an obsolete parameter
305 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500306
307 if (!isValidPrefix(addressFamily, prefixLength))
308 {
309 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700310 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500311 elog<InvalidArgument>(
312 Argument::ARGUMENT_NAME("prefixLength"),
313 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530314 }
315
Gunnar Mills57d9c502018-09-14 14:42:34 -0500316 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800317 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800318 this->addrs.insert_or_assign(ipaddress,
319 std::make_shared<phosphor::network::IPAddress>(
320 bus, objectPath.c_str(), *this, protType,
321 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530322
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700323 writeConfigurationFile();
324 manager.reloadConfigs();
325
raviteja-bce379562019-03-28 05:59:36 -0500326 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530327}
328
Patrick Williams6aef7692021-05-01 06:39:41 -0500329ObjectPath EthernetInterface::neighbor(std::string ipAddress,
330 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800331{
Patrick Williams6aef7692021-05-01 06:39:41 -0500332 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800333 {
334 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500335 entry("ADDRESS=%s", ipAddress.c_str()));
336 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
337 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800338 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500339 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800340 {
341 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500342 entry("MACADDRESS=%s", ipAddress.c_str()));
343 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
344 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800345 }
346
347 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500348 generateStaticNeighborObjectPath(ipAddress, macAddress);
349 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800350 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500351 bus, objectPath.c_str(), *this, ipAddress,
352 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700353
354 writeConfigurationFile();
355 manager.reloadConfigs();
356
William A. Kennington III08505792019-01-30 16:00:04 -0800357 return objectPath;
358}
359
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700360#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530361/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800362 Enable this code if your NIC driver supports the ETHTOOL features.
363 Do this by adding the following to your phosphor-network*.bbappend file.
364 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
365 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530366*/
367InterfaceInfo EthernetInterface::getInterfaceInfo() const
368{
William A. Kennington III05368f12021-05-13 18:40:47 -0700369 ifreq ifr = {};
370 ethtool_cmd edata = {};
371 LinkSpeed speed = {};
372 Autoneg autoneg = {};
373 DuplexMode duplex = {};
374 LinkUp linkState = {};
375 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530376 MTU mtuSize = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800377 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
378
379 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530380 {
Tejas Patil2c0fc562021-08-03 19:13:46 +0530381 return std::make_tuple(speed, duplex, autoneg, linkState, enabled,
382 mtuSize);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800383 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800385 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
386 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530387
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800388 edata.cmd = ETHTOOL_GSET;
389 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
390 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530391 speed = edata.speed;
392 duplex = edata.duplex;
393 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530394 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800395
William A. Kennington III96203312021-05-07 12:50:41 -0700396 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800397 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530398 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800399
Tejas Patil2c0fc562021-08-03 19:13:46 +0530400 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530401}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800402#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530403
404/** @brief get the mac address of the interface.
405 * @return macaddress on success
406 */
407
Gunnar Mills57d9c502018-09-14 14:42:34 -0500408std::string
409 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530410{
Patrick Williams6aef7692021-05-01 06:39:41 -0500411 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800412 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
413
414 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530415 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800416 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530417 }
418
William A. Kennington III05368f12021-05-13 18:40:47 -0700419 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800420 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
421 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530422 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530423 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500424 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700425 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530426 }
427
William A. Kennington III1137a972019-04-20 20:49:58 -0700428 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
429 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
430 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700431 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530432}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530433
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530434std::string EthernetInterface::generateId(const std::string& ipaddress,
435 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800436 const std::string& gateway,
437 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530438{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530439 std::stringstream hexId;
440 std::string hashString = ipaddress;
441 hashString += std::to_string(prefixLength);
442 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800443 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530444
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530445 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500446 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530447 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530448}
449
Patrick Williams6aef7692021-05-01 06:39:41 -0500450std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
451 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800452{
453 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500454 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800455
456 // Only want 8 hex digits.
457 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
458 return hexId.str();
459}
460
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530461void EthernetInterface::deleteObject(const std::string& ipaddress)
462{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530463 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530464 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530465 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530466 log<level::ERR>("DeleteObject:Unable to find the object.");
467 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530468 }
469 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700470
471 writeConfigurationFile();
472 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530473}
474
Patrick Williams6aef7692021-05-01 06:39:41 -0500475void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800476{
Patrick Williams6aef7692021-05-01 06:39:41 -0500477 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800478 if (it == staticNeighbors.end())
479 {
480 log<level::ERR>(
481 "DeleteStaticNeighborObject:Unable to find the object.");
482 return;
483 }
484 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700485
486 writeConfigurationFile();
487 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800488}
489
Ratan Guptae9c9b812017-09-22 17:15:37 +0530490void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530491{
Ratan Guptabc886292017-07-25 18:29:57 +0530492 auto confDir = manager.getConfDir();
493 fs::path networkFile = confDir;
494 networkFile /= systemd::config::networkFilePrefix + interface +
495 systemd::config::networkFileSuffix;
496
497 fs::path deviceFile = confDir;
498 deviceFile /= interface + systemd::config::deviceFileSuffix;
499
500 // delete the vlan network file
501 if (fs::is_regular_file(networkFile))
502 {
503 fs::remove(networkFile);
504 }
505
506 // delete the vlan device file
507 if (fs::is_regular_file(deviceFile))
508 {
509 fs::remove(deviceFile);
510 }
Ratan Guptabc886292017-07-25 18:29:57 +0530511
512 // TODO systemd doesn't delete the virtual network interface
513 // even after deleting all the related configuartion.
514 // https://github.com/systemd/systemd/issues/6600
515 try
516 {
517 deleteInterface(interface);
518 }
Patrick Williams5758db32021-10-06 12:29:22 -0500519 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530520 {
521 commit<InternalFailure>();
522 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530523}
524
525void EthernetInterface::deleteVLANObject(const std::string& interface)
526{
527 auto it = vlanInterfaces.find(interface);
528 if (it == vlanInterfaces.end())
529 {
530 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500531 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530532 return;
533 }
534
535 deleteVLANFromSystem(interface);
536 // delete the interface
537 vlanInterfaces.erase(it);
538
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700539 writeConfigurationFile();
540 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530541}
542
Gunnar Mills57d9c502018-09-14 14:42:34 -0500543std::string EthernetInterface::generateObjectPath(
544 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800545 uint8_t prefixLength, const std::string& gateway,
546 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530547{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530548 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530549 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530550 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
551
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530552 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530553 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530554 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800555 objectPath /=
556 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530557 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530558}
559
William A. Kennington III08505792019-01-30 16:00:04 -0800560std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500561 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800562{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530563 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800564 objectPath /= objPath;
565 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500566 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800567 return objectPath.string();
568}
569
Patrick Williams6aef7692021-05-01 06:39:41 -0500570bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700571{
Patrick Williams6aef7692021-05-01 06:39:41 -0500572 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700573 {
574 return value;
575 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500576 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700577
578 writeConfigurationFile();
579 manager.reloadConfigs();
580
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700581 return value;
582}
583
Patrick Williams6aef7692021-05-01 06:39:41 -0500584EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530585{
Patrick Williams6aef7692021-05-01 06:39:41 -0500586 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530587 {
588 return value;
589 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500590 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700591
592 writeConfigurationFile();
593 manager.reloadConfigs();
594
Ratan Gupta87c13982017-06-15 09:27:27 +0530595 return value;
596}
597
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800598bool EthernetInterface::linkUp() const
599{
600 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
601 bool value = EthernetInterfaceIntf::linkUp();
602
603 if (eifSocket.sock < 0)
604 {
605 return value;
606 }
607
William A. Kennington III05368f12021-05-13 18:40:47 -0700608 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800609 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
610 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
611 {
612 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
613 }
614 else
615 {
616 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
617 entry("ERROR=%s", strerror(errno)));
618 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700619 return value;
620}
621
Tejas Patil2c0fc562021-08-03 19:13:46 +0530622size_t EthernetInterface::mtu() const
623{
624 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
625 size_t value = EthernetInterfaceIntf::mtu();
626
627 if (eifSocket.sock < 0)
628 {
629 return value;
630 }
631
632 ifreq ifr = {};
633 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
634 if (ioctl(eifSocket.sock, SIOCGIFMTU, &ifr) == 0)
635 {
636 value = ifr.ifr_mtu;
637 }
638 else
639 {
640 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
641 entry("ERROR=%s", strerror(errno)));
642 }
643 return value;
644}
645
646size_t EthernetInterface::mtu(size_t value)
647{
648 if (value == EthernetInterfaceIntf::mtu())
649 {
650 return value;
651 }
652 else if (value == 0)
653 {
654 return EthernetInterfaceIntf::mtu();
655 }
656
657 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
658 if (eifSocket.sock < 0)
659 {
660 return EthernetInterfaceIntf::mtu();
661 }
662
663 ifreq ifr = {};
664 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
665 ifr.ifr_mtu = value;
666
667 if (ioctl(eifSocket.sock, SIOCSIFMTU, &ifr) != 0)
668 {
669 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
670 entry("ERROR=%s", strerror(errno)));
671 return EthernetInterfaceIntf::mtu();
672 }
673 EthernetInterfaceIntf::mtu(value);
674
675 return value;
676}
677
William A. Kennington III26275a32021-07-13 20:32:42 -0700678bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700679{
William A. Kennington III26275a32021-07-13 20:32:42 -0700680 constexpr auto svc = "org.freedesktop.network1";
681 constexpr auto intf = "org.freedesktop.network1.Link";
682 constexpr auto prop = "AdministrativeState";
683 char* rpath;
684 sd_bus_path_encode("/org/freedesktop/network1/link",
685 std::to_string(ifIndex()).c_str(), &rpath);
686 std::string path(rpath);
687 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700688
William A. Kennington III26275a32021-07-13 20:32:42 -0700689 // Store / Parser for the AdministrativeState return value
690 std::optional<bool> ret;
691 auto cb = [&](const std::string& state) {
692 if (state != "initialized")
693 {
694 ret = state != "unmanaged";
695 }
696 };
697
698 // Build a matcher before making the property call to ensure we
699 // can eventually get the value.
700 sdbusplus::bus::match::match match(
701 bus,
702 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
703 "'PropertiesChanged',arg0='{}',",
704 svc, path, PROPERTY_INTERFACE, intf)
705 .c_str(),
706 [&](sdbusplus::message::message& m) {
707 std::string intf;
708 std::unordered_map<std::string, std::variant<std::string>> values;
709 try
710 {
711 m.read(intf, values);
712 auto it = values.find(prop);
713 // Ignore properties that aren't AdministrativeState
714 if (it != values.end())
715 {
716 cb(std::get<std::string>(it->second));
717 }
718 }
719 catch (const std::exception& e)
720 {
721 log<level::ERR>(
722 fmt::format(
723 "AdministrativeState match parsing failed on {}: {}",
724 interfaceName(), e.what())
725 .c_str(),
726 entry("INTERFACE=%s", interfaceName().c_str()),
727 entry("ERROR=%s", e.what()));
728 }
729 });
730
731 // Actively call for the value in case the interface is already configured
732 auto method =
733 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
734 method.append(intf, prop);
735 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700736 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700737 auto reply = bus.call(method);
738 std::variant<std::string> state;
739 reply.read(state);
740 cb(std::get<std::string>(state));
741 }
742 catch (const std::exception& e)
743 {
744 log<level::ERR>(
745 fmt::format("Failed to get AdministrativeState on {}: {}",
746 interfaceName(), e.what())
747 .c_str(),
748 entry("INTERFACE=%s", interfaceName().c_str()),
749 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700750 }
751
William A. Kennington III26275a32021-07-13 20:32:42 -0700752 // The interface is not yet configured by systemd-networkd, wait until it
753 // signals us a valid state.
754 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700755 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700756 bus.wait();
757 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700758 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700759
760 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700761}
762
William A. Kennington III4209cee2021-10-23 18:14:21 -0700763static void setNICAdminState(int fd, const char* intf, bool up)
764{
765 ifreq ifr = {};
766 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
767 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0)
768 {
769 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
770 entry("ERROR=%s", strerror(errno)));
771 elog<InternalFailure>();
772 }
773
774 ifr.ifr_flags &= ~IFF_UP;
775 ifr.ifr_flags |= up ? IFF_UP : 0;
776
777 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
778 {
779 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
780 entry("ERROR=%s", strerror(errno)));
781 elog<InternalFailure>();
782 }
783}
784
Patrick Williams6aef7692021-05-01 06:39:41 -0500785bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700786{
Patrick Williams6aef7692021-05-01 06:39:41 -0500787 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700788 {
789 return value;
790 }
791
792 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
793 if (eifSocket.sock < 0)
794 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500795 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700796 }
William A. Kennington III4209cee2021-10-23 18:14:21 -0700797 auto ifname = interfaceName();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700798
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700799 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800800 if (!value)
801 {
802 // We only need to bring down the interface, networkd will always bring
803 // up managed interfaces
804 manager.addReloadPreHook(
805 [ifname = std::move(ifname), eifSocket = std::move(eifSocket)]() {
806 setNICAdminState(eifSocket.sock, ifname.c_str(), false);
807 });
808 }
809 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700810 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800811
812 return value;
813}
814
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530815ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530816{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530817 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
818 return EthernetInterfaceIntf::nameservers();
819}
820
821ServerList EthernetInterface::staticNameServers(ServerList value)
822{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530823 for (const auto& nameserverip : value)
824 {
825 if (!isValidIP(AF_INET, nameserverip) &&
826 !isValidIP(AF_INET6, nameserverip))
827 {
828 log<level::ERR>("Not a valid IP address"),
829 entry("ADDRESS=%s", nameserverip.c_str());
830 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530831 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530832 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
833 }
834 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530835 try
836 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530837 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700838
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530839 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700840 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530841 }
Patrick Williams5758db32021-10-06 12:29:22 -0500842 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530843 {
844 log<level::ERR>("Exception processing DNS entries");
845 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530846 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530847}
848
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530849void EthernetInterface::loadNameServers()
850{
851 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
852 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
853}
854
855ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530856{
857 fs::path confPath = manager.getConfDir();
858
859 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500860 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530861 confPath /= fileName;
862 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530863 config::Parser parser(confPath.string());
864 auto rc = config::ReturnCode::SUCCESS;
865
866 std::tie(rc, servers) = parser.getValues("Network", "DNS");
867 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530868 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530869 log<level::DEBUG>("Unable to get the value for network[DNS]",
870 entry("RC=%d", rc));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530871 }
872 return servers;
873}
874
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530875ServerList EthernetInterface::getNameServerFromResolvd()
876{
877 ServerList servers;
878 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
879
880 /*
881 The DNS property under org.freedesktop.resolve1.Link interface contains
882 an array containing all DNS servers currently used by resolved. It
883 contains similar information as the DNS server data written to
884 /run/systemd/resolve/resolv.conf.
885
886 Each structure in the array consists of a numeric network interface index,
887 an address family, and a byte array containing the DNS server address
888 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
889 The array contains DNS servers configured system-wide, including those
890 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
891 /etc/systemd/resolved.conf, as well as per-interface DNS server
892 information either retrieved from systemd-networkd or configured by
893 external software via SetLinkDNS().
894 */
895
896 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
897 std::variant<type> name; // Variable to capture the DNS property
898 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
899 PROPERTY_INTERFACE, METHOD_GET);
900
901 method.append(RESOLVED_INTERFACE, "DNS");
902 auto reply = bus.call(method);
903
904 try
905 {
906 reply.read(name);
907 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500908 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530909 {
910 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
911 }
912 auto tupleVector = std::get_if<type>(&name);
913 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
914 {
Alexander Filippov983da552021-02-08 15:26:54 +0300915 int addressFamily = std::get<0>(*i);
916 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
917
918 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530919 {
Alexander Filippov983da552021-02-08 15:26:54 +0300920 case AF_INET:
921 if (ipaddress.size() == sizeof(struct in_addr))
922 {
923 servers.push_back(toString(
924 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
925 }
926 else
927 {
928 log<level::ERR>(
929 "Invalid data recived from Systemd-Resolved");
930 }
931 break;
932
933 case AF_INET6:
934 if (ipaddress.size() == sizeof(struct in6_addr))
935 {
936 servers.push_back(toString(
937 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
938 }
939 else
940 {
941 log<level::ERR>(
942 "Invalid data recived from Systemd-Resolved");
943 }
944 break;
945
946 default:
947 log<level::ERR>(
948 "Unsupported address family in DNS from Systemd-Resolved");
949 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530950 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530951 }
952 return servers;
953}
954
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530955void EthernetInterface::loadVLAN(VlanId id)
956{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500957 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530958 std::string path = objPath;
959 path += "_" + std::to_string(id);
960
Johnathan Mantey817012a2020-01-30 15:07:39 -0800961 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500962 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530963 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500964 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800965 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530966
Gunnar Mills57d9c502018-09-14 14:42:34 -0500967 // Fetch the ip address from the system
968 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530969 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800970 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530971
972 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
973 std::move(vlanIntf));
974}
975
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700976ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530977{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500978 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530979 std::string path = objPath;
980 path += "_" + std::to_string(id);
981
Patrick Williams6aef7692021-05-01 06:39:41 -0500982 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530983 // VLAN interface can inherit.
984
Ratan Gupta5978dd12017-07-25 13:47:13 +0530985 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800986 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500987 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530988
989 // write the device file for the vlan interface.
990 vlanIntf->writeDeviceFile();
991
Gunnar Mills57d9c502018-09-14 14:42:34 -0500992 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700993
994 writeConfigurationFile();
995 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700996
997 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530998}
Ratan Gupta2b106532017-07-25 16:05:02 +0530999
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001000bool EthernetInterface::getIPv6AcceptRAFromConf()
1001{
1002 fs::path confPath = manager.getConfDir();
1003
1004 std::string fileName = systemd::config::networkFilePrefix +
1005 interfaceName() + systemd::config::networkFileSuffix;
1006 confPath /= fileName;
1007 config::ValueList values;
1008 config::Parser parser(confPath.string());
1009 auto rc = config::ReturnCode::SUCCESS;
1010 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
1011 if (rc != config::ReturnCode::SUCCESS)
1012 {
1013 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1014 entry("rc=%d", rc));
1015 return false;
1016 }
1017 return (values[0] == "true");
1018}
1019
Ratan Gupta497c0c92017-08-22 19:15:59 +05301020ServerList EthernetInterface::getNTPServersFromConf()
1021{
1022 fs::path confPath = manager.getConfDir();
1023
Gunnar Mills57d9c502018-09-14 14:42:34 -05001024 std::string fileName = systemd::config::networkFilePrefix +
1025 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301026 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301027
Ratan Gupta497c0c92017-08-22 19:15:59 +05301028 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301029 config::Parser parser(confPath.string());
1030 auto rc = config::ReturnCode::SUCCESS;
1031
1032 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1033 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301034 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301035 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1036 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301037 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301038
Ratan Gupta497c0c92017-08-22 19:15:59 +05301039 return servers;
1040}
1041
Patrick Williams6aef7692021-05-01 06:39:41 -05001042ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301043{
Patrick Williams6aef7692021-05-01 06:39:41 -05001044 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301045
1046 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001047 manager.reloadConfigs();
1048
Ratan Gupta497c0c92017-08-22 19:15:59 +05301049 return ntpServers;
1050}
Ratan Gupta2b106532017-07-25 16:05:02 +05301051// Need to merge the below function with the code which writes the
1052// config file during factory reset.
1053// TODO openbmc/openbmc#1751
1054
1055void EthernetInterface::writeConfigurationFile()
1056{
1057 // write all the static ip address in the systemd-network conf file
1058
1059 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301060 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301061
1062 // if there is vlan interafce then write the configuration file
1063 // for vlan also.
1064
Gunnar Mills57d9c502018-09-14 14:42:34 -05001065 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301066 {
1067 intf.second->writeConfigurationFile();
1068 }
1069
Ratan Gupta2b106532017-07-25 16:05:02 +05301070 fs::path confPath = manager.getConfDir();
1071
Gunnar Mills57d9c502018-09-14 14:42:34 -05001072 std::string fileName = systemd::config::networkFilePrefix +
1073 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301074 confPath /= fileName;
1075 std::fstream stream;
1076
1077 stream.open(confPath.c_str(), std::fstream::out);
1078 if (!stream.is_open())
1079 {
1080 log<level::ERR>("Unable to open the file",
1081 entry("FILE=%s", confPath.c_str()));
1082 elog<InternalFailure>();
1083 }
1084
1085 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001086 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301087 stream << "Name=" << interfaceName() << "\n";
1088
1089 auto addrs = getAddresses();
1090
William A. Kennington III15787212019-04-23 19:18:01 -07001091 // Write the link section
1092 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001093 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001094 if (!mac.empty())
1095 {
1096 stream << "MACAddress=" << mac << "\n";
1097 }
1098
Patrick Williams6aef7692021-05-01 06:39:41 -05001099 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001100 {
1101 stream << "Unmanaged=yes\n";
1102 }
1103
Ratan Gupta2b106532017-07-25 16:05:02 +05301104 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001105 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001106#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001107 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001108#else
1109 stream << "LinkLocalAddressing=no\n";
1110#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001111 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001112 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301113
1114 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001115 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301116 {
1117 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001118 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301119 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301120 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001121 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301122 {
1123 stream << "NTP=" << ntp << "\n";
1124 }
1125
1126 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301127 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301128 {
1129 stream << "DNS=" << dns << "\n";
1130 }
1131
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001132 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001133 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001134 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001135
Johnathan Mantey817012a2020-01-30 15:07:39 -08001136 // Static IP addresses
1137 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301138 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001139 if (originIsManuallyAssigned(addr.second->origin()) &&
1140 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001141 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001142 // Process all static addresses
1143 std::string address = addr.second->address() + "/" +
1144 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301145
Johnathan Mantey817012a2020-01-30 15:07:39 -08001146 // build the address entries. Do not use [Network] shortcuts to
1147 // insert address entries.
1148 stream << "[Address]\n";
1149 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001150 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001151 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001152
Lei YUcb2d4082021-08-12 15:26:49 +08001153 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001154 {
Lei YUcb2d4082021-08-12 15:26:49 +08001155 auto gateway = EthernetInterfaceIntf::defaultGateway();
1156 if (!gateway.empty())
1157 {
1158 stream << "[Route]\n";
1159 stream << "Gateway=" << gateway << "\n";
1160 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001161 }
1162
Lei YUcb2d4082021-08-12 15:26:49 +08001163 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001164 {
Lei YUcb2d4082021-08-12 15:26:49 +08001165 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1166 if (!gateway6.empty())
1167 {
1168 stream << "[Route]\n";
1169 stream << "Gateway=" << gateway6 << "\n";
1170 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001171 }
1172
William A. Kennington III08505792019-01-30 16:00:04 -08001173 // Write the neighbor sections
1174 for (const auto& neighbor : staticNeighbors)
1175 {
1176 stream << "[Neighbor]"
1177 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001178 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1179 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001180 }
1181
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001182 // Write the dhcp section irrespective of whether DHCP is enabled or not
1183 writeDHCPSection(stream);
1184
Ratan Gupta2b106532017-07-25 16:05:02 +05301185 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301186}
1187
1188void EthernetInterface::writeDHCPSection(std::fstream& stream)
1189{
1190 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301191 // write the dhcp section
1192 stream << "[DHCP]\n";
1193
1194 // Hardcoding the client identifier to mac, to address below issue
1195 // https://github.com/openbmc/openbmc/issues/1280
1196 stream << "ClientIdentifier=mac\n";
1197 if (manager.getDHCPConf())
1198 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001199 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301200 stream << "UseDNS="s + value + "\n";
1201
Patrick Williams6aef7692021-05-01 06:39:41 -05001202 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301203 stream << "UseNTP="s + value + "\n";
1204
1205 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1206 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001207
1208 value =
1209 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1210 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301211 }
1212}
1213
Patrick Williams6aef7692021-05-01 06:39:41 -05001214std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301215{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001216 ether_addr newMAC;
1217 try
1218 {
1219 newMAC = mac_address::fromString(value);
1220 }
Patrick Williams5758db32021-10-06 12:29:22 -05001221 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001222 {
1223 log<level::ERR>("MACAddress is not valid.",
1224 entry("MAC=%s", value.c_str()));
1225 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1226 Argument::ARGUMENT_VALUE(value.c_str()));
1227 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001228 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301229 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001230 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001231 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001232 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1233 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301234 }
1235
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001236 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001237 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001238
William A. Kennington III1137a972019-04-20 20:49:58 -07001239 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001240 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001241 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301242 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001243 // Update everything that depends on the MAC value
1244 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301245 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001246 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301247 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001248 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301249
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001250 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001251 manager.addReloadPreHook([interface]() {
1252 // The MAC and LLADDRs will only update if the NIC is already down
1253 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1254 setNICAdminState(eifSocket.sock, interface.c_str(), false);
1255 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001256 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301257 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001258
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001259#ifdef HAVE_UBOOT_ENV
1260 // Ensure that the valid address is stored in the u-boot-env
1261 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1262 if (envVar)
1263 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001264 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1265 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1266 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1267 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001268 }
1269#endif // HAVE_UBOOT_ENV
1270
William A. Kennington III1137a972019-04-20 20:49:58 -07001271 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301272}
1273
Ratan Guptae9c9b812017-09-22 17:15:37 +05301274void EthernetInterface::deleteAll()
1275{
Johnathan Mantey817012a2020-01-30 15:07:39 -08001276 if (dhcpIsEnabled(IP::Protocol::IPv4, true))
Ratan Guptae9c9b812017-09-22 17:15:37 +05301277 {
1278 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -05001279 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +05301280 }
1281
1282 // clear all the ip on the interface
1283 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001284
1285 writeConfigurationFile();
1286 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301287}
1288
Ravi Tejaa5a09442020-07-17 00:57:33 -05001289std::string EthernetInterface::defaultGateway(std::string gateway)
1290{
1291 auto gw = EthernetInterfaceIntf::defaultGateway();
1292 if (gw == gateway)
1293 {
1294 return gw;
1295 }
1296
1297 if (!isValidIP(AF_INET, gateway))
1298 {
1299 log<level::ERR>("Not a valid v4 Gateway",
1300 entry("GATEWAY=%s", gateway.c_str()));
1301 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1302 Argument::ARGUMENT_VALUE(gateway.c_str()));
1303 }
1304 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001305
1306 writeConfigurationFile();
1307 manager.reloadConfigs();
1308
Ravi Tejaa5a09442020-07-17 00:57:33 -05001309 return gw;
1310}
1311
1312std::string EthernetInterface::defaultGateway6(std::string gateway)
1313{
1314 auto gw = EthernetInterfaceIntf::defaultGateway6();
1315 if (gw == gateway)
1316 {
1317 return gw;
1318 }
1319
1320 if (!isValidIP(AF_INET6, gateway))
1321 {
1322 log<level::ERR>("Not a valid v6 Gateway",
1323 entry("GATEWAY=%s", gateway.c_str()));
1324 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1325 Argument::ARGUMENT_VALUE(gateway.c_str()));
1326 }
1327 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001328
1329 writeConfigurationFile();
1330 manager.reloadConfigs();
1331
Ravi Tejaa5a09442020-07-17 00:57:33 -05001332 return gw;
1333}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001334} // namespace network
1335} // namespace phosphor