blob: 0f8a3c00ac507bb761d1d608180b2d7eca81ca54 [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"
Ravi Tejaa5a09442020-07-17 00:57:33 -05008#include "routing_table.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05309#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +053010
Ratan Gupta82549cc2017-04-21 08:45:23 +053011#include <arpa/inet.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070012#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053013#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070014#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053016#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053017#include <netinet/in.h>
18#include <sys/ioctl.h>
19#include <sys/socket.h>
20#include <unistd.h>
21
Ratan Gupta82549cc2017-04-21 08:45:23 +053022#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053023#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070025#include <phosphor-logging/elog-errors.hpp>
26#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070027#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053028#include <sstream>
William A. Kennington III12beaad2020-06-13 19:30:41 -070029#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053030#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070031#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070032#include <unordered_map>
33#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070034#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053035
Ratan Gupta91a99cc2017-04-14 16:32:09 +053036namespace phosphor
37{
38namespace network
39{
40
41using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053042using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053043using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
44using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050045using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053046constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
47constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
48constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
49constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
50constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053051
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080052struct EthernetIntfSocket
53{
54 EthernetIntfSocket(int domain, int type, int protocol)
55 {
56 if ((sock = socket(domain, type, protocol)) < 0)
57 {
58 log<level::ERR>("socket creation failed:",
59 entry("ERROR=%s", strerror(errno)));
60 }
61 }
62
63 ~EthernetIntfSocket()
64 {
65 if (sock >= 0)
66 {
67 close(sock);
68 }
69 }
70
71 int sock{-1};
72};
73
Johnathan Mantey817012a2020-01-30 15:07:39 -080074std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
75 {EthernetInterface::DHCPConf::both, "true"},
76 {EthernetInterface::DHCPConf::v4, "ipv4"},
77 {EthernetInterface::DHCPConf::v6, "ipv6"},
78 {EthernetInterface::DHCPConf::none, "false"}};
79
Ratan Gupta91a99cc2017-04-14 16:32:09 +053080EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
81 const std::string& objPath,
Johnathan Mantey817012a2020-01-30 15:07:39 -080082 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070083 bool emitSignal,
84 std::optional<bool> enabled) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050085 Ifaces(bus, objPath.c_str(), true),
86 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053087{
88 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053089 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053090 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050091 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
92 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
William A. Kennington III26275a32021-07-13 20:32:42 -070093 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
Ravi Tejaa5a09442020-07-17 00:57:33 -050094 route::Table routingTable;
95 auto gatewayList = routingTable.getDefaultGateway();
96 auto gateway6List = routingTable.getDefaultGateway6();
97 std::string defaultGateway;
98 std::string defaultGateway6;
99
100 for (auto& gateway : gatewayList)
101 {
102 if (gateway.first == intfName)
103 {
104 defaultGateway = gateway.second;
105 break;
106 }
107 }
108
109 for (auto& gateway6 : gateway6List)
110 {
111 if (gateway6.first == intfName)
112 {
113 defaultGateway6 = gateway6.second;
114 break;
115 }
116 }
117
118 EthernetInterfaceIntf::defaultGateway(defaultGateway);
119 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530120 // Don't get the mac address from the system as the mac address
121 // would be same as parent interface.
122 if (intfName.find(".") == std::string::npos)
123 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500124 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530125 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500126 EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
Ratan Gupta613a0122020-04-24 15:18:53 +0530127
128 EthernetInterfaceIntf::linkUp(linkUp());
Ratan Gupta613a0122020-04-24 15:18:53 +0530129
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700130#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700131 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
132
133 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
134 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800135#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530136
Ratan Gupta29b0e432017-05-25 12:51:40 +0530137 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530138 if (emitSignal)
139 {
140 this->emit_object_added();
141 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530142}
143
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800144static IP::Protocol convertFamily(int family)
145{
146 switch (family)
147 {
148 case AF_INET:
149 return IP::Protocol::IPv4;
150 case AF_INET6:
151 return IP::Protocol::IPv6;
152 }
153
154 throw std::invalid_argument("Bad address family");
155}
156
Johnathan Mantey817012a2020-01-30 15:07:39 -0800157void EthernetInterface::disableDHCP(IP::Protocol protocol)
158{
Patrick Williams6aef7692021-05-01 06:39:41 -0500159 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800160 if (dhcpState == EthernetInterface::DHCPConf::both)
161 {
162 if (protocol == IP::Protocol::IPv4)
163 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500164 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800165 }
166 else if (protocol == IP::Protocol::IPv6)
167 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500168 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800169 }
170 }
171 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
172 (protocol == IP::Protocol::IPv4))
173 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500174 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800175 }
176 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
177 (protocol == IP::Protocol::IPv6))
178 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500179 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800180 }
181}
182
183bool EthernetInterface::dhcpIsEnabled(IP::Protocol family, bool ignoreProtocol)
184{
Patrick Williams6aef7692021-05-01 06:39:41 -0500185 return ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800186 EthernetInterface::DHCPConf::both) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500187 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800188 EthernetInterface::DHCPConf::v6) &&
189 ((family == IP::Protocol::IPv6) || ignoreProtocol)) ||
Patrick Williams6aef7692021-05-01 06:39:41 -0500190 ((EthernetInterfaceIntf::dhcpEnabled() ==
Johnathan Mantey817012a2020-01-30 15:07:39 -0800191 EthernetInterface::DHCPConf::v4) &&
192 ((family == IP::Protocol::IPv4) || ignoreProtocol)));
193}
194
195bool EthernetInterface::dhcpToBeEnabled(IP::Protocol family,
196 const std::string& nextDHCPState)
197{
198 return ((nextDHCPState == "true") ||
199 ((nextDHCPState == "ipv6") && (family == IP::Protocol::IPv6)) ||
200 ((nextDHCPState == "ipv4") && (family == IP::Protocol::IPv4)));
201}
202
203bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
204{
205 return (
206#ifdef LINK_LOCAL_AUTOCONFIGURATION
207 (origin == IP::AddressOrigin::Static)
208#else
209 (origin == IP::AddressOrigin::Static ||
210 origin == IP::AddressOrigin::LinkLocal)
211#endif
212
213 );
214}
215
Ratan Gupta87c13982017-06-15 09:27:27 +0530216void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530217{
Ratan Gupta87c13982017-06-15 09:27:27 +0530218 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530219
Ratan Gupta87c13982017-06-15 09:27:27 +0530220 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530221
Ratan Gupta6a387c12017-08-03 13:26:19 +0530222 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530223 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800224 IP::Protocol addressType = convertFamily(addr.addrType);
225 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800226 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530227 {
228 origin = IP::AddressOrigin::DHCP;
229 }
William A. Kennington III16893802019-01-30 16:01:01 -0800230 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530231 {
232 origin = IP::AddressOrigin::LinkLocal;
233 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700234 // Obsolete parameter
235 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530236
Gunnar Mills57d9c502018-09-14 14:42:34 -0500237 std::string ipAddressObjectPath = generateObjectPath(
238 addressType, addr.ipaddress, addr.prefix, gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530239
Lei YU7233c582021-04-08 14:39:43 +0800240 this->addrs.insert_or_assign(
241 addr.ipaddress,
242 std::make_shared<phosphor::network::IPAddress>(
243 bus, ipAddressObjectPath.c_str(), *this, addressType,
244 addr.ipaddress, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530245 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530246}
247
William A. Kennington III08505792019-01-30 16:00:04 -0800248void EthernetInterface::createStaticNeighborObjects()
249{
250 staticNeighbors.clear();
251
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700252 NeighborFilter filter;
253 filter.interface = ifIndex();
254 filter.state = NUD_PERMANENT;
255 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800256 for (const auto& neighbor : neighbors)
257 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700258 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800259 {
260 continue;
261 }
262 std::string ip = toString(neighbor.address);
263 std::string mac = mac_address::toString(*neighbor.mac);
264 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
265 staticNeighbors.emplace(ip,
266 std::make_shared<phosphor::network::Neighbor>(
267 bus, objectPath.c_str(), *this, ip, mac,
268 Neighbor::State::Permanent));
269 }
270}
271
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700272unsigned EthernetInterface::ifIndex() const
273{
274 unsigned idx = if_nametoindex(interfaceName().c_str());
275 if (idx == 0)
276 {
277 throw std::system_error(errno, std::generic_category(),
278 "if_nametoindex");
279 }
280 return idx;
281}
282
Patrick Williams6aef7692021-05-01 06:39:41 -0500283ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500284 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530285{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800286 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530287 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530288 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500289 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800290 disableDHCP(protType);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500291 }
292
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500293 IP::AddressOrigin origin = IP::AddressOrigin::Static;
294
295 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
296
297 if (!isValidIP(addressFamily, ipaddress))
298 {
299 log<level::ERR>("Not a valid IP address"),
300 entry("ADDRESS=%s", ipaddress.c_str());
301 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
302 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
303 }
304
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700305 // Gateway is an obsolete parameter
306 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500307
308 if (!isValidPrefix(addressFamily, prefixLength))
309 {
310 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700311 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500312 elog<InvalidArgument>(
313 Argument::ARGUMENT_NAME("prefixLength"),
314 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530315 }
316
Gunnar Mills57d9c502018-09-14 14:42:34 -0500317 std::string objectPath =
318 generateObjectPath(protType, ipaddress, prefixLength, gateway);
Lei YU7233c582021-04-08 14:39:43 +0800319 this->addrs.insert_or_assign(ipaddress,
320 std::make_shared<phosphor::network::IPAddress>(
321 bus, objectPath.c_str(), *this, protType,
322 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530323
Ratan Guptae05083a2017-09-16 07:12:11 +0530324 manager.writeToConfigurationFile();
raviteja-bce379562019-03-28 05:59:36 -0500325 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530326}
327
Patrick Williams6aef7692021-05-01 06:39:41 -0500328ObjectPath EthernetInterface::neighbor(std::string ipAddress,
329 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800330{
Patrick Williams6aef7692021-05-01 06:39:41 -0500331 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800332 {
333 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500334 entry("ADDRESS=%s", ipAddress.c_str()));
335 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
336 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800337 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500338 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800339 {
340 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500341 entry("MACADDRESS=%s", ipAddress.c_str()));
342 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
343 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800344 }
345
346 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500347 generateStaticNeighborObjectPath(ipAddress, macAddress);
348 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800349 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500350 bus, objectPath.c_str(), *this, ipAddress,
351 macAddress, Neighbor::State::Permanent));
William A. Kennington III08505792019-01-30 16:00:04 -0800352 manager.writeToConfigurationFile();
353 return objectPath;
354}
355
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700356#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530357/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800358 Enable this code if your NIC driver supports the ETHTOOL features.
359 Do this by adding the following to your phosphor-network*.bbappend file.
360 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
361 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530362*/
363InterfaceInfo EthernetInterface::getInterfaceInfo() const
364{
William A. Kennington III05368f12021-05-13 18:40:47 -0700365 ifreq ifr = {};
366 ethtool_cmd edata = {};
367 LinkSpeed speed = {};
368 Autoneg autoneg = {};
369 DuplexMode duplex = {};
370 LinkUp linkState = {};
371 NICEnabled enabled = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800372 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
373
374 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530375 {
William A. Kennington III96203312021-05-07 12:50:41 -0700376 return std::make_tuple(speed, duplex, autoneg, linkState, enabled);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800377 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530378
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800379 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
380 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530381
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800382 edata.cmd = ETHTOOL_GSET;
383 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
384 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530385 speed = edata.speed;
386 duplex = edata.duplex;
387 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530388 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800389
William A. Kennington III96203312021-05-07 12:50:41 -0700390 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800391 linkState = linkUp();
392
William A. Kennington III96203312021-05-07 12:50:41 -0700393 return std::make_tuple(speed, duplex, autoneg, linkState, enabled);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530394}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800395#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530396
397/** @brief get the mac address of the interface.
398 * @return macaddress on success
399 */
400
Gunnar Mills57d9c502018-09-14 14:42:34 -0500401std::string
402 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530403{
Patrick Williams6aef7692021-05-01 06:39:41 -0500404 std::string activeMACAddr = MacAddressIntf::macAddress();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800405 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
406
407 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530408 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800409 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530410 }
411
William A. Kennington III05368f12021-05-13 18:40:47 -0700412 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800413 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
414 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530415 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530416 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500417 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700418 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530419 }
420
William A. Kennington III1137a972019-04-20 20:49:58 -0700421 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
422 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
423 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700424 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530425}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530426
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530427std::string EthernetInterface::generateId(const std::string& ipaddress,
428 uint8_t prefixLength,
429 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530430{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530431 std::stringstream hexId;
432 std::string hashString = ipaddress;
433 hashString += std::to_string(prefixLength);
434 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530435
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530436 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500437 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530438 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530439}
440
Patrick Williams6aef7692021-05-01 06:39:41 -0500441std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
442 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800443{
444 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500445 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800446
447 // Only want 8 hex digits.
448 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
449 return hexId.str();
450}
451
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530452void EthernetInterface::deleteObject(const std::string& ipaddress)
453{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530454 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530455 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530456 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530457 log<level::ERR>("DeleteObject:Unable to find the object.");
458 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530459 }
460 this->addrs.erase(it);
Ratan Guptae05083a2017-09-16 07:12:11 +0530461 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530462}
463
Patrick Williams6aef7692021-05-01 06:39:41 -0500464void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800465{
Patrick Williams6aef7692021-05-01 06:39:41 -0500466 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800467 if (it == staticNeighbors.end())
468 {
469 log<level::ERR>(
470 "DeleteStaticNeighborObject:Unable to find the object.");
471 return;
472 }
473 staticNeighbors.erase(it);
474 manager.writeToConfigurationFile();
475}
476
Ratan Guptae9c9b812017-09-22 17:15:37 +0530477void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530478{
Ratan Guptabc886292017-07-25 18:29:57 +0530479 auto confDir = manager.getConfDir();
480 fs::path networkFile = confDir;
481 networkFile /= systemd::config::networkFilePrefix + interface +
482 systemd::config::networkFileSuffix;
483
484 fs::path deviceFile = confDir;
485 deviceFile /= interface + systemd::config::deviceFileSuffix;
486
487 // delete the vlan network file
488 if (fs::is_regular_file(networkFile))
489 {
490 fs::remove(networkFile);
491 }
492
493 // delete the vlan device file
494 if (fs::is_regular_file(deviceFile))
495 {
496 fs::remove(deviceFile);
497 }
Ratan Guptabc886292017-07-25 18:29:57 +0530498
499 // TODO systemd doesn't delete the virtual network interface
500 // even after deleting all the related configuartion.
501 // https://github.com/systemd/systemd/issues/6600
502 try
503 {
504 deleteInterface(interface);
505 }
506 catch (InternalFailure& e)
507 {
508 commit<InternalFailure>();
509 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530510}
511
512void EthernetInterface::deleteVLANObject(const std::string& interface)
513{
514 auto it = vlanInterfaces.find(interface);
515 if (it == vlanInterfaces.end())
516 {
517 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500518 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530519 return;
520 }
521
522 deleteVLANFromSystem(interface);
523 // delete the interface
524 vlanInterfaces.erase(it);
525
Ratan Guptae05083a2017-09-16 07:12:11 +0530526 manager.writeToConfigurationFile();
Ratan Guptabc886292017-07-25 18:29:57 +0530527}
528
Gunnar Mills57d9c502018-09-14 14:42:34 -0500529std::string EthernetInterface::generateObjectPath(
530 IP::Protocol addressType, const std::string& ipaddress,
531 uint8_t prefixLength, const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530532{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530533 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530534 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530535 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
536
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530537 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530538 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530539 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530540 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530541 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530542}
543
William A. Kennington III08505792019-01-30 16:00:04 -0800544std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500545 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800546{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530547 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800548 objectPath /= objPath;
549 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500550 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800551 return objectPath.string();
552}
553
Patrick Williams6aef7692021-05-01 06:39:41 -0500554bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700555{
Patrick Williams6aef7692021-05-01 06:39:41 -0500556 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700557 {
558 return value;
559 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500560 EthernetInterfaceIntf::ipv6AcceptRA(value);
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700561 manager.writeToConfigurationFile();
562 return value;
563}
564
Patrick Williams6aef7692021-05-01 06:39:41 -0500565EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530566{
Patrick Williams6aef7692021-05-01 06:39:41 -0500567 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530568 {
569 return value;
570 }
571
Patrick Williams6aef7692021-05-01 06:39:41 -0500572 EthernetInterfaceIntf::dhcpEnabled(value);
Ratan Guptae05083a2017-09-16 07:12:11 +0530573 manager.writeToConfigurationFile();
Ratan Gupta87c13982017-06-15 09:27:27 +0530574 return value;
575}
576
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800577bool EthernetInterface::linkUp() const
578{
579 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
580 bool value = EthernetInterfaceIntf::linkUp();
581
582 if (eifSocket.sock < 0)
583 {
584 return value;
585 }
586
William A. Kennington III05368f12021-05-13 18:40:47 -0700587 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800588 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
589 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
590 {
591 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
592 }
593 else
594 {
595 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
596 entry("ERROR=%s", strerror(errno)));
597 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700598 return value;
599}
600
William A. Kennington III26275a32021-07-13 20:32:42 -0700601bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700602{
William A. Kennington III26275a32021-07-13 20:32:42 -0700603 constexpr auto svc = "org.freedesktop.network1";
604 constexpr auto intf = "org.freedesktop.network1.Link";
605 constexpr auto prop = "AdministrativeState";
606 char* rpath;
607 sd_bus_path_encode("/org/freedesktop/network1/link",
608 std::to_string(ifIndex()).c_str(), &rpath);
609 std::string path(rpath);
610 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700611
William A. Kennington III26275a32021-07-13 20:32:42 -0700612 // Store / Parser for the AdministrativeState return value
613 std::optional<bool> ret;
614 auto cb = [&](const std::string& state) {
615 if (state != "initialized")
616 {
617 ret = state != "unmanaged";
618 }
619 };
620
621 // Build a matcher before making the property call to ensure we
622 // can eventually get the value.
623 sdbusplus::bus::match::match match(
624 bus,
625 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
626 "'PropertiesChanged',arg0='{}',",
627 svc, path, PROPERTY_INTERFACE, intf)
628 .c_str(),
629 [&](sdbusplus::message::message& m) {
630 std::string intf;
631 std::unordered_map<std::string, std::variant<std::string>> values;
632 try
633 {
634 m.read(intf, values);
635 auto it = values.find(prop);
636 // Ignore properties that aren't AdministrativeState
637 if (it != values.end())
638 {
639 cb(std::get<std::string>(it->second));
640 }
641 }
642 catch (const std::exception& e)
643 {
644 log<level::ERR>(
645 fmt::format(
646 "AdministrativeState match parsing failed on {}: {}",
647 interfaceName(), e.what())
648 .c_str(),
649 entry("INTERFACE=%s", interfaceName().c_str()),
650 entry("ERROR=%s", e.what()));
651 }
652 });
653
654 // Actively call for the value in case the interface is already configured
655 auto method =
656 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
657 method.append(intf, prop);
658 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700659 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700660 auto reply = bus.call(method);
661 std::variant<std::string> state;
662 reply.read(state);
663 cb(std::get<std::string>(state));
664 }
665 catch (const std::exception& e)
666 {
667 log<level::ERR>(
668 fmt::format("Failed to get AdministrativeState on {}: {}",
669 interfaceName(), e.what())
670 .c_str(),
671 entry("INTERFACE=%s", interfaceName().c_str()),
672 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700673 }
674
William A. Kennington III26275a32021-07-13 20:32:42 -0700675 // The interface is not yet configured by systemd-networkd, wait until it
676 // signals us a valid state.
677 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700678 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700679 bus.wait();
680 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700681 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700682
683 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700684}
685
Patrick Williams6aef7692021-05-01 06:39:41 -0500686bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700687{
Patrick Williams6aef7692021-05-01 06:39:41 -0500688 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700689 {
690 return value;
691 }
692
693 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
694 if (eifSocket.sock < 0)
695 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500696 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700697 }
698
William A. Kennington III05368f12021-05-13 18:40:47 -0700699 ifreq ifr = {};
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700700 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
701 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) != 0)
702 {
703 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
704 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500705 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700706 }
707
708 ifr.ifr_flags &= ~IFF_UP;
709 ifr.ifr_flags |= value ? IFF_UP : 0;
710
711 if (ioctl(eifSocket.sock, SIOCSIFFLAGS, &ifr) != 0)
712 {
713 log<level::ERR>("ioctl failed for SIOCSIFFLAGS:",
714 entry("ERROR=%s", strerror(errno)));
Patrick Williams6aef7692021-05-01 06:39:41 -0500715 return EthernetInterfaceIntf::nicEnabled();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700716 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500717 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700718 writeConfigurationFile();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800719
720 return value;
721}
722
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530723ServerList EthernetInterface::nameservers(ServerList /*value*/)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530724{
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530725 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
726 return EthernetInterfaceIntf::nameservers();
727}
728
729ServerList EthernetInterface::staticNameServers(ServerList value)
730{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530731 for (const auto& nameserverip : value)
732 {
733 if (!isValidIP(AF_INET, nameserverip) &&
734 !isValidIP(AF_INET6, nameserverip))
735 {
736 log<level::ERR>("Not a valid IP address"),
737 entry("ADDRESS=%s", nameserverip.c_str());
738 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530739 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530740 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
741 }
742 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530743 try
744 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530745 EthernetInterfaceIntf::staticNameServers(value);
Ratan Gupta6dec3902017-08-20 15:28:12 +0530746 writeConfigurationFile();
Ratan Guptab4005972019-09-19 06:19:16 +0530747 // resolved reads the DNS server configuration from the
748 // network file.
749 manager.restartSystemdUnit(networkdService);
Ratan Gupta6dec3902017-08-20 15:28:12 +0530750 }
751 catch (InternalFailure& e)
752 {
753 log<level::ERR>("Exception processing DNS entries");
754 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530755 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530756}
757
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530758void EthernetInterface::loadNameServers()
759{
760 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
761 EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
762}
763
764ServerList EthernetInterface::getstaticNameServerFromConf()
Ratan Gupta6dec3902017-08-20 15:28:12 +0530765{
766 fs::path confPath = manager.getConfDir();
767
768 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500769 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530770 confPath /= fileName;
771 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530772 config::Parser parser(confPath.string());
773 auto rc = config::ReturnCode::SUCCESS;
774
775 std::tie(rc, servers) = parser.getValues("Network", "DNS");
776 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530777 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530778 log<level::DEBUG>("Unable to get the value for network[DNS]",
779 entry("RC=%d", rc));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530780 }
781 return servers;
782}
783
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530784ServerList EthernetInterface::getNameServerFromResolvd()
785{
786 ServerList servers;
787 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
788
789 /*
790 The DNS property under org.freedesktop.resolve1.Link interface contains
791 an array containing all DNS servers currently used by resolved. It
792 contains similar information as the DNS server data written to
793 /run/systemd/resolve/resolv.conf.
794
795 Each structure in the array consists of a numeric network interface index,
796 an address family, and a byte array containing the DNS server address
797 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
798 The array contains DNS servers configured system-wide, including those
799 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
800 /etc/systemd/resolved.conf, as well as per-interface DNS server
801 information either retrieved from systemd-networkd or configured by
802 external software via SetLinkDNS().
803 */
804
805 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
806 std::variant<type> name; // Variable to capture the DNS property
807 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
808 PROPERTY_INTERFACE, METHOD_GET);
809
810 method.append(RESOLVED_INTERFACE, "DNS");
811 auto reply = bus.call(method);
812
813 try
814 {
815 reply.read(name);
816 }
817 catch (const sdbusplus::exception::SdBusError& e)
818 {
819 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
820 }
821 auto tupleVector = std::get_if<type>(&name);
822 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
823 {
Alexander Filippov983da552021-02-08 15:26:54 +0300824 int addressFamily = std::get<0>(*i);
825 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
826
827 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530828 {
Alexander Filippov983da552021-02-08 15:26:54 +0300829 case AF_INET:
830 if (ipaddress.size() == sizeof(struct in_addr))
831 {
832 servers.push_back(toString(
833 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
834 }
835 else
836 {
837 log<level::ERR>(
838 "Invalid data recived from Systemd-Resolved");
839 }
840 break;
841
842 case AF_INET6:
843 if (ipaddress.size() == sizeof(struct in6_addr))
844 {
845 servers.push_back(toString(
846 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
847 }
848 else
849 {
850 log<level::ERR>(
851 "Invalid data recived from Systemd-Resolved");
852 }
853 break;
854
855 default:
856 log<level::ERR>(
857 "Unsupported address family in DNS from Systemd-Resolved");
858 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530859 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530860 }
861 return servers;
862}
863
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530864void EthernetInterface::loadVLAN(VlanId id)
865{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500866 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530867 std::string path = objPath;
868 path += "_" + std::to_string(id);
869
Johnathan Mantey817012a2020-01-30 15:07:39 -0800870 DHCPConf dhcpEnabled =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500871 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530872 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500873 bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
Johnathan Mantey817012a2020-01-30 15:07:39 -0800874 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530875
Gunnar Mills57d9c502018-09-14 14:42:34 -0500876 // Fetch the ip address from the system
877 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530878 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800879 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530880
881 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
882 std::move(vlanIntf));
883}
884
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700885ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530886{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500887 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530888 std::string path = objPath;
889 path += "_" + std::to_string(id);
890
Patrick Williams6aef7692021-05-01 06:39:41 -0500891 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530892 // VLAN interface can inherit.
893
Ratan Gupta5978dd12017-07-25 13:47:13 +0530894 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Johnathan Mantey817012a2020-01-30 15:07:39 -0800895 bus, path.c_str(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500896 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530897
898 // write the device file for the vlan interface.
899 vlanIntf->writeDeviceFile();
900
Gunnar Mills57d9c502018-09-14 14:42:34 -0500901 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530902 // write the new vlan device entry to the configuration(network) file.
Ratan Guptae05083a2017-09-16 07:12:11 +0530903 manager.writeToConfigurationFile();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700904
905 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530906}
Ratan Gupta2b106532017-07-25 16:05:02 +0530907
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700908bool EthernetInterface::getIPv6AcceptRAFromConf()
909{
910 fs::path confPath = manager.getConfDir();
911
912 std::string fileName = systemd::config::networkFilePrefix +
913 interfaceName() + systemd::config::networkFileSuffix;
914 confPath /= fileName;
915 config::ValueList values;
916 config::Parser parser(confPath.string());
917 auto rc = config::ReturnCode::SUCCESS;
918 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
919 if (rc != config::ReturnCode::SUCCESS)
920 {
921 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
922 entry("rc=%d", rc));
923 return false;
924 }
925 return (values[0] == "true");
926}
927
Ratan Gupta497c0c92017-08-22 19:15:59 +0530928ServerList EthernetInterface::getNTPServersFromConf()
929{
930 fs::path confPath = manager.getConfDir();
931
Gunnar Mills57d9c502018-09-14 14:42:34 -0500932 std::string fileName = systemd::config::networkFilePrefix +
933 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +0530934 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +0530935
Ratan Gupta497c0c92017-08-22 19:15:59 +0530936 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530937 config::Parser parser(confPath.string());
938 auto rc = config::ReturnCode::SUCCESS;
939
940 std::tie(rc, servers) = parser.getValues("Network", "NTP");
941 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530942 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530943 log<level::DEBUG>("Unable to get the value for Network[NTP]",
944 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530945 }
Ratan Guptac27170a2017-11-22 15:44:42 +0530946
Ratan Gupta497c0c92017-08-22 19:15:59 +0530947 return servers;
948}
949
Patrick Williams6aef7692021-05-01 06:39:41 -0500950ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530951{
Patrick Williams6aef7692021-05-01 06:39:41 -0500952 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530953
954 writeConfigurationFile();
955 // timesynchd reads the NTP server configuration from the
956 // network file.
Ratan Gupta895f9e52018-11-26 20:57:34 +0530957 manager.restartSystemdUnit(networkdService);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530958 return ntpServers;
959}
Ratan Gupta2b106532017-07-25 16:05:02 +0530960// Need to merge the below function with the code which writes the
961// config file during factory reset.
962// TODO openbmc/openbmc#1751
963
964void EthernetInterface::writeConfigurationFile()
965{
966 // write all the static ip address in the systemd-network conf file
967
968 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530969 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530970
971 // if there is vlan interafce then write the configuration file
972 // for vlan also.
973
Gunnar Mills57d9c502018-09-14 14:42:34 -0500974 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530975 {
976 intf.second->writeConfigurationFile();
977 }
978
Ratan Gupta2b106532017-07-25 16:05:02 +0530979 fs::path confPath = manager.getConfDir();
980
Gunnar Mills57d9c502018-09-14 14:42:34 -0500981 std::string fileName = systemd::config::networkFilePrefix +
982 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +0530983 confPath /= fileName;
984 std::fstream stream;
985
986 stream.open(confPath.c_str(), std::fstream::out);
987 if (!stream.is_open())
988 {
989 log<level::ERR>("Unable to open the file",
990 entry("FILE=%s", confPath.c_str()));
991 elog<InternalFailure>();
992 }
993
994 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -0400995 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +0530996 stream << "Name=" << interfaceName() << "\n";
997
998 auto addrs = getAddresses();
999
William A. Kennington III15787212019-04-23 19:18:01 -07001000 // Write the link section
1001 stream << "[Link]\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001002 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -07001003 if (!mac.empty())
1004 {
1005 stream << "MACAddress=" << mac << "\n";
1006 }
1007
Patrick Williams6aef7692021-05-01 06:39:41 -05001008 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001009 {
1010 stream << "Unmanaged=yes\n";
1011 }
1012
Ratan Gupta2b106532017-07-25 16:05:02 +05301013 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -04001014 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001015#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -05001016 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -04001017#else
1018 stream << "LinkLocalAddressing=no\n";
1019#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001020 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001021 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301022
1023 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001024 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301025 {
1026 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001027 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301028 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301029 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001030 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301031 {
1032 stream << "NTP=" << ntp << "\n";
1033 }
1034
1035 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301036 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301037 {
1038 stream << "DNS=" << dns << "\n";
1039 }
1040
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001041 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001042 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001043 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001044
Johnathan Mantey817012a2020-01-30 15:07:39 -08001045 // Static IP addresses
1046 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301047 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001048 if (originIsManuallyAssigned(addr.second->origin()) &&
1049 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001050 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001051 // Process all static addresses
1052 std::string address = addr.second->address() + "/" +
1053 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301054
Johnathan Mantey817012a2020-01-30 15:07:39 -08001055 // build the address entries. Do not use [Network] shortcuts to
1056 // insert address entries.
1057 stream << "[Address]\n";
1058 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001059 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001060 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001061
Ravi Tejaa5a09442020-07-17 00:57:33 -05001062 auto gateway = EthernetInterfaceIntf::defaultGateway();
1063 if (!gateway.empty())
1064 {
Ravi Tejac14b4b32021-03-16 00:01:17 -05001065 stream << "[Route]\n";
Ravi Tejaa5a09442020-07-17 00:57:33 -05001066 stream << "Gateway=" << gateway << "\n";
1067 }
1068
1069 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1070 if (!gateway6.empty())
1071 {
Ravi Tejac14b4b32021-03-16 00:01:17 -05001072 stream << "[Route]\n";
Ravi Tejaa5a09442020-07-17 00:57:33 -05001073 stream << "Gateway=" << gateway6 << "\n";
1074 }
1075
Johnathan Mantey817012a2020-01-30 15:07:39 -08001076 if (manager.getSystemConf())
1077 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001078 const auto& gateway = manager.getSystemConf()->defaultGateway();
1079 if (!gateway.empty())
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001080 {
Ravi Tejac14b4b32021-03-16 00:01:17 -05001081 stream << "[Route]\n";
Johnathan Mantey817012a2020-01-30 15:07:39 -08001082 stream << "Gateway=" << gateway << "\n";
1083 }
1084 const auto& gateway6 = manager.getSystemConf()->defaultGateway6();
1085 if (!gateway6.empty())
1086 {
Ravi Tejac14b4b32021-03-16 00:01:17 -05001087 stream << "[Route]\n";
Johnathan Mantey817012a2020-01-30 15:07:39 -08001088 stream << "Gateway=" << gateway6 << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001089 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301090 }
1091
William A. Kennington III08505792019-01-30 16:00:04 -08001092 // Write the neighbor sections
1093 for (const auto& neighbor : staticNeighbors)
1094 {
1095 stream << "[Neighbor]"
1096 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001097 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1098 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001099 }
1100
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001101 // Write the dhcp section irrespective of whether DHCP is enabled or not
1102 writeDHCPSection(stream);
1103
Ratan Gupta2b106532017-07-25 16:05:02 +05301104 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +05301105}
1106
1107void EthernetInterface::writeDHCPSection(std::fstream& stream)
1108{
1109 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301110 // write the dhcp section
1111 stream << "[DHCP]\n";
1112
1113 // Hardcoding the client identifier to mac, to address below issue
1114 // https://github.com/openbmc/openbmc/issues/1280
1115 stream << "ClientIdentifier=mac\n";
1116 if (manager.getDHCPConf())
1117 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001118 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301119 stream << "UseDNS="s + value + "\n";
1120
Patrick Williams6aef7692021-05-01 06:39:41 -05001121 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301122 stream << "UseNTP="s + value + "\n";
1123
1124 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1125 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001126
1127 value =
1128 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1129 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301130 }
1131}
1132
Patrick Williams6aef7692021-05-01 06:39:41 -05001133std::string EthernetInterface::macAddress(std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301134{
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001135 ether_addr newMAC;
1136 try
1137 {
1138 newMAC = mac_address::fromString(value);
1139 }
1140 catch (std::invalid_argument&)
1141 {
1142 log<level::ERR>("MACAddress is not valid.",
1143 entry("MAC=%s", value.c_str()));
1144 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1145 Argument::ARGUMENT_VALUE(value.c_str()));
1146 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001147 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301148 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001149 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001150 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001151 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1152 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301153 }
1154
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001155 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001156 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001157
William A. Kennington III1137a972019-04-20 20:49:58 -07001158 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001159 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001160 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301161 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001162 // Update everything that depends on the MAC value
1163 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301164 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001165 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301166 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001167 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301168
William A. Kennington III15787212019-04-23 19:18:01 -07001169 // TODO: would remove the call below and
1170 // just restart systemd-netwokd
William A. Kennington III1137a972019-04-20 20:49:58 -07001171 // through https://github.com/systemd/systemd/issues/6696
1172 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(),
1173 "down");
William A. Kennington III15787212019-04-23 19:18:01 -07001174 manager.writeToConfigurationFile();
Ratan Gupta677ae122017-09-18 16:28:50 +05301175 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001176
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001177#ifdef HAVE_UBOOT_ENV
1178 // Ensure that the valid address is stored in the u-boot-env
1179 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1180 if (envVar)
1181 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001182 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1183 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1184 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1185 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001186 }
1187#endif // HAVE_UBOOT_ENV
1188
William A. Kennington III1137a972019-04-20 20:49:58 -07001189 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +05301190}
1191
Ratan Guptae9c9b812017-09-22 17:15:37 +05301192void EthernetInterface::deleteAll()
1193{
Johnathan Mantey817012a2020-01-30 15:07:39 -08001194 if (dhcpIsEnabled(IP::Protocol::IPv4, true))
Ratan Guptae9c9b812017-09-22 17:15:37 +05301195 {
1196 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -05001197 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +05301198 }
1199
1200 // clear all the ip on the interface
1201 addrs.clear();
1202 manager.writeToConfigurationFile();
1203}
1204
Ravi Tejaa5a09442020-07-17 00:57:33 -05001205std::string EthernetInterface::defaultGateway(std::string gateway)
1206{
1207 auto gw = EthernetInterfaceIntf::defaultGateway();
1208 if (gw == gateway)
1209 {
1210 return gw;
1211 }
1212
1213 if (!isValidIP(AF_INET, gateway))
1214 {
1215 log<level::ERR>("Not a valid v4 Gateway",
1216 entry("GATEWAY=%s", gateway.c_str()));
1217 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1218 Argument::ARGUMENT_VALUE(gateway.c_str()));
1219 }
1220 gw = EthernetInterfaceIntf::defaultGateway(gateway);
1221 manager.writeToConfigurationFile();
1222 return gw;
1223}
1224
1225std::string EthernetInterface::defaultGateway6(std::string gateway)
1226{
1227 auto gw = EthernetInterfaceIntf::defaultGateway6();
1228 if (gw == gateway)
1229 {
1230 return gw;
1231 }
1232
1233 if (!isValidIP(AF_INET6, gateway))
1234 {
1235 log<level::ERR>("Not a valid v6 Gateway",
1236 entry("GATEWAY=%s", gateway.c_str()));
1237 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1238 Argument::ARGUMENT_VALUE(gateway.c_str()));
1239 }
1240 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
1241 manager.writeToConfigurationFile();
1242 return gw;
1243}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001244} // namespace network
1245} // namespace phosphor