blob: 44f46f6ff93f9dfe605fff7d83a900faa69c72e1 [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include "config.h"
2
Patrick Venture189d44e2018-07-09 12:30:59 -07003#include "ethernet_interface.hpp"
4
Ratan Gupta497c0c92017-08-22 19:15:59 +05305#include "config_parser.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08006#include "neighbor.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05307#include "network_manager.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05308#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309
Ratan Gupta82549cc2017-04-21 08:45:23 +053010#include <arpa/inet.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070011#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053012#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070013#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016#include <netinet/in.h>
17#include <sys/ioctl.h>
18#include <sys/socket.h>
19#include <unistd.h>
20
Ratan Gupta82549cc2017-04-21 08:45:23 +053021#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053022#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070024#include <phosphor-logging/elog-errors.hpp>
25#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070026#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053027#include <sstream>
William A. Kennington III12beaad2020-06-13 19:30:41 -070028#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053029#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070030#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070031#include <unordered_map>
32#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070033#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053034
Ratan Gupta91a99cc2017-04-14 16:32:09 +053035namespace phosphor
36{
37namespace network
38{
39
40using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053041using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053042using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
43using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050044using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053045constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
46constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
47constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
48constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
49constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053050
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080051struct EthernetIntfSocket
52{
53 EthernetIntfSocket(int domain, int type, int protocol)
54 {
55 if ((sock = socket(domain, type, protocol)) < 0)
56 {
57 log<level::ERR>("socket creation failed:",
58 entry("ERROR=%s", strerror(errno)));
59 }
60 }
61
62 ~EthernetIntfSocket()
63 {
64 if (sock >= 0)
65 {
66 close(sock);
67 }
68 }
69
70 int sock{-1};
71};
72
Johnathan Mantey817012a2020-01-30 15:07:39 -080073std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
74 {EthernetInterface::DHCPConf::both, "true"},
75 {EthernetInterface::DHCPConf::v4, "ipv4"},
76 {EthernetInterface::DHCPConf::v6, "ipv6"},
77 {EthernetInterface::DHCPConf::none, "false"}};
78
Ratan Gupta91a99cc2017-04-14 16:32:09 +053079EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
80 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080081 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070082 bool emitSignal,
83 std::optional<bool> enabled) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050084 Ifaces(bus, objPath.c_str(), true),
85 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053086{
87 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053088 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053089 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050090 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
91 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070092 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070093 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
94 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050095 std::string defaultGateway;
96 std::string defaultGateway6;
97
William A. Kennington IIIe0564842021-10-23 16:02:22 -070098 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050099 {
100 if (gateway.first == intfName)
101 {
102 defaultGateway = gateway.second;
103 break;
104 }
105 }
106
William A. Kennington IIIe0564842021-10-23 16:02:22 -0700107 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500108 {
109 if (gateway6.first == intfName)
110 {
111 defaultGateway6 = gateway6.second;
112 break;
113 }
114 }
115
116 EthernetInterfaceIntf::defaultGateway(defaultGateway);
117 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530118 // Don't get the mac address from the system as the mac address
119 // would be same as parent interface.
120 if (intfName.find(".") == std::string::npos)
121 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500122 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530123 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500124 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
Ratan Gupta613a0122020-04-24 15:18:53 +0530125
126 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530127 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530128
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700129#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700130 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
131
132 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
133 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800134#endif
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530135
Ratan Gupta29b0e432017-05-25 12:51:40 +0530136 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530137 if (emitSignal)
138 {
139 this->emit_object_added();
140 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530141}
142
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800143static IP::Protocol convertFamily(int family)
144{
145 switch (family)
146 {
147 case AF_INET:
148 return IP::Protocol::IPv4;
149 case AF_INET6:
150 return IP::Protocol::IPv6;
151 }
152
153 throw std::invalid_argument("Bad address family");
154}
155
Johnathan Mantey817012a2020-01-30 15:07:39 -0800156void EthernetInterface::disableDHCP(IP::Protocol protocol)
157{
Patrick Williams6aef7692021-05-01 06:39:41 -0500158 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800159 if (dhcpState == EthernetInterface::DHCPConf::both)
160 {
161 if (protocol == IP::Protocol::IPv4)
162 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500163 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800164 }
165 else if (protocol == IP::Protocol::IPv6)
166 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500167 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800168 }
169 }
170 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
171 (protocol == IP::Protocol::IPv4))
172 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500173 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800174 }
175 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
176 (protocol == IP::Protocol::IPv6))
177 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500178 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800179 }
180}
181
William A. Kennington III24957b92021-12-03 13:59:19 -0800182bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800183{
William A. Kennington III24957b92021-12-03 13:59:19 -0800184 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
185 return cur == EthernetInterface::DHCPConf::both ||
186 (family == IP::Protocol::IPv6 &&
187 cur == EthernetInterface::DHCPConf::v6) ||
188 (family == IP::Protocol::IPv4 &&
189 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800190}
191
Johnathan Mantey817012a2020-01-30 15:07:39 -0800192bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
193{
194 return (
195#ifdef LINK_LOCAL_AUTOCONFIGURATION
196 (origin == IP::AddressOrigin::Static)
197#else
198 (origin == IP::AddressOrigin::Static ||
199 origin == IP::AddressOrigin::LinkLocal)
200#endif
201
202 );
203}
204
Ratan Gupta87c13982017-06-15 09:27:27 +0530205void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530206{
Ratan Gupta87c13982017-06-15 09:27:27 +0530207 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530208
Ratan Gupta87c13982017-06-15 09:27:27 +0530209 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530210
Ratan Gupta6a387c12017-08-03 13:26:19 +0530211 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530212 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800213 IP::Protocol addressType = convertFamily(addr.addrType);
214 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800215 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530216 {
217 origin = IP::AddressOrigin::DHCP;
218 }
William A. Kennington III16893802019-01-30 16:01:01 -0800219 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530220 {
221 origin = IP::AddressOrigin::LinkLocal;
222 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700223 // Obsolete parameter
224 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530225
Gunnar Mills57d9c502018-09-14 14:42:34 -0500226 std::string ipAddressObjectPath = generateObjectPath(
Lei YU34027572021-08-11 15:23:52 +0800227 addressType, addr.ipaddress, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530228
Lei YU7233c582021-04-08 14:39:43 +0800229 this->addrs.insert_or_assign(
230 addr.ipaddress,
231 std::make_shared<phosphor::network::IPAddress>(
232 bus, ipAddressObjectPath.c_str(), *this, addressType,
233 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530234 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530235}
236
William A. Kennington III08505792019-01-30 16:00:04 -0800237void EthernetInterface::createStaticNeighborObjects()
238{
239 staticNeighbors.clear();
240
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700241 NeighborFilter filter;
242 filter.interface = ifIndex();
243 filter.state = NUD_PERMANENT;
244 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800245 for (const auto& neighbor : neighbors)
246 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700247 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800248 {
249 continue;
250 }
251 std::string ip = toString(neighbor.address);
252 std::string mac = mac_address::toString(*neighbor.mac);
253 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
254 staticNeighbors.emplace(ip,
255 std::make_shared<phosphor::network::Neighbor>(
256 bus, objectPath.c_str(), *this, ip, mac,
257 Neighbor::State::Permanent));
258 }
259}
260
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700261unsigned EthernetInterface::ifIndex() const
262{
263 unsigned idx = if_nametoindex(interfaceName().c_str());
264 if (idx == 0)
265 {
266 throw std::system_error(errno, std::generic_category(),
267 "if_nametoindex");
268 }
269 return idx;
270}
271
Patrick Williams6aef7692021-05-01 06:39:41 -0500272ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500273 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530274{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800275 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530276 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530277 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500278 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800279 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500280 }
281
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500282 IP::AddressOrigin origin = IP::AddressOrigin::Static;
283
284 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
285
286 if (!isValidIP(addressFamily, ipaddress))
287 {
288 log<level::ERR>("Not a valid IP address"),
289 entry("ADDRESS=%s", ipaddress.c_str());
290 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
291 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
292 }
293
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700294 // Gateway is an obsolete parameter
295 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500296
297 if (!isValidPrefix(addressFamily, prefixLength))
298 {
299 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700300 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500301 elog<InvalidArgument>(
302 Argument::ARGUMENT_NAME("prefixLength"),
303 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530304 }
305
Gunnar Mills57d9c502018-09-14 14:42:34 -0500306 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800307 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800308 this->addrs.insert_or_assign(ipaddress,
309 std::make_shared<phosphor::network::IPAddress>(
310 bus, objectPath.c_str(), *this, protType,
311 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530312
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700313 writeConfigurationFile();
314 manager.reloadConfigs();
315
raviteja-bce379562019-03-28 05:59:36 -0500316 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530317}
318
Patrick Williams6aef7692021-05-01 06:39:41 -0500319ObjectPath EthernetInterface::neighbor(std::string ipAddress,
320 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800321{
Patrick Williams6aef7692021-05-01 06:39:41 -0500322 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800323 {
324 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500325 entry("ADDRESS=%s", ipAddress.c_str()));
326 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
327 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800328 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500329 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800330 {
331 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500332 entry("MACADDRESS=%s", ipAddress.c_str()));
333 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
334 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800335 }
336
337 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500338 generateStaticNeighborObjectPath(ipAddress, macAddress);
339 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800340 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500341 bus, objectPath.c_str(), *this, ipAddress,
342 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700343
344 writeConfigurationFile();
345 manager.reloadConfigs();
346
William A. Kennington III08505792019-01-30 16:00:04 -0800347 return objectPath;
348}
349
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700350#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530351/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800352 Enable this code if your NIC driver supports the ETHTOOL features.
353 Do this by adding the following to your phosphor-network*.bbappend file.
354 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
355 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530356*/
357InterfaceInfo EthernetInterface::getInterfaceInfo() const
358{
William A. Kennington III05368f12021-05-13 18:40:47 -0700359 ifreq ifr = {};
360 ethtool_cmd edata = {};
361 LinkSpeed speed = {};
362 Autoneg autoneg = {};
363 DuplexMode duplex = {};
364 LinkUp linkState = {};
365 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530366 MTU mtuSize = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800367 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
368
369 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530370 {
Tejas Patil2c0fc562021-08-03 19:13:46 +0530371 return std::make_tuple(speed, duplex, autoneg, linkState, enabled,
372 mtuSize);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800373 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530374
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800375 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
376 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530377
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800378 edata.cmd = ETHTOOL_GSET;
379 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
380 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530381 speed = edata.speed;
382 duplex = edata.duplex;
383 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800385
William A. Kennington III96203312021-05-07 12:50:41 -0700386 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800387 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530388 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800389
Tejas Patil2c0fc562021-08-03 19:13:46 +0530390 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530391}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800392#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530393
394/** @brief get the mac address of the interface.
395 * @return macaddress on success
396 */
397
Gunnar Mills57d9c502018-09-14 14:42:34 -0500398std::string
399 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530400{
Patrick Williams6aef7692021-05-01 06:39:41 -0500401 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800402 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
403
404 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530405 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800406 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530407 }
408
William A. Kennington III05368f12021-05-13 18:40:47 -0700409 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800410 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
411 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530412 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530413 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500414 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700415 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530416 }
417
William A. Kennington III1137a972019-04-20 20:49:58 -0700418 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
419 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
420 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700421 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530422}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530423
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530424std::string EthernetInterface::generateId(const std::string& ipaddress,
425 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800426 const std::string& gateway,
427 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530428{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530429 std::stringstream hexId;
430 std::string hashString = ipaddress;
431 hashString += std::to_string(prefixLength);
432 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800433 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530434
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530435 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500436 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530437 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530438}
439
Patrick Williams6aef7692021-05-01 06:39:41 -0500440std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
441 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800442{
443 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500444 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800445
446 // Only want 8 hex digits.
447 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
448 return hexId.str();
449}
450
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530451void EthernetInterface::deleteObject(const std::string& ipaddress)
452{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530453 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530454 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530455 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530456 log<level::ERR>("DeleteObject:Unable to find the object.");
457 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530458 }
459 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700460
461 writeConfigurationFile();
462 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530463}
464
Patrick Williams6aef7692021-05-01 06:39:41 -0500465void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800466{
Patrick Williams6aef7692021-05-01 06:39:41 -0500467 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800468 if (it == staticNeighbors.end())
469 {
470 log<level::ERR>(
471 "DeleteStaticNeighborObject:Unable to find the object.");
472 return;
473 }
474 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700475
476 writeConfigurationFile();
477 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800478}
479
Ratan Guptae9c9b812017-09-22 17:15:37 +0530480void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530481{
Ratan Guptabc886292017-07-25 18:29:57 +0530482 auto confDir = manager.getConfDir();
483 fs::path networkFile = confDir;
484 networkFile /= systemd::config::networkFilePrefix + interface +
485 systemd::config::networkFileSuffix;
486
487 fs::path deviceFile = confDir;
488 deviceFile /= interface + systemd::config::deviceFileSuffix;
489
490 // delete the vlan network file
491 if (fs::is_regular_file(networkFile))
492 {
493 fs::remove(networkFile);
494 }
495
496 // delete the vlan device file
497 if (fs::is_regular_file(deviceFile))
498 {
499 fs::remove(deviceFile);
500 }
Ratan Guptabc886292017-07-25 18:29:57 +0530501
502 // TODO systemd doesn't delete the virtual network interface
503 // even after deleting all the related configuartion.
504 // https://github.com/systemd/systemd/issues/6600
505 try
506 {
507 deleteInterface(interface);
508 }
Patrick Williams5758db32021-10-06 12:29:22 -0500509 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530510 {
511 commit<InternalFailure>();
512 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530513}
514
515void EthernetInterface::deleteVLANObject(const std::string& interface)
516{
517 auto it = vlanInterfaces.find(interface);
518 if (it == vlanInterfaces.end())
519 {
520 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500521 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530522 return;
523 }
524
525 deleteVLANFromSystem(interface);
526 // delete the interface
527 vlanInterfaces.erase(it);
528
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700529 writeConfigurationFile();
530 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530531}
532
Gunnar Mills57d9c502018-09-14 14:42:34 -0500533std::string EthernetInterface::generateObjectPath(
534 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800535 uint8_t prefixLength, const std::string& gateway,
536 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530537{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530538 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530539 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530540 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
541
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530542 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530543 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530544 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800545 objectPath /=
546 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530547 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530548}
549
William A. Kennington III08505792019-01-30 16:00:04 -0800550std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500551 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800552{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530553 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800554 objectPath /= objPath;
555 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500556 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800557 return objectPath.string();
558}
559
Patrick Williams6aef7692021-05-01 06:39:41 -0500560bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700561{
Patrick Williams6aef7692021-05-01 06:39:41 -0500562 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700563 {
564 return value;
565 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500566 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700567
568 writeConfigurationFile();
569 manager.reloadConfigs();
570
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700571 return value;
572}
573
Patrick Williams6aef7692021-05-01 06:39:41 -0500574EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530575{
Patrick Williams6aef7692021-05-01 06:39:41 -0500576 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530577 {
578 return value;
579 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500580 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700581
582 writeConfigurationFile();
583 manager.reloadConfigs();
584
Ratan Gupta87c13982017-06-15 09:27:27 +0530585 return value;
586}
587
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800588bool EthernetInterface::linkUp() const
589{
590 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
591 bool value = EthernetInterfaceIntf::linkUp();
592
593 if (eifSocket.sock < 0)
594 {
595 return value;
596 }
597
William A. Kennington III05368f12021-05-13 18:40:47 -0700598 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800599 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
600 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
601 {
602 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
603 }
604 else
605 {
606 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
607 entry("ERROR=%s", strerror(errno)));
608 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700609 return value;
610}
611
Tejas Patil2c0fc562021-08-03 19:13:46 +0530612size_t EthernetInterface::mtu() const
613{
614 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
615 size_t value = EthernetInterfaceIntf::mtu();
616
617 if (eifSocket.sock < 0)
618 {
619 return value;
620 }
621
622 ifreq ifr = {};
623 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
624 if (ioctl(eifSocket.sock, SIOCGIFMTU, &ifr) == 0)
625 {
626 value = ifr.ifr_mtu;
627 }
628 else
629 {
630 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
631 entry("ERROR=%s", strerror(errno)));
632 }
633 return value;
634}
635
636size_t EthernetInterface::mtu(size_t value)
637{
638 if (value == EthernetInterfaceIntf::mtu())
639 {
640 return value;
641 }
642 else if (value == 0)
643 {
644 return EthernetInterfaceIntf::mtu();
645 }
646
647 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
648 if (eifSocket.sock < 0)
649 {
650 return EthernetInterfaceIntf::mtu();
651 }
652
653 ifreq ifr = {};
654 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
655 ifr.ifr_mtu = value;
656
657 if (ioctl(eifSocket.sock, SIOCSIFMTU, &ifr) != 0)
658 {
659 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
660 entry("ERROR=%s", strerror(errno)));
661 return EthernetInterfaceIntf::mtu();
662 }
663 EthernetInterfaceIntf::mtu(value);
664
665 return value;
666}
667
William A. Kennington III26275a32021-07-13 20:32:42 -0700668bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700669{
William A. Kennington III26275a32021-07-13 20:32:42 -0700670 constexpr auto svc = "org.freedesktop.network1";
671 constexpr auto intf = "org.freedesktop.network1.Link";
672 constexpr auto prop = "AdministrativeState";
673 char* rpath;
674 sd_bus_path_encode("/org/freedesktop/network1/link",
675 std::to_string(ifIndex()).c_str(), &rpath);
676 std::string path(rpath);
677 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700678
William A. Kennington III26275a32021-07-13 20:32:42 -0700679 // Store / Parser for the AdministrativeState return value
680 std::optional<bool> ret;
681 auto cb = [&](const std::string& state) {
682 if (state != "initialized")
683 {
684 ret = state != "unmanaged";
685 }
686 };
687
688 // Build a matcher before making the property call to ensure we
689 // can eventually get the value.
690 sdbusplus::bus::match::match match(
691 bus,
692 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
693 "'PropertiesChanged',arg0='{}',",
694 svc, path, PROPERTY_INTERFACE, intf)
695 .c_str(),
696 [&](sdbusplus::message::message& m) {
697 std::string intf;
698 std::unordered_map<std::string, std::variant<std::string>> values;
699 try
700 {
701 m.read(intf, values);
702 auto it = values.find(prop);
703 // Ignore properties that aren't AdministrativeState
704 if (it != values.end())
705 {
706 cb(std::get<std::string>(it->second));
707 }
708 }
709 catch (const std::exception& e)
710 {
711 log<level::ERR>(
712 fmt::format(
713 "AdministrativeState match parsing failed on {}: {}",
714 interfaceName(), e.what())
715 .c_str(),
716 entry("INTERFACE=%s", interfaceName().c_str()),
717 entry("ERROR=%s", e.what()));
718 }
719 });
720
721 // Actively call for the value in case the interface is already configured
722 auto method =
723 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
724 method.append(intf, prop);
725 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700726 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700727 auto reply = bus.call(method);
728 std::variant<std::string> state;
729 reply.read(state);
730 cb(std::get<std::string>(state));
731 }
732 catch (const std::exception& e)
733 {
734 log<level::ERR>(
735 fmt::format("Failed to get AdministrativeState on {}: {}",
736 interfaceName(), e.what())
737 .c_str(),
738 entry("INTERFACE=%s", interfaceName().c_str()),
739 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700740 }
741
William A. Kennington III26275a32021-07-13 20:32:42 -0700742 // The interface is not yet configured by systemd-networkd, wait until it
743 // signals us a valid state.
744 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700745 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700746 bus.wait();
747 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700748 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700749
750 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700751}
752
William A. Kennington III4209cee2021-10-23 18:14:21 -0700753static void setNICAdminState(int fd, const char* intf, bool up)
754{
755 ifreq ifr = {};
756 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
757 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0)
758 {
759 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
760 entry("ERROR=%s", strerror(errno)));
761 elog<InternalFailure>();
762 }
763
764 ifr.ifr_flags &= ~IFF_UP;
765 ifr.ifr_flags |= up ? IFF_UP : 0;
766
767 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
768 {
769 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
770 entry("ERROR=%s", strerror(errno)));
771 elog<InternalFailure>();
772 }
773}
774
Patrick Williams6aef7692021-05-01 06:39:41 -0500775bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700776{
Patrick Williams6aef7692021-05-01 06:39:41 -0500777 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700778 {
779 return value;
780 }
781
782 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
783 if (eifSocket.sock < 0)
784 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500785 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700786 }
William A. Kennington III4209cee2021-10-23 18:14:21 -0700787 auto ifname = interfaceName();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700788
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700789 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800790 if (!value)
791 {
792 // We only need to bring down the interface, networkd will always bring
793 // up managed interfaces
794 manager.addReloadPreHook(
795 [ifname = std::move(ifname), eifSocket = std::move(eifSocket)]() {
796 setNICAdminState(eifSocket.sock, ifname.c_str(), false);
797 });
798 }
799 EthernetInterfaceIntf::nicEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700800 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800801
802 return value;
803}
804
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530805ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530806{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530807 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
808 return EthernetInterfaceIntf::nameservers();
809}
810
811ServerList EthernetInterface::staticNameServers(ServerList value)
812{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530813 for (const auto& nameserverip : value)
814 {
815 if (!isValidIP(AF_INET, nameserverip) &&
816 !isValidIP(AF_INET6, nameserverip))
817 {
818 log<level::ERR>("Not a valid IP address"),
819 entry("ADDRESS=%s", nameserverip.c_str());
820 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530821 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530822 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
823 }
824 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530825 try
826 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530827 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700828
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530829 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700830 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530831 }
Patrick Williams5758db32021-10-06 12:29:22 -0500832 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530833 {
834 log<level::ERR>("Exception processing DNS entries");
835 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530836 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530837}
838
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530839void EthernetInterface::loadNameServers()
840{
841 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
842 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
843}
844
845ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530846{
847 fs::path confPath = manager.getConfDir();
848
849 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500850 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530851 confPath /= fileName;
852 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530853 config::Parser parser(confPath.string());
854 auto rc = config::ReturnCode::SUCCESS;
855
856 std::tie(rc, servers) = parser.getValues("Network", "DNS");
857 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530858 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530859 log<level::DEBUG>("Unable to get the value for network[DNS]",
860 entry("RC=%d", rc));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530861 }
862 return servers;
863}
864
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530865ServerList EthernetInterface::getNameServerFromResolvd()
866{
867 ServerList servers;
868 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
869
870 /*
871 The DNS property under org.freedesktop.resolve1.Link interface contains
872 an array containing all DNS servers currently used by resolved. It
873 contains similar information as the DNS server data written to
874 /run/systemd/resolve/resolv.conf.
875
876 Each structure in the array consists of a numeric network interface index,
877 an address family, and a byte array containing the DNS server address
878 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
879 The array contains DNS servers configured system-wide, including those
880 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
881 /etc/systemd/resolved.conf, as well as per-interface DNS server
882 information either retrieved from systemd-networkd or configured by
883 external software via SetLinkDNS().
884 */
885
886 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
887 std::variant<type> name; // Variable to capture the DNS property
888 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
889 PROPERTY_INTERFACE, METHOD_GET);
890
891 method.append(RESOLVED_INTERFACE, "DNS");
892 auto reply = bus.call(method);
893
894 try
895 {
896 reply.read(name);
897 }
Patrick Williamsb108fd72021-09-02 09:45:39 -0500898 catch (const sdbusplus::exception::exception& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530899 {
900 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
901 }
902 auto tupleVector = std::get_if<type>(&name);
903 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
904 {
Alexander Filippov983da552021-02-08 15:26:54 +0300905 int addressFamily = std::get<0>(*i);
906 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
907
908 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530909 {
Alexander Filippov983da552021-02-08 15:26:54 +0300910 case AF_INET:
911 if (ipaddress.size() == sizeof(struct in_addr))
912 {
913 servers.push_back(toString(
914 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
915 }
916 else
917 {
918 log<level::ERR>(
919 "Invalid data recived from Systemd-Resolved");
920 }
921 break;
922
923 case AF_INET6:
924 if (ipaddress.size() == sizeof(struct in6_addr))
925 {
926 servers.push_back(toString(
927 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
928 }
929 else
930 {
931 log<level::ERR>(
932 "Invalid data recived from Systemd-Resolved");
933 }
934 break;
935
936 default:
937 log<level::ERR>(
938 "Unsupported address family in DNS from Systemd-Resolved");
939 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530940 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530941 }
942 return servers;
943}
944
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530945void EthernetInterface::loadVLAN(VlanId id)
946{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500947 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530948 std::string path = objPath;
949 path += "_" + std::to_string(id);
950
Johnathan Mantey817012a2020-01-30 15:07:39 -0800951 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500952 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530953 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500954 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800955 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530956
Gunnar Mills57d9c502018-09-14 14:42:34 -0500957 // Fetch the ip address from the system
958 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530959 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800960 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530961
962 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
963 std::move(vlanIntf));
964}
965
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700966ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530967{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500968 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530969 std::string path = objPath;
970 path += "_" + std::to_string(id);
971
Patrick Williams6aef7692021-05-01 06:39:41 -0500972 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530973 // VLAN interface can inherit.
974
Ratan Gupta5978dd12017-07-25 13:47:13 +0530975 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800976 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500977 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530978
979 // write the device file for the vlan interface.
980 vlanIntf->writeDeviceFile();
981
Gunnar Mills57d9c502018-09-14 14:42:34 -0500982 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700983
984 writeConfigurationFile();
985 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700986
987 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530988}
Ratan Gupta2b106532017-07-25 16:05:02 +0530989
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700990bool EthernetInterface::getIPv6AcceptRAFromConf()
991{
992 fs::path confPath = manager.getConfDir();
993
994 std::string fileName = systemd::config::networkFilePrefix +
995 interfaceName() + systemd::config::networkFileSuffix;
996 confPath /= fileName;
997 config::ValueList values;
998 config::Parser parser(confPath.string());
999 auto rc = config::ReturnCode::SUCCESS;
1000 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
1001 if (rc != config::ReturnCode::SUCCESS)
1002 {
1003 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
1004 entry("rc=%d", rc));
1005 return false;
1006 }
1007 return (values[0] == "true");
1008}
1009
Ratan Gupta497c0c92017-08-22 19:15:59 +05301010ServerList EthernetInterface::getNTPServersFromConf()
1011{
1012 fs::path confPath = manager.getConfDir();
1013
Gunnar Mills57d9c502018-09-14 14:42:34 -05001014 std::string fileName = systemd::config::networkFilePrefix +
1015 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +05301016 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +05301017
Ratan Gupta497c0c92017-08-22 19:15:59 +05301018 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +05301019 config::Parser parser(confPath.string());
1020 auto rc = config::ReturnCode::SUCCESS;
1021
1022 std::tie(rc, servers) = parser.getValues("Network", "NTP");
1023 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301024 {
Ratan Guptac27170a2017-11-22 15:44:42 +05301025 log<level::DEBUG>("Unable to get the value for Network[NTP]",
1026 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +05301027 }
Ratan Guptac27170a2017-11-22 15:44:42 +05301028
Ratan Gupta497c0c92017-08-22 19:15:59 +05301029 return servers;
1030}
1031
Patrick Williams6aef7692021-05-01 06:39:41 -05001032ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +05301033{
Patrick Williams6aef7692021-05-01 06:39:41 -05001034 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +05301035
1036 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001037 manager.reloadConfigs();
1038
Ratan Gupta497c0c92017-08-22 19:15:59 +05301039 return ntpServers;
1040}
Ratan Gupta2b106532017-07-25 16:05:02 +05301041// Need to merge the below function with the code which writes the
1042// config file during factory reset.
1043// TODO openbmc/openbmc#1751
1044
1045void EthernetInterface::writeConfigurationFile()
1046{
1047 // write all the static ip address in the systemd-network conf file
1048
1049 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +05301050 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +05301051
1052 // if there is vlan interafce then write the configuration file
1053 // for vlan also.
1054
Gunnar Mills57d9c502018-09-14 14:42:34 -05001055 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +05301056 {
1057 intf.second->writeConfigurationFile();
1058 }
1059
Ratan Gupta2b106532017-07-25 16:05:02 +05301060 fs::path confPath = manager.getConfDir();
1061
Gunnar Mills57d9c502018-09-14 14:42:34 -05001062 std::string fileName = systemd::config::networkFilePrefix +
1063 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +05301064 confPath /= fileName;
1065 std::fstream stream;
1066
1067 stream.open(confPath.c_str(), std::fstream::out);
1068 if (!stream.is_open())
1069 {
1070 log<level::ERR>("Unable to open the file",
1071 entry("FILE=%s", confPath.c_str()));
1072 elog<InternalFailure>();
1073 }
1074
1075 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001076 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301077 stream << "Name=" << interfaceName() << "\n";
1078
1079 auto addrs = getAddresses();
1080
William A. Kennington III15787212019-04-23 19:18:01 -07001081 // Write the link section
1082 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001083 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001084 if (!mac.empty())
1085 {
1086 stream << "MACAddress=" << mac << "\n";
1087 }
1088
Patrick Williams6aef7692021-05-01 06:39:41 -05001089 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001090 {
1091 stream << "Unmanaged=yes\n";
1092 }
1093
Ratan Gupta2b106532017-07-25 16:05:02 +05301094 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001095 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001096#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001097 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001098#else
1099 stream << "LinkLocalAddressing=no\n";
1100#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001101 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001102 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301103
1104 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001105 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301106 {
1107 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001108 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301109 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301110 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001111 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301112 {
1113 stream << "NTP=" << ntp << "\n";
1114 }
1115
1116 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301117 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301118 {
1119 stream << "DNS=" << dns << "\n";
1120 }
1121
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001122 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001123 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001124 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001125
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001126 stream << "[IPv6AcceptRA]\n";
1127 stream << "DHCPv6Client=";
1128 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
1129
Johnathan Mantey817012a2020-01-30 15:07:39 -08001130 // Static IP addresses
1131 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301132 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001133 if (originIsManuallyAssigned(addr.second->origin()) &&
1134 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001135 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001136 // Process all static addresses
1137 std::string address = addr.second->address() + "/" +
1138 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301139
Johnathan Mantey817012a2020-01-30 15:07:39 -08001140 // build the address entries. Do not use [Network] shortcuts to
1141 // insert address entries.
1142 stream << "[Address]\n";
1143 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001144 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001145 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001146
Lei YUcb2d4082021-08-12 15:26:49 +08001147 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001148 {
Lei YUcb2d4082021-08-12 15:26:49 +08001149 auto gateway = EthernetInterfaceIntf::defaultGateway();
1150 if (!gateway.empty())
1151 {
1152 stream << "[Route]\n";
1153 stream << "Gateway=" << gateway << "\n";
1154 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001155 }
1156
Lei YUcb2d4082021-08-12 15:26:49 +08001157 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001158 {
Lei YUcb2d4082021-08-12 15:26:49 +08001159 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1160 if (!gateway6.empty())
1161 {
1162 stream << "[Route]\n";
1163 stream << "Gateway=" << gateway6 << "\n";
1164 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001165 }
1166
William A. Kennington III08505792019-01-30 16:00:04 -08001167 // Write the neighbor sections
1168 for (const auto& neighbor : staticNeighbors)
1169 {
1170 stream << "[Neighbor]"
1171 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001172 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1173 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001174 }
1175
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001176 // Write the dhcp section irrespective of whether DHCP is enabled or not
1177 writeDHCPSection(stream);
1178
Ratan Gupta2b106532017-07-25 16:05:02 +05301179 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301180}
1181
1182void EthernetInterface::writeDHCPSection(std::fstream& stream)
1183{
1184 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301185 // write the dhcp section
1186 stream << "[DHCP]\n";
1187
1188 // Hardcoding the client identifier to mac, to address below issue
1189 // https://github.com/openbmc/openbmc/issues/1280
1190 stream << "ClientIdentifier=mac\n";
1191 if (manager.getDHCPConf())
1192 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001193 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301194 stream << "UseDNS="s + value + "\n";
1195
Patrick Williams6aef7692021-05-01 06:39:41 -05001196 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301197 stream << "UseNTP="s + value + "\n";
1198
1199 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1200 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001201
1202 value =
1203 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1204 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301205 }
1206}
1207
Patrick Williams6aef7692021-05-01 06:39:41 -05001208std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301209{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001210 ether_addr newMAC;
1211 try
1212 {
1213 newMAC = mac_address::fromString(value);
1214 }
Patrick Williams5758db32021-10-06 12:29:22 -05001215 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001216 {
1217 log<level::ERR>("MACAddress is not valid.",
1218 entry("MAC=%s", value.c_str()));
1219 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1220 Argument::ARGUMENT_VALUE(value.c_str()));
1221 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001222 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301223 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001224 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001225 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001226 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1227 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301228 }
1229
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001230 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001231 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001232
William A. Kennington III1137a972019-04-20 20:49:58 -07001233 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001234 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001235 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301236 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001237 // Update everything that depends on the MAC value
1238 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301239 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001240 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301241 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001242 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301243
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001244 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001245 manager.addReloadPreHook([interface]() {
1246 // The MAC and LLADDRs will only update if the NIC is already down
1247 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
1248 setNICAdminState(eifSocket.sock, interface.c_str(), false);
1249 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001250 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301251 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001252
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001253#ifdef HAVE_UBOOT_ENV
1254 // Ensure that the valid address is stored in the u-boot-env
1255 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1256 if (envVar)
1257 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001258 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1259 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1260 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1261 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001262 }
1263#endif // HAVE_UBOOT_ENV
1264
William A. Kennington III1137a972019-04-20 20:49:58 -07001265 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301266}
1267
Ratan Guptae9c9b812017-09-22 17:15:37 +05301268void EthernetInterface::deleteAll()
1269{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301270 // clear all the ip on the interface
1271 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001272
1273 writeConfigurationFile();
1274 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301275}
1276
Ravi Tejaa5a09442020-07-17 00:57:33 -05001277std::string EthernetInterface::defaultGateway(std::string gateway)
1278{
1279 auto gw = EthernetInterfaceIntf::defaultGateway();
1280 if (gw == gateway)
1281 {
1282 return gw;
1283 }
1284
1285 if (!isValidIP(AF_INET, gateway))
1286 {
1287 log<level::ERR>("Not a valid v4 Gateway",
1288 entry("GATEWAY=%s", gateway.c_str()));
1289 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1290 Argument::ARGUMENT_VALUE(gateway.c_str()));
1291 }
1292 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001293
1294 writeConfigurationFile();
1295 manager.reloadConfigs();
1296
Ravi Tejaa5a09442020-07-17 00:57:33 -05001297 return gw;
1298}
1299
1300std::string EthernetInterface::defaultGateway6(std::string gateway)
1301{
1302 auto gw = EthernetInterfaceIntf::defaultGateway6();
1303 if (gw == gateway)
1304 {
1305 return gw;
1306 }
1307
1308 if (!isValidIP(AF_INET6, gateway))
1309 {
1310 log<level::ERR>("Not a valid v6 Gateway",
1311 entry("GATEWAY=%s", gateway.c_str()));
1312 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1313 Argument::ARGUMENT_VALUE(gateway.c_str()));
1314 }
1315 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001316
1317 writeConfigurationFile();
1318 manager.reloadConfigs();
1319
Ravi Tejaa5a09442020-07-17 00:57:33 -05001320 return gw;
1321}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001322} // namespace network
1323} // namespace phosphor