blob: 1574d813172b1a011b042a2a378b15d3f71fcb83 [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 Tanousef4c65b2023-04-24 15:28:50 -070031#include <boost/url/format.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
George Liu7a1dbc42022-12-07 16:03:22 +080033#include <array>
Ed Tanousa24526d2018-12-10 15:17:59 -080034#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070035#include <ranges>
Joshi-Mansiab6554f2020-03-10 18:33:36 +053036#include <regex>
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <string_view>
Ed Tanous77179532023-02-28 10:45:28 -080038#include <vector>
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010039
Ed Tanous1abe55e2018-09-05 08:30:59 -070040namespace redfish
41{
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010042
Ed Tanous4a0cb852018-10-15 07:55:04 -070043enum class LinkType
44{
45 Local,
46 Global
47};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010048
49/**
50 * Structure for keeping IPv4 data required by Redfish
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010051 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070052struct IPv4AddressData
53{
54 std::string id;
Ed Tanous4a0cb852018-10-15 07:55:04 -070055 std::string address;
56 std::string domain;
57 std::string gateway;
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 std::string netmask;
59 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080060 LinkType linktype{};
61 bool isActive{};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010062};
63
64/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -050065 * Structure for keeping IPv6 data required by Redfish
66 */
67struct IPv6AddressData
68{
69 std::string id;
70 std::string address;
71 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080072 uint8_t prefixLength = 0;
Ravi Tejae48c0fc2019-04-16 08:37:20 -050073};
74/**
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010075 * Structure for keeping basic single Ethernet Interface information
76 * available from DBus
77 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070078struct EthernetInterfaceData
79{
Ed Tanous4a0cb852018-10-15 07:55:04 -070080 uint32_t speed;
Tejas Patil35fb5312021-09-20 15:35:20 +053081 size_t mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080082 bool autoNeg;
Jishnu CMe4588152023-05-11 00:04:40 -050083 bool dnsv4Enabled;
84 bool dnsv6Enabled;
Ravi Teja91c441e2024-02-23 09:03:43 -060085 bool domainv4Enabled;
86 bool domainv6Enabled;
Jishnu CMe4588152023-05-11 00:04:40 -050087 bool ntpv4Enabled;
88 bool ntpv6Enabled;
89 bool hostNamev4Enabled;
90 bool hostNamev6Enabled;
Johnathan Manteyaa05fb22020-01-08 12:08:44 -080091 bool linkUp;
Johnathan Manteyeeedda22019-10-29 16:09:52 -070092 bool nicEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -050093 bool ipv6AcceptRa;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080094 std::string dhcpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -070095 std::string operatingMode;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080096 std::string hostName;
97 std::string defaultGateway;
98 std::string ipv6DefaultGateway;
99 std::string macAddress;
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800100 std::optional<uint32_t> vlanId;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500101 std::vector<std::string> nameServers;
102 std::vector<std::string> staticNameServers;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800103 std::vector<std::string> domainnames;
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100104};
105
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700106struct DHCPParameters
107{
108 std::optional<bool> dhcpv4Enabled;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800109 std::optional<bool> useDnsServers;
110 std::optional<bool> useNtpServers;
111 std::optional<bool> useDomainName;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700112 std::optional<std::string> dhcpv6OperatingMode;
113};
114
Ed Tanous4a0cb852018-10-15 07:55:04 -0700115// Helper function that changes bits netmask notation (i.e. /24)
116// into full dot notation
117inline std::string getNetmask(unsigned int bits)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700118{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700119 uint32_t value = 0xffffffff << (32 - bits);
120 std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
121 std::to_string((value >> 16) & 0xff) + "." +
122 std::to_string((value >> 8) & 0xff) + "." +
123 std::to_string(value & 0xff);
124 return netmask;
125}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100126
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800127inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700128 bool isIPv4)
129{
130 if (isIPv4)
131 {
132 return (
133 (inputDHCP ==
134 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
135 (inputDHCP ==
136 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
137 }
138 return ((inputDHCP ==
139 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
140 (inputDHCP ==
141 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
142}
143
Ed Tanous2c70f802020-09-28 14:29:23 -0700144inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700145{
146 if (isIPv4 && isIPv6)
147 {
148 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
149 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700150 if (isIPv4)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700151 {
152 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
153 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700154 if (isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700155 {
156 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
157 }
158 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
159}
160
Ed Tanous4a0cb852018-10-15 07:55:04 -0700161inline std::string
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500162 translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700163 bool isIPv4)
164{
165 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700166 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700167 return "Static";
168 }
169 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
170 {
171 if (isIPv4)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700172 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700173 return "IPv4LinkLocal";
174 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700175 return "LinkLocal";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700176 }
177 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
178 {
179 if (isIPv4)
180 {
181 return "DHCP";
182 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700183 return "DHCPv6";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700184 }
185 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
186 {
187 return "SLAAC";
188 }
189 return "";
190}
191
Ed Tanous02cad962022-06-30 16:50:15 -0700192inline bool extractEthernetInterfaceData(
193 const std::string& ethifaceId,
194 const dbus::utility::ManagedObjectType& dbusData,
195 EthernetInterfaceData& ethData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700196{
Ed Tanous4c9afe42019-05-03 16:59:57 -0700197 bool idFound = false;
Ed Tanous02cad962022-06-30 16:50:15 -0700198 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700199 {
Ed Tanous02cad962022-06-30 16:50:15 -0700200 for (const auto& ifacePair : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700201 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000202 if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700203 {
Ed Tanous4c9afe42019-05-03 16:59:57 -0700204 idFound = true;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700205 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500207 for (const auto& propertyPair : ifacePair.second)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700209 if (propertyPair.first == "MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700210 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500211 const std::string* mac =
Ed Tanousabf2add2019-01-22 16:40:12 -0800212 std::get_if<std::string>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700213 if (mac != nullptr)
214 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800215 ethData.macAddress = *mac;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700216 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700217 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700218 }
219 }
220 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
221 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500222 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700223 {
224 if (propertyPair.first == "Id")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700225 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500226 const uint32_t* id =
Ed Tanousabf2add2019-01-22 16:40:12 -0800227 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700228 if (id != nullptr)
229 {
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800230 ethData.vlanId = *id;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700231 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700232 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700233 }
234 }
235 else if (ifacePair.first ==
236 "xyz.openbmc_project.Network.EthernetInterface")
237 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500238 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700239 {
240 if (propertyPair.first == "AutoNeg")
241 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700242 const bool* autoNeg =
Ed Tanousabf2add2019-01-22 16:40:12 -0800243 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700244 if (autoNeg != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700245 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800246 ethData.autoNeg = *autoNeg;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700247 }
248 }
249 else if (propertyPair.first == "Speed")
250 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500251 const uint32_t* speed =
Ed Tanousabf2add2019-01-22 16:40:12 -0800252 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700253 if (speed != nullptr)
254 {
255 ethData.speed = *speed;
256 }
257 }
Tejas Patil35fb5312021-09-20 15:35:20 +0530258 else if (propertyPair.first == "MTU")
259 {
Anthony3e7a8da2023-10-23 14:22:43 +0800260 const size_t* mtuSize =
261 std::get_if<size_t>(&propertyPair.second);
Tejas Patil35fb5312021-09-20 15:35:20 +0530262 if (mtuSize != nullptr)
263 {
264 ethData.mtuSize = *mtuSize;
265 }
266 }
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800267 else if (propertyPair.first == "LinkUp")
268 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500269 const bool* linkUp =
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800270 std::get_if<bool>(&propertyPair.second);
271 if (linkUp != nullptr)
272 {
273 ethData.linkUp = *linkUp;
274 }
275 }
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700276 else if (propertyPair.first == "NICEnabled")
277 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500278 const bool* nicEnabled =
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700279 std::get_if<bool>(&propertyPair.second);
280 if (nicEnabled != nullptr)
281 {
282 ethData.nicEnabled = *nicEnabled;
283 }
284 }
Ravi Tejab10d8db2022-05-24 09:04:12 -0500285 else if (propertyPair.first == "IPv6AcceptRA")
286 {
287 const bool* ipv6AcceptRa =
288 std::get_if<bool>(&propertyPair.second);
289 if (ipv6AcceptRa != nullptr)
290 {
291 ethData.ipv6AcceptRa = *ipv6AcceptRa;
292 }
293 }
RAJESWARAN THILLAIGOVINDANf85837b2019-04-04 05:18:53 -0500294 else if (propertyPair.first == "Nameservers")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700295 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500296 const std::vector<std::string>* nameservers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500297 std::get_if<std::vector<std::string>>(
Ed Tanous029573d2019-02-01 10:57:49 -0800298 &propertyPair.second);
299 if (nameservers != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700300 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700301 ethData.nameServers = *nameservers;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500302 }
303 }
304 else if (propertyPair.first == "StaticNameServers")
305 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500306 const std::vector<std::string>* staticNameServers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500307 std::get_if<std::vector<std::string>>(
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500308 &propertyPair.second);
309 if (staticNameServers != nullptr)
310 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700311 ethData.staticNameServers = *staticNameServers;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700312 }
313 }
manojkiraneda2a133282019-02-19 13:09:43 +0530314 else if (propertyPair.first == "DHCPEnabled")
315 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700316 const std::string* dhcpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700317 std::get_if<std::string>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700318 if (dhcpEnabled != nullptr)
manojkiraneda2a133282019-02-19 13:09:43 +0530319 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800320 ethData.dhcpEnabled = *dhcpEnabled;
manojkiraneda2a133282019-02-19 13:09:43 +0530321 }
322 }
Jennifer Leed24bfc72019-03-05 13:03:37 -0800323 else if (propertyPair.first == "DomainName")
324 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500325 const std::vector<std::string>* domainNames =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500326 std::get_if<std::vector<std::string>>(
Jennifer Leed24bfc72019-03-05 13:03:37 -0800327 &propertyPair.second);
328 if (domainNames != nullptr)
329 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700330 ethData.domainnames = *domainNames;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800331 }
332 }
Ravi Teja9010ec22019-08-01 23:30:25 -0500333 else if (propertyPair.first == "DefaultGateway")
334 {
335 const std::string* defaultGateway =
336 std::get_if<std::string>(&propertyPair.second);
337 if (defaultGateway != nullptr)
338 {
339 std::string defaultGatewayStr = *defaultGateway;
340 if (defaultGatewayStr.empty())
341 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800342 ethData.defaultGateway = "0.0.0.0";
Ravi Teja9010ec22019-08-01 23:30:25 -0500343 }
344 else
345 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800346 ethData.defaultGateway = defaultGatewayStr;
Ravi Teja9010ec22019-08-01 23:30:25 -0500347 }
348 }
349 }
350 else if (propertyPair.first == "DefaultGateway6")
351 {
352 const std::string* defaultGateway6 =
353 std::get_if<std::string>(&propertyPair.second);
354 if (defaultGateway6 != nullptr)
355 {
356 std::string defaultGateway6Str =
357 *defaultGateway6;
358 if (defaultGateway6Str.empty())
359 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800360 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500361 "0:0:0:0:0:0:0:0";
362 }
363 else
364 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800365 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500366 defaultGateway6Str;
367 }
368 }
369 }
Ed Tanous029573d2019-02-01 10:57:49 -0800370 }
371 }
372 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700373
Jishnu CMe4588152023-05-11 00:04:40 -0500374 sdbusplus::message::object_path path(
375 "/xyz/openbmc_project/network");
376 sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
377 "dhcp4";
378
379 if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700380 {
381 if (ifacePair.first ==
382 "xyz.openbmc_project.Network.DHCPConfiguration")
383 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500384 for (const auto& propertyPair : ifacePair.second)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700385 {
386 if (propertyPair.first == "DNSEnabled")
387 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700388 const bool* dnsEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700389 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700390 if (dnsEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700391 {
Jishnu CMe4588152023-05-11 00:04:40 -0500392 ethData.dnsv4Enabled = *dnsEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700393 }
394 }
Ravi Teja91c441e2024-02-23 09:03:43 -0600395 else if (propertyPair.first == "DomainEnabled")
396 {
397 const bool* domainEnabled =
398 std::get_if<bool>(&propertyPair.second);
399 if (domainEnabled != nullptr)
400 {
401 ethData.domainv4Enabled = *domainEnabled;
402 }
403 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700404 else if (propertyPair.first == "NTPEnabled")
405 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700406 const bool* ntpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700407 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700408 if (ntpEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700409 {
Jishnu CMe4588152023-05-11 00:04:40 -0500410 ethData.ntpv4Enabled = *ntpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700411 }
412 }
413 else if (propertyPair.first == "HostNameEnabled")
414 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700415 const bool* hostNameEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700416 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700417 if (hostNameEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700418 {
Jishnu CMe4588152023-05-11 00:04:40 -0500419 ethData.hostNamev4Enabled = *hostNameEnabled;
420 }
421 }
422 }
423 }
424 }
425
426 sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
427 "dhcp6";
428
429 if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
430 {
431 if (ifacePair.first ==
432 "xyz.openbmc_project.Network.DHCPConfiguration")
433 {
434 for (const auto& propertyPair : ifacePair.second)
435 {
436 if (propertyPair.first == "DNSEnabled")
437 {
438 const bool* dnsEnabled =
439 std::get_if<bool>(&propertyPair.second);
440 if (dnsEnabled != nullptr)
441 {
442 ethData.dnsv6Enabled = *dnsEnabled;
443 }
444 }
Ravi Teja91c441e2024-02-23 09:03:43 -0600445 if (propertyPair.first == "DomainEnabled")
446 {
447 const bool* domainEnabled =
448 std::get_if<bool>(&propertyPair.second);
449 if (domainEnabled != nullptr)
450 {
451 ethData.domainv6Enabled = *domainEnabled;
452 }
453 }
Jishnu CMe4588152023-05-11 00:04:40 -0500454 else if (propertyPair.first == "NTPEnabled")
455 {
456 const bool* ntpEnabled =
457 std::get_if<bool>(&propertyPair.second);
458 if (ntpEnabled != nullptr)
459 {
460 ethData.ntpv6Enabled = *ntpEnabled;
461 }
462 }
463 else if (propertyPair.first == "HostNameEnabled")
464 {
465 const bool* hostNameEnabled =
466 std::get_if<bool>(&propertyPair.second);
467 if (hostNameEnabled != nullptr)
468 {
469 ethData.hostNamev6Enabled = *hostNameEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700470 }
471 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700472 }
473 }
474 }
Ed Tanous029573d2019-02-01 10:57:49 -0800475 // System configuration shows up in the global namespace, so no need
476 // to check eth number
477 if (ifacePair.first ==
478 "xyz.openbmc_project.Network.SystemConfiguration")
479 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500480 for (const auto& propertyPair : ifacePair.second)
Ed Tanous029573d2019-02-01 10:57:49 -0800481 {
482 if (propertyPair.first == "HostName")
483 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500484 const std::string* hostname =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500485 std::get_if<std::string>(&propertyPair.second);
Ed Tanous029573d2019-02-01 10:57:49 -0800486 if (hostname != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700487 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800488 ethData.hostName = *hostname;
Ed Tanous029573d2019-02-01 10:57:49 -0800489 }
490 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700491 }
492 }
493 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700494 }
Ed Tanous4c9afe42019-05-03 16:59:57 -0700495 return idFound;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700496}
497
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500498// Helper function that extracts data for single ethernet ipv6 address
Ed Tanous77179532023-02-28 10:45:28 -0800499inline void extractIPV6Data(const std::string& ethifaceId,
500 const dbus::utility::ManagedObjectType& dbusData,
501 std::vector<IPv6AddressData>& ipv6Config)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500502{
Patrick Williams89492a12023-05-10 07:51:34 -0500503 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
504 ethifaceId;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500505
506 // Since there might be several IPv6 configurations aligned with
507 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000508 for (const auto& objpath : dbusData)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500509 {
510 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800511 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500512 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800513 for (const auto& interface : objpath.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500514 {
515 if (interface.first == "xyz.openbmc_project.Network.IP")
516 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700517 auto type = std::ranges::find_if(interface.second,
518 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800519 return property.first == "Type";
520 });
521 if (type == interface.second.end())
522 {
523 continue;
524 }
525
526 const std::string* typeStr =
527 std::get_if<std::string>(&type->second);
528
529 if (typeStr == nullptr ||
530 (*typeStr !=
531 "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
532 {
533 continue;
534 }
535
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500536 // Instance IPv6AddressData structure, and set as
537 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800538 IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700539 ipv6Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800540 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800541 for (const auto& property : interface.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500542 {
543 if (property.first == "Address")
544 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500545 const std::string* address =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500546 std::get_if<std::string>(&property.second);
547 if (address != nullptr)
548 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700549 ipv6Address.address = *address;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500550 }
551 }
552 else if (property.first == "Origin")
553 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500554 const std::string* origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500555 std::get_if<std::string>(&property.second);
556 if (origin != nullptr)
557 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700558 ipv6Address.origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500559 translateAddressOriginDbusToRedfish(*origin,
560 false);
561 }
562 }
563 else if (property.first == "PrefixLength")
564 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500565 const uint8_t* prefix =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500566 std::get_if<uint8_t>(&property.second);
567 if (prefix != nullptr)
568 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700569 ipv6Address.prefixLength = *prefix;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500570 }
571 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600572 else if (property.first == "Type" ||
573 property.first == "Gateway")
574 {
575 // Type & Gateway is not used
576 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500577 else
578 {
Ed Tanous62598e32023-07-17 17:06:25 -0700579 BMCWEB_LOG_ERROR(
580 "Got extra property: {} on the {} object",
581 property.first, objpath.first.str);
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500582 }
583 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500584 }
585 }
586 }
587 }
588}
589
Ed Tanous4a0cb852018-10-15 07:55:04 -0700590// Helper function that extracts data for single ethernet ipv4 address
Ed Tanous77179532023-02-28 10:45:28 -0800591inline void extractIPData(const std::string& ethifaceId,
592 const dbus::utility::ManagedObjectType& dbusData,
593 std::vector<IPv4AddressData>& ipv4Config)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700594{
Patrick Williams89492a12023-05-10 07:51:34 -0500595 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
596 ethifaceId;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700597
598 // Since there might be several IPv4 configurations aligned with
599 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000600 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700601 {
602 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800603 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700604 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800605 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700606 {
607 if (interface.first == "xyz.openbmc_project.Network.IP")
608 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700609 auto type = std::ranges::find_if(interface.second,
610 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800611 return property.first == "Type";
612 });
613 if (type == interface.second.end())
614 {
615 continue;
616 }
617
618 const std::string* typeStr =
619 std::get_if<std::string>(&type->second);
620
621 if (typeStr == nullptr ||
622 (*typeStr !=
623 "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
624 {
625 continue;
626 }
627
Ed Tanous4a0cb852018-10-15 07:55:04 -0700628 // Instance IPv4AddressData structure, and set as
629 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800630 IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700631 ipv4Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800632 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800633 for (const auto& property : interface.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700634 {
635 if (property.first == "Address")
636 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500637 const std::string* address =
Ed Tanousabf2add2019-01-22 16:40:12 -0800638 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700639 if (address != nullptr)
640 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700641 ipv4Address.address = *address;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700642 }
643 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700644 else if (property.first == "Origin")
645 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500646 const std::string* origin =
Ed Tanousabf2add2019-01-22 16:40:12 -0800647 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700648 if (origin != nullptr)
649 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700650 ipv4Address.origin =
Ed Tanous4a0cb852018-10-15 07:55:04 -0700651 translateAddressOriginDbusToRedfish(*origin,
652 true);
653 }
654 }
655 else if (property.first == "PrefixLength")
656 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500657 const uint8_t* mask =
Ed Tanousabf2add2019-01-22 16:40:12 -0800658 std::get_if<uint8_t>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700659 if (mask != nullptr)
660 {
661 // convert it to the string
Ed Tanous2c70f802020-09-28 14:29:23 -0700662 ipv4Address.netmask = getNetmask(*mask);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700663 }
664 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600665 else if (property.first == "Type" ||
666 property.first == "Gateway")
667 {
668 // Type & Gateway is not used
669 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700670 else
671 {
Ed Tanous62598e32023-07-17 17:06:25 -0700672 BMCWEB_LOG_ERROR(
673 "Got extra property: {} on the {} object",
674 property.first, objpath.first.str);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700675 }
676 }
677 // Check if given address is local, or global
Ed Tanous2c70f802020-09-28 14:29:23 -0700678 ipv4Address.linktype =
Ed Tanous11ba3972022-07-11 09:50:41 -0700679 ipv4Address.address.starts_with("169.254.")
Johnathan Mantey18659d12019-06-07 10:26:29 -0700680 ? LinkType::Local
681 : LinkType::Global;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700682 }
683 }
684 }
685 }
686}
687
688/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700689 * @brief Deletes given IPv4 interface
Ed Tanous4a0cb852018-10-15 07:55:04 -0700690 *
691 * @param[in] ifaceId Id of interface whose IP should be deleted
Ed Tanous4a0cb852018-10-15 07:55:04 -0700692 * @param[in] ipHash DBus Hash id of IP that should be deleted
693 * @param[io] asyncResp Response object that will be returned to client
694 *
695 * @return None
696 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600697inline void deleteIPAddress(const std::string& ifaceId,
698 const std::string& ipHash,
699 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700700{
701 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800702 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700703 if (ec)
704 {
705 messages::internalError(asyncResp->res);
706 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500707 },
Ed Tanous4a0cb852018-10-15 07:55:04 -0700708 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600709 "/xyz/openbmc_project/network/" + ifaceId + ipHash,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700710 "xyz.openbmc_project.Object.Delete", "Delete");
711}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700712
Gunnar Mills244b6d52021-04-12 15:44:23 -0500713inline void updateIPv4DefaultGateway(
714 const std::string& ifaceId, const std::string& gateway,
715 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Teja9010ec22019-08-01 23:30:25 -0500716{
George Liu9ae226f2023-06-21 17:56:46 +0800717 sdbusplus::asio::setProperty(
718 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ravi Teja9010ec22019-08-01 23:30:25 -0500719 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9010ec22019-08-01 23:30:25 -0500720 "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
George Liu9ae226f2023-06-21 17:56:46 +0800721 gateway, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -0500722 if (ec)
723 {
724 messages::internalError(asyncResp->res);
725 return;
726 }
727 asyncResp->res.result(boost::beast::http::status::no_content);
728 });
Ravi Teja9010ec22019-08-01 23:30:25 -0500729}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700730/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700731 * @brief Creates a static IPv4 entry
Ed Tanous4a0cb852018-10-15 07:55:04 -0700732 *
Johnathan Mantey01784822019-06-18 12:44:21 -0700733 * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
734 * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
735 * @param[in] gateway IPv4 address of this interfaces gateway
736 * @param[in] address IPv4 address to assign to this interface
737 * @param[io] asyncResp Response object that will be returned to client
Ed Tanous4a0cb852018-10-15 07:55:04 -0700738 *
739 * @return None
740 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000741inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
742 const std::string& gateway, const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800743 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700744{
Patrick Williams5a39f772023-10-20 11:20:21 -0500745 auto createIpHandler = [asyncResp, ifaceId,
746 gateway](const boost::system::error_code& ec) {
Ravi Teja9010ec22019-08-01 23:30:25 -0500747 if (ec)
748 {
749 messages::internalError(asyncResp->res);
750 return;
751 }
752 updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
753 };
754
Ed Tanous4a0cb852018-10-15 07:55:04 -0700755 crow::connections::systemBus->async_method_call(
Ravi Teja9010ec22019-08-01 23:30:25 -0500756 std::move(createIpHandler), "xyz.openbmc_project.Network",
Ed Tanous4a0cb852018-10-15 07:55:04 -0700757 "/xyz/openbmc_project/network/" + ifaceId,
758 "xyz.openbmc_project.Network.IP.Create", "IP",
Johnathan Mantey01784822019-06-18 12:44:21 -0700759 "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700760 gateway);
761}
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500762
763/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700764 * @brief Deletes the IPv6 entry for this interface and creates a replacement
765 * static IPv6 entry
766 *
767 * @param[in] ifaceId Id of interface upon which to create the IPv6 entry
768 * @param[in] id The unique hash entry identifying the DBus entry
769 * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
770 * @param[in] address IPv6 address to assign to this interface
771 * @param[io] asyncResp Response object that will be returned to client
772 *
773 * @return None
774 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600775
776enum class IpVersion
777{
778 IpV4,
779 IpV6
780};
781
782inline void deleteAndCreateIPAddress(
783 IpVersion version, const std::string& ifaceId, const std::string& id,
784 uint8_t prefixLength, const std::string& address,
785 const std::string& gateway,
786 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Johnathan Mantey01784822019-06-18 12:44:21 -0700787{
788 crow::connections::systemBus->async_method_call(
Ravi Teja9c5e5852023-02-26 21:33:52 -0600789 [asyncResp, version, ifaceId, address, prefixLength,
790 gateway](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700791 if (ec)
792 {
793 messages::internalError(asyncResp->res);
794 }
Ravi Teja9c5e5852023-02-26 21:33:52 -0600795 std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
796 protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
Ed Tanous002d39b2022-05-31 08:59:27 -0700797 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800798 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700799 if (ec2)
Johnathan Mantey01784822019-06-18 12:44:21 -0700800 {
801 messages::internalError(asyncResp->res);
802 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500803 },
Ed Tanous002d39b2022-05-31 08:59:27 -0700804 "xyz.openbmc_project.Network",
805 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9c5e5852023-02-26 21:33:52 -0600806 "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
807 prefixLength, gateway);
Patrick Williams5a39f772023-10-20 11:20:21 -0500808 },
Johnathan Mantey01784822019-06-18 12:44:21 -0700809 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600810 "/xyz/openbmc_project/network/" + ifaceId + id,
Johnathan Mantey01784822019-06-18 12:44:21 -0700811 "xyz.openbmc_project.Object.Delete", "Delete");
812}
813
814/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500815 * @brief Creates IPv6 with given data
816 *
817 * @param[in] ifaceId Id of interface whose IP should be added
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500818 * @param[in] prefixLength Prefix length that needs to be added
819 * @param[in] address IP address that needs to be added
820 * @param[io] asyncResp Response object that will be returned to client
821 *
822 * @return None
823 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500824inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
825 const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800826 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500827{
Patrick Williams5a39f772023-10-20 11:20:21 -0500828 auto createIpHandler = [asyncResp,
829 address](const boost::system::error_code& ec) {
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500830 if (ec)
831 {
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500832 if (ec == boost::system::errc::io_error)
833 {
834 messages::propertyValueFormatError(asyncResp->res, address,
835 "Address");
836 }
837 else
838 {
839 messages::internalError(asyncResp->res);
840 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500841 }
842 };
843 // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500844 // does not have associated gateway property
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500845 crow::connections::systemBus->async_method_call(
846 std::move(createIpHandler), "xyz.openbmc_project.Network",
847 "/xyz/openbmc_project/network/" + ifaceId,
848 "xyz.openbmc_project.Network.IP.Create", "IP",
849 "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
850 "");
851}
852
Ed Tanous4a0cb852018-10-15 07:55:04 -0700853/**
854 * Function that retrieves all properties for given Ethernet Interface
855 * Object
856 * from EntityManager Network Manager
857 * @param ethiface_id a eth interface id to query on DBus
858 * @param callback a function that shall be called to convert Dbus output
859 * into JSON
860 */
861template <typename CallbackFunc>
Ed Tanous81ce6092020-12-17 16:54:55 +0000862void getEthernetIfaceData(const std::string& ethifaceId,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500863 CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700864{
George Liuf5892d02023-03-01 10:37:08 +0800865 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
866 dbus::utility::getManagedObjects(
867 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800868 [ethifaceId{std::string{ethifaceId}},
869 callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700870 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700871 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700872 EthernetInterfaceData ethData{};
Ed Tanous77179532023-02-28 10:45:28 -0800873 std::vector<IPv4AddressData> ipv4Data;
874 std::vector<IPv6AddressData> ipv6Data;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700875
Ed Tanous8b242752023-06-27 17:17:13 -0700876 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700877 {
878 callback(false, ethData, ipv4Data, ipv6Data);
879 return;
880 }
881
882 bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
883 if (!found)
884 {
885 callback(false, ethData, ipv4Data, ipv6Data);
886 return;
887 }
888
889 extractIPData(ethifaceId, resp, ipv4Data);
890 // Fix global GW
891 for (IPv4AddressData& ipv4 : ipv4Data)
892 {
893 if (((ipv4.linktype == LinkType::Global) &&
894 (ipv4.gateway == "0.0.0.0")) ||
895 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700896 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700897 ipv4.gateway = ethData.defaultGateway;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700898 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700899 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700900
Ed Tanous002d39b2022-05-31 08:59:27 -0700901 extractIPV6Data(ethifaceId, resp, ipv6Data);
902 // Finally make a callback with useful data
903 callback(true, ethData, ipv4Data, ipv6Data);
Patrick Williams5a39f772023-10-20 11:20:21 -0500904 });
Ed Tanous271584a2019-07-09 16:24:22 -0700905}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700906
907/**
908 * Function that retrieves all Ethernet Interfaces available through Network
909 * Manager
910 * @param callback a function that shall be called to convert Dbus output
911 * into JSON.
912 */
913template <typename CallbackFunc>
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500914void getEthernetIfaceList(CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700915{
George Liuf5892d02023-03-01 10:37:08 +0800916 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
917 dbus::utility::getManagedObjects(
918 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800919 [callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700920 const boost::system::error_code& ec,
George Liuf5892d02023-03-01 10:37:08 +0800921 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700922 // Callback requires vector<string> to retrieve all available
923 // ethernet interfaces
Ed Tanous77179532023-02-28 10:45:28 -0800924 std::vector<std::string> ifaceList;
Ed Tanous002d39b2022-05-31 08:59:27 -0700925 ifaceList.reserve(resp.size());
Ed Tanous8b242752023-06-27 17:17:13 -0700926 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700927 {
928 callback(false, ifaceList);
929 return;
930 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700931
Ed Tanous002d39b2022-05-31 08:59:27 -0700932 // Iterate over all retrieved ObjectPaths.
933 for (const auto& objpath : resp)
934 {
935 // And all interfaces available for certain ObjectPath.
936 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700937 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700938 // If interface is
939 // xyz.openbmc_project.Network.EthernetInterface, this is
940 // what we're looking for.
941 if (interface.first ==
942 "xyz.openbmc_project.Network.EthernetInterface")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700943 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700944 std::string ifaceId = objpath.first.filename();
945 if (ifaceId.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700946 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700947 continue;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700948 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700949 // and put it into output vector.
Ed Tanous77179532023-02-28 10:45:28 -0800950 ifaceList.emplace_back(ifaceId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700951 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700952 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700953 }
Ed Tanous2c5875a2023-05-15 09:56:06 -0700954
Ed Tanous3544d2a2023-08-06 18:12:20 -0700955 std::ranges::sort(ifaceList, AlphanumLess<std::string>());
Ed Tanous2c5875a2023-05-15 09:56:06 -0700956
Ed Tanous002d39b2022-05-31 08:59:27 -0700957 // Finally make a callback with useful data
958 callback(true, ifaceList);
Patrick Williams5a39f772023-10-20 11:20:21 -0500959 });
Ed Tanous271584a2019-07-09 16:24:22 -0700960}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100961
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700962inline void
963 handleHostnamePatch(const std::string& hostname,
964 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700965{
Ed Tanousbf648f72021-06-03 15:00:14 -0700966 // SHOULD handle host names of up to 255 characters(RFC 1123)
967 if (hostname.length() > 255)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700968 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700969 messages::propertyValueFormatError(asyncResp->res, hostname,
970 "HostName");
971 return;
972 }
George Liu9ae226f2023-06-21 17:56:46 +0800973 sdbusplus::asio::setProperty(
974 *crow::connections::systemBus, "xyz.openbmc_project.Network",
975 "/xyz/openbmc_project/network/config",
976 "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800977 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700978 if (ec)
979 {
980 messages::internalError(asyncResp->res);
981 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500982 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700983}
984
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700985inline void
Tejas Patil35fb5312021-09-20 15:35:20 +0530986 handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
987 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
988{
Patrick Williams89492a12023-05-10 07:51:34 -0500989 sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
990 ifaceId;
George Liu9ae226f2023-06-21 17:56:46 +0800991 sdbusplus::asio::setProperty(
992 *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
993 "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800994 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700995 if (ec)
996 {
997 messages::internalError(asyncResp->res);
998 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500999 });
Tejas Patil35fb5312021-09-20 15:35:20 +05301000}
1001
1002inline void
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001003 handleDomainnamePatch(const std::string& ifaceId,
1004 const std::string& domainname,
1005 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001006{
1007 std::vector<std::string> vectorDomainname = {domainname};
George Liu9ae226f2023-06-21 17:56:46 +08001008 sdbusplus::asio::setProperty(
1009 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ed Tanousbf648f72021-06-03 15:00:14 -07001010 "/xyz/openbmc_project/network/" + ifaceId,
Ed Tanousbf648f72021-06-03 15:00:14 -07001011 "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
George Liu9ae226f2023-06-21 17:56:46 +08001012 vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -05001013 if (ec)
1014 {
1015 messages::internalError(asyncResp->res);
1016 }
1017 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001018}
1019
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001020inline bool isHostnameValid(const std::string& hostname)
Ed Tanousbf648f72021-06-03 15:00:14 -07001021{
1022 // A valid host name can never have the dotted-decimal form (RFC 1123)
Ed Tanous3544d2a2023-08-06 18:12:20 -07001023 if (std::ranges::all_of(hostname, ::isdigit))
Ed Tanousbf648f72021-06-03 15:00:14 -07001024 {
1025 return false;
1026 }
1027 // Each label(hostname/subdomains) within a valid FQDN
1028 // MUST handle host names of up to 63 characters (RFC 1123)
1029 // labels cannot start or end with hyphens (RFC 952)
1030 // labels can start with numbers (RFC 1123)
Ed Tanous4b242742023-05-11 09:51:51 -07001031 const static std::regex pattern(
Ed Tanousbf648f72021-06-03 15:00:14 -07001032 "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1033
1034 return std::regex_match(hostname, pattern);
1035}
1036
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001037inline bool isDomainnameValid(const std::string& domainname)
Ed Tanousbf648f72021-06-03 15:00:14 -07001038{
1039 // Can have multiple subdomains
1040 // Top Level Domain's min length is 2 character
Ed Tanous4b242742023-05-11 09:51:51 -07001041 const static std::regex pattern(
George Liu0fda0f12021-11-16 10:06:17 +08001042 "^([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 -07001043
1044 return std::regex_match(domainname, pattern);
1045}
1046
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001047inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
1048 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001049{
1050 // Total length of FQDN must not exceed 255 characters(RFC 1035)
1051 if (fqdn.length() > 255)
1052 {
1053 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1054 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001055 }
1056
Ed Tanousbf648f72021-06-03 15:00:14 -07001057 size_t pos = fqdn.find('.');
1058 if (pos == std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001059 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001060 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1061 return;
1062 }
zhanghch058d1b46d2021-04-01 11:18:24 +08001063
Ed Tanousbf648f72021-06-03 15:00:14 -07001064 std::string hostname;
1065 std::string domainname;
1066 domainname = (fqdn).substr(pos + 1);
1067 hostname = (fqdn).substr(0, pos);
1068
1069 if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1070 {
1071 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1072 return;
1073 }
1074
1075 handleHostnamePatch(hostname, asyncResp);
1076 handleDomainnamePatch(ifaceId, domainname, asyncResp);
1077}
1078
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001079inline void
1080 handleMACAddressPatch(const std::string& ifaceId,
1081 const std::string& macAddress,
1082 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001083{
Johnathan Mantey58283f42022-08-15 14:38:36 -07001084 static constexpr std::string_view dbusNotAllowedError =
1085 "xyz.openbmc_project.Common.Error.NotAllowed";
1086
George Liu9ae226f2023-06-21 17:56:46 +08001087 sdbusplus::asio::setProperty(
1088 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1089 "/xyz/openbmc_project/network/" + ifaceId,
1090 "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
1091 [asyncResp](const boost::system::error_code& ec,
1092 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001093 if (ec)
1094 {
Johnathan Mantey58283f42022-08-15 14:38:36 -07001095 const sd_bus_error* err = msg.get_error();
1096 if (err == nullptr)
1097 {
1098 messages::internalError(asyncResp->res);
1099 return;
1100 }
1101 if (err->name == dbusNotAllowedError)
1102 {
1103 messages::propertyNotWritable(asyncResp->res, "MACAddress");
1104 return;
1105 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001106 messages::internalError(asyncResp->res);
1107 return;
1108 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001109 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001110}
1111
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001112inline void setDHCPEnabled(const std::string& ifaceId,
1113 const std::string& propertyName, const bool v4Value,
1114 const bool v6Value,
1115 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001116{
1117 const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
George Liu9ae226f2023-06-21 17:56:46 +08001118 sdbusplus::asio::setProperty(
1119 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1120 "/xyz/openbmc_project/network/" + ifaceId,
1121 "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001122 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001123 if (ec)
1124 {
Ed Tanous62598e32023-07-17 17:06:25 -07001125 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001126 messages::internalError(asyncResp->res);
1127 return;
1128 }
1129 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05001130 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001131}
1132
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001133inline void setEthernetInterfaceBoolProperty(
Ed Tanousbf648f72021-06-03 15:00:14 -07001134 const std::string& ifaceId, const std::string& propertyName,
1135 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1136{
George Liu9ae226f2023-06-21 17:56:46 +08001137 sdbusplus::asio::setProperty(
1138 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1139 "/xyz/openbmc_project/network/" + ifaceId,
1140 "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001141 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001142 if (ec)
1143 {
Ed Tanous62598e32023-07-17 17:06:25 -07001144 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 messages::internalError(asyncResp->res);
1146 return;
1147 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001148 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001149}
1150
Jishnu CMe4588152023-05-11 00:04:40 -05001151enum class NetworkType
1152{
1153 dhcp4,
1154 dhcp6
1155};
1156
1157inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1158 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1159 const std::string& ethifaceId, NetworkType type)
Ed Tanousbf648f72021-06-03 15:00:14 -07001160{
Ed Tanous62598e32023-07-17 17:06:25 -07001161 BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
Jishnu CMe4588152023-05-11 00:04:40 -05001162 sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1163 path /= ethifaceId;
1164
1165 if (type == NetworkType::dhcp4)
1166 {
1167 path /= "dhcp4";
1168 }
1169 else
1170 {
1171 path /= "dhcp6";
1172 }
1173
George Liu9ae226f2023-06-21 17:56:46 +08001174 sdbusplus::asio::setProperty(
Jishnu CMe4588152023-05-11 00:04:40 -05001175 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
George Liu9ae226f2023-06-21 17:56:46 +08001176 "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001177 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001178 if (ec)
1179 {
Ed Tanous62598e32023-07-17 17:06:25 -07001180 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001181 messages::internalError(asyncResp->res);
1182 return;
1183 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001184 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001185}
1186
Ravi Tejab10d8db2022-05-24 09:04:12 -05001187inline void handleSLAACAutoConfigPatch(
1188 const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1189 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1190{
1191 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1192 path /= ifaceId;
1193 sdbusplus::asio::setProperty(
1194 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1195 "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1196 ipv6AutoConfigEnabled,
1197 [asyncResp](const boost::system::error_code& ec) {
1198 if (ec)
1199 {
1200 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1201 messages::internalError(asyncResp->res);
1202 return;
1203 }
1204 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05001205 });
Ravi Tejab10d8db2022-05-24 09:04:12 -05001206}
1207
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001208inline void handleDHCPPatch(const std::string& ifaceId,
1209 const EthernetInterfaceData& ethData,
1210 const DHCPParameters& v4dhcpParms,
1211 const DHCPParameters& v6dhcpParms,
1212 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001213{
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001214 bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1215 bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
Ed Tanousbf648f72021-06-03 15:00:14 -07001216
1217 bool nextv4DHCPState =
1218 v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
1219
1220 bool nextv6DHCPState{};
1221 if (v6dhcpParms.dhcpv6OperatingMode)
1222 {
Ravi Tejab10d8db2022-05-24 09:04:12 -05001223 if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
Ed Tanousbf648f72021-06-03 15:00:14 -07001224 (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
1225 {
1226 messages::propertyValueFormatError(asyncResp->res,
1227 *v6dhcpParms.dhcpv6OperatingMode,
1228 "OperatingMode");
1229 return;
1230 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001231 nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
Ed Tanousbf648f72021-06-03 15:00:14 -07001232 }
1233 else
1234 {
1235 nextv6DHCPState = ipv6Active;
1236 }
1237
Jishnu CMe4588152023-05-11 00:04:40 -05001238 bool nextDNSv4 = ethData.dnsv4Enabled;
1239 bool nextDNSv6 = ethData.dnsv6Enabled;
1240 if (v4dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001241 {
Jishnu CMe4588152023-05-11 00:04:40 -05001242 nextDNSv4 = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001243 }
Jishnu CMe4588152023-05-11 00:04:40 -05001244 if (v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001245 {
Jishnu CMe4588152023-05-11 00:04:40 -05001246 nextDNSv6 = *v6dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001247 }
1248
Jishnu CMe4588152023-05-11 00:04:40 -05001249 bool nextNTPv4 = ethData.ntpv4Enabled;
1250 bool nextNTPv6 = ethData.ntpv6Enabled;
1251 if (v4dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001252 {
Jishnu CMe4588152023-05-11 00:04:40 -05001253 nextNTPv4 = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001254 }
Jishnu CMe4588152023-05-11 00:04:40 -05001255 if (v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001256 {
Jishnu CMe4588152023-05-11 00:04:40 -05001257 nextNTPv6 = *v6dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001258 }
1259
Ravi Teja91c441e2024-02-23 09:03:43 -06001260 bool nextUsev4Domain = ethData.domainv4Enabled;
1261 bool nextUsev6Domain = ethData.domainv6Enabled;
Jishnu CMe4588152023-05-11 00:04:40 -05001262 if (v4dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001263 {
Jishnu CMe4588152023-05-11 00:04:40 -05001264 nextUsev4Domain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001265 }
Jishnu CMe4588152023-05-11 00:04:40 -05001266 if (v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001267 {
Jishnu CMe4588152023-05-11 00:04:40 -05001268 nextUsev6Domain = *v6dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001269 }
1270
Ed Tanous62598e32023-07-17 17:06:25 -07001271 BMCWEB_LOG_DEBUG("set DHCPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001272 setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
1273 asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001274 BMCWEB_LOG_DEBUG("set DNSEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001275 setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1276 NetworkType::dhcp4);
Ed Tanous62598e32023-07-17 17:06:25 -07001277 BMCWEB_LOG_DEBUG("set NTPEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001278 setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1279 NetworkType::dhcp4);
Ravi Teja91c441e2024-02-23 09:03:43 -06001280 BMCWEB_LOG_DEBUG("set DomainEnabled...");
1281 setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
Jishnu CMe4588152023-05-11 00:04:40 -05001282 NetworkType::dhcp4);
1283 BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1284 setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1285 NetworkType::dhcp6);
1286 BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1287 setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1288 NetworkType::dhcp6);
Ravi Teja91c441e2024-02-23 09:03:43 -06001289 BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
1290 setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
Jishnu CMe4588152023-05-11 00:04:40 -05001291 NetworkType::dhcp6);
Ed Tanousbf648f72021-06-03 15:00:14 -07001292}
1293
Ed Tanous77179532023-02-28 10:45:28 -08001294inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
1295 const std::vector<IPv4AddressData>::const_iterator& head,
1296 const std::vector<IPv4AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001297{
1298 return std::find_if(head, end, [](const IPv4AddressData& value) {
1299 return value.origin == "Static";
1300 });
1301}
1302
Ed Tanous77179532023-02-28 10:45:28 -08001303inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
1304 const std::vector<IPv6AddressData>::const_iterator& head,
1305 const std::vector<IPv6AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001306{
1307 return std::find_if(head, end, [](const IPv6AddressData& value) {
1308 return value.origin == "Static";
1309 });
1310}
1311
Ed Tanous77179532023-02-28 10:45:28 -08001312inline void
Ed Tanousddd70dc2023-03-01 16:00:27 -08001313 handleIPv4StaticPatch(const std::string& ifaceId,
1314 nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001315 const std::vector<IPv4AddressData>& ipv4Data,
1316 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001317{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001318 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001319 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001320 messages::propertyValueTypeError(asyncResp->res, input,
1321 "IPv4StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001322 return;
1323 }
1324
1325 unsigned entryIdx = 1;
1326 // Find the first static IP address currently active on the NIC and
1327 // match it to the first JSON element in the IPv4StaticAddresses array.
1328 // Match each subsequent JSON element to the next static IP programmed
1329 // into the NIC.
Ed Tanous77179532023-02-28 10:45:28 -08001330 std::vector<IPv4AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001331 getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
1332
1333 for (nlohmann::json& thisJson : input)
1334 {
Patrick Williams89492a12023-05-10 07:51:34 -05001335 std::string pathString = "IPv4StaticAddresses/" +
1336 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001337
1338 if (!thisJson.is_null() && !thisJson.empty())
1339 {
1340 std::optional<std::string> address;
1341 std::optional<std::string> subnetMask;
1342 std::optional<std::string> gateway;
1343
1344 if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1345 address, "SubnetMask", subnetMask,
1346 "Gateway", gateway))
1347 {
Ed Tanousf818b042022-06-27 13:17:35 -07001348 messages::propertyValueFormatError(asyncResp->res, thisJson,
1349 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001350 return;
1351 }
1352
1353 // Find the address/subnet/gateway values. Any values that are
1354 // not explicitly provided are assumed to be unmodified from the
1355 // current state of the interface. Merge existing state into the
1356 // current request.
Ed Tanousbf648f72021-06-03 15:00:14 -07001357 if (address)
1358 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001359 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001360 {
1361 messages::propertyValueFormatError(asyncResp->res, *address,
1362 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001363 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001364 }
1365 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001366 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001367 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001368 address = (nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001369 }
1370 else
1371 {
1372 messages::propertyMissing(asyncResp->res,
1373 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001374 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001375 }
1376
Ed Tanouse01d0c32023-06-30 13:21:32 -07001377 uint8_t prefixLength = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001378 if (subnetMask)
1379 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001380 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1381 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001382 {
1383 messages::propertyValueFormatError(
1384 asyncResp->res, *subnetMask,
1385 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001386 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001387 }
1388 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001389 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001390 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001391 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1392 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001393 {
1394 messages::propertyValueFormatError(
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001395 asyncResp->res, nicIpEntry->netmask,
Ed Tanousbf648f72021-06-03 15:00:14 -07001396 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001397 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001398 }
1399 }
1400 else
1401 {
1402 messages::propertyMissing(asyncResp->res,
1403 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001404 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001405 }
1406
1407 if (gateway)
1408 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001409 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001410 {
1411 messages::propertyValueFormatError(asyncResp->res, *gateway,
1412 pathString + "/Gateway");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001413 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001414 }
1415 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001416 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001417 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001418 gateway = nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001419 }
1420 else
1421 {
1422 messages::propertyMissing(asyncResp->res,
1423 pathString + "/Gateway");
Ed Tanousbf648f72021-06-03 15:00:14 -07001424 return;
1425 }
1426
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001427 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001428 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001429 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001430 nicIpEntry->id, prefixLength, *address,
1431 *gateway, asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001432 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1433 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001434 }
1435 else
1436 {
1437 createIPv4(ifaceId, prefixLength, *gateway, *address,
1438 asyncResp);
1439 }
1440 entryIdx++;
1441 }
1442 else
1443 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001444 if (nicIpEntry == ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001445 {
1446 // Requesting a DELETE/DO NOT MODIFY action for an item
1447 // that isn't present on the eth(n) interface. Input JSON is
1448 // in error, so bail out.
1449 if (thisJson.is_null())
1450 {
1451 messages::resourceCannotBeDeleted(asyncResp->res);
1452 return;
1453 }
Ed Tanousf818b042022-06-27 13:17:35 -07001454 messages::propertyValueFormatError(asyncResp->res, thisJson,
1455 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001456 return;
1457 }
1458
1459 if (thisJson.is_null())
1460 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001461 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001462 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001463 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001464 {
Patrick Williams89492a12023-05-10 07:51:34 -05001465 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1466 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001467 }
1468 entryIdx++;
1469 }
1470 }
1471}
1472
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001473inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001474 const std::string& ifaceId,
1475 const std::vector<std::string>& updatedStaticNameServers,
1476 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1477{
George Liu9ae226f2023-06-21 17:56:46 +08001478 sdbusplus::asio::setProperty(
1479 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1480 "/xyz/openbmc_project/network/" + ifaceId,
1481 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1482 updatedStaticNameServers,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001483 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001484 if (ec)
1485 {
1486 messages::internalError(asyncResp->res);
1487 return;
1488 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001489 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001490}
1491
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001492inline void handleIPv6StaticAddressesPatch(
Ed Tanousddd70dc2023-03-01 16:00:27 -08001493 const std::string& ifaceId, const nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001494 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001495 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1496{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001497 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001498 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001499 messages::propertyValueTypeError(asyncResp->res, input,
1500 "IPv6StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001501 return;
1502 }
1503 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001504 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001505 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1506 for (const nlohmann::json& thisJson : input)
1507 {
Patrick Williams89492a12023-05-10 07:51:34 -05001508 std::string pathString = "IPv6StaticAddresses/" +
1509 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001510
1511 if (!thisJson.is_null() && !thisJson.empty())
1512 {
1513 std::optional<std::string> address;
1514 std::optional<uint8_t> prefixLength;
1515 nlohmann::json thisJsonCopy = thisJson;
1516 if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1517 address, "PrefixLength", prefixLength))
1518 {
Ed Tanousf818b042022-06-27 13:17:35 -07001519 messages::propertyValueFormatError(asyncResp->res, thisJson,
1520 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001521 return;
1522 }
1523
Ed Tanous543f4402022-01-06 13:12:53 -08001524 const std::string* addr = nullptr;
1525 uint8_t prefix = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001526
1527 // Find the address and prefixLength values. Any values that are
1528 // not explicitly provided are assumed to be unmodified from the
1529 // current state of the interface. Merge existing state into the
1530 // current request.
1531 if (address)
1532 {
1533 addr = &(*address);
1534 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001535 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001536 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001537 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001538 }
1539 else
1540 {
1541 messages::propertyMissing(asyncResp->res,
1542 pathString + "/Address");
1543 return;
1544 }
1545
1546 if (prefixLength)
1547 {
1548 prefix = *prefixLength;
1549 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001550 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001551 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001552 prefix = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001553 }
1554 else
1555 {
1556 messages::propertyMissing(asyncResp->res,
1557 pathString + "/PrefixLength");
1558 return;
1559 }
1560
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001561 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001562 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001563 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001564 nicIpEntry->id, prefix, *addr, "",
Ravi Teja9c5e5852023-02-26 21:33:52 -06001565 asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001566 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1567 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001568 }
1569 else
1570 {
1571 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1572 }
1573 entryIdx++;
1574 }
1575 else
1576 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001577 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001578 {
1579 // Requesting a DELETE/DO NOT MODIFY action for an item
1580 // that isn't present on the eth(n) interface. Input JSON is
1581 // in error, so bail out.
1582 if (thisJson.is_null())
1583 {
1584 messages::resourceCannotBeDeleted(asyncResp->res);
1585 return;
1586 }
Ed Tanousf818b042022-06-27 13:17:35 -07001587 messages::propertyValueFormatError(asyncResp->res, thisJson,
1588 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001589 return;
1590 }
1591
1592 if (thisJson.is_null())
1593 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001594 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001595 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001596 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001597 {
Patrick Williams89492a12023-05-10 07:51:34 -05001598 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1599 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001600 }
1601 entryIdx++;
1602 }
1603 }
1604}
1605
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001606inline std::string extractParentInterfaceName(const std::string& ifaceId)
1607{
1608 std::size_t pos = ifaceId.find('_');
1609 return ifaceId.substr(0, pos);
1610}
1611
Ed Tanous77179532023-02-28 10:45:28 -08001612inline void
1613 parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1614 const std::string& ifaceId,
1615 const EthernetInterfaceData& ethData,
1616 const std::vector<IPv4AddressData>& ipv4Data,
1617 const std::vector<IPv6AddressData>& ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001618{
Ed Tanousbf648f72021-06-03 15:00:14 -07001619 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1620 jsonResponse["Id"] = ifaceId;
Ed Tanousef4c65b2023-04-24 15:28:50 -07001621 jsonResponse["@odata.id"] = boost::urls::format(
1622 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001623 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1624
Willy Tu13451e32023-05-24 16:08:18 -07001625 if constexpr (bmcwebEnableHealthPopulate)
1626 {
1627 constexpr std::array<std::string_view, 1> inventoryForEthernet = {
1628 "xyz.openbmc_project.Inventory.Item.Ethernet"};
1629 auto health = std::make_shared<HealthPopulate>(asyncResp);
1630 dbus::utility::getSubTreePaths(
1631 "/", 0, inventoryForEthernet,
1632 [health](const boost::system::error_code& ec,
1633 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1634 if (ec)
1635 {
1636 return;
1637 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001638
Willy Tu13451e32023-05-24 16:08:18 -07001639 health->inventory = resp;
Patrick Williams5a39f772023-10-20 11:20:21 -05001640 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001641
Willy Tu13451e32023-05-24 16:08:18 -07001642 health->populate();
1643 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001644
1645 if (ethData.nicEnabled)
1646 {
Johnathan Mantey0ef0e282022-11-15 12:15:02 -08001647 jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
Ed Tanousbf648f72021-06-03 15:00:14 -07001648 jsonResponse["Status"]["State"] = "Enabled";
1649 }
1650 else
1651 {
1652 jsonResponse["LinkStatus"] = "NoLink";
1653 jsonResponse["Status"]["State"] = "Disabled";
1654 }
1655
Ed Tanousbf648f72021-06-03 15:00:14 -07001656 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301657 jsonResponse["MTUSize"] = ethData.mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001658 jsonResponse["MACAddress"] = ethData.macAddress;
Ed Tanousbf648f72021-06-03 15:00:14 -07001659 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001660 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
Jishnu CMe4588152023-05-11 00:04:40 -05001661 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1662 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1663 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001664 jsonResponse["DHCPv6"]["OperatingMode"] =
Ravi Tejab10d8db2022-05-24 09:04:12 -05001665 translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
Ed Tanousbf648f72021-06-03 15:00:14 -07001666 : "Disabled";
Jishnu CMe4588152023-05-11 00:04:40 -05001667 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1668 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1669 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001670 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1671 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001672
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001673 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001674 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001675 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001676
1677 // When domain name is empty then it means, that it is a network
1678 // without domain names, and the host name itself must be treated as
1679 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001680 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001681 if (!ethData.domainnames.empty())
1682 {
1683 fqdn += "." + ethData.domainnames[0];
1684 }
1685 jsonResponse["FQDN"] = fqdn;
1686 }
1687
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001688 if (ethData.vlanId)
1689 {
1690 jsonResponse["EthernetInterfaceType"] = "Virtual";
1691 jsonResponse["VLAN"]["VLANEnable"] = true;
1692 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1693 jsonResponse["VLAN"]["Tagged"] = true;
1694
1695 nlohmann::json::array_t relatedInterfaces;
1696 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1697 parentInterface["@odata.id"] =
1698 boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
1699 extractParentInterfaceName(ifaceId));
1700 jsonResponse["Links"]["RelatedInterfaces"] =
1701 std::move(relatedInterfaces);
1702 }
1703 else
1704 {
1705 jsonResponse["EthernetInterfaceType"] = "Physical";
1706 }
1707
Ed Tanousbf648f72021-06-03 15:00:14 -07001708 jsonResponse["NameServers"] = ethData.nameServers;
1709 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1710
1711 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1712 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1713 ipv4Array = nlohmann::json::array();
1714 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001715 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001716 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001717 std::string gatewayStr = ipv4Config.gateway;
1718 if (gatewayStr.empty())
1719 {
1720 gatewayStr = "0.0.0.0";
1721 }
Ed Tanous14766872022-03-15 10:44:42 -07001722 nlohmann::json::object_t ipv4;
1723 ipv4["AddressOrigin"] = ipv4Config.origin;
1724 ipv4["SubnetMask"] = ipv4Config.netmask;
1725 ipv4["Address"] = ipv4Config.address;
1726 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001727
Ed Tanousbf648f72021-06-03 15:00:14 -07001728 if (ipv4Config.origin == "Static")
1729 {
Ed Tanous14766872022-03-15 10:44:42 -07001730 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001731 }
Ed Tanous14766872022-03-15 10:44:42 -07001732
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001733 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001734 }
1735
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001736 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001737 if (ipv6GatewayStr.empty())
1738 {
1739 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1740 }
1741
1742 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1743
1744 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1745 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1746 ipv6Array = nlohmann::json::array();
1747 ipv6StaticArray = nlohmann::json::array();
1748 nlohmann::json& ipv6AddrPolicyTable =
1749 jsonResponse["IPv6AddressPolicyTable"];
1750 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001751 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001752 {
Ed Tanous14766872022-03-15 10:44:42 -07001753 nlohmann::json::object_t ipv6;
1754 ipv6["Address"] = ipv6Config.address;
1755 ipv6["PrefixLength"] = ipv6Config.prefixLength;
1756 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05001757
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001758 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07001759 if (ipv6Config.origin == "Static")
1760 {
Ed Tanous14766872022-03-15 10:44:42 -07001761 nlohmann::json::object_t ipv6Static;
1762 ipv6Static["Address"] = ipv6Config.address;
1763 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001764 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07001765 }
1766 }
1767}
1768
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001769inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1770 const std::string& ifaceId,
1771 const boost::system::error_code& ec,
1772 const sdbusplus::message_t& m)
1773{
1774 if (!ec)
1775 {
1776 return;
1777 }
1778 const sd_bus_error* dbusError = m.get_error();
1779 if (dbusError == nullptr)
1780 {
1781 messages::internalError(asyncResp->res);
1782 return;
1783 }
Ed Tanous62598e32023-07-17 17:06:25 -07001784 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001785
1786 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1787 dbusError->name)
1788 {
1789 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1790 ifaceId);
1791 return;
1792 }
1793 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1794 dbusError->name)
1795 {
1796 messages::resourceCannotBeDeleted(asyncResp->res);
1797 return;
1798 }
1799 messages::internalError(asyncResp->res);
1800}
1801
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001802inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1803 const std::string& parentInterfaceUri,
1804 const std::string& vlanInterface,
1805 const boost::system::error_code& ec,
1806 const sdbusplus::message_t& m
1807
1808)
1809{
1810 if (ec)
1811 {
1812 const sd_bus_error* dbusError = m.get_error();
1813 if (dbusError == nullptr)
1814 {
1815 messages::internalError(asyncResp->res);
1816 return;
1817 }
Ed Tanous62598e32023-07-17 17:06:25 -07001818 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001819
1820 if (std::string_view(
1821 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1822 dbusError->name)
1823 {
1824 messages::propertyValueNotInList(
1825 asyncResp->res, parentInterfaceUri,
1826 "Links/RelatedInterfaces/0/@odata.id");
1827 return;
1828 }
1829 if (std::string_view(
1830 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1831 dbusError->name)
1832 {
1833 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1834 "Id", vlanInterface);
1835 return;
1836 }
1837 messages::internalError(asyncResp->res);
1838 return;
1839 }
1840
1841 const boost::urls::url vlanInterfaceUri = boost::urls::format(
1842 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1843 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1844}
1845
Ed Tanousbf648f72021-06-03 15:00:14 -07001846inline void requestEthernetInterfacesRoutes(App& app)
1847{
1848 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07001849 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07001850 .methods(boost::beast::http::verb::get)(
1851 [&app](const crow::Request& req,
1852 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001853 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001854 {
1855 return;
1856 }
1857
1858 asyncResp->res.jsonValue["@odata.type"] =
1859 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1860 asyncResp->res.jsonValue["@odata.id"] =
1861 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1862 asyncResp->res.jsonValue["Name"] =
1863 "Ethernet Network Interface Collection";
1864 asyncResp->res.jsonValue["Description"] =
1865 "Collection of EthernetInterfaces for this Manager";
1866
1867 // Get eth interface list, and call the below callback for JSON
1868 // preparation
1869 getEthernetIfaceList(
Ed Tanous77179532023-02-28 10:45:28 -08001870 [asyncResp](const bool& success,
1871 const std::vector<std::string>& ifaceList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001872 if (!success)
1873 {
1874 messages::internalError(asyncResp->res);
1875 return;
1876 }
1877
1878 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1879 ifaceArray = nlohmann::json::array();
Ed Tanous002d39b2022-05-31 08:59:27 -07001880 for (const std::string& ifaceItem : ifaceList)
1881 {
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001882 nlohmann::json::object_t iface;
1883 iface["@odata.id"] = boost::urls::format(
1884 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1885 ifaceItem);
1886 ifaceArray.push_back(std::move(iface));
Ed Tanous002d39b2022-05-31 08:59:27 -07001887 }
Jason M. Billsf12894f2018-10-09 12:45:45 -07001888
Ed Tanous002d39b2022-05-31 08:59:27 -07001889 asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1890 asyncResp->res.jsonValue["@odata.id"] =
1891 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1892 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001893 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001894
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001895 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1896 .privileges(redfish::privileges::postEthernetInterfaceCollection)
1897 .methods(boost::beast::http::verb::post)(
1898 [&app](const crow::Request& req,
1899 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1900 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1901 {
1902 return;
1903 }
1904
1905 bool vlanEnable = false;
1906 uint32_t vlanId = 0;
1907 nlohmann::json::array_t relatedInterfaces;
1908
1909 if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1910 vlanEnable, "VLAN/VLANId", vlanId,
1911 "Links/RelatedInterfaces",
1912 relatedInterfaces))
1913 {
1914 return;
1915 }
1916
1917 if (relatedInterfaces.size() != 1)
1918 {
1919 messages::arraySizeTooLong(asyncResp->res,
1920 "Links/RelatedInterfaces",
1921 relatedInterfaces.size());
1922 return;
1923 }
1924
1925 std::string parentInterfaceUri;
1926 if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1927 "@odata.id", parentInterfaceUri))
1928 {
1929 messages::propertyMissing(asyncResp->res,
1930 "Links/RelatedInterfaces/0/@odata.id");
1931 return;
1932 }
Ed Tanous62598e32023-07-17 17:06:25 -07001933 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001934
Ed Tanous6fd29552023-10-04 09:40:14 -07001935 boost::system::result<boost::urls::url_view> parsedUri =
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001936 boost::urls::parse_relative_ref(parentInterfaceUri);
1937 if (!parsedUri)
1938 {
1939 messages::propertyValueFormatError(
1940 asyncResp->res, parentInterfaceUri,
1941 "Links/RelatedInterfaces/0/@odata.id");
1942 return;
1943 }
1944
1945 std::string parentInterface;
1946 if (!crow::utility::readUrlSegments(
1947 *parsedUri, "redfish", "v1", "Managers", "bmc",
1948 "EthernetInterfaces", std::ref(parentInterface)))
1949 {
1950 messages::propertyValueNotInList(
1951 asyncResp->res, parentInterfaceUri,
1952 "Links/RelatedInterfaces/0/@odata.id");
1953 return;
1954 }
1955
1956 if (!vlanEnable)
1957 {
1958 // In OpenBMC implementation, VLANEnable cannot be false on
1959 // create
1960 messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1961 "false");
1962 return;
1963 }
1964
1965 std::string vlanInterface = parentInterface + "_" +
1966 std::to_string(vlanId);
1967 crow::connections::systemBus->async_method_call(
1968 [asyncResp, parentInterfaceUri,
1969 vlanInterface](const boost::system::error_code& ec,
1970 const sdbusplus::message_t& m) {
1971 afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1972 m);
Patrick Williams5a39f772023-10-20 11:20:21 -05001973 },
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001974 "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1975 "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1976 vlanId);
Patrick Williams5a39f772023-10-20 11:20:21 -05001977 });
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001978
Ed Tanousbf648f72021-06-03 15:00:14 -07001979 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001980 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001981 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001982 [&app](const crow::Request& req,
1983 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1984 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001985 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001986 {
1987 return;
1988 }
1989 getEthernetIfaceData(
1990 ifaceId,
Ed Tanous77179532023-02-28 10:45:28 -08001991 [asyncResp, ifaceId](const bool& success,
1992 const EthernetInterfaceData& ethData,
1993 const std::vector<IPv4AddressData>& ipv4Data,
1994 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001995 if (!success)
1996 {
1997 // TODO(Pawel)consider distinguish between non
1998 // existing object, and other errors
1999 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2000 ifaceId);
2001 return;
2002 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002003
Ed Tanous002d39b2022-05-31 08:59:27 -07002004 asyncResp->res.jsonValue["@odata.type"] =
Jiaqing Zhao93bbc952023-02-23 14:11:20 +08002005 "#EthernetInterface.v1_9_0.EthernetInterface";
Ed Tanous002d39b2022-05-31 08:59:27 -07002006 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
2007 asyncResp->res.jsonValue["Description"] =
2008 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05302009
Ed Tanous002d39b2022-05-31 08:59:27 -07002010 parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
Ed Tanous002d39b2022-05-31 08:59:27 -07002011 });
Patrick Williams5a39f772023-10-20 11:20:21 -05002012 });
Johnathan Mantey01784822019-06-18 12:44:21 -07002013
Ed Tanousbf648f72021-06-03 15:00:14 -07002014 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002015 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07002016 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002017 [&app](const crow::Request& req,
2018 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2019 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002020 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002021 {
2022 return;
2023 }
2024 std::optional<std::string> hostname;
2025 std::optional<std::string> fqdn;
2026 std::optional<std::string> macAddress;
2027 std::optional<std::string> ipv6DefaultGateway;
Ed Tanousddd70dc2023-03-01 16:00:27 -08002028 std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2029 std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002030 std::optional<std::vector<std::string>> staticNameServers;
2031 std::optional<nlohmann::json> dhcpv4;
2032 std::optional<nlohmann::json> dhcpv6;
Ravi Tejab10d8db2022-05-24 09:04:12 -05002033 std::optional<bool> ipv6AutoConfigEnabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002034 std::optional<bool> interfaceEnabled;
2035 std::optional<size_t> mtuSize;
2036 DHCPParameters v4dhcpParms;
2037 DHCPParameters v6dhcpParms;
Ravi Tejab10d8db2022-05-24 09:04:12 -05002038 // clang-format off
Ed Tanous002d39b2022-05-31 08:59:27 -07002039 if (!json_util::readJsonPatch(
Ravi Tejab10d8db2022-05-24 09:04:12 -05002040 req, asyncResp->res,
2041 "DHCPv4", dhcpv4,
2042 "DHCPv6", dhcpv6,
2043 "FQDN", fqdn,
2044 "HostName", hostname,
2045 "IPv4StaticAddresses", ipv4StaticAddresses,
2046 "IPv6DefaultGateway", ipv6DefaultGateway,
2047 "IPv6StaticAddresses", ipv6StaticAddresses,
2048 "InterfaceEnabled", interfaceEnabled,
2049 "MACAddress", macAddress,
2050 "MTUSize", mtuSize,
2051 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2052 "StaticNameServers", staticNameServers
2053 )
2054 )
Ed Tanous002d39b2022-05-31 08:59:27 -07002055 {
2056 return;
2057 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05002058 //clang-format on
Ed Tanous002d39b2022-05-31 08:59:27 -07002059 if (dhcpv4)
2060 {
2061 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
2062 v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
2063 v4dhcpParms.useDnsServers, "UseNTPServers",
2064 v4dhcpParms.useNtpServers, "UseDomainName",
2065 v4dhcpParms.useDomainName))
2066 {
2067 return;
2068 }
2069 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002070
Ed Tanous002d39b2022-05-31 08:59:27 -07002071 if (dhcpv6)
2072 {
2073 if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2074 v6dhcpParms.dhcpv6OperatingMode,
2075 "UseDNSServers", v6dhcpParms.useDnsServers,
2076 "UseNTPServers", v6dhcpParms.useNtpServers,
2077 "UseDomainName",
2078 v6dhcpParms.useDomainName))
2079 {
2080 return;
2081 }
2082 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002083
Ed Tanous002d39b2022-05-31 08:59:27 -07002084 // Get single eth interface data, and call the below callback
2085 // for JSON preparation
2086 getEthernetIfaceData(
2087 ifaceId,
2088 [asyncResp, ifaceId, hostname = std::move(hostname),
2089 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2090 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2091 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2092 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2093 staticNameServers = std::move(staticNameServers),
Ed Tanousbc200892022-06-30 17:49:12 -07002094 dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
Ravi Tejab10d8db2022-05-24 09:04:12 -05002095 ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
Ed Tanous002d39b2022-05-31 08:59:27 -07002096 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2097 const bool& success, const EthernetInterfaceData& ethData,
Ed Tanous77179532023-02-28 10:45:28 -08002098 const std::vector<IPv4AddressData>& ipv4Data,
2099 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002100 if (!success)
2101 {
2102 // ... otherwise return error
2103 // TODO(Pawel)consider distinguish between non
2104 // existing object, and other errors
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +08002105 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
Ed Tanous002d39b2022-05-31 08:59:27 -07002106 ifaceId);
2107 return;
2108 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002109
Ed Tanous002d39b2022-05-31 08:59:27 -07002110 if (dhcpv4 || dhcpv6)
2111 {
2112 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
Ed Tanousbf648f72021-06-03 15:00:14 -07002113 asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002114 }
Tejas Patil35fb5312021-09-20 15:35:20 +05302115
Ed Tanous002d39b2022-05-31 08:59:27 -07002116 if (hostname)
2117 {
2118 handleHostnamePatch(*hostname, asyncResp);
2119 }
2120
Ravi Tejab10d8db2022-05-24 09:04:12 -05002121 if (ipv6AutoConfigEnabled)
2122 {
2123 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2124 asyncResp);
2125 }
2126
Ed Tanous002d39b2022-05-31 08:59:27 -07002127 if (fqdn)
2128 {
2129 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2130 }
2131
2132 if (macAddress)
2133 {
2134 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2135 }
2136
2137 if (ipv4StaticAddresses)
2138 {
2139 // TODO(ed) for some reason the capture of
2140 // ipv4Addresses above is returning a const value,
2141 // not a non-const value. This doesn't really work
2142 // for us, as we need to be able to efficiently move
2143 // out the intermedia nlohmann::json objects. This
2144 // makes a copy of the structure, and operates on
2145 // that, but could be done more efficiently
Ed Tanousddd70dc2023-03-01 16:00:27 -08002146 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002147 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
2148 }
2149
2150 if (staticNameServers)
2151 {
2152 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2153 asyncResp);
2154 }
2155
2156 if (ipv6DefaultGateway)
2157 {
2158 messages::propertyNotWritable(asyncResp->res,
2159 "IPv6DefaultGateway");
2160 }
2161
2162 if (ipv6StaticAddresses)
2163 {
Ed Tanousddd70dc2023-03-01 16:00:27 -08002164 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2165 ipv6Data, asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002166 }
2167
2168 if (interfaceEnabled)
2169 {
2170 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2171 *interfaceEnabled, asyncResp);
2172 }
2173
2174 if (mtuSize)
2175 {
2176 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2177 }
Ed Tanousbf648f72021-06-03 15:00:14 -07002178 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002179 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002180
2181 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2182 .privileges(redfish::privileges::deleteEthernetInterface)
2183 .methods(boost::beast::http::verb::delete_)(
2184 [&app](const crow::Request& req,
2185 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2186 const std::string& ifaceId) {
2187 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2188 {
2189 return;
2190 }
2191
2192 crow::connections::systemBus->async_method_call(
2193 [asyncResp, ifaceId](const boost::system::error_code& ec,
2194 const sdbusplus::message_t& m) {
2195 afterDelete(asyncResp, ifaceId, ec, m);
2196 },
2197 "xyz.openbmc_project.Network",
2198 std::string("/xyz/openbmc_project/network/") + ifaceId,
2199 "xyz.openbmc_project.Object.Delete", "Delete");
2200 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002201}
2202
Ed Tanous1abe55e2018-09-05 08:30:59 -07002203} // namespace redfish