blob: a42488d3b54f2205d9ecc2ce4e1e6a4105bb68d0 [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
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
Patrick Williams6aef7692021-05-01 06:39:41 -0500763bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700764{
Patrick Williams6aef7692021-05-01 06:39:41 -0500765 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700766 {
767 return value;
768 }
769
770 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
771 if (eifSocket.sock < 0)
772 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500773 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700774 }
775
William A. Kennington III05368f12021-05-13 18:40:47 -0700776 ifreq ifr = {};
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700777 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
778 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) != 0)
779 {
780 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
781 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500782 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700783 }
784
785 ifr.ifr_flags &= ~IFF_UP;
786 ifr.ifr_flags |= value ? IFF_UP : 0;
787
788 if (ioctl(eifSocket.sock, SIOCSIFFLAGS, &ifr) != 0)
789 {
790 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
791 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500792 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700793 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500794 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700795
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700796 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700797 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800798
799 return value;
800}
801
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530802ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530803{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530804 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
805 return EthernetInterfaceIntf::nameservers();
806}
807
808ServerList EthernetInterface::staticNameServers(ServerList value)
809{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530810 for (const auto& nameserverip : value)
811 {
812 if (!isValidIP(AF_INET, nameserverip) &&
813 !isValidIP(AF_INET6, nameserverip))
814 {
815 log<level::ERR>("Not a valid IP address"),
816 entry("ADDRESS=%s", nameserverip.c_str());
817 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530818 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530819 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
820 }
821 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530822 try
823 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530824 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700825
Ratan Gupta6dec3902017-08-20 15:28:12 +0530826 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700827 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530828 }
Patrick Williams5758db32021-10-06 12:29:22 -0500829 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530830 {
831 log<level::ERR>("Exception processing DNS entries");
832 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530833 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530834}
835
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530836void EthernetInterface::loadNameServers()
837{
838 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
839 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
840}
841
842ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec3902017-08-20 15:28:12 +0530843{
844 fs::path confPath = manager.getConfDir();
845
846 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500847 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530848 confPath /= fileName;
849 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530850 config::Parser parser(confPath.string());
851 auto rc = config::ReturnCode::SUCCESS;
852
853 std::tie(rc, servers) = parser.getValues("Network", "DNS");
854 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530855 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530856 log<level::DEBUG>("Unable to get the value for network[DNS]",
857 entry("RC=%d", rc));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530858 }
859 return servers;
860}
861
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530862ServerList EthernetInterface::getNameServerFromResolvd()
863{
864 ServerList servers;
865 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
866
867 /*
868 The DNS property under org.freedesktop.resolve1.Link interface contains
869 an array containing all DNS servers currently used by resolved. It
870 contains similar information as the DNS server data written to
871 /run/systemd/resolve/resolv.conf.
872
873 Each structure in the array consists of a numeric network interface index,
874 an address family, and a byte array containing the DNS server address
875 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
876 The array contains DNS servers configured system-wide, including those
877 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
878 /etc/systemd/resolved.conf, as well as per-interface DNS server
879 information either retrieved from systemd-networkd or configured by
880 external software via SetLinkDNS().
881 */
882
883 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
884 std::variant<type> name; // Variable to capture the DNS property
885 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
886 PROPERTY_INTERFACE, METHOD_GET);
887
888 method.append(RESOLVED_INTERFACE, "DNS");
889 auto reply = bus.call(method);
890
891 try
892 {
893 reply.read(name);
894 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500895 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530896 {
897 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
898 }
899 auto tupleVector = std::get_if<type>(&name);
900 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
901 {
Alexander Filippov983da552021-02-08 15:26:54 +0300902 int addressFamily = std::get<0>(*i);
903 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
904
905 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530906 {
Alexander Filippov983da552021-02-08 15:26:54 +0300907 case AF_INET:
908 if (ipaddress.size() == sizeof(struct in_addr))
909 {
910 servers.push_back(toString(
911 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
912 }
913 else
914 {
915 log<level::ERR>(
916 "Invalid data recived from Systemd-Resolved");
917 }
918 break;
919
920 case AF_INET6:
921 if (ipaddress.size() == sizeof(struct in6_addr))
922 {
923 servers.push_back(toString(
924 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
925 }
926 else
927 {
928 log<level::ERR>(
929 "Invalid data recived from Systemd-Resolved");
930 }
931 break;
932
933 default:
934 log<level::ERR>(
935 "Unsupported address family in DNS from Systemd-Resolved");
936 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530937 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530938 }
939 return servers;
940}
941
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530942void EthernetInterface::loadVLAN(VlanId id)
943{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500944 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530945 std::string path = objPath;
946 path += "_" + std::to_string(id);
947
Johnathan Mantey817012a2020-01-30 15:07:39 -0800948 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500949 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530950 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500951 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800952 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530953
Gunnar Mills57d9c502018-09-14 14:42:34 -0500954 // Fetch the ip address from the system
955 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530956 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800957 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530958
959 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
960 std::move(vlanIntf));
961}
962
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700963ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530964{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500965 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530966 std::string path = objPath;
967 path += "_" + std::to_string(id);
968
Patrick Williams6aef7692021-05-01 06:39:41 -0500969 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530970 // VLAN interface can inherit.
971
Ratan Gupta5978dd12017-07-25 13:47:13 +0530972 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800973 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500974 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530975
976 // write the device file for the vlan interface.
977 vlanIntf->writeDeviceFile();
978
Gunnar Mills57d9c502018-09-14 14:42:34 -0500979 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700980
981 writeConfigurationFile();
982 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700983
984 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530985}
Ratan Gupta2b106532017-07-25 16:05:02 +0530986
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700987bool EthernetInterface::getIPv6AcceptRAFromConf()
988{
989 fs::path confPath = manager.getConfDir();
990
991 std::string fileName = systemd::config::networkFilePrefix +
992 interfaceName() + systemd::config::networkFileSuffix;
993 confPath /= fileName;
994 config::ValueList values;
995 config::Parser parser(confPath.string());
996 auto rc = config::ReturnCode::SUCCESS;
997 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
998 if (rc != config::ReturnCode::SUCCESS)
999 {
1000 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1001 entry("rc=%d", rc));
1002 return false;
1003 }
1004 return (values[0] == "true");
1005}
1006
Ratan Gupta497c0c92017-08-22 19:15:59 +05301007ServerList EthernetInterface::getNTPServersFromConf()
1008{
1009 fs::path confPath = manager.getConfDir();
1010
Gunnar Mills57d9c502018-09-14 14:42:34 -05001011 std::string fileName = systemd::config::networkFilePrefix +
1012 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301013 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301014
Ratan Gupta497c0c92017-08-22 19:15:59 +05301015 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301016 config::Parser parser(confPath.string());
1017 auto rc = config::ReturnCode::SUCCESS;
1018
1019 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1020 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301021 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301022 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1023 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301024 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301025
Ratan Gupta497c0c92017-08-22 19:15:59 +05301026 return servers;
1027}
1028
Patrick Williams6aef7692021-05-01 06:39:41 -05001029ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301030{
Patrick Williams6aef7692021-05-01 06:39:41 -05001031 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301032
1033 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001034 manager.reloadConfigs();
1035
Ratan Gupta497c0c92017-08-22 19:15:59 +05301036 return ntpServers;
1037}
Ratan Gupta2b106532017-07-25 16:05:02 +05301038// Need to merge the below function with the code which writes the
1039// config file during factory reset.
1040// TODO openbmc/openbmc#1751
1041
1042void EthernetInterface::writeConfigurationFile()
1043{
1044 // write all the static ip address in the systemd-network conf file
1045
1046 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301047 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301048
1049 // if there is vlan interafce then write the configuration file
1050 // for vlan also.
1051
Gunnar Mills57d9c502018-09-14 14:42:34 -05001052 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301053 {
1054 intf.second->writeConfigurationFile();
1055 }
1056
Ratan Gupta2b106532017-07-25 16:05:02 +05301057 fs::path confPath = manager.getConfDir();
1058
Gunnar Mills57d9c502018-09-14 14:42:34 -05001059 std::string fileName = systemd::config::networkFilePrefix +
1060 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301061 confPath /= fileName;
1062 std::fstream stream;
1063
1064 stream.open(confPath.c_str(), std::fstream::out);
1065 if (!stream.is_open())
1066 {
1067 log<level::ERR>("Unable to open the file",
1068 entry("FILE=%s", confPath.c_str()));
1069 elog<InternalFailure>();
1070 }
1071
1072 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001073 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301074 stream << "Name=" << interfaceName() << "\n";
1075
1076 auto addrs = getAddresses();
1077
William A. Kennington III15787212019-04-23 19:18:01 -07001078 // Write the link section
1079 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001080 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001081 if (!mac.empty())
1082 {
1083 stream << "MACAddress=" << mac << "\n";
1084 }
1085
Patrick Williams6aef7692021-05-01 06:39:41 -05001086 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001087 {
1088 stream << "Unmanaged=yes\n";
1089 }
1090
Ratan Gupta2b106532017-07-25 16:05:02 +05301091 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001092 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001093#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001094 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001095#else
1096 stream << "LinkLocalAddressing=no\n";
1097#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001098 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001099 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301100
1101 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001102 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301103 {
1104 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001105 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301106 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301107 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001108 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301109 {
1110 stream << "NTP=" << ntp << "\n";
1111 }
1112
1113 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301114 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301115 {
1116 stream << "DNS=" << dns << "\n";
1117 }
1118
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001119 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001120 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001121 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001122
Johnathan Mantey817012a2020-01-30 15:07:39 -08001123 // Static IP addresses
1124 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301125 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001126 if (originIsManuallyAssigned(addr.second->origin()) &&
1127 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001128 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001129 // Process all static addresses
1130 std::string address = addr.second->address() + "/" +
1131 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301132
Johnathan Mantey817012a2020-01-30 15:07:39 -08001133 // build the address entries. Do not use [Network] shortcuts to
1134 // insert address entries.
1135 stream << "[Address]\n";
1136 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001137 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001138 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001139
Lei YUcb2d4082021-08-12 15:26:49 +08001140 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001141 {
Lei YUcb2d4082021-08-12 15:26:49 +08001142 auto gateway = EthernetInterfaceIntf::defaultGateway();
1143 if (!gateway.empty())
1144 {
1145 stream << "[Route]\n";
1146 stream << "Gateway=" << gateway << "\n";
1147 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001148 }
1149
Lei YUcb2d4082021-08-12 15:26:49 +08001150 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001151 {
Lei YUcb2d4082021-08-12 15:26:49 +08001152 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1153 if (!gateway6.empty())
1154 {
1155 stream << "[Route]\n";
1156 stream << "Gateway=" << gateway6 << "\n";
1157 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001158 }
1159
William A. Kennington III08505792019-01-30 16:00:04 -08001160 // Write the neighbor sections
1161 for (const auto& neighbor : staticNeighbors)
1162 {
1163 stream << "[Neighbor]"
1164 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001165 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1166 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001167 }
1168
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001169 // Write the dhcp section irrespective of whether DHCP is enabled or not
1170 writeDHCPSection(stream);
1171
Ratan Gupta2b106532017-07-25 16:05:02 +05301172 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301173}
1174
1175void EthernetInterface::writeDHCPSection(std::fstream& stream)
1176{
1177 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301178 // write the dhcp section
1179 stream << "[DHCP]\n";
1180
1181 // Hardcoding the client identifier to mac, to address below issue
1182 // https://github.com/openbmc/openbmc/issues/1280
1183 stream << "ClientIdentifier=mac\n";
1184 if (manager.getDHCPConf())
1185 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001186 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301187 stream << "UseDNS="s + value + "\n";
1188
Patrick Williams6aef7692021-05-01 06:39:41 -05001189 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301190 stream << "UseNTP="s + value + "\n";
1191
1192 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1193 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001194
1195 value =
1196 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1197 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301198 }
1199}
1200
Patrick Williams6aef7692021-05-01 06:39:41 -05001201std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301202{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001203 ether_addr newMAC;
1204 try
1205 {
1206 newMAC = mac_address::fromString(value);
1207 }
Patrick Williams5758db32021-10-06 12:29:22 -05001208 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001209 {
1210 log<level::ERR>("MACAddress is not valid.",
1211 entry("MAC=%s", value.c_str()));
1212 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1213 Argument::ARGUMENT_VALUE(value.c_str()));
1214 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001215 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301216 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001217 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001218 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001219 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1220 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301221 }
1222
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001223 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001224 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001225
William A. Kennington III1137a972019-04-20 20:49:58 -07001226 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001227 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001228 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301229 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001230 // Update everything that depends on the MAC value
1231 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301232 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001233 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301234 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001235 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301236
William A. Kennington III15787212019-04-23 19:18:01 -07001237 // TODO: would remove the call below and
1238 // just restart systemd-netwokd
William A. Kennington III1137a972019-04-20 20:49:58 -07001239 // through https://github.com/systemd/systemd/issues/6696
1240 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(),
1241 "down");
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001242 writeConfigurationFile();
1243 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301244 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001245
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001246#ifdef HAVE_UBOOT_ENV
1247 // Ensure that the valid address is stored in the u-boot-env
1248 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1249 if (envVar)
1250 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001251 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1252 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1253 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1254 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001255 }
1256#endif // HAVE_UBOOT_ENV
1257
William A. Kennington III1137a972019-04-20 20:49:58 -07001258 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301259}
1260
Ratan Guptae9c9b812017-09-22 17:15:37 +05301261void EthernetInterface::deleteAll()
1262{
Johnathan Mantey817012a2020-01-30 15:07:39 -08001263 if (dhcpIsEnabled(IP::Protocol::IPv4, true))
Ratan Guptae9c9b812017-09-22 17:15:37 +05301264 {
1265 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -05001266 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +05301267 }
1268
1269 // clear all the ip on the interface
1270 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001271
1272 writeConfigurationFile();
1273 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301274}
1275
Ravi Tejaa5a09442020-07-17 00:57:33 -05001276std::string EthernetInterface::defaultGateway(std::string gateway)
1277{
1278 auto gw = EthernetInterfaceIntf::defaultGateway();
1279 if (gw == gateway)
1280 {
1281 return gw;
1282 }
1283
1284 if (!isValidIP(AF_INET, gateway))
1285 {
1286 log<level::ERR>("Not a valid v4 Gateway",
1287 entry("GATEWAY=%s", gateway.c_str()));
1288 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1289 Argument::ARGUMENT_VALUE(gateway.c_str()));
1290 }
1291 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001292
1293 writeConfigurationFile();
1294 manager.reloadConfigs();
1295
Ravi Tejaa5a09442020-07-17 00:57:33 -05001296 return gw;
1297}
1298
1299std::string EthernetInterface::defaultGateway6(std::string gateway)
1300{
1301 auto gw = EthernetInterfaceIntf::defaultGateway6();
1302 if (gw == gateway)
1303 {
1304 return gw;
1305 }
1306
1307 if (!isValidIP(AF_INET6, gateway))
1308 {
1309 log<level::ERR>("Not a valid v6 Gateway",
1310 entry("GATEWAY=%s", gateway.c_str()));
1311 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1312 Argument::ARGUMENT_VALUE(gateway.c_str()));
1313 }
1314 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001315
1316 writeConfigurationFile();
1317 manager.reloadConfigs();
1318
Ravi Tejaa5a09442020-07-17 00:57:33 -05001319 return gw;
1320}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001321} // namespace network
1322} // namespace phosphor