blob: 2e15803bd36081f6aebddcf3a6bc4ae41a9c2354 [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
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();
798 setNICAdminState(eifSocket.sock, ifname.c_str(), value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700799
Patrick Williams6aef7692021-05-01 06:39:41 -0500800 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700801
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700802 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700803 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800804
805 return value;
806}
807
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530808ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530809{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530810 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
811 return EthernetInterfaceIntf::nameservers();
812}
813
814ServerList EthernetInterface::staticNameServers(ServerList value)
815{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530816 for (const auto& nameserverip : value)
817 {
818 if (!isValidIP(AF_INET, nameserverip) &&
819 !isValidIP(AF_INET6, nameserverip))
820 {
821 log<level::ERR>("Not a valid IP address"),
822 entry("ADDRESS=%s", nameserverip.c_str());
823 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530824 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530825 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
826 }
827 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530828 try
829 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530830 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700831
Ratan Gupta6dec3902017-08-20 15:28:12 +0530832 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700833 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530834 }
Patrick Williams5758db32021-10-06 12:29:22 -0500835 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530836 {
837 log<level::ERR>("Exception processing DNS entries");
838 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530839 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530840}
841
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530842void EthernetInterface::loadNameServers()
843{
844 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
845 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
846}
847
848ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec3902017-08-20 15:28:12 +0530849{
850 fs::path confPath = manager.getConfDir();
851
852 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500853 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530854 confPath /= fileName;
855 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530856 config::Parser parser(confPath.string());
857 auto rc = config::ReturnCode::SUCCESS;
858
859 std::tie(rc, servers) = parser.getValues("Network", "DNS");
860 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530861 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530862 log<level::DEBUG>("Unable to get the value for network[DNS]",
863 entry("RC=%d", rc));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530864 }
865 return servers;
866}
867
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530868ServerList EthernetInterface::getNameServerFromResolvd()
869{
870 ServerList servers;
871 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
872
873 /*
874 The DNS property under org.freedesktop.resolve1.Link interface contains
875 an array containing all DNS servers currently used by resolved. It
876 contains similar information as the DNS server data written to
877 /run/systemd/resolve/resolv.conf.
878
879 Each structure in the array consists of a numeric network interface index,
880 an address family, and a byte array containing the DNS server address
881 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
882 The array contains DNS servers configured system-wide, including those
883 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
884 /etc/systemd/resolved.conf, as well as per-interface DNS server
885 information either retrieved from systemd-networkd or configured by
886 external software via SetLinkDNS().
887 */
888
889 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
890 std::variant<type> name; // Variable to capture the DNS property
891 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
892 PROPERTY_INTERFACE, METHOD_GET);
893
894 method.append(RESOLVED_INTERFACE, "DNS");
895 auto reply = bus.call(method);
896
897 try
898 {
899 reply.read(name);
900 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500901 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530902 {
903 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
904 }
905 auto tupleVector = std::get_if<type>(&name);
906 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
907 {
Alexander Filippov983da552021-02-08 15:26:54 +0300908 int addressFamily = std::get<0>(*i);
909 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
910
911 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530912 {
Alexander Filippov983da552021-02-08 15:26:54 +0300913 case AF_INET:
914 if (ipaddress.size() == sizeof(struct in_addr))
915 {
916 servers.push_back(toString(
917 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
918 }
919 else
920 {
921 log<level::ERR>(
922 "Invalid data recived from Systemd-Resolved");
923 }
924 break;
925
926 case AF_INET6:
927 if (ipaddress.size() == sizeof(struct in6_addr))
928 {
929 servers.push_back(toString(
930 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
931 }
932 else
933 {
934 log<level::ERR>(
935 "Invalid data recived from Systemd-Resolved");
936 }
937 break;
938
939 default:
940 log<level::ERR>(
941 "Unsupported address family in DNS from Systemd-Resolved");
942 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530943 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530944 }
945 return servers;
946}
947
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530948void EthernetInterface::loadVLAN(VlanId id)
949{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500950 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530951 std::string path = objPath;
952 path += "_" + std::to_string(id);
953
Johnathan Mantey817012a2020-01-30 15:07:39 -0800954 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500955 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530956 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500957 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800958 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530959
Gunnar Mills57d9c502018-09-14 14:42:34 -0500960 // Fetch the ip address from the system
961 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530962 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800963 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530964
965 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
966 std::move(vlanIntf));
967}
968
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700969ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530970{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500971 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530972 std::string path = objPath;
973 path += "_" + std::to_string(id);
974
Patrick Williams6aef7692021-05-01 06:39:41 -0500975 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530976 // VLAN interface can inherit.
977
Ratan Gupta5978dd12017-07-25 13:47:13 +0530978 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800979 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500980 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530981
982 // write the device file for the vlan interface.
983 vlanIntf->writeDeviceFile();
984
Gunnar Mills57d9c502018-09-14 14:42:34 -0500985 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700986
987 writeConfigurationFile();
988 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700989
990 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530991}
Ratan Gupta2b106532017-07-25 16:05:02 +0530992
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700993bool EthernetInterface::getIPv6AcceptRAFromConf()
994{
995 fs::path confPath = manager.getConfDir();
996
997 std::string fileName = systemd::config::networkFilePrefix +
998 interfaceName() + systemd::config::networkFileSuffix;
999 confPath /= fileName;
1000 config::ValueList values;
1001 config::Parser parser(confPath.string());
1002 auto rc = config::ReturnCode::SUCCESS;
1003 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
1004 if (rc != config::ReturnCode::SUCCESS)
1005 {
1006 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1007 entry("rc=%d", rc));
1008 return false;
1009 }
1010 return (values[0] == "true");
1011}
1012
Ratan Gupta497c0c92017-08-22 19:15:59 +05301013ServerList EthernetInterface::getNTPServersFromConf()
1014{
1015 fs::path confPath = manager.getConfDir();
1016
Gunnar Mills57d9c502018-09-14 14:42:34 -05001017 std::string fileName = systemd::config::networkFilePrefix +
1018 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301019 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301020
Ratan Gupta497c0c92017-08-22 19:15:59 +05301021 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301022 config::Parser parser(confPath.string());
1023 auto rc = config::ReturnCode::SUCCESS;
1024
1025 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1026 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301027 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301028 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1029 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301030 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301031
Ratan Gupta497c0c92017-08-22 19:15:59 +05301032 return servers;
1033}
1034
Patrick Williams6aef7692021-05-01 06:39:41 -05001035ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301036{
Patrick Williams6aef7692021-05-01 06:39:41 -05001037 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301038
1039 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001040 manager.reloadConfigs();
1041
Ratan Gupta497c0c92017-08-22 19:15:59 +05301042 return ntpServers;
1043}
Ratan Gupta2b106532017-07-25 16:05:02 +05301044// Need to merge the below function with the code which writes the
1045// config file during factory reset.
1046// TODO openbmc/openbmc#1751
1047
1048void EthernetInterface::writeConfigurationFile()
1049{
1050 // write all the static ip address in the systemd-network conf file
1051
1052 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301053 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301054
1055 // if there is vlan interafce then write the configuration file
1056 // for vlan also.
1057
Gunnar Mills57d9c502018-09-14 14:42:34 -05001058 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301059 {
1060 intf.second->writeConfigurationFile();
1061 }
1062
Ratan Gupta2b106532017-07-25 16:05:02 +05301063 fs::path confPath = manager.getConfDir();
1064
Gunnar Mills57d9c502018-09-14 14:42:34 -05001065 std::string fileName = systemd::config::networkFilePrefix +
1066 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301067 confPath /= fileName;
1068 std::fstream stream;
1069
1070 stream.open(confPath.c_str(), std::fstream::out);
1071 if (!stream.is_open())
1072 {
1073 log<level::ERR>("Unable to open the file",
1074 entry("FILE=%s", confPath.c_str()));
1075 elog<InternalFailure>();
1076 }
1077
1078 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001079 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301080 stream << "Name=" << interfaceName() << "\n";
1081
1082 auto addrs = getAddresses();
1083
William A. Kennington III15787212019-04-23 19:18:01 -07001084 // Write the link section
1085 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001086 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001087 if (!mac.empty())
1088 {
1089 stream << "MACAddress=" << mac << "\n";
1090 }
1091
Patrick Williams6aef7692021-05-01 06:39:41 -05001092 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001093 {
1094 stream << "Unmanaged=yes\n";
1095 }
1096
Ratan Gupta2b106532017-07-25 16:05:02 +05301097 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001098 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001099#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001100 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001101#else
1102 stream << "LinkLocalAddressing=no\n";
1103#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001104 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001105 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301106
1107 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001108 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301109 {
1110 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001111 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301112 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301113 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001114 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301115 {
1116 stream << "NTP=" << ntp << "\n";
1117 }
1118
1119 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301120 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301121 {
1122 stream << "DNS=" << dns << "\n";
1123 }
1124
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001125 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001126 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001127 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001128
Johnathan Mantey817012a2020-01-30 15:07:39 -08001129 // Static IP addresses
1130 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301131 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001132 if (originIsManuallyAssigned(addr.second->origin()) &&
1133 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001134 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001135 // Process all static addresses
1136 std::string address = addr.second->address() + "/" +
1137 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301138
Johnathan Mantey817012a2020-01-30 15:07:39 -08001139 // build the address entries. Do not use [Network] shortcuts to
1140 // insert address entries.
1141 stream << "[Address]\n";
1142 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001143 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001144 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001145
Lei YUcb2d4082021-08-12 15:26:49 +08001146 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001147 {
Lei YUcb2d4082021-08-12 15:26:49 +08001148 auto gateway = EthernetInterfaceIntf::defaultGateway();
1149 if (!gateway.empty())
1150 {
1151 stream << "[Route]\n";
1152 stream << "Gateway=" << gateway << "\n";
1153 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001154 }
1155
Lei YUcb2d4082021-08-12 15:26:49 +08001156 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001157 {
Lei YUcb2d4082021-08-12 15:26:49 +08001158 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1159 if (!gateway6.empty())
1160 {
1161 stream << "[Route]\n";
1162 stream << "Gateway=" << gateway6 << "\n";
1163 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001164 }
1165
William A. Kennington III08505792019-01-30 16:00:04 -08001166 // Write the neighbor sections
1167 for (const auto& neighbor : staticNeighbors)
1168 {
1169 stream << "[Neighbor]"
1170 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001171 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1172 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001173 }
1174
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001175 // Write the dhcp section irrespective of whether DHCP is enabled or not
1176 writeDHCPSection(stream);
1177
Ratan Gupta2b106532017-07-25 16:05:02 +05301178 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301179}
1180
1181void EthernetInterface::writeDHCPSection(std::fstream& stream)
1182{
1183 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301184 // write the dhcp section
1185 stream << "[DHCP]\n";
1186
1187 // Hardcoding the client identifier to mac, to address below issue
1188 // https://github.com/openbmc/openbmc/issues/1280
1189 stream << "ClientIdentifier=mac\n";
1190 if (manager.getDHCPConf())
1191 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001192 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301193 stream << "UseDNS="s + value + "\n";
1194
Patrick Williams6aef7692021-05-01 06:39:41 -05001195 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301196 stream << "UseNTP="s + value + "\n";
1197
1198 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1199 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001200
1201 value =
1202 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1203 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301204 }
1205}
1206
Patrick Williams6aef7692021-05-01 06:39:41 -05001207std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301208{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001209 ether_addr newMAC;
1210 try
1211 {
1212 newMAC = mac_address::fromString(value);
1213 }
Patrick Williams5758db32021-10-06 12:29:22 -05001214 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001215 {
1216 log<level::ERR>("MACAddress is not valid.",
1217 entry("MAC=%s", value.c_str()));
1218 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1219 Argument::ARGUMENT_VALUE(value.c_str()));
1220 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001221 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301222 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001223 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001224 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001225 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1226 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301227 }
1228
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001229 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001230 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001231
William A. Kennington III1137a972019-04-20 20:49:58 -07001232 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001233 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001234 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301235 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001236 // Update everything that depends on the MAC value
1237 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301238 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001239 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301240 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001241 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301242
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001243 writeConfigurationFile();
William A. Kennington III4209cee2021-10-23 18:14:21 -07001244 // The MAC and LLADDRs will only update if the NIC is already down
1245 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1246 setNICAdminState(eifSocket.sock, interface.c_str(), false);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001247 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301248 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001249
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001250#ifdef HAVE_UBOOT_ENV
1251 // Ensure that the valid address is stored in the u-boot-env
1252 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1253 if (envVar)
1254 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001255 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1256 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1257 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1258 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001259 }
1260#endif // HAVE_UBOOT_ENV
1261
William A. Kennington III1137a972019-04-20 20:49:58 -07001262 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301263}
1264
Ratan Guptae9c9b812017-09-22 17:15:37 +05301265void EthernetInterface::deleteAll()
1266{
Johnathan Mantey817012a2020-01-30 15:07:39 -08001267 if (dhcpIsEnabled(IP::Protocol::IPv4, true))
Ratan Guptae9c9b812017-09-22 17:15:37 +05301268 {
1269 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -05001270 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +05301271 }
1272
1273 // clear all the ip on the interface
1274 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001275
1276 writeConfigurationFile();
1277 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301278}
1279
Ravi Tejaa5a09442020-07-17 00:57:33 -05001280std::string EthernetInterface::defaultGateway(std::string gateway)
1281{
1282 auto gw = EthernetInterfaceIntf::defaultGateway();
1283 if (gw == gateway)
1284 {
1285 return gw;
1286 }
1287
1288 if (!isValidIP(AF_INET, gateway))
1289 {
1290 log<level::ERR>("Not a valid v4 Gateway",
1291 entry("GATEWAY=%s", gateway.c_str()));
1292 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1293 Argument::ARGUMENT_VALUE(gateway.c_str()));
1294 }
1295 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001296
1297 writeConfigurationFile();
1298 manager.reloadConfigs();
1299
Ravi Tejaa5a09442020-07-17 00:57:33 -05001300 return gw;
1301}
1302
1303std::string EthernetInterface::defaultGateway6(std::string gateway)
1304{
1305 auto gw = EthernetInterfaceIntf::defaultGateway6();
1306 if (gw == gateway)
1307 {
1308 return gw;
1309 }
1310
1311 if (!isValidIP(AF_INET6, gateway))
1312 {
1313 log<level::ERR>("Not a valid v6 Gateway",
1314 entry("GATEWAY=%s", gateway.c_str()));
1315 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1316 Argument::ARGUMENT_VALUE(gateway.c_str()));
1317 }
1318 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001319
1320 writeConfigurationFile();
1321 manager.reloadConfigs();
1322
Ravi Tejaa5a09442020-07-17 00:57:33 -05001323 return gw;
1324}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001325} // namespace network
1326} // namespace phosphor