blob: bd446771cb748ed9f05d0e4dbfee9faad22ba65c [file] [log] [blame]
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
21#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "error_messages.hpp"
24#include "health.hpp"
Ed Tanous2c5875a2023-05-15 09:56:06 -070025#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "query.hpp"
27#include "registries/privilege_registry.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070028#include "utils/ip_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "utils/json_utils.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070030
Ed Tanous11ba3972022-07-11 09:50:41 -070031#include <boost/algorithm/string/classification.hpp>
32#include <boost/algorithm/string/split.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070033#include <boost/url/format.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050034
George Liu7a1dbc42022-12-07 16:03:22 +080035#include <array>
Ed Tanousa24526d2018-12-10 15:17:59 -080036#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070037#include <ranges>
Joshi-Mansiab6554f2020-03-10 18:33:36 +053038#include <regex>
George Liu7a1dbc42022-12-07 16:03:22 +080039#include <string_view>
Ed Tanous77179532023-02-28 10:45:28 -080040#include <vector>
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010041
Ed Tanous1abe55e2018-09-05 08:30:59 -070042namespace redfish
43{
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010044
Ed Tanous4a0cb852018-10-15 07:55:04 -070045enum class LinkType
46{
47 Local,
48 Global
49};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010050
51/**
52 * Structure for keeping IPv4 data required by Redfish
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010053 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070054struct IPv4AddressData
55{
56 std::string id;
Ed Tanous4a0cb852018-10-15 07:55:04 -070057 std::string address;
58 std::string domain;
59 std::string gateway;
Ed Tanous1abe55e2018-09-05 08:30:59 -070060 std::string netmask;
61 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080062 LinkType linktype{};
63 bool isActive{};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010064};
65
66/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -050067 * Structure for keeping IPv6 data required by Redfish
68 */
69struct IPv6AddressData
70{
71 std::string id;
72 std::string address;
73 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080074 uint8_t prefixLength = 0;
Ravi Tejae48c0fc2019-04-16 08:37:20 -050075};
76/**
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010077 * Structure for keeping basic single Ethernet Interface information
78 * available from DBus
79 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070080struct EthernetInterfaceData
81{
Ed Tanous4a0cb852018-10-15 07:55:04 -070082 uint32_t speed;
Tejas Patil35fb5312021-09-20 15:35:20 +053083 size_t mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080084 bool autoNeg;
85 bool dnsEnabled;
86 bool ntpEnabled;
87 bool hostNameEnabled;
Johnathan Manteyaa05fb22020-01-08 12:08:44 -080088 bool linkUp;
Johnathan Manteyeeedda22019-10-29 16:09:52 -070089 bool nicEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -050090 bool ipv6AcceptRa;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080091 std::string dhcpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -070092 std::string operatingMode;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080093 std::string hostName;
94 std::string defaultGateway;
95 std::string ipv6DefaultGateway;
96 std::string macAddress;
Jiaqing Zhao17e22022022-04-14 18:58:06 +080097 std::optional<uint32_t> vlanId;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -050098 std::vector<std::string> nameServers;
99 std::vector<std::string> staticNameServers;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800100 std::vector<std::string> domainnames;
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100101};
102
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700103struct DHCPParameters
104{
105 std::optional<bool> dhcpv4Enabled;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800106 std::optional<bool> useDnsServers;
107 std::optional<bool> useNtpServers;
108 std::optional<bool> useDomainName;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700109 std::optional<std::string> dhcpv6OperatingMode;
110};
111
Ed Tanous4a0cb852018-10-15 07:55:04 -0700112// Helper function that changes bits netmask notation (i.e. /24)
113// into full dot notation
114inline std::string getNetmask(unsigned int bits)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700115{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700116 uint32_t value = 0xffffffff << (32 - bits);
117 std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
118 std::to_string((value >> 16) & 0xff) + "." +
119 std::to_string((value >> 8) & 0xff) + "." +
120 std::to_string(value & 0xff);
121 return netmask;
122}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100123
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800124inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700125 bool isIPv4)
126{
127 if (isIPv4)
128 {
129 return (
130 (inputDHCP ==
131 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
132 (inputDHCP ==
133 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
134 }
135 return ((inputDHCP ==
136 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
137 (inputDHCP ==
138 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
139}
140
Ed Tanous2c70f802020-09-28 14:29:23 -0700141inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700142{
143 if (isIPv4 && isIPv6)
144 {
145 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
146 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700147 if (isIPv4)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700148 {
149 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
150 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700151 if (isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700152 {
153 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
154 }
155 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
156}
157
Ed Tanous4a0cb852018-10-15 07:55:04 -0700158inline std::string
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500159 translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700160 bool isIPv4)
161{
162 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700163 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700164 return "Static";
165 }
166 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
167 {
168 if (isIPv4)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700169 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700170 return "IPv4LinkLocal";
171 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700172 return "LinkLocal";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700173 }
174 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
175 {
176 if (isIPv4)
177 {
178 return "DHCP";
179 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700180 return "DHCPv6";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700181 }
182 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
183 {
184 return "SLAAC";
185 }
186 return "";
187}
188
Ed Tanous02cad962022-06-30 16:50:15 -0700189inline bool extractEthernetInterfaceData(
190 const std::string& ethifaceId,
191 const dbus::utility::ManagedObjectType& dbusData,
192 EthernetInterfaceData& ethData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700193{
Ed Tanous4c9afe42019-05-03 16:59:57 -0700194 bool idFound = false;
Ed Tanous02cad962022-06-30 16:50:15 -0700195 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700196 {
Ed Tanous02cad962022-06-30 16:50:15 -0700197 for (const auto& ifacePair : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700198 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000199 if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700200 {
Ed Tanous4c9afe42019-05-03 16:59:57 -0700201 idFound = true;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700202 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700203 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500204 for (const auto& propertyPair : ifacePair.second)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700205 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700206 if (propertyPair.first == "MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700207 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500208 const std::string* mac =
Ed Tanousabf2add2019-01-22 16:40:12 -0800209 std::get_if<std::string>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700210 if (mac != nullptr)
211 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800212 ethData.macAddress = *mac;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700213 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700214 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700215 }
216 }
217 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
218 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500219 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700220 {
221 if (propertyPair.first == "Id")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700222 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500223 const uint32_t* id =
Ed Tanousabf2add2019-01-22 16:40:12 -0800224 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700225 if (id != nullptr)
226 {
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800227 ethData.vlanId = *id;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700228 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700229 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700230 }
231 }
232 else if (ifacePair.first ==
233 "xyz.openbmc_project.Network.EthernetInterface")
234 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500235 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700236 {
237 if (propertyPair.first == "AutoNeg")
238 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700239 const bool* autoNeg =
Ed Tanousabf2add2019-01-22 16:40:12 -0800240 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700241 if (autoNeg != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700242 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800243 ethData.autoNeg = *autoNeg;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700244 }
245 }
246 else if (propertyPair.first == "Speed")
247 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500248 const uint32_t* speed =
Ed Tanousabf2add2019-01-22 16:40:12 -0800249 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700250 if (speed != nullptr)
251 {
252 ethData.speed = *speed;
253 }
254 }
Tejas Patil35fb5312021-09-20 15:35:20 +0530255 else if (propertyPair.first == "MTU")
256 {
257 const uint32_t* mtuSize =
258 std::get_if<uint32_t>(&propertyPair.second);
259 if (mtuSize != nullptr)
260 {
261 ethData.mtuSize = *mtuSize;
262 }
263 }
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800264 else if (propertyPair.first == "LinkUp")
265 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500266 const bool* linkUp =
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800267 std::get_if<bool>(&propertyPair.second);
268 if (linkUp != nullptr)
269 {
270 ethData.linkUp = *linkUp;
271 }
272 }
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700273 else if (propertyPair.first == "NICEnabled")
274 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500275 const bool* nicEnabled =
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700276 std::get_if<bool>(&propertyPair.second);
277 if (nicEnabled != nullptr)
278 {
279 ethData.nicEnabled = *nicEnabled;
280 }
281 }
Ravi Tejab10d8db2022-05-24 09:04:12 -0500282 else if (propertyPair.first == "IPv6AcceptRA")
283 {
284 const bool* ipv6AcceptRa =
285 std::get_if<bool>(&propertyPair.second);
286 if (ipv6AcceptRa != nullptr)
287 {
288 ethData.ipv6AcceptRa = *ipv6AcceptRa;
289 }
290 }
RAJESWARAN THILLAIGOVINDANf85837b2019-04-04 05:18:53 -0500291 else if (propertyPair.first == "Nameservers")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700292 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500293 const std::vector<std::string>* nameservers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500294 std::get_if<std::vector<std::string>>(
Ed Tanous029573d2019-02-01 10:57:49 -0800295 &propertyPair.second);
296 if (nameservers != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700297 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700298 ethData.nameServers = *nameservers;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500299 }
300 }
301 else if (propertyPair.first == "StaticNameServers")
302 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500303 const std::vector<std::string>* staticNameServers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500304 std::get_if<std::vector<std::string>>(
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500305 &propertyPair.second);
306 if (staticNameServers != nullptr)
307 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700308 ethData.staticNameServers = *staticNameServers;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700309 }
310 }
manojkiraneda2a133282019-02-19 13:09:43 +0530311 else if (propertyPair.first == "DHCPEnabled")
312 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700313 const std::string* dhcpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700314 std::get_if<std::string>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700315 if (dhcpEnabled != nullptr)
manojkiraneda2a133282019-02-19 13:09:43 +0530316 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800317 ethData.dhcpEnabled = *dhcpEnabled;
manojkiraneda2a133282019-02-19 13:09:43 +0530318 }
319 }
Jennifer Leed24bfc72019-03-05 13:03:37 -0800320 else if (propertyPair.first == "DomainName")
321 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500322 const std::vector<std::string>* domainNames =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500323 std::get_if<std::vector<std::string>>(
Jennifer Leed24bfc72019-03-05 13:03:37 -0800324 &propertyPair.second);
325 if (domainNames != nullptr)
326 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700327 ethData.domainnames = *domainNames;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800328 }
329 }
Ravi Teja9010ec22019-08-01 23:30:25 -0500330 else if (propertyPair.first == "DefaultGateway")
331 {
332 const std::string* defaultGateway =
333 std::get_if<std::string>(&propertyPair.second);
334 if (defaultGateway != nullptr)
335 {
336 std::string defaultGatewayStr = *defaultGateway;
337 if (defaultGatewayStr.empty())
338 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800339 ethData.defaultGateway = "0.0.0.0";
Ravi Teja9010ec22019-08-01 23:30:25 -0500340 }
341 else
342 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800343 ethData.defaultGateway = defaultGatewayStr;
Ravi Teja9010ec22019-08-01 23:30:25 -0500344 }
345 }
346 }
347 else if (propertyPair.first == "DefaultGateway6")
348 {
349 const std::string* defaultGateway6 =
350 std::get_if<std::string>(&propertyPair.second);
351 if (defaultGateway6 != nullptr)
352 {
353 std::string defaultGateway6Str =
354 *defaultGateway6;
355 if (defaultGateway6Str.empty())
356 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800357 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500358 "0:0:0:0:0:0:0:0";
359 }
360 else
361 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800362 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500363 defaultGateway6Str;
364 }
365 }
366 }
Ed Tanous029573d2019-02-01 10:57:49 -0800367 }
368 }
369 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700370
Jian Zhang1e3f85e2022-12-13 13:50:35 +0800371 if (objpath.first == "/xyz/openbmc_project/network/dhcp")
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700372 {
373 if (ifacePair.first ==
374 "xyz.openbmc_project.Network.DHCPConfiguration")
375 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500376 for (const auto& propertyPair : ifacePair.second)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700377 {
378 if (propertyPair.first == "DNSEnabled")
379 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700380 const bool* dnsEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700381 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700382 if (dnsEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700383 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800384 ethData.dnsEnabled = *dnsEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700385 }
386 }
387 else if (propertyPair.first == "NTPEnabled")
388 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700389 const bool* ntpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700390 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700391 if (ntpEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700392 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800393 ethData.ntpEnabled = *ntpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700394 }
395 }
396 else if (propertyPair.first == "HostNameEnabled")
397 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700398 const bool* hostNameEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700399 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700400 if (hostNameEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700401 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800402 ethData.hostNameEnabled = *hostNameEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700403 }
404 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700405 }
406 }
407 }
Ed Tanous029573d2019-02-01 10:57:49 -0800408 // System configuration shows up in the global namespace, so no need
409 // to check eth number
410 if (ifacePair.first ==
411 "xyz.openbmc_project.Network.SystemConfiguration")
412 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500413 for (const auto& propertyPair : ifacePair.second)
Ed Tanous029573d2019-02-01 10:57:49 -0800414 {
415 if (propertyPair.first == "HostName")
416 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500417 const std::string* hostname =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500418 std::get_if<std::string>(&propertyPair.second);
Ed Tanous029573d2019-02-01 10:57:49 -0800419 if (hostname != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700420 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800421 ethData.hostName = *hostname;
Ed Tanous029573d2019-02-01 10:57:49 -0800422 }
423 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700424 }
425 }
426 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700427 }
Ed Tanous4c9afe42019-05-03 16:59:57 -0700428 return idFound;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700429}
430
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500431// Helper function that extracts data for single ethernet ipv6 address
Ed Tanous77179532023-02-28 10:45:28 -0800432inline void extractIPV6Data(const std::string& ethifaceId,
433 const dbus::utility::ManagedObjectType& dbusData,
434 std::vector<IPv6AddressData>& ipv6Config)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500435{
Patrick Williams89492a12023-05-10 07:51:34 -0500436 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
437 ethifaceId;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500438
439 // Since there might be several IPv6 configurations aligned with
440 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000441 for (const auto& objpath : dbusData)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500442 {
443 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800444 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500445 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800446 for (const auto& interface : objpath.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500447 {
448 if (interface.first == "xyz.openbmc_project.Network.IP")
449 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700450 auto type = std::ranges::find_if(interface.second,
451 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800452 return property.first == "Type";
453 });
454 if (type == interface.second.end())
455 {
456 continue;
457 }
458
459 const std::string* typeStr =
460 std::get_if<std::string>(&type->second);
461
462 if (typeStr == nullptr ||
463 (*typeStr !=
464 "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
465 {
466 continue;
467 }
468
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500469 // Instance IPv6AddressData structure, and set as
470 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800471 IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700472 ipv6Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800473 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800474 for (const auto& property : interface.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500475 {
476 if (property.first == "Address")
477 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500478 const std::string* address =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500479 std::get_if<std::string>(&property.second);
480 if (address != nullptr)
481 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700482 ipv6Address.address = *address;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500483 }
484 }
485 else if (property.first == "Origin")
486 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500487 const std::string* origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500488 std::get_if<std::string>(&property.second);
489 if (origin != nullptr)
490 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700491 ipv6Address.origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500492 translateAddressOriginDbusToRedfish(*origin,
493 false);
494 }
495 }
496 else if (property.first == "PrefixLength")
497 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500498 const uint8_t* prefix =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500499 std::get_if<uint8_t>(&property.second);
500 if (prefix != nullptr)
501 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700502 ipv6Address.prefixLength = *prefix;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500503 }
504 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600505 else if (property.first == "Type" ||
506 property.first == "Gateway")
507 {
508 // Type & Gateway is not used
509 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500510 else
511 {
Ed Tanous62598e32023-07-17 17:06:25 -0700512 BMCWEB_LOG_ERROR(
513 "Got extra property: {} on the {} object",
514 property.first, objpath.first.str);
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500515 }
516 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500517 }
518 }
519 }
520 }
521}
522
Ed Tanous4a0cb852018-10-15 07:55:04 -0700523// Helper function that extracts data for single ethernet ipv4 address
Ed Tanous77179532023-02-28 10:45:28 -0800524inline void extractIPData(const std::string& ethifaceId,
525 const dbus::utility::ManagedObjectType& dbusData,
526 std::vector<IPv4AddressData>& ipv4Config)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700527{
Patrick Williams89492a12023-05-10 07:51:34 -0500528 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
529 ethifaceId;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700530
531 // Since there might be several IPv4 configurations aligned with
532 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000533 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700534 {
535 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800536 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700537 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800538 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700539 {
540 if (interface.first == "xyz.openbmc_project.Network.IP")
541 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700542 auto type = std::ranges::find_if(interface.second,
543 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800544 return property.first == "Type";
545 });
546 if (type == interface.second.end())
547 {
548 continue;
549 }
550
551 const std::string* typeStr =
552 std::get_if<std::string>(&type->second);
553
554 if (typeStr == nullptr ||
555 (*typeStr !=
556 "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
557 {
558 continue;
559 }
560
Ed Tanous4a0cb852018-10-15 07:55:04 -0700561 // Instance IPv4AddressData structure, and set as
562 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800563 IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700564 ipv4Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800565 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800566 for (const auto& property : interface.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700567 {
568 if (property.first == "Address")
569 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500570 const std::string* address =
Ed Tanousabf2add2019-01-22 16:40:12 -0800571 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700572 if (address != nullptr)
573 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700574 ipv4Address.address = *address;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700575 }
576 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700577 else if (property.first == "Origin")
578 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500579 const std::string* origin =
Ed Tanousabf2add2019-01-22 16:40:12 -0800580 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700581 if (origin != nullptr)
582 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700583 ipv4Address.origin =
Ed Tanous4a0cb852018-10-15 07:55:04 -0700584 translateAddressOriginDbusToRedfish(*origin,
585 true);
586 }
587 }
588 else if (property.first == "PrefixLength")
589 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500590 const uint8_t* mask =
Ed Tanousabf2add2019-01-22 16:40:12 -0800591 std::get_if<uint8_t>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700592 if (mask != nullptr)
593 {
594 // convert it to the string
Ed Tanous2c70f802020-09-28 14:29:23 -0700595 ipv4Address.netmask = getNetmask(*mask);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700596 }
597 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600598 else if (property.first == "Type" ||
599 property.first == "Gateway")
600 {
601 // Type & Gateway is not used
602 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700603 else
604 {
Ed Tanous62598e32023-07-17 17:06:25 -0700605 BMCWEB_LOG_ERROR(
606 "Got extra property: {} on the {} object",
607 property.first, objpath.first.str);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700608 }
609 }
610 // Check if given address is local, or global
Ed Tanous2c70f802020-09-28 14:29:23 -0700611 ipv4Address.linktype =
Ed Tanous11ba3972022-07-11 09:50:41 -0700612 ipv4Address.address.starts_with("169.254.")
Johnathan Mantey18659d12019-06-07 10:26:29 -0700613 ? LinkType::Local
614 : LinkType::Global;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700615 }
616 }
617 }
618 }
619}
620
621/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700622 * @brief Deletes given IPv4 interface
Ed Tanous4a0cb852018-10-15 07:55:04 -0700623 *
624 * @param[in] ifaceId Id of interface whose IP should be deleted
Ed Tanous4a0cb852018-10-15 07:55:04 -0700625 * @param[in] ipHash DBus Hash id of IP that should be deleted
626 * @param[io] asyncResp Response object that will be returned to client
627 *
628 * @return None
629 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600630inline void deleteIPAddress(const std::string& ifaceId,
631 const std::string& ipHash,
632 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700633{
634 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800635 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700636 if (ec)
637 {
638 messages::internalError(asyncResp->res);
639 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700640 },
641 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600642 "/xyz/openbmc_project/network/" + ifaceId + ipHash,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700643 "xyz.openbmc_project.Object.Delete", "Delete");
644}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700645
Gunnar Mills244b6d52021-04-12 15:44:23 -0500646inline void updateIPv4DefaultGateway(
647 const std::string& ifaceId, const std::string& gateway,
648 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Teja9010ec22019-08-01 23:30:25 -0500649{
George Liu9ae226f2023-06-21 17:56:46 +0800650 sdbusplus::asio::setProperty(
651 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ravi Teja9010ec22019-08-01 23:30:25 -0500652 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9010ec22019-08-01 23:30:25 -0500653 "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
George Liu9ae226f2023-06-21 17:56:46 +0800654 gateway, [asyncResp](const boost::system::error_code& ec) {
655 if (ec)
656 {
657 messages::internalError(asyncResp->res);
658 return;
659 }
660 asyncResp->res.result(boost::beast::http::status::no_content);
661 });
Ravi Teja9010ec22019-08-01 23:30:25 -0500662}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700663/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700664 * @brief Creates a static IPv4 entry
Ed Tanous4a0cb852018-10-15 07:55:04 -0700665 *
Johnathan Mantey01784822019-06-18 12:44:21 -0700666 * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
667 * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
668 * @param[in] gateway IPv4 address of this interfaces gateway
669 * @param[in] address IPv4 address to assign to this interface
670 * @param[io] asyncResp Response object that will be returned to client
Ed Tanous4a0cb852018-10-15 07:55:04 -0700671 *
672 * @return None
673 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000674inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
675 const std::string& gateway, const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800676 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700677{
Ed Tanous002d39b2022-05-31 08:59:27 -0700678 auto createIpHandler =
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800679 [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
Ravi Teja9010ec22019-08-01 23:30:25 -0500680 if (ec)
681 {
682 messages::internalError(asyncResp->res);
683 return;
684 }
685 updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
686 };
687
Ed Tanous4a0cb852018-10-15 07:55:04 -0700688 crow::connections::systemBus->async_method_call(
Ravi Teja9010ec22019-08-01 23:30:25 -0500689 std::move(createIpHandler), "xyz.openbmc_project.Network",
Ed Tanous4a0cb852018-10-15 07:55:04 -0700690 "/xyz/openbmc_project/network/" + ifaceId,
691 "xyz.openbmc_project.Network.IP.Create", "IP",
Johnathan Mantey01784822019-06-18 12:44:21 -0700692 "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700693 gateway);
694}
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500695
696/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700697 * @brief Deletes the IPv6 entry for this interface and creates a replacement
698 * static IPv6 entry
699 *
700 * @param[in] ifaceId Id of interface upon which to create the IPv6 entry
701 * @param[in] id The unique hash entry identifying the DBus entry
702 * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
703 * @param[in] address IPv6 address to assign to this interface
704 * @param[io] asyncResp Response object that will be returned to client
705 *
706 * @return None
707 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600708
709enum class IpVersion
710{
711 IpV4,
712 IpV6
713};
714
715inline void deleteAndCreateIPAddress(
716 IpVersion version, const std::string& ifaceId, const std::string& id,
717 uint8_t prefixLength, const std::string& address,
718 const std::string& gateway,
719 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Johnathan Mantey01784822019-06-18 12:44:21 -0700720{
721 crow::connections::systemBus->async_method_call(
Ravi Teja9c5e5852023-02-26 21:33:52 -0600722 [asyncResp, version, ifaceId, address, prefixLength,
723 gateway](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700724 if (ec)
725 {
726 messages::internalError(asyncResp->res);
727 }
Ravi Teja9c5e5852023-02-26 21:33:52 -0600728 std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
729 protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
Ed Tanous002d39b2022-05-31 08:59:27 -0700730 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800731 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700732 if (ec2)
Johnathan Mantey01784822019-06-18 12:44:21 -0700733 {
734 messages::internalError(asyncResp->res);
735 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700736 },
737 "xyz.openbmc_project.Network",
738 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9c5e5852023-02-26 21:33:52 -0600739 "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
740 prefixLength, gateway);
Johnathan Mantey01784822019-06-18 12:44:21 -0700741 },
742 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600743 "/xyz/openbmc_project/network/" + ifaceId + id,
Johnathan Mantey01784822019-06-18 12:44:21 -0700744 "xyz.openbmc_project.Object.Delete", "Delete");
745}
746
747/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500748 * @brief Creates IPv6 with given data
749 *
750 * @param[in] ifaceId Id of interface whose IP should be added
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500751 * @param[in] prefixLength Prefix length that needs to be added
752 * @param[in] address IP address that needs to be added
753 * @param[io] asyncResp Response object that will be returned to client
754 *
755 * @return None
756 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500757inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
758 const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800759 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500760{
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500761 auto createIpHandler =
762 [asyncResp, address](const boost::system::error_code& ec) {
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500763 if (ec)
764 {
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500765 if (ec == boost::system::errc::io_error)
766 {
767 messages::propertyValueFormatError(asyncResp->res, address,
768 "Address");
769 }
770 else
771 {
772 messages::internalError(asyncResp->res);
773 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500774 }
775 };
776 // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500777 // does not have associated gateway property
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500778 crow::connections::systemBus->async_method_call(
779 std::move(createIpHandler), "xyz.openbmc_project.Network",
780 "/xyz/openbmc_project/network/" + ifaceId,
781 "xyz.openbmc_project.Network.IP.Create", "IP",
782 "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
783 "");
784}
785
Ed Tanous4a0cb852018-10-15 07:55:04 -0700786/**
787 * Function that retrieves all properties for given Ethernet Interface
788 * Object
789 * from EntityManager Network Manager
790 * @param ethiface_id a eth interface id to query on DBus
791 * @param callback a function that shall be called to convert Dbus output
792 * into JSON
793 */
794template <typename CallbackFunc>
Ed Tanous81ce6092020-12-17 16:54:55 +0000795void getEthernetIfaceData(const std::string& ethifaceId,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500796 CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700797{
George Liuf5892d02023-03-01 10:37:08 +0800798 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
799 dbus::utility::getManagedObjects(
800 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800801 [ethifaceId{std::string{ethifaceId}},
802 callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700803 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700804 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700805 EthernetInterfaceData ethData{};
Ed Tanous77179532023-02-28 10:45:28 -0800806 std::vector<IPv4AddressData> ipv4Data;
807 std::vector<IPv6AddressData> ipv6Data;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700808
Ed Tanous8b242752023-06-27 17:17:13 -0700809 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700810 {
811 callback(false, ethData, ipv4Data, ipv6Data);
812 return;
813 }
814
815 bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
816 if (!found)
817 {
818 callback(false, ethData, ipv4Data, ipv6Data);
819 return;
820 }
821
822 extractIPData(ethifaceId, resp, ipv4Data);
823 // Fix global GW
824 for (IPv4AddressData& ipv4 : ipv4Data)
825 {
826 if (((ipv4.linktype == LinkType::Global) &&
827 (ipv4.gateway == "0.0.0.0")) ||
828 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700829 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700830 ipv4.gateway = ethData.defaultGateway;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700831 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700832 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700833
Ed Tanous002d39b2022-05-31 08:59:27 -0700834 extractIPV6Data(ethifaceId, resp, ipv6Data);
835 // Finally make a callback with useful data
836 callback(true, ethData, ipv4Data, ipv6Data);
George Liuf5892d02023-03-01 10:37:08 +0800837 });
Ed Tanous271584a2019-07-09 16:24:22 -0700838}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700839
840/**
841 * Function that retrieves all Ethernet Interfaces available through Network
842 * Manager
843 * @param callback a function that shall be called to convert Dbus output
844 * into JSON.
845 */
846template <typename CallbackFunc>
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500847void getEthernetIfaceList(CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700848{
George Liuf5892d02023-03-01 10:37:08 +0800849 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
850 dbus::utility::getManagedObjects(
851 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800852 [callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700853 const boost::system::error_code& ec,
George Liuf5892d02023-03-01 10:37:08 +0800854 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700855 // Callback requires vector<string> to retrieve all available
856 // ethernet interfaces
Ed Tanous77179532023-02-28 10:45:28 -0800857 std::vector<std::string> ifaceList;
Ed Tanous002d39b2022-05-31 08:59:27 -0700858 ifaceList.reserve(resp.size());
Ed Tanous8b242752023-06-27 17:17:13 -0700859 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700860 {
861 callback(false, ifaceList);
862 return;
863 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700864
Ed Tanous002d39b2022-05-31 08:59:27 -0700865 // Iterate over all retrieved ObjectPaths.
866 for (const auto& objpath : resp)
867 {
868 // And all interfaces available for certain ObjectPath.
869 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700870 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700871 // If interface is
872 // xyz.openbmc_project.Network.EthernetInterface, this is
873 // what we're looking for.
874 if (interface.first ==
875 "xyz.openbmc_project.Network.EthernetInterface")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700876 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700877 std::string ifaceId = objpath.first.filename();
878 if (ifaceId.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700879 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700880 continue;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700881 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700882 // and put it into output vector.
Ed Tanous77179532023-02-28 10:45:28 -0800883 ifaceList.emplace_back(ifaceId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700884 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700885 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700886 }
Ed Tanous2c5875a2023-05-15 09:56:06 -0700887
Ed Tanous3544d2a2023-08-06 18:12:20 -0700888 std::ranges::sort(ifaceList, AlphanumLess<std::string>());
Ed Tanous2c5875a2023-05-15 09:56:06 -0700889
Ed Tanous002d39b2022-05-31 08:59:27 -0700890 // Finally make a callback with useful data
891 callback(true, ifaceList);
George Liuf5892d02023-03-01 10:37:08 +0800892 });
Ed Tanous271584a2019-07-09 16:24:22 -0700893}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100894
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700895inline void
896 handleHostnamePatch(const std::string& hostname,
897 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700898{
Ed Tanousbf648f72021-06-03 15:00:14 -0700899 // SHOULD handle host names of up to 255 characters(RFC 1123)
900 if (hostname.length() > 255)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700901 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700902 messages::propertyValueFormatError(asyncResp->res, hostname,
903 "HostName");
904 return;
905 }
George Liu9ae226f2023-06-21 17:56:46 +0800906 sdbusplus::asio::setProperty(
907 *crow::connections::systemBus, "xyz.openbmc_project.Network",
908 "/xyz/openbmc_project/network/config",
909 "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800910 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700911 if (ec)
912 {
913 messages::internalError(asyncResp->res);
914 }
George Liu9ae226f2023-06-21 17:56:46 +0800915 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700916}
917
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700918inline void
Tejas Patil35fb5312021-09-20 15:35:20 +0530919 handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
920 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
921{
Patrick Williams89492a12023-05-10 07:51:34 -0500922 sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
923 ifaceId;
George Liu9ae226f2023-06-21 17:56:46 +0800924 sdbusplus::asio::setProperty(
925 *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
926 "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800927 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700928 if (ec)
929 {
930 messages::internalError(asyncResp->res);
931 }
George Liu9ae226f2023-06-21 17:56:46 +0800932 });
Tejas Patil35fb5312021-09-20 15:35:20 +0530933}
934
935inline void
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700936 handleDomainnamePatch(const std::string& ifaceId,
937 const std::string& domainname,
938 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700939{
940 std::vector<std::string> vectorDomainname = {domainname};
George Liu9ae226f2023-06-21 17:56:46 +0800941 sdbusplus::asio::setProperty(
942 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ed Tanousbf648f72021-06-03 15:00:14 -0700943 "/xyz/openbmc_project/network/" + ifaceId,
Ed Tanousbf648f72021-06-03 15:00:14 -0700944 "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
George Liu9ae226f2023-06-21 17:56:46 +0800945 vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
946 if (ec)
947 {
948 messages::internalError(asyncResp->res);
949 }
950 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700951}
952
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700953inline bool isHostnameValid(const std::string& hostname)
Ed Tanousbf648f72021-06-03 15:00:14 -0700954{
955 // A valid host name can never have the dotted-decimal form (RFC 1123)
Ed Tanous3544d2a2023-08-06 18:12:20 -0700956 if (std::ranges::all_of(hostname, ::isdigit))
Ed Tanousbf648f72021-06-03 15:00:14 -0700957 {
958 return false;
959 }
960 // Each label(hostname/subdomains) within a valid FQDN
961 // MUST handle host names of up to 63 characters (RFC 1123)
962 // labels cannot start or end with hyphens (RFC 952)
963 // labels can start with numbers (RFC 1123)
Ed Tanous4b242742023-05-11 09:51:51 -0700964 const static std::regex pattern(
Ed Tanousbf648f72021-06-03 15:00:14 -0700965 "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
966
967 return std::regex_match(hostname, pattern);
968}
969
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700970inline bool isDomainnameValid(const std::string& domainname)
Ed Tanousbf648f72021-06-03 15:00:14 -0700971{
972 // Can have multiple subdomains
973 // Top Level Domain's min length is 2 character
Ed Tanous4b242742023-05-11 09:51:51 -0700974 const static std::regex pattern(
George Liu0fda0f12021-11-16 10:06:17 +0800975 "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
Ed Tanousbf648f72021-06-03 15:00:14 -0700976
977 return std::regex_match(domainname, pattern);
978}
979
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700980inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
981 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700982{
983 // Total length of FQDN must not exceed 255 characters(RFC 1035)
984 if (fqdn.length() > 255)
985 {
986 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
987 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700988 }
989
Ed Tanousbf648f72021-06-03 15:00:14 -0700990 size_t pos = fqdn.find('.');
991 if (pos == std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700992 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700993 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
994 return;
995 }
zhanghch058d1b46d2021-04-01 11:18:24 +0800996
Ed Tanousbf648f72021-06-03 15:00:14 -0700997 std::string hostname;
998 std::string domainname;
999 domainname = (fqdn).substr(pos + 1);
1000 hostname = (fqdn).substr(0, pos);
1001
1002 if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1003 {
1004 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1005 return;
1006 }
1007
1008 handleHostnamePatch(hostname, asyncResp);
1009 handleDomainnamePatch(ifaceId, domainname, asyncResp);
1010}
1011
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001012inline void
1013 handleMACAddressPatch(const std::string& ifaceId,
1014 const std::string& macAddress,
1015 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001016{
Johnathan Mantey58283f42022-08-15 14:38:36 -07001017 static constexpr std::string_view dbusNotAllowedError =
1018 "xyz.openbmc_project.Common.Error.NotAllowed";
1019
George Liu9ae226f2023-06-21 17:56:46 +08001020 sdbusplus::asio::setProperty(
1021 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1022 "/xyz/openbmc_project/network/" + ifaceId,
1023 "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
1024 [asyncResp](const boost::system::error_code& ec,
1025 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001026 if (ec)
1027 {
Johnathan Mantey58283f42022-08-15 14:38:36 -07001028 const sd_bus_error* err = msg.get_error();
1029 if (err == nullptr)
1030 {
1031 messages::internalError(asyncResp->res);
1032 return;
1033 }
1034 if (err->name == dbusNotAllowedError)
1035 {
1036 messages::propertyNotWritable(asyncResp->res, "MACAddress");
1037 return;
1038 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001039 messages::internalError(asyncResp->res);
1040 return;
1041 }
George Liu9ae226f2023-06-21 17:56:46 +08001042 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001043}
1044
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001045inline void setDHCPEnabled(const std::string& ifaceId,
1046 const std::string& propertyName, const bool v4Value,
1047 const bool v6Value,
1048 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001049{
1050 const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
George Liu9ae226f2023-06-21 17:56:46 +08001051 sdbusplus::asio::setProperty(
1052 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1053 "/xyz/openbmc_project/network/" + ifaceId,
1054 "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001055 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001056 if (ec)
1057 {
Ed Tanous62598e32023-07-17 17:06:25 -07001058 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001059 messages::internalError(asyncResp->res);
1060 return;
1061 }
1062 messages::success(asyncResp->res);
George Liu9ae226f2023-06-21 17:56:46 +08001063 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001064}
1065
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001066inline void setEthernetInterfaceBoolProperty(
Ed Tanousbf648f72021-06-03 15:00:14 -07001067 const std::string& ifaceId, const std::string& propertyName,
1068 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1069{
George Liu9ae226f2023-06-21 17:56:46 +08001070 sdbusplus::asio::setProperty(
1071 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1072 "/xyz/openbmc_project/network/" + ifaceId,
1073 "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001074 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001075 if (ec)
1076 {
Ed Tanous62598e32023-07-17 17:06:25 -07001077 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001078 messages::internalError(asyncResp->res);
1079 return;
1080 }
George Liu9ae226f2023-06-21 17:56:46 +08001081 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001082}
1083
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001084inline void setDHCPv4Config(const std::string& propertyName, const bool& value,
1085 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001086{
Ed Tanous62598e32023-07-17 17:06:25 -07001087 BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
George Liu9ae226f2023-06-21 17:56:46 +08001088 sdbusplus::asio::setProperty(
1089 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1090 "/xyz/openbmc_project/network/dhcp",
1091 "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001092 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001093 if (ec)
1094 {
Ed Tanous62598e32023-07-17 17:06:25 -07001095 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001096 messages::internalError(asyncResp->res);
1097 return;
1098 }
George Liu9ae226f2023-06-21 17:56:46 +08001099 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001100}
1101
Ravi Tejab10d8db2022-05-24 09:04:12 -05001102inline void handleSLAACAutoConfigPatch(
1103 const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1104 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1105{
1106 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1107 path /= ifaceId;
1108 sdbusplus::asio::setProperty(
1109 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1110 "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1111 ipv6AutoConfigEnabled,
1112 [asyncResp](const boost::system::error_code& ec) {
1113 if (ec)
1114 {
1115 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1116 messages::internalError(asyncResp->res);
1117 return;
1118 }
1119 messages::success(asyncResp->res);
1120 });
1121}
1122
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001123inline void handleDHCPPatch(const std::string& ifaceId,
1124 const EthernetInterfaceData& ethData,
1125 const DHCPParameters& v4dhcpParms,
1126 const DHCPParameters& v6dhcpParms,
1127 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001128{
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001129 bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1130 bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
Ed Tanousbf648f72021-06-03 15:00:14 -07001131
1132 bool nextv4DHCPState =
1133 v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
1134
1135 bool nextv6DHCPState{};
1136 if (v6dhcpParms.dhcpv6OperatingMode)
1137 {
Ravi Tejab10d8db2022-05-24 09:04:12 -05001138 if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
Ed Tanousbf648f72021-06-03 15:00:14 -07001139 (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
1140 {
1141 messages::propertyValueFormatError(asyncResp->res,
1142 *v6dhcpParms.dhcpv6OperatingMode,
1143 "OperatingMode");
1144 return;
1145 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001146 nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
Ed Tanousbf648f72021-06-03 15:00:14 -07001147 }
1148 else
1149 {
1150 nextv6DHCPState = ipv6Active;
1151 }
1152
1153 bool nextDNS{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001154 if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001155 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001156 if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001157 {
1158 messages::generalError(asyncResp->res);
1159 return;
1160 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001161 nextDNS = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001162 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001163 else if (v4dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001164 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001165 nextDNS = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001166 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001167 else if (v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001168 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001169 nextDNS = *v6dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001170 }
1171 else
1172 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001173 nextDNS = ethData.dnsEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001174 }
1175
1176 bool nextNTP{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001177 if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001178 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001179 if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001180 {
1181 messages::generalError(asyncResp->res);
1182 return;
1183 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001184 nextNTP = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001185 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001186 else if (v4dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001187 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001188 nextNTP = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001189 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001190 else if (v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001191 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001192 nextNTP = *v6dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001193 }
1194 else
1195 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001196 nextNTP = ethData.ntpEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001197 }
1198
1199 bool nextUseDomain{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001200 if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001201 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001202 if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001203 {
1204 messages::generalError(asyncResp->res);
1205 return;
1206 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001207 nextUseDomain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001208 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001209 else if (v4dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001210 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001211 nextUseDomain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001212 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001213 else if (v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001214 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001215 nextUseDomain = *v6dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001216 }
1217 else
1218 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001219 nextUseDomain = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001220 }
1221
Ed Tanous62598e32023-07-17 17:06:25 -07001222 BMCWEB_LOG_DEBUG("set DHCPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001223 setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
1224 asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001225 BMCWEB_LOG_DEBUG("set DNSEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001226 setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001227 BMCWEB_LOG_DEBUG("set NTPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001228 setDHCPv4Config("NTPEnabled", nextNTP, asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001229 BMCWEB_LOG_DEBUG("set HostNameEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001230 setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp);
1231}
1232
Ed Tanous77179532023-02-28 10:45:28 -08001233inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
1234 const std::vector<IPv4AddressData>::const_iterator& head,
1235 const std::vector<IPv4AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001236{
1237 return std::find_if(head, end, [](const IPv4AddressData& value) {
1238 return value.origin == "Static";
1239 });
1240}
1241
Ed Tanous77179532023-02-28 10:45:28 -08001242inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
1243 const std::vector<IPv6AddressData>::const_iterator& head,
1244 const std::vector<IPv6AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001245{
1246 return std::find_if(head, end, [](const IPv6AddressData& value) {
1247 return value.origin == "Static";
1248 });
1249}
1250
Ed Tanous77179532023-02-28 10:45:28 -08001251inline void
Ed Tanousddd70dc2023-03-01 16:00:27 -08001252 handleIPv4StaticPatch(const std::string& ifaceId,
1253 nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001254 const std::vector<IPv4AddressData>& ipv4Data,
1255 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001256{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001257 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001258 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001259 messages::propertyValueTypeError(asyncResp->res, input,
1260 "IPv4StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001261 return;
1262 }
1263
1264 unsigned entryIdx = 1;
1265 // Find the first static IP address currently active on the NIC and
1266 // match it to the first JSON element in the IPv4StaticAddresses array.
1267 // Match each subsequent JSON element to the next static IP programmed
1268 // into the NIC.
Ed Tanous77179532023-02-28 10:45:28 -08001269 std::vector<IPv4AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001270 getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
1271
1272 for (nlohmann::json& thisJson : input)
1273 {
Patrick Williams89492a12023-05-10 07:51:34 -05001274 std::string pathString = "IPv4StaticAddresses/" +
1275 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001276
1277 if (!thisJson.is_null() && !thisJson.empty())
1278 {
1279 std::optional<std::string> address;
1280 std::optional<std::string> subnetMask;
1281 std::optional<std::string> gateway;
1282
1283 if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1284 address, "SubnetMask", subnetMask,
1285 "Gateway", gateway))
1286 {
Ed Tanousf818b042022-06-27 13:17:35 -07001287 messages::propertyValueFormatError(asyncResp->res, thisJson,
1288 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001289 return;
1290 }
1291
1292 // Find the address/subnet/gateway values. Any values that are
1293 // not explicitly provided are assumed to be unmodified from the
1294 // current state of the interface. Merge existing state into the
1295 // current request.
Ed Tanousbf648f72021-06-03 15:00:14 -07001296 if (address)
1297 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001298 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001299 {
1300 messages::propertyValueFormatError(asyncResp->res, *address,
1301 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001302 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001303 }
1304 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001305 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001306 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001307 address = (nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001308 }
1309 else
1310 {
1311 messages::propertyMissing(asyncResp->res,
1312 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001313 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001314 }
1315
Ed Tanouse01d0c32023-06-30 13:21:32 -07001316 uint8_t prefixLength = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001317 if (subnetMask)
1318 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001319 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1320 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001321 {
1322 messages::propertyValueFormatError(
1323 asyncResp->res, *subnetMask,
1324 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001325 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001326 }
1327 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001328 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001329 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001330 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1331 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001332 {
1333 messages::propertyValueFormatError(
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001334 asyncResp->res, nicIpEntry->netmask,
Ed Tanousbf648f72021-06-03 15:00:14 -07001335 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001336 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001337 }
1338 }
1339 else
1340 {
1341 messages::propertyMissing(asyncResp->res,
1342 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001343 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001344 }
1345
1346 if (gateway)
1347 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001348 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001349 {
1350 messages::propertyValueFormatError(asyncResp->res, *gateway,
1351 pathString + "/Gateway");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001352 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001353 }
1354 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001355 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001356 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001357 gateway = nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001358 }
1359 else
1360 {
1361 messages::propertyMissing(asyncResp->res,
1362 pathString + "/Gateway");
Ed Tanousbf648f72021-06-03 15:00:14 -07001363 return;
1364 }
1365
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001366 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001367 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001368 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001369 nicIpEntry->id, prefixLength, *address,
1370 *gateway, asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001371 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1372 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001373 }
1374 else
1375 {
1376 createIPv4(ifaceId, prefixLength, *gateway, *address,
1377 asyncResp);
1378 }
1379 entryIdx++;
1380 }
1381 else
1382 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001383 if (nicIpEntry == ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001384 {
1385 // Requesting a DELETE/DO NOT MODIFY action for an item
1386 // that isn't present on the eth(n) interface. Input JSON is
1387 // in error, so bail out.
1388 if (thisJson.is_null())
1389 {
1390 messages::resourceCannotBeDeleted(asyncResp->res);
1391 return;
1392 }
Ed Tanousf818b042022-06-27 13:17:35 -07001393 messages::propertyValueFormatError(asyncResp->res, thisJson,
1394 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001395 return;
1396 }
1397
1398 if (thisJson.is_null())
1399 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001400 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001401 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001402 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001403 {
Patrick Williams89492a12023-05-10 07:51:34 -05001404 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1405 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001406 }
1407 entryIdx++;
1408 }
1409 }
1410}
1411
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001412inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001413 const std::string& ifaceId,
1414 const std::vector<std::string>& updatedStaticNameServers,
1415 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1416{
George Liu9ae226f2023-06-21 17:56:46 +08001417 sdbusplus::asio::setProperty(
1418 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1419 "/xyz/openbmc_project/network/" + ifaceId,
1420 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1421 updatedStaticNameServers,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001422 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001423 if (ec)
1424 {
1425 messages::internalError(asyncResp->res);
1426 return;
1427 }
George Liu9ae226f2023-06-21 17:56:46 +08001428 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001429}
1430
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001431inline void handleIPv6StaticAddressesPatch(
Ed Tanousddd70dc2023-03-01 16:00:27 -08001432 const std::string& ifaceId, const nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001433 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001434 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1435{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001436 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001437 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001438 messages::propertyValueTypeError(asyncResp->res, input,
1439 "IPv6StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001440 return;
1441 }
1442 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001443 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001444 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1445 for (const nlohmann::json& thisJson : input)
1446 {
Patrick Williams89492a12023-05-10 07:51:34 -05001447 std::string pathString = "IPv6StaticAddresses/" +
1448 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001449
1450 if (!thisJson.is_null() && !thisJson.empty())
1451 {
1452 std::optional<std::string> address;
1453 std::optional<uint8_t> prefixLength;
1454 nlohmann::json thisJsonCopy = thisJson;
1455 if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1456 address, "PrefixLength", prefixLength))
1457 {
Ed Tanousf818b042022-06-27 13:17:35 -07001458 messages::propertyValueFormatError(asyncResp->res, thisJson,
1459 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001460 return;
1461 }
1462
Ed Tanous543f4402022-01-06 13:12:53 -08001463 const std::string* addr = nullptr;
1464 uint8_t prefix = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001465
1466 // Find the address and prefixLength values. Any values that are
1467 // not explicitly provided are assumed to be unmodified from the
1468 // current state of the interface. Merge existing state into the
1469 // current request.
1470 if (address)
1471 {
1472 addr = &(*address);
1473 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001474 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001475 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001476 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001477 }
1478 else
1479 {
1480 messages::propertyMissing(asyncResp->res,
1481 pathString + "/Address");
1482 return;
1483 }
1484
1485 if (prefixLength)
1486 {
1487 prefix = *prefixLength;
1488 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001489 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001490 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001491 prefix = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001492 }
1493 else
1494 {
1495 messages::propertyMissing(asyncResp->res,
1496 pathString + "/PrefixLength");
1497 return;
1498 }
1499
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001500 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001501 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001502 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001503 nicIpEntry->id, prefix, *addr, "",
Ravi Teja9c5e5852023-02-26 21:33:52 -06001504 asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001505 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1506 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001507 }
1508 else
1509 {
1510 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1511 }
1512 entryIdx++;
1513 }
1514 else
1515 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001516 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001517 {
1518 // Requesting a DELETE/DO NOT MODIFY action for an item
1519 // that isn't present on the eth(n) interface. Input JSON is
1520 // in error, so bail out.
1521 if (thisJson.is_null())
1522 {
1523 messages::resourceCannotBeDeleted(asyncResp->res);
1524 return;
1525 }
Ed Tanousf818b042022-06-27 13:17:35 -07001526 messages::propertyValueFormatError(asyncResp->res, thisJson,
1527 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001528 return;
1529 }
1530
1531 if (thisJson.is_null())
1532 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001533 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001534 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001535 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001536 {
Patrick Williams89492a12023-05-10 07:51:34 -05001537 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1538 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001539 }
1540 entryIdx++;
1541 }
1542 }
1543}
1544
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001545inline std::string extractParentInterfaceName(const std::string& ifaceId)
1546{
1547 std::size_t pos = ifaceId.find('_');
1548 return ifaceId.substr(0, pos);
1549}
1550
Ed Tanous77179532023-02-28 10:45:28 -08001551inline void
1552 parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1553 const std::string& ifaceId,
1554 const EthernetInterfaceData& ethData,
1555 const std::vector<IPv4AddressData>& ipv4Data,
1556 const std::vector<IPv6AddressData>& ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001557{
Ed Tanousbf648f72021-06-03 15:00:14 -07001558 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1559 jsonResponse["Id"] = ifaceId;
Ed Tanousef4c65b2023-04-24 15:28:50 -07001560 jsonResponse["@odata.id"] = boost::urls::format(
1561 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001562 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1563
Willy Tu13451e32023-05-24 16:08:18 -07001564 if constexpr (bmcwebEnableHealthPopulate)
1565 {
1566 constexpr std::array<std::string_view, 1> inventoryForEthernet = {
1567 "xyz.openbmc_project.Inventory.Item.Ethernet"};
1568 auto health = std::make_shared<HealthPopulate>(asyncResp);
1569 dbus::utility::getSubTreePaths(
1570 "/", 0, inventoryForEthernet,
1571 [health](const boost::system::error_code& ec,
1572 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1573 if (ec)
1574 {
1575 return;
1576 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001577
Willy Tu13451e32023-05-24 16:08:18 -07001578 health->inventory = resp;
1579 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001580
Willy Tu13451e32023-05-24 16:08:18 -07001581 health->populate();
1582 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001583
1584 if (ethData.nicEnabled)
1585 {
Johnathan Mantey0ef0e282022-11-15 12:15:02 -08001586 jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
Ed Tanousbf648f72021-06-03 15:00:14 -07001587 jsonResponse["Status"]["State"] = "Enabled";
1588 }
1589 else
1590 {
1591 jsonResponse["LinkStatus"] = "NoLink";
1592 jsonResponse["Status"]["State"] = "Disabled";
1593 }
1594
Ed Tanousbf648f72021-06-03 15:00:14 -07001595 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301596 jsonResponse["MTUSize"] = ethData.mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001597 jsonResponse["MACAddress"] = ethData.macAddress;
Ed Tanousbf648f72021-06-03 15:00:14 -07001598 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001599 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1600 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled;
1601 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled;
1602 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001603
1604 jsonResponse["DHCPv6"]["OperatingMode"] =
Ravi Tejab10d8db2022-05-24 09:04:12 -05001605 translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
Ed Tanousbf648f72021-06-03 15:00:14 -07001606 : "Disabled";
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001607 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled;
1608 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled;
1609 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001610 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1611 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001612
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001613 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001614 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001615 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001616
1617 // When domain name is empty then it means, that it is a network
1618 // without domain names, and the host name itself must be treated as
1619 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001620 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001621 if (!ethData.domainnames.empty())
1622 {
1623 fqdn += "." + ethData.domainnames[0];
1624 }
1625 jsonResponse["FQDN"] = fqdn;
1626 }
1627
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001628 if (ethData.vlanId)
1629 {
1630 jsonResponse["EthernetInterfaceType"] = "Virtual";
1631 jsonResponse["VLAN"]["VLANEnable"] = true;
1632 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1633 jsonResponse["VLAN"]["Tagged"] = true;
1634
1635 nlohmann::json::array_t relatedInterfaces;
1636 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1637 parentInterface["@odata.id"] =
1638 boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
1639 extractParentInterfaceName(ifaceId));
1640 jsonResponse["Links"]["RelatedInterfaces"] =
1641 std::move(relatedInterfaces);
1642 }
1643 else
1644 {
1645 jsonResponse["EthernetInterfaceType"] = "Physical";
1646 }
1647
Ed Tanousbf648f72021-06-03 15:00:14 -07001648 jsonResponse["NameServers"] = ethData.nameServers;
1649 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1650
1651 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1652 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1653 ipv4Array = nlohmann::json::array();
1654 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001655 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001656 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001657 std::string gatewayStr = ipv4Config.gateway;
1658 if (gatewayStr.empty())
1659 {
1660 gatewayStr = "0.0.0.0";
1661 }
Ed Tanous14766872022-03-15 10:44:42 -07001662 nlohmann::json::object_t ipv4;
1663 ipv4["AddressOrigin"] = ipv4Config.origin;
1664 ipv4["SubnetMask"] = ipv4Config.netmask;
1665 ipv4["Address"] = ipv4Config.address;
1666 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001667
Ed Tanousbf648f72021-06-03 15:00:14 -07001668 if (ipv4Config.origin == "Static")
1669 {
Ed Tanous14766872022-03-15 10:44:42 -07001670 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001671 }
Ed Tanous14766872022-03-15 10:44:42 -07001672
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001673 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001674 }
1675
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001676 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001677 if (ipv6GatewayStr.empty())
1678 {
1679 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1680 }
1681
1682 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1683
1684 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1685 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1686 ipv6Array = nlohmann::json::array();
1687 ipv6StaticArray = nlohmann::json::array();
1688 nlohmann::json& ipv6AddrPolicyTable =
1689 jsonResponse["IPv6AddressPolicyTable"];
1690 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001691 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001692 {
Ed Tanous14766872022-03-15 10:44:42 -07001693 nlohmann::json::object_t ipv6;
1694 ipv6["Address"] = ipv6Config.address;
1695 ipv6["PrefixLength"] = ipv6Config.prefixLength;
1696 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05001697
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001698 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07001699 if (ipv6Config.origin == "Static")
1700 {
Ed Tanous14766872022-03-15 10:44:42 -07001701 nlohmann::json::object_t ipv6Static;
1702 ipv6Static["Address"] = ipv6Config.address;
1703 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001704 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07001705 }
1706 }
1707}
1708
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001709inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1710 const std::string& ifaceId,
1711 const boost::system::error_code& ec,
1712 const sdbusplus::message_t& m)
1713{
1714 if (!ec)
1715 {
1716 return;
1717 }
1718 const sd_bus_error* dbusError = m.get_error();
1719 if (dbusError == nullptr)
1720 {
1721 messages::internalError(asyncResp->res);
1722 return;
1723 }
Ed Tanous62598e32023-07-17 17:06:25 -07001724 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001725
1726 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1727 dbusError->name)
1728 {
1729 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1730 ifaceId);
1731 return;
1732 }
1733 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1734 dbusError->name)
1735 {
1736 messages::resourceCannotBeDeleted(asyncResp->res);
1737 return;
1738 }
1739 messages::internalError(asyncResp->res);
1740}
1741
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001742inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1743 const std::string& parentInterfaceUri,
1744 const std::string& vlanInterface,
1745 const boost::system::error_code& ec,
1746 const sdbusplus::message_t& m
1747
1748)
1749{
1750 if (ec)
1751 {
1752 const sd_bus_error* dbusError = m.get_error();
1753 if (dbusError == nullptr)
1754 {
1755 messages::internalError(asyncResp->res);
1756 return;
1757 }
Ed Tanous62598e32023-07-17 17:06:25 -07001758 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001759
1760 if (std::string_view(
1761 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1762 dbusError->name)
1763 {
1764 messages::propertyValueNotInList(
1765 asyncResp->res, parentInterfaceUri,
1766 "Links/RelatedInterfaces/0/@odata.id");
1767 return;
1768 }
1769 if (std::string_view(
1770 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1771 dbusError->name)
1772 {
1773 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1774 "Id", vlanInterface);
1775 return;
1776 }
1777 messages::internalError(asyncResp->res);
1778 return;
1779 }
1780
1781 const boost::urls::url vlanInterfaceUri = boost::urls::format(
1782 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1783 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1784}
1785
Ed Tanousbf648f72021-06-03 15:00:14 -07001786inline void requestEthernetInterfacesRoutes(App& app)
1787{
1788 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07001789 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07001790 .methods(boost::beast::http::verb::get)(
1791 [&app](const crow::Request& req,
1792 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001793 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001794 {
1795 return;
1796 }
1797
1798 asyncResp->res.jsonValue["@odata.type"] =
1799 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1800 asyncResp->res.jsonValue["@odata.id"] =
1801 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1802 asyncResp->res.jsonValue["Name"] =
1803 "Ethernet Network Interface Collection";
1804 asyncResp->res.jsonValue["Description"] =
1805 "Collection of EthernetInterfaces for this Manager";
1806
1807 // Get eth interface list, and call the below callback for JSON
1808 // preparation
1809 getEthernetIfaceList(
Ed Tanous77179532023-02-28 10:45:28 -08001810 [asyncResp](const bool& success,
1811 const std::vector<std::string>& ifaceList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001812 if (!success)
1813 {
1814 messages::internalError(asyncResp->res);
1815 return;
1816 }
1817
1818 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1819 ifaceArray = nlohmann::json::array();
Ed Tanous002d39b2022-05-31 08:59:27 -07001820 for (const std::string& ifaceItem : ifaceList)
1821 {
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001822 nlohmann::json::object_t iface;
1823 iface["@odata.id"] = boost::urls::format(
1824 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1825 ifaceItem);
1826 ifaceArray.push_back(std::move(iface));
Ed Tanous002d39b2022-05-31 08:59:27 -07001827 }
Jason M. Billsf12894f2018-10-09 12:45:45 -07001828
Ed Tanous002d39b2022-05-31 08:59:27 -07001829 asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1830 asyncResp->res.jsonValue["@odata.id"] =
1831 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1832 });
1833 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001834
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001835 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1836 .privileges(redfish::privileges::postEthernetInterfaceCollection)
1837 .methods(boost::beast::http::verb::post)(
1838 [&app](const crow::Request& req,
1839 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1840 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1841 {
1842 return;
1843 }
1844
1845 bool vlanEnable = false;
1846 uint32_t vlanId = 0;
1847 nlohmann::json::array_t relatedInterfaces;
1848
1849 if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1850 vlanEnable, "VLAN/VLANId", vlanId,
1851 "Links/RelatedInterfaces",
1852 relatedInterfaces))
1853 {
1854 return;
1855 }
1856
1857 if (relatedInterfaces.size() != 1)
1858 {
1859 messages::arraySizeTooLong(asyncResp->res,
1860 "Links/RelatedInterfaces",
1861 relatedInterfaces.size());
1862 return;
1863 }
1864
1865 std::string parentInterfaceUri;
1866 if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1867 "@odata.id", parentInterfaceUri))
1868 {
1869 messages::propertyMissing(asyncResp->res,
1870 "Links/RelatedInterfaces/0/@odata.id");
1871 return;
1872 }
Ed Tanous62598e32023-07-17 17:06:25 -07001873 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001874
Ed Tanous6fd29552023-10-04 09:40:14 -07001875 boost::system::result<boost::urls::url_view> parsedUri =
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001876 boost::urls::parse_relative_ref(parentInterfaceUri);
1877 if (!parsedUri)
1878 {
1879 messages::propertyValueFormatError(
1880 asyncResp->res, parentInterfaceUri,
1881 "Links/RelatedInterfaces/0/@odata.id");
1882 return;
1883 }
1884
1885 std::string parentInterface;
1886 if (!crow::utility::readUrlSegments(
1887 *parsedUri, "redfish", "v1", "Managers", "bmc",
1888 "EthernetInterfaces", std::ref(parentInterface)))
1889 {
1890 messages::propertyValueNotInList(
1891 asyncResp->res, parentInterfaceUri,
1892 "Links/RelatedInterfaces/0/@odata.id");
1893 return;
1894 }
1895
1896 if (!vlanEnable)
1897 {
1898 // In OpenBMC implementation, VLANEnable cannot be false on
1899 // create
1900 messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1901 "false");
1902 return;
1903 }
1904
1905 std::string vlanInterface = parentInterface + "_" +
1906 std::to_string(vlanId);
1907 crow::connections::systemBus->async_method_call(
1908 [asyncResp, parentInterfaceUri,
1909 vlanInterface](const boost::system::error_code& ec,
1910 const sdbusplus::message_t& m) {
1911 afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1912 m);
1913 },
1914 "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1915 "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1916 vlanId);
1917 });
1918
Ed Tanousbf648f72021-06-03 15:00:14 -07001919 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001920 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001921 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001922 [&app](const crow::Request& req,
1923 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1924 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001925 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001926 {
1927 return;
1928 }
1929 getEthernetIfaceData(
1930 ifaceId,
Ed Tanous77179532023-02-28 10:45:28 -08001931 [asyncResp, ifaceId](const bool& success,
1932 const EthernetInterfaceData& ethData,
1933 const std::vector<IPv4AddressData>& ipv4Data,
1934 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001935 if (!success)
1936 {
1937 // TODO(Pawel)consider distinguish between non
1938 // existing object, and other errors
1939 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1940 ifaceId);
1941 return;
1942 }
Johnathan Mantey01784822019-06-18 12:44:21 -07001943
Ed Tanous002d39b2022-05-31 08:59:27 -07001944 asyncResp->res.jsonValue["@odata.type"] =
Jiaqing Zhao93bbc952023-02-23 14:11:20 +08001945 "#EthernetInterface.v1_9_0.EthernetInterface";
Ed Tanous002d39b2022-05-31 08:59:27 -07001946 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
1947 asyncResp->res.jsonValue["Description"] =
1948 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05301949
Ed Tanous002d39b2022-05-31 08:59:27 -07001950 parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
Ed Tanousbf648f72021-06-03 15:00:14 -07001951 });
Ed Tanous002d39b2022-05-31 08:59:27 -07001952 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001953
Ed Tanousbf648f72021-06-03 15:00:14 -07001954 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001955 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001956 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001957 [&app](const crow::Request& req,
1958 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1959 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001960 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001961 {
1962 return;
1963 }
1964 std::optional<std::string> hostname;
1965 std::optional<std::string> fqdn;
1966 std::optional<std::string> macAddress;
1967 std::optional<std::string> ipv6DefaultGateway;
Ed Tanousddd70dc2023-03-01 16:00:27 -08001968 std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
1969 std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07001970 std::optional<std::vector<std::string>> staticNameServers;
1971 std::optional<nlohmann::json> dhcpv4;
1972 std::optional<nlohmann::json> dhcpv6;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001973 std::optional<bool> ipv6AutoConfigEnabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07001974 std::optional<bool> interfaceEnabled;
1975 std::optional<size_t> mtuSize;
1976 DHCPParameters v4dhcpParms;
1977 DHCPParameters v6dhcpParms;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001978 // clang-format off
Ed Tanous002d39b2022-05-31 08:59:27 -07001979 if (!json_util::readJsonPatch(
Ravi Tejab10d8db2022-05-24 09:04:12 -05001980 req, asyncResp->res,
1981 "DHCPv4", dhcpv4,
1982 "DHCPv6", dhcpv6,
1983 "FQDN", fqdn,
1984 "HostName", hostname,
1985 "IPv4StaticAddresses", ipv4StaticAddresses,
1986 "IPv6DefaultGateway", ipv6DefaultGateway,
1987 "IPv6StaticAddresses", ipv6StaticAddresses,
1988 "InterfaceEnabled", interfaceEnabled,
1989 "MACAddress", macAddress,
1990 "MTUSize", mtuSize,
1991 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
1992 "StaticNameServers", staticNameServers
1993 )
1994 )
Ed Tanous002d39b2022-05-31 08:59:27 -07001995 {
1996 return;
1997 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001998 //clang-format on
Ed Tanous002d39b2022-05-31 08:59:27 -07001999 if (dhcpv4)
2000 {
2001 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
2002 v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
2003 v4dhcpParms.useDnsServers, "UseNTPServers",
2004 v4dhcpParms.useNtpServers, "UseDomainName",
2005 v4dhcpParms.useDomainName))
2006 {
2007 return;
2008 }
2009 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002010
Ed Tanous002d39b2022-05-31 08:59:27 -07002011 if (dhcpv6)
2012 {
2013 if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2014 v6dhcpParms.dhcpv6OperatingMode,
2015 "UseDNSServers", v6dhcpParms.useDnsServers,
2016 "UseNTPServers", v6dhcpParms.useNtpServers,
2017 "UseDomainName",
2018 v6dhcpParms.useDomainName))
2019 {
2020 return;
2021 }
2022 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002023
Ed Tanous002d39b2022-05-31 08:59:27 -07002024 // Get single eth interface data, and call the below callback
2025 // for JSON preparation
2026 getEthernetIfaceData(
2027 ifaceId,
2028 [asyncResp, ifaceId, hostname = std::move(hostname),
2029 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2030 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2031 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2032 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2033 staticNameServers = std::move(staticNameServers),
Ed Tanousbc200892022-06-30 17:49:12 -07002034 dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
Ravi Tejab10d8db2022-05-24 09:04:12 -05002035 ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
Ed Tanous002d39b2022-05-31 08:59:27 -07002036 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2037 const bool& success, const EthernetInterfaceData& ethData,
Ed Tanous77179532023-02-28 10:45:28 -08002038 const std::vector<IPv4AddressData>& ipv4Data,
2039 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002040 if (!success)
2041 {
2042 // ... otherwise return error
2043 // TODO(Pawel)consider distinguish between non
2044 // existing object, and other errors
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +08002045 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
Ed Tanous002d39b2022-05-31 08:59:27 -07002046 ifaceId);
2047 return;
2048 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002049
Ed Tanous002d39b2022-05-31 08:59:27 -07002050 if (dhcpv4 || dhcpv6)
2051 {
2052 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
Ed Tanousbf648f72021-06-03 15:00:14 -07002053 asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002054 }
Tejas Patil35fb5312021-09-20 15:35:20 +05302055
Ed Tanous002d39b2022-05-31 08:59:27 -07002056 if (hostname)
2057 {
2058 handleHostnamePatch(*hostname, asyncResp);
2059 }
2060
Ravi Tejab10d8db2022-05-24 09:04:12 -05002061 if (ipv6AutoConfigEnabled)
2062 {
2063 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2064 asyncResp);
2065 }
2066
Ed Tanous002d39b2022-05-31 08:59:27 -07002067 if (fqdn)
2068 {
2069 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2070 }
2071
2072 if (macAddress)
2073 {
2074 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2075 }
2076
2077 if (ipv4StaticAddresses)
2078 {
2079 // TODO(ed) for some reason the capture of
2080 // ipv4Addresses above is returning a const value,
2081 // not a non-const value. This doesn't really work
2082 // for us, as we need to be able to efficiently move
2083 // out the intermedia nlohmann::json objects. This
2084 // makes a copy of the structure, and operates on
2085 // that, but could be done more efficiently
Ed Tanousddd70dc2023-03-01 16:00:27 -08002086 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002087 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
2088 }
2089
2090 if (staticNameServers)
2091 {
2092 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2093 asyncResp);
2094 }
2095
2096 if (ipv6DefaultGateway)
2097 {
2098 messages::propertyNotWritable(asyncResp->res,
2099 "IPv6DefaultGateway");
2100 }
2101
2102 if (ipv6StaticAddresses)
2103 {
Ed Tanousddd70dc2023-03-01 16:00:27 -08002104 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2105 ipv6Data, asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002106 }
2107
2108 if (interfaceEnabled)
2109 {
2110 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2111 *interfaceEnabled, asyncResp);
2112 }
2113
2114 if (mtuSize)
2115 {
2116 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2117 }
Ed Tanousbf648f72021-06-03 15:00:14 -07002118 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002119 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002120
2121 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2122 .privileges(redfish::privileges::deleteEthernetInterface)
2123 .methods(boost::beast::http::verb::delete_)(
2124 [&app](const crow::Request& req,
2125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2126 const std::string& ifaceId) {
2127 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2128 {
2129 return;
2130 }
2131
2132 crow::connections::systemBus->async_method_call(
2133 [asyncResp, ifaceId](const boost::system::error_code& ec,
2134 const sdbusplus::message_t& m) {
2135 afterDelete(asyncResp, ifaceId, ec, m);
2136 },
2137 "xyz.openbmc_project.Network",
2138 std::string("/xyz/openbmc_project/network/") + ifaceId,
2139 "xyz.openbmc_project.Object.Delete", "Delete");
2140 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002141}
2142
Ed Tanous1abe55e2018-09-05 08:30:59 -07002143} // namespace redfish