blob: c6bdfe00d51abfe55a57923a429cadd08b172ce1 [file] [log] [blame]
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +01001/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2018 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010015*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
19#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070022#include "generated/enums/ethernet_interface.hpp"
23#include "generated/enums/resource.hpp"
Ed Tanous2c5875a2023-05-15 09:56:06 -070024#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080025#include "query.hpp"
26#include "registries/privilege_registry.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070027#include "utils/ip_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080028#include "utils/json_utils.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070029
Sunitha Harishce73d5c2023-04-07 06:46:49 -050030#include <boost/system/error_code.hpp>
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 Tanous3dfed532024-03-06 14:41:27 -080034#include <cstddef>
Sunitha Harishce73d5c2023-04-07 06:46:49 -050035#include <memory>
Ed Tanousa24526d2018-12-10 15:17:59 -080036#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070037#include <ranges>
Joshi-Mansiab6554f2020-03-10 18:33:36 +053038#include <regex>
George Liu7a1dbc42022-12-07 16:03:22 +080039#include <string_view>
Ed Tanous3dfed532024-03-06 14:41:27 -080040#include <variant>
Ed Tanous77179532023-02-28 10:45:28 -080041#include <vector>
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010042
Ed Tanous1abe55e2018-09-05 08:30:59 -070043namespace redfish
44{
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010045
Ed Tanous4a0cb852018-10-15 07:55:04 -070046enum class LinkType
47{
48 Local,
49 Global
50};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010051
Johnathan Mantey743eb1c2024-04-03 12:05:57 -070052enum class IpVersion
53{
54 IpV4,
55 IpV6
56};
57
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010058/**
59 * Structure for keeping IPv4 data required by Redfish
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010060 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070061struct IPv4AddressData
62{
63 std::string id;
Ed Tanous4a0cb852018-10-15 07:55:04 -070064 std::string address;
65 std::string domain;
66 std::string gateway;
Ed Tanous1abe55e2018-09-05 08:30:59 -070067 std::string netmask;
68 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080069 LinkType linktype{};
70 bool isActive{};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010071};
72
73/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -050074 * Structure for keeping IPv6 data required by Redfish
75 */
76struct IPv6AddressData
77{
78 std::string id;
79 std::string address;
80 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080081 uint8_t prefixLength = 0;
Ravi Tejae48c0fc2019-04-16 08:37:20 -050082};
Sunitha Harishce73d5c2023-04-07 06:46:49 -050083
84/**
85 * Structure for keeping static route data required by Redfish
86 */
87struct StaticGatewayData
88{
89 std::string id;
90 std::string gateway;
91 size_t prefixLength = 0;
92 std::string protocol;
93};
94
Ravi Tejae48c0fc2019-04-16 08:37:20 -050095/**
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010096 * Structure for keeping basic single Ethernet Interface information
97 * available from DBus
98 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070099struct EthernetInterfaceData
100{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700101 uint32_t speed;
Tejas Patil35fb5312021-09-20 15:35:20 +0530102 size_t mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800103 bool autoNeg;
Jishnu CMe4588152023-05-11 00:04:40 -0500104 bool dnsv4Enabled;
105 bool dnsv6Enabled;
Ravi Teja91c441e2024-02-23 09:03:43 -0600106 bool domainv4Enabled;
107 bool domainv6Enabled;
Jishnu CMe4588152023-05-11 00:04:40 -0500108 bool ntpv4Enabled;
109 bool ntpv6Enabled;
110 bool hostNamev4Enabled;
111 bool hostNamev6Enabled;
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800112 bool linkUp;
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700113 bool nicEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -0500114 bool ipv6AcceptRa;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800115 std::string dhcpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700116 std::string operatingMode;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800117 std::string hostName;
118 std::string defaultGateway;
119 std::string ipv6DefaultGateway;
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500120 std::string ipv6StaticDefaultGateway;
Asmitha Karunanithi4652c642024-07-30 11:35:53 -0500121 std::optional<std::string> macAddress;
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800122 std::optional<uint32_t> vlanId;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500123 std::vector<std::string> nameServers;
124 std::vector<std::string> staticNameServers;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800125 std::vector<std::string> domainnames;
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100126};
127
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700128struct DHCPParameters
129{
130 std::optional<bool> dhcpv4Enabled;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800131 std::optional<bool> useDnsServers;
132 std::optional<bool> useNtpServers;
133 std::optional<bool> useDomainName;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700134 std::optional<std::string> dhcpv6OperatingMode;
135};
136
Ed Tanous4a0cb852018-10-15 07:55:04 -0700137// Helper function that changes bits netmask notation (i.e. /24)
138// into full dot notation
139inline std::string getNetmask(unsigned int bits)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700140{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700141 uint32_t value = 0xffffffff << (32 - bits);
142 std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
143 std::to_string((value >> 16) & 0xff) + "." +
144 std::to_string((value >> 8) & 0xff) + "." +
145 std::to_string(value & 0xff);
146 return netmask;
147}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100148
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800149inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700150 bool isIPv4)
151{
152 if (isIPv4)
153 {
154 return (
155 (inputDHCP ==
156 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
157 (inputDHCP ==
158 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
159 }
160 return ((inputDHCP ==
161 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
162 (inputDHCP ==
163 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
164}
165
Ed Tanous2c70f802020-09-28 14:29:23 -0700166inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700167{
168 if (isIPv4 && isIPv6)
169 {
170 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
171 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700172 if (isIPv4)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700173 {
174 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
175 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700176 if (isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700177 {
178 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
179 }
180 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
181}
182
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400183inline std::string translateAddressOriginDbusToRedfish(
184 const std::string& inputOrigin, bool isIPv4)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700185{
186 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700187 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700188 return "Static";
189 }
190 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
191 {
192 if (isIPv4)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700193 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700194 return "IPv4LinkLocal";
195 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700196 return "LinkLocal";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700197 }
198 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
199 {
200 if (isIPv4)
201 {
202 return "DHCP";
203 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700204 return "DHCPv6";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700205 }
206 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
207 {
208 return "SLAAC";
209 }
210 return "";
211}
212
Ed Tanous02cad962022-06-30 16:50:15 -0700213inline bool extractEthernetInterfaceData(
214 const std::string& ethifaceId,
215 const dbus::utility::ManagedObjectType& dbusData,
216 EthernetInterfaceData& ethData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700217{
Ed Tanous4c9afe42019-05-03 16:59:57 -0700218 bool idFound = false;
Ed Tanous02cad962022-06-30 16:50:15 -0700219 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700220 {
Ed Tanous02cad962022-06-30 16:50:15 -0700221 for (const auto& ifacePair : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700222 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000223 if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700224 {
Ed Tanous4c9afe42019-05-03 16:59:57 -0700225 idFound = true;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700226 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500228 for (const auto& propertyPair : ifacePair.second)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700229 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700230 if (propertyPair.first == "MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500232 const std::string* mac =
Ed Tanousabf2add2019-01-22 16:40:12 -0800233 std::get_if<std::string>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700234 if (mac != nullptr)
235 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800236 ethData.macAddress = *mac;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700237 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700238 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700239 }
240 }
241 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
242 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500243 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700244 {
245 if (propertyPair.first == "Id")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700246 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500247 const uint32_t* id =
Ed Tanousabf2add2019-01-22 16:40:12 -0800248 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700249 if (id != nullptr)
250 {
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800251 ethData.vlanId = *id;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700252 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700253 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700254 }
255 }
256 else if (ifacePair.first ==
257 "xyz.openbmc_project.Network.EthernetInterface")
258 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500259 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700260 {
261 if (propertyPair.first == "AutoNeg")
262 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700263 const bool* autoNeg =
Ed Tanousabf2add2019-01-22 16:40:12 -0800264 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700265 if (autoNeg != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700266 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800267 ethData.autoNeg = *autoNeg;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700268 }
269 }
270 else if (propertyPair.first == "Speed")
271 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500272 const uint32_t* speed =
Ed Tanousabf2add2019-01-22 16:40:12 -0800273 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700274 if (speed != nullptr)
275 {
276 ethData.speed = *speed;
277 }
278 }
Tejas Patil35fb5312021-09-20 15:35:20 +0530279 else if (propertyPair.first == "MTU")
280 {
Anthony3e7a8da2023-10-23 14:22:43 +0800281 const size_t* mtuSize =
282 std::get_if<size_t>(&propertyPair.second);
Tejas Patil35fb5312021-09-20 15:35:20 +0530283 if (mtuSize != nullptr)
284 {
285 ethData.mtuSize = *mtuSize;
286 }
287 }
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800288 else if (propertyPair.first == "LinkUp")
289 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500290 const bool* linkUp =
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800291 std::get_if<bool>(&propertyPair.second);
292 if (linkUp != nullptr)
293 {
294 ethData.linkUp = *linkUp;
295 }
296 }
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700297 else if (propertyPair.first == "NICEnabled")
298 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500299 const bool* nicEnabled =
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700300 std::get_if<bool>(&propertyPair.second);
301 if (nicEnabled != nullptr)
302 {
303 ethData.nicEnabled = *nicEnabled;
304 }
305 }
Ravi Tejab10d8db2022-05-24 09:04:12 -0500306 else if (propertyPair.first == "IPv6AcceptRA")
307 {
308 const bool* ipv6AcceptRa =
309 std::get_if<bool>(&propertyPair.second);
310 if (ipv6AcceptRa != nullptr)
311 {
312 ethData.ipv6AcceptRa = *ipv6AcceptRa;
313 }
314 }
RAJESWARAN THILLAIGOVINDANf85837b2019-04-04 05:18:53 -0500315 else if (propertyPair.first == "Nameservers")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700316 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500317 const std::vector<std::string>* nameservers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500318 std::get_if<std::vector<std::string>>(
Ed Tanous029573d2019-02-01 10:57:49 -0800319 &propertyPair.second);
320 if (nameservers != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700321 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700322 ethData.nameServers = *nameservers;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500323 }
324 }
325 else if (propertyPair.first == "StaticNameServers")
326 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500327 const std::vector<std::string>* staticNameServers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500328 std::get_if<std::vector<std::string>>(
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500329 &propertyPair.second);
330 if (staticNameServers != nullptr)
331 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700332 ethData.staticNameServers = *staticNameServers;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700333 }
334 }
manojkiraneda2a133282019-02-19 13:09:43 +0530335 else if (propertyPair.first == "DHCPEnabled")
336 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700337 const std::string* dhcpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700338 std::get_if<std::string>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700339 if (dhcpEnabled != nullptr)
manojkiraneda2a133282019-02-19 13:09:43 +0530340 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800341 ethData.dhcpEnabled = *dhcpEnabled;
manojkiraneda2a133282019-02-19 13:09:43 +0530342 }
343 }
Jennifer Leed24bfc72019-03-05 13:03:37 -0800344 else if (propertyPair.first == "DomainName")
345 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500346 const std::vector<std::string>* domainNames =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500347 std::get_if<std::vector<std::string>>(
Jennifer Leed24bfc72019-03-05 13:03:37 -0800348 &propertyPair.second);
349 if (domainNames != nullptr)
350 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700351 ethData.domainnames = *domainNames;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800352 }
353 }
Ravi Teja9010ec22019-08-01 23:30:25 -0500354 else if (propertyPair.first == "DefaultGateway")
355 {
356 const std::string* defaultGateway =
357 std::get_if<std::string>(&propertyPair.second);
358 if (defaultGateway != nullptr)
359 {
360 std::string defaultGatewayStr = *defaultGateway;
361 if (defaultGatewayStr.empty())
362 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800363 ethData.defaultGateway = "0.0.0.0";
Ravi Teja9010ec22019-08-01 23:30:25 -0500364 }
365 else
366 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800367 ethData.defaultGateway = defaultGatewayStr;
Ravi Teja9010ec22019-08-01 23:30:25 -0500368 }
369 }
370 }
371 else if (propertyPair.first == "DefaultGateway6")
372 {
373 const std::string* defaultGateway6 =
374 std::get_if<std::string>(&propertyPair.second);
375 if (defaultGateway6 != nullptr)
376 {
377 std::string defaultGateway6Str =
378 *defaultGateway6;
379 if (defaultGateway6Str.empty())
380 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800381 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500382 "0:0:0:0:0:0:0:0";
383 }
384 else
385 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800386 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500387 defaultGateway6Str;
388 }
389 }
390 }
Ed Tanous029573d2019-02-01 10:57:49 -0800391 }
392 }
393 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700394
Jishnu CMe4588152023-05-11 00:04:40 -0500395 sdbusplus::message::object_path path(
396 "/xyz/openbmc_project/network");
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400397 sdbusplus::message::object_path dhcp4Path =
398 path / ethifaceId / "dhcp4";
Jishnu CMe4588152023-05-11 00:04:40 -0500399
400 if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700401 {
402 if (ifacePair.first ==
403 "xyz.openbmc_project.Network.DHCPConfiguration")
404 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500405 for (const auto& propertyPair : ifacePair.second)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700406 {
407 if (propertyPair.first == "DNSEnabled")
408 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700409 const bool* dnsEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700410 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700411 if (dnsEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700412 {
Jishnu CMe4588152023-05-11 00:04:40 -0500413 ethData.dnsv4Enabled = *dnsEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700414 }
415 }
Ravi Teja91c441e2024-02-23 09:03:43 -0600416 else if (propertyPair.first == "DomainEnabled")
417 {
418 const bool* domainEnabled =
419 std::get_if<bool>(&propertyPair.second);
420 if (domainEnabled != nullptr)
421 {
422 ethData.domainv4Enabled = *domainEnabled;
423 }
424 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700425 else if (propertyPair.first == "NTPEnabled")
426 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700427 const bool* ntpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700428 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700429 if (ntpEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700430 {
Jishnu CMe4588152023-05-11 00:04:40 -0500431 ethData.ntpv4Enabled = *ntpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700432 }
433 }
434 else if (propertyPair.first == "HostNameEnabled")
435 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700436 const bool* hostNameEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700437 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700438 if (hostNameEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700439 {
Jishnu CMe4588152023-05-11 00:04:40 -0500440 ethData.hostNamev4Enabled = *hostNameEnabled;
441 }
442 }
443 }
444 }
445 }
446
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400447 sdbusplus::message::object_path dhcp6Path =
448 path / ethifaceId / "dhcp6";
Jishnu CMe4588152023-05-11 00:04:40 -0500449
450 if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
451 {
452 if (ifacePair.first ==
453 "xyz.openbmc_project.Network.DHCPConfiguration")
454 {
455 for (const auto& propertyPair : ifacePair.second)
456 {
457 if (propertyPair.first == "DNSEnabled")
458 {
459 const bool* dnsEnabled =
460 std::get_if<bool>(&propertyPair.second);
461 if (dnsEnabled != nullptr)
462 {
463 ethData.dnsv6Enabled = *dnsEnabled;
464 }
465 }
Ravi Teja91c441e2024-02-23 09:03:43 -0600466 if (propertyPair.first == "DomainEnabled")
467 {
468 const bool* domainEnabled =
469 std::get_if<bool>(&propertyPair.second);
470 if (domainEnabled != nullptr)
471 {
472 ethData.domainv6Enabled = *domainEnabled;
473 }
474 }
Jishnu CMe4588152023-05-11 00:04:40 -0500475 else if (propertyPair.first == "NTPEnabled")
476 {
477 const bool* ntpEnabled =
478 std::get_if<bool>(&propertyPair.second);
479 if (ntpEnabled != nullptr)
480 {
481 ethData.ntpv6Enabled = *ntpEnabled;
482 }
483 }
484 else if (propertyPair.first == "HostNameEnabled")
485 {
486 const bool* hostNameEnabled =
487 std::get_if<bool>(&propertyPair.second);
488 if (hostNameEnabled != nullptr)
489 {
490 ethData.hostNamev6Enabled = *hostNameEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700491 }
492 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700493 }
494 }
495 }
Ed Tanous029573d2019-02-01 10:57:49 -0800496 // System configuration shows up in the global namespace, so no need
497 // to check eth number
498 if (ifacePair.first ==
499 "xyz.openbmc_project.Network.SystemConfiguration")
500 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500501 for (const auto& propertyPair : ifacePair.second)
Ed Tanous029573d2019-02-01 10:57:49 -0800502 {
503 if (propertyPair.first == "HostName")
504 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500505 const std::string* hostname =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500506 std::get_if<std::string>(&propertyPair.second);
Ed Tanous029573d2019-02-01 10:57:49 -0800507 if (hostname != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700508 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800509 ethData.hostName = *hostname;
Ed Tanous029573d2019-02-01 10:57:49 -0800510 }
511 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700512 }
513 }
514 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700515 }
Ed Tanous4c9afe42019-05-03 16:59:57 -0700516 return idFound;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700517}
518
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500519// Helper function that extracts data for single ethernet ipv6 address
Ed Tanous77179532023-02-28 10:45:28 -0800520inline void extractIPV6Data(const std::string& ethifaceId,
521 const dbus::utility::ManagedObjectType& dbusData,
522 std::vector<IPv6AddressData>& ipv6Config)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500523{
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400524 const std::string ipPathStart =
525 "/xyz/openbmc_project/network/" + ethifaceId;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500526
527 // Since there might be several IPv6 configurations aligned with
528 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000529 for (const auto& objpath : dbusData)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500530 {
531 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800532 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500533 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800534 for (const auto& interface : objpath.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500535 {
536 if (interface.first == "xyz.openbmc_project.Network.IP")
537 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400538 auto type = std::ranges::find_if(
539 interface.second, [](const auto& property) {
540 return property.first == "Type";
541 });
Tony Lee353163e2022-11-23 11:06:10 +0800542 if (type == interface.second.end())
543 {
544 continue;
545 }
546
547 const std::string* typeStr =
548 std::get_if<std::string>(&type->second);
549
550 if (typeStr == nullptr ||
551 (*typeStr !=
552 "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
553 {
554 continue;
555 }
556
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500557 // Instance IPv6AddressData structure, and set as
558 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800559 IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700560 ipv6Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800561 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800562 for (const auto& property : interface.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500563 {
564 if (property.first == "Address")
565 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500566 const std::string* address =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500567 std::get_if<std::string>(&property.second);
568 if (address != nullptr)
569 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700570 ipv6Address.address = *address;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500571 }
572 }
573 else if (property.first == "Origin")
574 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500575 const std::string* origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500576 std::get_if<std::string>(&property.second);
577 if (origin != nullptr)
578 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700579 ipv6Address.origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500580 translateAddressOriginDbusToRedfish(*origin,
581 false);
582 }
583 }
584 else if (property.first == "PrefixLength")
585 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500586 const uint8_t* prefix =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500587 std::get_if<uint8_t>(&property.second);
588 if (prefix != nullptr)
589 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700590 ipv6Address.prefixLength = *prefix;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500591 }
592 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600593 else if (property.first == "Type" ||
594 property.first == "Gateway")
595 {
596 // Type & Gateway is not used
597 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500598 else
599 {
Ed Tanous62598e32023-07-17 17:06:25 -0700600 BMCWEB_LOG_ERROR(
601 "Got extra property: {} on the {} object",
602 property.first, objpath.first.str);
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500603 }
604 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500605 }
606 }
607 }
608 }
609}
610
Ed Tanous4a0cb852018-10-15 07:55:04 -0700611// Helper function that extracts data for single ethernet ipv4 address
Ed Tanous77179532023-02-28 10:45:28 -0800612inline void extractIPData(const std::string& ethifaceId,
613 const dbus::utility::ManagedObjectType& dbusData,
614 std::vector<IPv4AddressData>& ipv4Config)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700615{
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400616 const std::string ipPathStart =
617 "/xyz/openbmc_project/network/" + ethifaceId;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700618
619 // Since there might be several IPv4 configurations aligned with
620 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000621 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700622 {
623 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800624 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700625 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800626 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700627 {
628 if (interface.first == "xyz.openbmc_project.Network.IP")
629 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400630 auto type = std::ranges::find_if(
631 interface.second, [](const auto& property) {
632 return property.first == "Type";
633 });
Tony Lee353163e2022-11-23 11:06:10 +0800634 if (type == interface.second.end())
635 {
636 continue;
637 }
638
639 const std::string* typeStr =
640 std::get_if<std::string>(&type->second);
641
642 if (typeStr == nullptr ||
643 (*typeStr !=
644 "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
645 {
646 continue;
647 }
648
Ed Tanous4a0cb852018-10-15 07:55:04 -0700649 // Instance IPv4AddressData structure, and set as
650 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800651 IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700652 ipv4Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800653 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800654 for (const auto& property : interface.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700655 {
656 if (property.first == "Address")
657 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500658 const std::string* address =
Ed Tanousabf2add2019-01-22 16:40:12 -0800659 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700660 if (address != nullptr)
661 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700662 ipv4Address.address = *address;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700663 }
664 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700665 else if (property.first == "Origin")
666 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500667 const std::string* origin =
Ed Tanousabf2add2019-01-22 16:40:12 -0800668 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700669 if (origin != nullptr)
670 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700671 ipv4Address.origin =
Ed Tanous4a0cb852018-10-15 07:55:04 -0700672 translateAddressOriginDbusToRedfish(*origin,
673 true);
674 }
675 }
676 else if (property.first == "PrefixLength")
677 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500678 const uint8_t* mask =
Ed Tanousabf2add2019-01-22 16:40:12 -0800679 std::get_if<uint8_t>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700680 if (mask != nullptr)
681 {
682 // convert it to the string
Ed Tanous2c70f802020-09-28 14:29:23 -0700683 ipv4Address.netmask = getNetmask(*mask);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700684 }
685 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600686 else if (property.first == "Type" ||
687 property.first == "Gateway")
688 {
689 // Type & Gateway is not used
690 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700691 else
692 {
Ed Tanous62598e32023-07-17 17:06:25 -0700693 BMCWEB_LOG_ERROR(
694 "Got extra property: {} on the {} object",
695 property.first, objpath.first.str);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700696 }
697 }
698 // Check if given address is local, or global
Ed Tanous2c70f802020-09-28 14:29:23 -0700699 ipv4Address.linktype =
Ed Tanous11ba3972022-07-11 09:50:41 -0700700 ipv4Address.address.starts_with("169.254.")
Johnathan Mantey18659d12019-06-07 10:26:29 -0700701 ? LinkType::Local
702 : LinkType::Global;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700703 }
704 }
705 }
706 }
707}
708
709/**
Johnathan Mantey743eb1c2024-04-03 12:05:57 -0700710 * @brief Modifies the default gateway assigned to the NIC
711 *
712 * @param[in] ifaceId Id of network interface whose default gateway is to be
713 * changed
714 * @param[in] gateway The new gateway value. Assigning an empty string
715 * causes the gateway to be deleted
716 * @param[io] asyncResp Response object that will be returned to client
717 *
718 * @return None
719 */
720inline void updateIPv4DefaultGateway(
721 const std::string& ifaceId, const std::string& gateway,
722 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
723{
724 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +0530725 asyncResp, "Gateway", "xyz.openbmc_project.Network",
Johnathan Mantey743eb1c2024-04-03 12:05:57 -0700726 sdbusplus::message::object_path("/xyz/openbmc_project/network") /
727 ifaceId,
728 "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
Ginu Georgee93abac2024-06-14 17:35:27 +0530729 gateway);
Johnathan Mantey743eb1c2024-04-03 12:05:57 -0700730}
731
732/**
733 * @brief Deletes given static IP address for the interface
Ed Tanous4a0cb852018-10-15 07:55:04 -0700734 *
735 * @param[in] ifaceId Id of interface whose IP should be deleted
Ed Tanous4a0cb852018-10-15 07:55:04 -0700736 * @param[in] ipHash DBus Hash id of IP that should be deleted
737 * @param[io] asyncResp Response object that will be returned to client
738 *
739 * @return None
740 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600741inline void deleteIPAddress(const std::string& ifaceId,
742 const std::string& ipHash,
743 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700744{
745 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800746 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400747 if (ec)
748 {
749 messages::internalError(asyncResp->res);
750 }
751 },
Ed Tanous4a0cb852018-10-15 07:55:04 -0700752 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600753 "/xyz/openbmc_project/network/" + ifaceId + ipHash,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700754 "xyz.openbmc_project.Object.Delete", "Delete");
755}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700756
Ed Tanous4a0cb852018-10-15 07:55:04 -0700757/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700758 * @brief Creates a static IPv4 entry
Ed Tanous4a0cb852018-10-15 07:55:04 -0700759 *
Johnathan Mantey01784822019-06-18 12:44:21 -0700760 * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
761 * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
762 * @param[in] gateway IPv4 address of this interfaces gateway
763 * @param[in] address IPv4 address to assign to this interface
764 * @param[io] asyncResp Response object that will be returned to client
Ed Tanous4a0cb852018-10-15 07:55:04 -0700765 *
766 * @return None
767 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000768inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
769 const std::string& gateway, const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800770 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700771{
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400772 auto createIpHandler =
773 [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
774 if (ec)
775 {
776 messages::internalError(asyncResp->res);
777 return;
778 }
779 };
Ravi Teja9010ec22019-08-01 23:30:25 -0500780
Ed Tanous4a0cb852018-10-15 07:55:04 -0700781 crow::connections::systemBus->async_method_call(
Ravi Teja9010ec22019-08-01 23:30:25 -0500782 std::move(createIpHandler), "xyz.openbmc_project.Network",
Ed Tanous4a0cb852018-10-15 07:55:04 -0700783 "/xyz/openbmc_project/network/" + ifaceId,
784 "xyz.openbmc_project.Network.IP.Create", "IP",
Johnathan Mantey01784822019-06-18 12:44:21 -0700785 "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700786 gateway);
787}
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500788
789/**
Johnathan Mantey743eb1c2024-04-03 12:05:57 -0700790 * @brief Deletes the IP entry for this interface and creates a replacement
791 * static entry
Johnathan Mantey01784822019-06-18 12:44:21 -0700792 *
Johnathan Mantey743eb1c2024-04-03 12:05:57 -0700793 * @param[in] ifaceId Id of interface upon which to create the IPv6 entry
794 * @param[in] id The unique hash entry identifying the DBus entry
795 * @param[in] prefixLength Prefix syntax for the subnet mask
796 * @param[in] address Address to assign to this interface
797 * @param[in] numStaticAddrs Count of IPv4 static addresses
798 * @param[io] asyncResp Response object that will be returned to client
Johnathan Mantey01784822019-06-18 12:44:21 -0700799 *
800 * @return None
801 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600802
Ravi Teja9c5e5852023-02-26 21:33:52 -0600803inline void deleteAndCreateIPAddress(
804 IpVersion version, const std::string& ifaceId, const std::string& id,
805 uint8_t prefixLength, const std::string& address,
806 const std::string& gateway,
807 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Johnathan Mantey01784822019-06-18 12:44:21 -0700808{
809 crow::connections::systemBus->async_method_call(
Ravi Teja9c5e5852023-02-26 21:33:52 -0600810 [asyncResp, version, ifaceId, address, prefixLength,
811 gateway](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400812 if (ec)
Johnathan Mantey01784822019-06-18 12:44:21 -0700813 {
814 messages::internalError(asyncResp->res);
815 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400816 std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
817 protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
818 crow::connections::systemBus->async_method_call(
819 [asyncResp](const boost::system::error_code& ec2) {
820 if (ec2)
821 {
822 messages::internalError(asyncResp->res);
823 }
824 },
825 "xyz.openbmc_project.Network",
826 "/xyz/openbmc_project/network/" + ifaceId,
827 "xyz.openbmc_project.Network.IP.Create", "IP", protocol,
828 address, prefixLength, gateway);
Patrick Williams5a39f772023-10-20 11:20:21 -0500829 },
Johnathan Mantey01784822019-06-18 12:44:21 -0700830 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600831 "/xyz/openbmc_project/network/" + ifaceId + id,
Johnathan Mantey01784822019-06-18 12:44:21 -0700832 "xyz.openbmc_project.Object.Delete", "Delete");
833}
834
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500835inline bool extractIPv6DefaultGatewayData(
836 const std::string& ethifaceId,
837 const dbus::utility::ManagedObjectType& dbusData,
838 std::vector<StaticGatewayData>& staticGatewayConfig)
839{
840 std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
841 staticGatewayPathStart += ethifaceId;
842
843 for (const auto& objpath : dbusData)
844 {
845 if (!std::string_view(objpath.first.str)
846 .starts_with(staticGatewayPathStart))
847 {
848 continue;
849 }
850 for (const auto& interface : objpath.second)
851 {
852 if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
853 {
854 continue;
855 }
856 StaticGatewayData& staticGateway =
857 staticGatewayConfig.emplace_back();
858 staticGateway.id = objpath.first.filename();
859
860 bool success = sdbusplus::unpackPropertiesNoThrow(
861 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
Ravi Tejaab0d4392024-09-03 12:27:40 -0500862 "Gateway", staticGateway.gateway, "ProtocolType",
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500863 staticGateway.protocol);
864 if (!success)
865 {
866 return false;
867 }
868 }
869 }
870 return true;
871}
872
Johnathan Mantey01784822019-06-18 12:44:21 -0700873/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500874 * @brief Creates IPv6 with given data
875 *
876 * @param[in] ifaceId Id of interface whose IP should be added
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500877 * @param[in] prefixLength Prefix length that needs to be added
878 * @param[in] address IP address that needs to be added
879 * @param[io] asyncResp Response object that will be returned to client
880 *
881 * @return None
882 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500883inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
884 const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800885 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500886{
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500887 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
888 path /= ifaceId;
889
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400890 auto createIpHandler =
891 [asyncResp, address](const boost::system::error_code& ec) {
892 if (ec)
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500893 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400894 if (ec == boost::system::errc::io_error)
895 {
896 messages::propertyValueFormatError(asyncResp->res, address,
897 "Address");
898 }
899 else
900 {
901 messages::internalError(asyncResp->res);
902 }
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500903 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400904 };
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500905 // Passing null for gateway, as per redfish spec IPv6StaticAddresses
906 // object does not have associated gateway property
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500907 crow::connections::systemBus->async_method_call(
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500908 std::move(createIpHandler), "xyz.openbmc_project.Network", path,
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500909 "xyz.openbmc_project.Network.IP.Create", "IP",
910 "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
911 "");
912}
913
Ed Tanous4a0cb852018-10-15 07:55:04 -0700914/**
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500915 * @brief Deletes given IPv6 Static Gateway
916 *
917 * @param[in] ifaceId Id of interface whose IP should be deleted
918 * @param[in] ipHash DBus Hash id of IP that should be deleted
919 * @param[io] asyncResp Response object that will be returned to client
920 *
921 * @return None
922 */
923inline void
Ravi Teja739b27b2024-08-27 21:03:53 -0500924 deleteIPv6Gateway(std::string_view ifaceId, std::string_view gatewayId,
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500925 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
926{
927 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
Ravi Teja739b27b2024-08-27 21:03:53 -0500928 path /= ifaceId;
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500929 path /= gatewayId;
930 crow::connections::systemBus->async_method_call(
931 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400932 if (ec)
933 {
934 messages::internalError(asyncResp->res);
935 }
936 },
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500937 "xyz.openbmc_project.Network", path,
938 "xyz.openbmc_project.Object.Delete", "Delete");
939}
940
941/**
942 * @brief Creates IPv6 static default gateway with given data
943 *
944 * @param[in] ifaceId Id of interface whose IP should be added
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500945 * @param[in] gateway Gateway address that needs to be added
946 * @param[io] asyncResp Response object that will be returned to client
947 *
948 * @return None
949 */
950inline void createIPv6DefaultGateway(
Ravi Tejaab0d4392024-09-03 12:27:40 -0500951 std::string_view ifaceId, std::string_view gateway,
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500952 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
953{
954 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
955 path /= ifaceId;
956 auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
957 if (ec)
958 {
959 messages::internalError(asyncResp->res);
960 }
961 };
962 crow::connections::systemBus->async_method_call(
963 std::move(createIpHandler), "xyz.openbmc_project.Network", path,
964 "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
Ravi Tejaab0d4392024-09-03 12:27:40 -0500965 gateway, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500966}
967
968/**
969 * @brief Deletes the IPv6 default gateway entry for this interface and
970 * creates a replacement IPv6 default gateway entry
971 *
972 * @param[in] ifaceId Id of interface upon which to create the IPv6
973 * entry
974 * @param[in] gateway IPv6 gateway to assign to this interface
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500975 * @param[io] asyncResp Response object that will be returned to client
976 *
977 * @return None
978 */
979inline void deleteAndCreateIPv6DefaultGateway(
980 std::string_view ifaceId, std::string_view gatewayId,
Ravi Tejaab0d4392024-09-03 12:27:40 -0500981 std::string_view gateway,
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500982 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
983{
984 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
Ravi Teja739b27b2024-08-27 21:03:53 -0500985 path /= ifaceId;
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500986 path /= gatewayId;
987 crow::connections::systemBus->async_method_call(
Ravi Tejaab0d4392024-09-03 12:27:40 -0500988 [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400989 if (ec)
990 {
991 messages::internalError(asyncResp->res);
992 return;
993 }
Ravi Tejaab0d4392024-09-03 12:27:40 -0500994 createIPv6DefaultGateway(ifaceId, gateway, asyncResp);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400995 },
Sunitha Harishce73d5c2023-04-07 06:46:49 -0500996 "xyz.openbmc_project.Network", path,
997 "xyz.openbmc_project.Object.Delete", "Delete");
998}
999
1000/**
1001 * @brief Sets IPv6 default gateway with given data
1002 *
1003 * @param[in] ifaceId Id of interface whose gateway should be added
1004 * @param[in] input Contains address that needs to be added
1005 * @param[in] staticGatewayData Current static gateways in the system
1006 * @param[io] asyncResp Response object that will be returned to client
1007 *
1008 * @return None
1009 */
1010
1011inline void handleIPv6DefaultGateway(
Ed Tanous3dfed532024-03-06 14:41:27 -08001012 const std::string& ifaceId,
1013 std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001014 const std::vector<StaticGatewayData>& staticGatewayData,
1015 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1016{
1017 size_t entryIdx = 1;
1018 std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1019 staticGatewayData.begin();
1020
Ed Tanous3dfed532024-03-06 14:41:27 -08001021 for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
1022 input)
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001023 {
1024 // find the next gateway entry
1025 while (staticGatewayEntry != staticGatewayData.end())
1026 {
1027 if (staticGatewayEntry->protocol ==
1028 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1029 {
1030 break;
1031 }
1032 staticGatewayEntry++;
1033 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001034 std::string pathString =
1035 "IPv6StaticDefaultGateways/" + std::to_string(entryIdx);
Ed Tanous3dfed532024-03-06 14:41:27 -08001036 nlohmann::json::object_t* obj =
1037 std::get_if<nlohmann::json::object_t>(&thisJson);
1038 if (obj == nullptr)
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001039 {
1040 if (staticGatewayEntry == staticGatewayData.end())
1041 {
1042 messages::resourceCannotBeDeleted(asyncResp->res);
1043 return;
1044 }
Ravi Teja739b27b2024-08-27 21:03:53 -05001045 deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp);
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001046 return;
1047 }
Ed Tanous3dfed532024-03-06 14:41:27 -08001048 if (obj->empty())
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001049 {
1050 // Do nothing, but make sure the entry exists.
1051 if (staticGatewayEntry == staticGatewayData.end())
1052 {
Ed Tanous3dfed532024-03-06 14:41:27 -08001053 messages::propertyValueFormatError(asyncResp->res, *obj,
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001054 pathString);
1055 return;
1056 }
1057 }
1058 std::optional<std::string> address;
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001059
Ravi Tejaab0d4392024-09-03 12:27:40 -05001060 if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
1061 address))
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001062 {
1063 return;
1064 }
1065 const std::string* addr = nullptr;
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001066 if (address)
1067 {
1068 addr = &(*address);
1069 }
1070 else if (staticGatewayEntry != staticGatewayData.end())
1071 {
1072 addr = &(staticGatewayEntry->gateway);
1073 }
1074 else
1075 {
1076 messages::propertyMissing(asyncResp->res, pathString + "/Address");
1077 return;
1078 }
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001079 if (staticGatewayEntry != staticGatewayData.end())
1080 {
1081 deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
Ravi Tejaab0d4392024-09-03 12:27:40 -05001082 *addr, asyncResp);
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001083 staticGatewayEntry++;
1084 }
1085 else
1086 {
Ravi Tejaab0d4392024-09-03 12:27:40 -05001087 createIPv6DefaultGateway(ifaceId, *addr, asyncResp);
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001088 }
1089 entryIdx++;
1090 }
1091}
1092
1093/**
Ed Tanous4a0cb852018-10-15 07:55:04 -07001094 * Function that retrieves all properties for given Ethernet Interface
1095 * Object
1096 * from EntityManager Network Manager
1097 * @param ethiface_id a eth interface id to query on DBus
1098 * @param callback a function that shall be called to convert Dbus output
1099 * into JSON
1100 */
1101template <typename CallbackFunc>
Ed Tanous81ce6092020-12-17 16:54:55 +00001102void getEthernetIfaceData(const std::string& ethifaceId,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001103 CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -07001104{
George Liuf5892d02023-03-01 10:37:08 +08001105 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1106 dbus::utility::getManagedObjects(
1107 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -08001108 [ethifaceId{std::string{ethifaceId}},
Ed Tanous8cb2c022024-03-27 16:31:46 -07001109 callback = std::forward<CallbackFunc>(callback)](
Ed Tanous8b242752023-06-27 17:17:13 -07001110 const boost::system::error_code& ec,
Ed Tanous3dfed532024-03-06 14:41:27 -08001111 const dbus::utility::ManagedObjectType& resp) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001112 EthernetInterfaceData ethData{};
1113 std::vector<IPv4AddressData> ipv4Data;
1114 std::vector<IPv6AddressData> ipv6Data;
1115 std::vector<StaticGatewayData> ipv6GatewayData;
Ed Tanous4a0cb852018-10-15 07:55:04 -07001116
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001117 if (ec)
Ed Tanous4a0cb852018-10-15 07:55:04 -07001118 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001119 callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1120 return;
Ed Tanous4a0cb852018-10-15 07:55:04 -07001121 }
1122
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001123 bool found =
1124 extractEthernetInterfaceData(ethifaceId, resp, ethData);
1125 if (!found)
1126 {
1127 callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1128 return;
1129 }
1130
1131 extractIPData(ethifaceId, resp, ipv4Data);
1132 // Fix global GW
1133 for (IPv4AddressData& ipv4 : ipv4Data)
1134 {
1135 if (((ipv4.linktype == LinkType::Global) &&
1136 (ipv4.gateway == "0.0.0.0")) ||
1137 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
1138 {
1139 ipv4.gateway = ethData.defaultGateway;
1140 }
1141 }
1142
1143 extractIPV6Data(ethifaceId, resp, ipv6Data);
1144 if (!extractIPv6DefaultGatewayData(ethifaceId, resp,
1145 ipv6GatewayData))
1146 {
1147 callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1148 }
1149 // Finally make a callback with useful data
1150 callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1151 });
Ed Tanous271584a2019-07-09 16:24:22 -07001152}
Ed Tanous4a0cb852018-10-15 07:55:04 -07001153
1154/**
1155 * Function that retrieves all Ethernet Interfaces available through Network
1156 * Manager
1157 * @param callback a function that shall be called to convert Dbus output
1158 * into JSON.
1159 */
1160template <typename CallbackFunc>
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001161void getEthernetIfaceList(CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -07001162{
George Liuf5892d02023-03-01 10:37:08 +08001163 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1164 dbus::utility::getManagedObjects(
1165 "xyz.openbmc_project.Network", path,
Ed Tanous8cb2c022024-03-27 16:31:46 -07001166 [callback = std::forward<CallbackFunc>(callback)](
Ed Tanous8b242752023-06-27 17:17:13 -07001167 const boost::system::error_code& ec,
George Liuf5892d02023-03-01 10:37:08 +08001168 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001169 // Callback requires vector<string> to retrieve all available
1170 // ethernet interfaces
1171 std::vector<std::string> ifaceList;
1172 ifaceList.reserve(resp.size());
1173 if (ec)
Ed Tanous4a0cb852018-10-15 07:55:04 -07001174 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001175 callback(false, ifaceList);
1176 return;
1177 }
1178
1179 // Iterate over all retrieved ObjectPaths.
1180 for (const auto& objpath : resp)
1181 {
1182 // And all interfaces available for certain ObjectPath.
1183 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -07001184 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001185 // If interface is
1186 // xyz.openbmc_project.Network.EthernetInterface, this is
1187 // what we're looking for.
1188 if (interface.first ==
1189 "xyz.openbmc_project.Network.EthernetInterface")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001190 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001191 std::string ifaceId = objpath.first.filename();
1192 if (ifaceId.empty())
1193 {
1194 continue;
1195 }
1196 // and put it into output vector.
1197 ifaceList.emplace_back(ifaceId);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001198 }
1199 }
Ed Tanous4a0cb852018-10-15 07:55:04 -07001200 }
Ed Tanous2c5875a2023-05-15 09:56:06 -07001201
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001202 std::ranges::sort(ifaceList, AlphanumLess<std::string>());
Ed Tanous2c5875a2023-05-15 09:56:06 -07001203
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001204 // Finally make a callback with useful data
1205 callback(true, ifaceList);
1206 });
Ed Tanous271584a2019-07-09 16:24:22 -07001207}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +01001208
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001209inline void
1210 handleHostnamePatch(const std::string& hostname,
1211 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001212{
Ed Tanousbf648f72021-06-03 15:00:14 -07001213 // SHOULD handle host names of up to 255 characters(RFC 1123)
1214 if (hostname.length() > 255)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001215 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001216 messages::propertyValueFormatError(asyncResp->res, hostname,
1217 "HostName");
1218 return;
1219 }
Ed Tanousd02aad32024-02-13 14:43:34 -08001220 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301221 asyncResp, "HostName", "xyz.openbmc_project.Network",
Ed Tanousd02aad32024-02-13 14:43:34 -08001222 sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1223 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ginu Georgee93abac2024-06-14 17:35:27 +05301224 hostname);
Ed Tanousbf648f72021-06-03 15:00:14 -07001225}
1226
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001227inline void
Tejas Patil35fb5312021-09-20 15:35:20 +05301228 handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
1229 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1230{
Ed Tanousd02aad32024-02-13 14:43:34 -08001231 sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1232 objPath /= ifaceId;
Ginu Georgee93abac2024-06-14 17:35:27 +05301233 setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network",
1234 objPath, "xyz.openbmc_project.Network.EthernetInterface",
1235 "MTU", mtuSize);
Tejas Patil35fb5312021-09-20 15:35:20 +05301236}
1237
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001238inline void handleDomainnamePatch(
1239 const std::string& ifaceId, const std::string& domainname,
1240 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001241{
1242 std::vector<std::string> vectorDomainname = {domainname};
Ed Tanousd02aad32024-02-13 14:43:34 -08001243 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301244 asyncResp, "FQDN", "xyz.openbmc_project.Network",
Ed Tanousd02aad32024-02-13 14:43:34 -08001245 sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1246 ifaceId,
Ginu Georgee93abac2024-06-14 17:35:27 +05301247 "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
Ed Tanousd02aad32024-02-13 14:43:34 -08001248 vectorDomainname);
Ed Tanousbf648f72021-06-03 15:00:14 -07001249}
1250
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001251inline bool isHostnameValid(const std::string& hostname)
Ed Tanousbf648f72021-06-03 15:00:14 -07001252{
1253 // A valid host name can never have the dotted-decimal form (RFC 1123)
Ed Tanous3544d2a2023-08-06 18:12:20 -07001254 if (std::ranges::all_of(hostname, ::isdigit))
Ed Tanousbf648f72021-06-03 15:00:14 -07001255 {
1256 return false;
1257 }
1258 // Each label(hostname/subdomains) within a valid FQDN
1259 // MUST handle host names of up to 63 characters (RFC 1123)
1260 // labels cannot start or end with hyphens (RFC 952)
1261 // labels can start with numbers (RFC 1123)
Ed Tanous4b242742023-05-11 09:51:51 -07001262 const static std::regex pattern(
Ed Tanousbf648f72021-06-03 15:00:14 -07001263 "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1264
1265 return std::regex_match(hostname, pattern);
1266}
1267
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001268inline bool isDomainnameValid(const std::string& domainname)
Ed Tanousbf648f72021-06-03 15:00:14 -07001269{
1270 // Can have multiple subdomains
1271 // Top Level Domain's min length is 2 character
Ed Tanous4b242742023-05-11 09:51:51 -07001272 const static std::regex pattern(
George Liu0fda0f12021-11-16 10:06:17 +08001273 "^([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 -07001274
1275 return std::regex_match(domainname, pattern);
1276}
1277
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001278inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
1279 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001280{
1281 // Total length of FQDN must not exceed 255 characters(RFC 1035)
1282 if (fqdn.length() > 255)
1283 {
1284 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1285 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001286 }
1287
Ed Tanousbf648f72021-06-03 15:00:14 -07001288 size_t pos = fqdn.find('.');
1289 if (pos == std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001290 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001291 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1292 return;
1293 }
zhanghch058d1b46d2021-04-01 11:18:24 +08001294
Ed Tanousbf648f72021-06-03 15:00:14 -07001295 std::string hostname;
1296 std::string domainname;
1297 domainname = (fqdn).substr(pos + 1);
1298 hostname = (fqdn).substr(0, pos);
1299
1300 if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1301 {
1302 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1303 return;
1304 }
1305
1306 handleHostnamePatch(hostname, asyncResp);
1307 handleDomainnamePatch(ifaceId, domainname, asyncResp);
1308}
1309
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001310inline void handleMACAddressPatch(
1311 const std::string& ifaceId, const std::string& macAddress,
1312 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001313{
Ed Tanousd02aad32024-02-13 14:43:34 -08001314 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301315 asyncResp, "MACAddress", "xyz.openbmc_project.Network",
Ed Tanousd02aad32024-02-13 14:43:34 -08001316 sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1317 ifaceId,
Ginu Georgee93abac2024-06-14 17:35:27 +05301318 "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress);
Ed Tanousbf648f72021-06-03 15:00:14 -07001319}
1320
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001321inline void setDHCPEnabled(const std::string& ifaceId,
1322 const std::string& propertyName, const bool v4Value,
1323 const bool v6Value,
1324 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001325{
1326 const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
Ed Tanousd02aad32024-02-13 14:43:34 -08001327 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301328 asyncResp, "DHCPv4", "xyz.openbmc_project.Network",
Ed Tanousd02aad32024-02-13 14:43:34 -08001329 sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1330 ifaceId,
Ginu Georgee93abac2024-06-14 17:35:27 +05301331 "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001332}
1333
Jishnu CMe4588152023-05-11 00:04:40 -05001334enum class NetworkType
1335{
1336 dhcp4,
1337 dhcp6
1338};
1339
1340inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1341 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1342 const std::string& ethifaceId, NetworkType type)
Ed Tanousbf648f72021-06-03 15:00:14 -07001343{
Ed Tanous62598e32023-07-17 17:06:25 -07001344 BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
Asmitha Karunanithi1847f2a2024-03-26 22:03:48 -05001345 std::string redfishPropertyName;
Jishnu CMe4588152023-05-11 00:04:40 -05001346 sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1347 path /= ethifaceId;
1348
1349 if (type == NetworkType::dhcp4)
1350 {
1351 path /= "dhcp4";
Asmitha Karunanithi1847f2a2024-03-26 22:03:48 -05001352 redfishPropertyName = "DHCPv4";
Jishnu CMe4588152023-05-11 00:04:40 -05001353 }
1354 else
1355 {
1356 path /= "dhcp6";
Asmitha Karunanithi1847f2a2024-03-26 22:03:48 -05001357 redfishPropertyName = "DHCPv6";
Jishnu CMe4588152023-05-11 00:04:40 -05001358 }
1359
Ginu Georgee93abac2024-06-14 17:35:27 +05301360 setDbusProperty(
1361 asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path,
1362 "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value);
Ed Tanousbf648f72021-06-03 15:00:14 -07001363}
1364
Ravi Tejab10d8db2022-05-24 09:04:12 -05001365inline void handleSLAACAutoConfigPatch(
1366 const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1367 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1368{
1369 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1370 path /= ifaceId;
Ginu Georgee93abac2024-06-14 17:35:27 +05301371 setDbusProperty(asyncResp,
Asmitha Karunanithi1847f2a2024-03-26 22:03:48 -05001372 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301373 "xyz.openbmc_project.Network", path,
1374 "xyz.openbmc_project.Network.EthernetInterface",
1375 "IPv6AcceptRA", ipv6AutoConfigEnabled);
Ravi Tejab10d8db2022-05-24 09:04:12 -05001376}
1377
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001378inline void handleDHCPPatch(
1379 const std::string& ifaceId, const EthernetInterfaceData& ethData,
1380 const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms,
1381 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001382{
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001383 bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1384 bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
Ed Tanousbf648f72021-06-03 15:00:14 -07001385
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001386 if (ipv4Active)
1387 {
1388 updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1389 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001390 bool nextv4DHCPState =
1391 v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
1392
1393 bool nextv6DHCPState{};
1394 if (v6dhcpParms.dhcpv6OperatingMode)
1395 {
Ravi Tejab10d8db2022-05-24 09:04:12 -05001396 if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
Ed Tanousbf648f72021-06-03 15:00:14 -07001397 (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
1398 {
1399 messages::propertyValueFormatError(asyncResp->res,
1400 *v6dhcpParms.dhcpv6OperatingMode,
1401 "OperatingMode");
1402 return;
1403 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001404 nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
Ed Tanousbf648f72021-06-03 15:00:14 -07001405 }
1406 else
1407 {
1408 nextv6DHCPState = ipv6Active;
1409 }
1410
Jishnu CMe4588152023-05-11 00:04:40 -05001411 bool nextDNSv4 = ethData.dnsv4Enabled;
1412 bool nextDNSv6 = ethData.dnsv6Enabled;
1413 if (v4dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001414 {
Jishnu CMe4588152023-05-11 00:04:40 -05001415 nextDNSv4 = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001416 }
Jishnu CMe4588152023-05-11 00:04:40 -05001417 if (v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001418 {
Jishnu CMe4588152023-05-11 00:04:40 -05001419 nextDNSv6 = *v6dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001420 }
1421
Jishnu CMe4588152023-05-11 00:04:40 -05001422 bool nextNTPv4 = ethData.ntpv4Enabled;
1423 bool nextNTPv6 = ethData.ntpv6Enabled;
1424 if (v4dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001425 {
Jishnu CMe4588152023-05-11 00:04:40 -05001426 nextNTPv4 = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001427 }
Jishnu CMe4588152023-05-11 00:04:40 -05001428 if (v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001429 {
Jishnu CMe4588152023-05-11 00:04:40 -05001430 nextNTPv6 = *v6dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001431 }
1432
Ravi Teja91c441e2024-02-23 09:03:43 -06001433 bool nextUsev4Domain = ethData.domainv4Enabled;
1434 bool nextUsev6Domain = ethData.domainv6Enabled;
Jishnu CMe4588152023-05-11 00:04:40 -05001435 if (v4dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001436 {
Jishnu CMe4588152023-05-11 00:04:40 -05001437 nextUsev4Domain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001438 }
Jishnu CMe4588152023-05-11 00:04:40 -05001439 if (v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001440 {
Jishnu CMe4588152023-05-11 00:04:40 -05001441 nextUsev6Domain = *v6dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001442 }
1443
Ed Tanous62598e32023-07-17 17:06:25 -07001444 BMCWEB_LOG_DEBUG("set DHCPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001445 setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
1446 asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001447 BMCWEB_LOG_DEBUG("set DNSEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001448 setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1449 NetworkType::dhcp4);
Ed Tanous62598e32023-07-17 17:06:25 -07001450 BMCWEB_LOG_DEBUG("set NTPEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001451 setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1452 NetworkType::dhcp4);
Ravi Teja91c441e2024-02-23 09:03:43 -06001453 BMCWEB_LOG_DEBUG("set DomainEnabled...");
1454 setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
Jishnu CMe4588152023-05-11 00:04:40 -05001455 NetworkType::dhcp4);
1456 BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1457 setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1458 NetworkType::dhcp6);
1459 BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1460 setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1461 NetworkType::dhcp6);
Ravi Teja91c441e2024-02-23 09:03:43 -06001462 BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
1463 setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
Jishnu CMe4588152023-05-11 00:04:40 -05001464 NetworkType::dhcp6);
Ed Tanousbf648f72021-06-03 15:00:14 -07001465}
1466
Ed Tanous77179532023-02-28 10:45:28 -08001467inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
1468 const std::vector<IPv4AddressData>::const_iterator& head,
1469 const std::vector<IPv4AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001470{
1471 return std::find_if(head, end, [](const IPv4AddressData& value) {
1472 return value.origin == "Static";
1473 });
1474}
1475
Ed Tanous77179532023-02-28 10:45:28 -08001476inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
1477 const std::vector<IPv6AddressData>::const_iterator& head,
1478 const std::vector<IPv6AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001479{
1480 return std::find_if(head, end, [](const IPv6AddressData& value) {
1481 return value.origin == "Static";
1482 });
1483}
1484
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001485enum class AddrChange
Ed Tanousbf648f72021-06-03 15:00:14 -07001486{
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001487 Noop,
1488 Delete,
1489 Update,
1490};
1491
1492// Struct representing a dbus change
1493struct AddressPatch
1494{
1495 std::string address;
1496 std::string gateway;
1497 uint8_t prefixLength = 0;
1498 std::string existingDbusId;
1499 AddrChange operation = AddrChange::Noop;
1500};
1501
1502inline bool parseAddresses(
1503 std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1504 const std::vector<IPv4AddressData>& ipv4Data, crow::Response& res,
1505 std::vector<AddressPatch>& addressesOut, std::string& gatewayOut)
1506{
Ed Tanous77179532023-02-28 10:45:28 -08001507 std::vector<IPv4AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001508 getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
1509
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001510 std::string lastGatewayPath;
1511 size_t entryIdx = 0;
Ed Tanous3dfed532024-03-06 14:41:27 -08001512 for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
1513 input)
Ed Tanousbf648f72021-06-03 15:00:14 -07001514 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001515 std::string pathString =
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001516 std::format("IPv4StaticAddresses/{}", entryIdx);
1517 AddressPatch& thisAddress = addressesOut.emplace_back();
Ed Tanous3dfed532024-03-06 14:41:27 -08001518 nlohmann::json::object_t* obj =
1519 std::get_if<nlohmann::json::object_t>(&thisJson);
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001520 if (nicIpEntry != ipv4Data.cend())
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001521 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001522 thisAddress.existingDbusId = nicIpEntry->id;
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001523 }
1524
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001525 if (obj == nullptr)
1526 {
1527 if (thisAddress.existingDbusId.empty())
1528 {
1529 // Received a DELETE action on an entry not assigned to the NIC
1530 messages::resourceCannotBeDeleted(res);
1531 return false;
1532 }
1533 thisAddress.operation = AddrChange::Delete;
1534 }
1535 else
Ed Tanousbf648f72021-06-03 15:00:14 -07001536 {
1537 std::optional<std::string> address;
Ed Tanousbf648f72021-06-03 15:00:14 -07001538 std::optional<std::string> gateway;
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001539 std::optional<std::string> subnetMask;
1540 if (!obj->empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001541 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001542 if (!json_util::readJsonObject( //
1543 *obj, res, //
1544 "Address", address, //
1545 "Gateway", gateway, //
1546 "SubnetMask", subnetMask //
1547 ))
1548 {
1549 messages::propertyValueFormatError(res, *obj, pathString);
1550 return false;
1551 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001552 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001553 // Find the address/subnet/gateway values. Any values that are
1554 // not explicitly provided are assumed to be unmodified from the
1555 // current state of the interface. Merge existing state into the
1556 // current request.
Ed Tanousbf648f72021-06-03 15:00:14 -07001557 if (address)
1558 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001559 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001560 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001561 messages::propertyValueFormatError(res, *address,
Ed Tanousbf648f72021-06-03 15:00:14 -07001562 pathString + "/Address");
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001563 return false;
Ed Tanousbf648f72021-06-03 15:00:14 -07001564 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001565 thisAddress.operation = AddrChange::Update;
1566 thisAddress.address = *address;
Ed Tanousbf648f72021-06-03 15:00:14 -07001567 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001568 else if (thisAddress.existingDbusId.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001569 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001570 messages::propertyMissing(res, pathString + "/Address");
1571 return false;
Ed Tanousbf648f72021-06-03 15:00:14 -07001572 }
1573 else
1574 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001575 thisAddress.address = nicIpEntry->address;
Ed Tanousbf648f72021-06-03 15:00:14 -07001576 }
1577
1578 if (subnetMask)
1579 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001580 uint8_t prefixLength = 0;
Ed Tanous033f1e42022-08-15 09:47:37 -07001581 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1582 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001583 {
1584 messages::propertyValueFormatError(
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001585 res, *subnetMask, pathString + "/SubnetMask");
1586 return false;
Ed Tanousbf648f72021-06-03 15:00:14 -07001587 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001588 thisAddress.prefixLength = prefixLength;
1589 thisAddress.operation = AddrChange::Update;
Ed Tanousbf648f72021-06-03 15:00:14 -07001590 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001591 else if (thisAddress.existingDbusId.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001592 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001593 messages::propertyMissing(res, pathString + "/SubnetMask");
1594 return false;
Ed Tanousbf648f72021-06-03 15:00:14 -07001595 }
1596 else
1597 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001598 uint8_t prefixLength = 0;
1599 // Ignore return code. It came from internal, it's it's invalid
1600 // nothing we can do
1601 ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1602 &prefixLength);
Ed Tanousbf648f72021-06-03 15:00:14 -07001603
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001604 thisAddress.prefixLength = prefixLength;
1605 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001606 if (gateway)
1607 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001608 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001609 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001610 messages::propertyValueFormatError(res, *gateway,
Ed Tanousbf648f72021-06-03 15:00:14 -07001611 pathString + "/Gateway");
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001612 return false;
Ed Tanousbf648f72021-06-03 15:00:14 -07001613 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001614 thisAddress.operation = AddrChange::Update;
1615 thisAddress.gateway = *gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001616 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001617 else if (thisAddress.existingDbusId.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001618 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001619 // Default to null gateway
1620 gateway = "";
Ed Tanousbf648f72021-06-03 15:00:14 -07001621 }
1622 else
1623 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001624 thisAddress.gateway = nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001625 }
1626
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001627 // Changing gateway from existing
1628 if (!thisAddress.gateway.empty() &&
1629 thisAddress.gateway != "0.0.0.0")
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001630 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001631 if (!gatewayOut.empty() && gatewayOut != thisAddress.gateway)
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001632 {
1633 // A NIC can only have a single active gateway value.
1634 // If any gateway in the array of static addresses
1635 // mismatch the PATCH is in error.
1636 std::string arg1 = pathString + "/Gateway";
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001637 std::string arg2 = lastGatewayPath + "/Gateway";
1638 messages::propertyValueConflict(res, arg1, arg2);
1639 return false;
1640 }
1641 gatewayOut = thisAddress.gateway;
1642 lastGatewayPath = pathString;
1643 }
1644 }
1645 nicIpEntry++;
1646 nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend());
1647 entryIdx++;
1648 }
1649
1650 // Delete the remaining IPs
1651 while (nicIpEntry != ipv4Data.cend())
1652 {
1653 AddressPatch& thisAddress = addressesOut.emplace_back();
1654 thisAddress.operation = AddrChange::Delete;
1655 thisAddress.existingDbusId = nicIpEntry->id;
1656 nicIpEntry++;
1657 nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend());
1658 }
1659
1660 return true;
1661}
1662
1663inline void handleIPv4StaticPatch(
1664 const std::string& ifaceId,
1665 std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1666 const EthernetInterfaceData& ethData,
1667 const std::vector<IPv4AddressData>& ipv4Data,
1668 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1669{
1670 std::vector<AddressPatch> addresses;
1671 std::string gatewayOut;
1672 if (!parseAddresses(input, ipv4Data, asyncResp->res, addresses, gatewayOut))
1673 {
1674 return;
1675 }
1676
1677 // If we're setting the gateway to something new, delete the
1678 // existing so we won't conflict
1679 if (!ethData.defaultGateway.empty() && ethData.defaultGateway != gatewayOut)
1680 {
1681 updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1682 }
1683
1684 for (const AddressPatch& address : addresses)
1685 {
1686 switch (address.operation)
1687 {
1688 case AddrChange::Delete:
1689 {
1690 BMCWEB_LOG_ERROR("Deleting id {} on interface {}",
1691 address.existingDbusId, ifaceId);
1692 deleteIPAddress(ifaceId, address.existingDbusId, asyncResp);
1693 }
1694 break;
1695 case AddrChange::Update:
1696 {
1697 // Update is a delete then a recreate
1698 // Only need to update if there is an existing ip at this index
1699 if (!address.existingDbusId.empty())
1700 {
1701 BMCWEB_LOG_ERROR("Deleting id {} on interface {}",
1702 address.existingDbusId, ifaceId);
1703 deleteAndCreateIPAddress(
1704 IpVersion::IpV4, ifaceId, address.existingDbusId,
1705 address.prefixLength, address.address, address.gateway,
1706 asyncResp);
1707 }
1708 else
1709 {
1710 // Otherwise, just create a new one
1711 BMCWEB_LOG_ERROR(
1712 "creating ip {} prefix {} gateway {} on interface {}",
1713 address.address, address.prefixLength, address.gateway,
1714 ifaceId);
1715 createIPv4(ifaceId, address.prefixLength, address.gateway,
1716 address.address, asyncResp);
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001717 }
1718 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001719 break;
1720 default:
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001721 {
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001722 // Leave alone
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001723 }
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001724 break;
1725 }
1726 }
Johnathan Mantey743eb1c2024-04-03 12:05:57 -07001727
Ed Tanous6e1a52f2024-11-15 19:44:16 -08001728 // now update to the new gateway.
1729 // Default gateway is already empty, so no need to update if we're clearing
1730 if (!gatewayOut.empty() && ethData.defaultGateway != gatewayOut)
1731 {
1732 updateIPv4DefaultGateway(ifaceId, gatewayOut, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001733 }
1734}
1735
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001736inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001737 const std::string& ifaceId,
1738 const std::vector<std::string>& updatedStaticNameServers,
1739 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1740{
Asmitha Karunanithi1847f2a2024-03-26 22:03:48 -05001741 setDbusProperty(
Ginu Georgee93abac2024-06-14 17:35:27 +05301742 asyncResp, "StaticNameServers", "xyz.openbmc_project.Network",
Asmitha Karunanithi1847f2a2024-03-26 22:03:48 -05001743 sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1744 ifaceId,
George Liu9ae226f2023-06-21 17:56:46 +08001745 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
Ginu Georgee93abac2024-06-14 17:35:27 +05301746 updatedStaticNameServers);
Ed Tanousbf648f72021-06-03 15:00:14 -07001747}
1748
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001749inline void handleIPv6StaticAddressesPatch(
Ed Tanous3dfed532024-03-06 14:41:27 -08001750 const std::string& ifaceId,
1751 std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
Ed Tanous77179532023-02-28 10:45:28 -08001752 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001753 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1754{
Ed Tanousbf648f72021-06-03 15:00:14 -07001755 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001756 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001757 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
Ed Tanous3dfed532024-03-06 14:41:27 -08001758 for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
1759 input)
Ed Tanousbf648f72021-06-03 15:00:14 -07001760 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001761 std::string pathString =
1762 "IPv6StaticAddresses/" + std::to_string(entryIdx);
Ed Tanous3dfed532024-03-06 14:41:27 -08001763 nlohmann::json::object_t* obj =
1764 std::get_if<nlohmann::json::object_t>(&thisJson);
1765 if (obj != nullptr && !obj->empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001766 {
1767 std::optional<std::string> address;
1768 std::optional<uint8_t> prefixLength;
Ed Tanous3dfed532024-03-06 14:41:27 -08001769 nlohmann::json::object_t thisJsonCopy = *obj;
Myung Baeafc474a2024-10-09 00:53:29 -07001770 if (!json_util::readJsonObject( //
1771 thisJsonCopy, asyncResp->res, //
1772 "Address", address, //
1773 "PrefixLength", prefixLength //
1774 ))
Ed Tanousbf648f72021-06-03 15:00:14 -07001775 {
Ed Tanous3dfed532024-03-06 14:41:27 -08001776 messages::propertyValueFormatError(asyncResp->res, thisJsonCopy,
Ed Tanousf818b042022-06-27 13:17:35 -07001777 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001778 return;
1779 }
1780
Ed Tanousbf648f72021-06-03 15:00:14 -07001781 // Find the address and prefixLength values. Any values that are
1782 // not explicitly provided are assumed to be unmodified from the
1783 // current state of the interface. Merge existing state into the
1784 // current request.
Ed Tanousd547d8d2024-03-16 18:04:41 -07001785 if (!address)
Ed Tanousbf648f72021-06-03 15:00:14 -07001786 {
Ed Tanousd547d8d2024-03-16 18:04:41 -07001787 if (nicIpEntry == ipv6Data.end())
1788 {
1789 messages::propertyMissing(asyncResp->res,
1790 pathString + "/Address");
1791 return;
1792 }
1793 address = nicIpEntry->address;
Ed Tanousbf648f72021-06-03 15:00:14 -07001794 }
1795
Ed Tanousd547d8d2024-03-16 18:04:41 -07001796 if (!prefixLength)
Ed Tanousbf648f72021-06-03 15:00:14 -07001797 {
Ed Tanousd547d8d2024-03-16 18:04:41 -07001798 if (nicIpEntry == ipv6Data.end())
1799 {
1800 messages::propertyMissing(asyncResp->res,
1801 pathString + "/PrefixLength");
1802 return;
1803 }
1804 prefixLength = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001805 }
1806
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001807 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001808 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001809 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
Ed Tanousd547d8d2024-03-16 18:04:41 -07001810 nicIpEntry->id, *prefixLength,
1811 *address, "", asyncResp);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001812 nicIpEntry =
1813 getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001814 }
1815 else
1816 {
Ed Tanousd547d8d2024-03-16 18:04:41 -07001817 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001818 }
1819 entryIdx++;
1820 }
1821 else
1822 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001823 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001824 {
1825 // Requesting a DELETE/DO NOT MODIFY action for an item
1826 // that isn't present on the eth(n) interface. Input JSON is
1827 // in error, so bail out.
Ed Tanous3dfed532024-03-06 14:41:27 -08001828 if (obj == nullptr)
Ed Tanousbf648f72021-06-03 15:00:14 -07001829 {
1830 messages::resourceCannotBeDeleted(asyncResp->res);
1831 return;
1832 }
Ed Tanous3dfed532024-03-06 14:41:27 -08001833 messages::propertyValueFormatError(asyncResp->res, *obj,
Ed Tanousf818b042022-06-27 13:17:35 -07001834 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001835 return;
1836 }
1837
Ed Tanous3dfed532024-03-06 14:41:27 -08001838 if (obj == nullptr)
Ed Tanousbf648f72021-06-03 15:00:14 -07001839 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001840 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001841 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001842 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001843 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001844 nicIpEntry =
1845 getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001846 }
1847 entryIdx++;
1848 }
1849 }
1850}
1851
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001852inline std::string extractParentInterfaceName(const std::string& ifaceId)
1853{
1854 std::size_t pos = ifaceId.find('_');
1855 return ifaceId.substr(0, pos);
1856}
1857
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001858inline void parseInterfaceData(
1859 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1860 const std::string& ifaceId, const EthernetInterfaceData& ethData,
1861 const std::vector<IPv4AddressData>& ipv4Data,
1862 const std::vector<IPv6AddressData>& ipv6Data,
1863 const std::vector<StaticGatewayData>& ipv6GatewayData)
Ed Tanousbf648f72021-06-03 15:00:14 -07001864{
Ed Tanousbf648f72021-06-03 15:00:14 -07001865 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1866 jsonResponse["Id"] = ifaceId;
Ed Tanous253f11b2024-05-16 09:38:31 -07001867 jsonResponse["@odata.id"] =
1868 boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
1869 BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001870 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1871
Ed Tanousbf648f72021-06-03 15:00:14 -07001872 if (ethData.nicEnabled)
1873 {
Ed Tanous539d8c62024-06-19 14:38:27 -07001874 jsonResponse["LinkStatus"] =
1875 ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp
1876 : ethernet_interface::LinkStatus::LinkDown;
1877 jsonResponse["Status"]["State"] = resource::State::Enabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001878 }
1879 else
1880 {
Ed Tanous539d8c62024-06-19 14:38:27 -07001881 jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink;
1882 jsonResponse["Status"]["State"] = resource::State::Disabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001883 }
1884
Ed Tanousbf648f72021-06-03 15:00:14 -07001885 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301886 jsonResponse["MTUSize"] = ethData.mtuSize;
Asmitha Karunanithi4652c642024-07-30 11:35:53 -05001887 if (ethData.macAddress)
1888 {
1889 jsonResponse["MACAddress"] = *ethData.macAddress;
1890 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001891 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001892 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
Jishnu CMe4588152023-05-11 00:04:40 -05001893 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1894 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
Ravi Tejade9ad762024-06-03 02:00:15 -05001895 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001896 jsonResponse["DHCPv6"]["OperatingMode"] =
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001897 translateDhcpEnabledToBool(ethData.dhcpEnabled, false)
1898 ? "Enabled"
1899 : "Disabled";
Jishnu CMe4588152023-05-11 00:04:40 -05001900 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1901 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
Ravi Tejade9ad762024-06-03 02:00:15 -05001902 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001903 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1904 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001905
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001906 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001907 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001908 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001909
1910 // When domain name is empty then it means, that it is a network
1911 // without domain names, and the host name itself must be treated as
1912 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001913 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001914 if (!ethData.domainnames.empty())
1915 {
1916 fqdn += "." + ethData.domainnames[0];
1917 }
1918 jsonResponse["FQDN"] = fqdn;
1919 }
1920
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001921 if (ethData.vlanId)
1922 {
Ed Tanous539d8c62024-06-19 14:38:27 -07001923 jsonResponse["EthernetInterfaceType"] =
1924 ethernet_interface::EthernetDeviceType::Virtual;
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001925 jsonResponse["VLAN"]["VLANEnable"] = true;
1926 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1927 jsonResponse["VLAN"]["Tagged"] = true;
1928
1929 nlohmann::json::array_t relatedInterfaces;
1930 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1931 parentInterface["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07001932 boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
1933 BMCWEB_REDFISH_MANAGER_URI_NAME,
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001934 extractParentInterfaceName(ifaceId));
1935 jsonResponse["Links"]["RelatedInterfaces"] =
1936 std::move(relatedInterfaces);
1937 }
1938 else
1939 {
Ed Tanous539d8c62024-06-19 14:38:27 -07001940 jsonResponse["EthernetInterfaceType"] =
1941 ethernet_interface::EthernetDeviceType::Physical;
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001942 }
1943
Ed Tanousbf648f72021-06-03 15:00:14 -07001944 jsonResponse["NameServers"] = ethData.nameServers;
1945 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1946
1947 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1948 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1949 ipv4Array = nlohmann::json::array();
1950 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001951 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001952 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001953 std::string gatewayStr = ipv4Config.gateway;
1954 if (gatewayStr.empty())
1955 {
1956 gatewayStr = "0.0.0.0";
1957 }
Ed Tanous14766872022-03-15 10:44:42 -07001958 nlohmann::json::object_t ipv4;
1959 ipv4["AddressOrigin"] = ipv4Config.origin;
1960 ipv4["SubnetMask"] = ipv4Config.netmask;
1961 ipv4["Address"] = ipv4Config.address;
1962 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001963
Ed Tanousbf648f72021-06-03 15:00:14 -07001964 if (ipv4Config.origin == "Static")
1965 {
Ed Tanous14766872022-03-15 10:44:42 -07001966 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001967 }
Ed Tanous14766872022-03-15 10:44:42 -07001968
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001969 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001970 }
1971
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001972 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001973 if (ipv6GatewayStr.empty())
1974 {
1975 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1976 }
1977
1978 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1979
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001980 nlohmann::json::array_t ipv6StaticGatewayArray;
1981 for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1982 {
1983 nlohmann::json::object_t ipv6Gateway;
1984 ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
Sunitha Harishce73d5c2023-04-07 06:46:49 -05001985 ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1986 }
1987 jsonResponse["IPv6StaticDefaultGateways"] =
1988 std::move(ipv6StaticGatewayArray);
1989
Ed Tanousbf648f72021-06-03 15:00:14 -07001990 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1991 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1992 ipv6Array = nlohmann::json::array();
1993 ipv6StaticArray = nlohmann::json::array();
1994 nlohmann::json& ipv6AddrPolicyTable =
1995 jsonResponse["IPv6AddressPolicyTable"];
1996 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001997 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001998 {
Ed Tanous14766872022-03-15 10:44:42 -07001999 nlohmann::json::object_t ipv6;
2000 ipv6["Address"] = ipv6Config.address;
2001 ipv6["PrefixLength"] = ipv6Config.prefixLength;
2002 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05002003
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002004 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07002005 if (ipv6Config.origin == "Static")
2006 {
Ed Tanous14766872022-03-15 10:44:42 -07002007 nlohmann::json::object_t ipv6Static;
2008 ipv6Static["Address"] = ipv6Config.address;
2009 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002010 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07002011 }
2012 }
2013}
2014
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002015inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2016 const std::string& ifaceId,
2017 const boost::system::error_code& ec,
2018 const sdbusplus::message_t& m)
2019{
2020 if (!ec)
2021 {
2022 return;
2023 }
2024 const sd_bus_error* dbusError = m.get_error();
2025 if (dbusError == nullptr)
2026 {
2027 messages::internalError(asyncResp->res);
2028 return;
2029 }
Ed Tanous62598e32023-07-17 17:06:25 -07002030 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002031
2032 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
2033 dbusError->name)
2034 {
2035 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2036 ifaceId);
2037 return;
2038 }
2039 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
2040 dbusError->name)
2041 {
2042 messages::resourceCannotBeDeleted(asyncResp->res);
2043 return;
2044 }
2045 messages::internalError(asyncResp->res);
2046}
2047
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002048inline void afterVlanCreate(
2049 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2050 const std::string& parentInterfaceUri, const std::string& vlanInterface,
2051 const boost::system::error_code& ec, const sdbusplus::message_t& m
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002052
2053)
2054{
2055 if (ec)
2056 {
2057 const sd_bus_error* dbusError = m.get_error();
2058 if (dbusError == nullptr)
2059 {
2060 messages::internalError(asyncResp->res);
2061 return;
2062 }
Ed Tanous62598e32023-07-17 17:06:25 -07002063 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002064
2065 if (std::string_view(
2066 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2067 dbusError->name)
2068 {
2069 messages::propertyValueNotInList(
2070 asyncResp->res, parentInterfaceUri,
2071 "Links/RelatedInterfaces/0/@odata.id");
2072 return;
2073 }
2074 if (std::string_view(
2075 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2076 dbusError->name)
2077 {
2078 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2079 "Id", vlanInterface);
2080 return;
2081 }
2082 messages::internalError(asyncResp->res);
2083 return;
2084 }
2085
Ed Tanous253f11b2024-05-16 09:38:31 -07002086 const boost::urls::url vlanInterfaceUri =
2087 boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2088 BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002089 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2090}
2091
Ed Tanousbf648f72021-06-03 15:00:14 -07002092inline void requestEthernetInterfacesRoutes(App& app)
2093{
Ed Tanous253f11b2024-05-16 09:38:31 -07002094 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07002095 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07002096 .methods(boost::beast::http::verb::get)(
2097 [&app](const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002098 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2099 const std::string& managerId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002100 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2101 {
2102 return;
2103 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002104
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002105 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2106 {
2107 messages::resourceNotFound(asyncResp->res, "Manager",
2108 managerId);
2109 return;
2110 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002111
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002112 asyncResp->res.jsonValue["@odata.type"] =
2113 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2114 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2115 "/redfish/v1/Managers/{}/EthernetInterfaces",
2116 BMCWEB_REDFISH_MANAGER_URI_NAME);
2117 asyncResp->res.jsonValue["Name"] =
2118 "Ethernet Network Interface Collection";
2119 asyncResp->res.jsonValue["Description"] =
2120 "Collection of EthernetInterfaces for this Manager";
2121
2122 // Get eth interface list, and call the below callback for JSON
2123 // preparation
2124 getEthernetIfaceList(
2125 [asyncResp](const bool& success,
2126 const std::vector<std::string>& ifaceList) {
2127 if (!success)
2128 {
2129 messages::internalError(asyncResp->res);
2130 return;
2131 }
2132
2133 nlohmann::json& ifaceArray =
2134 asyncResp->res.jsonValue["Members"];
2135 ifaceArray = nlohmann::json::array();
2136 for (const std::string& ifaceItem : ifaceList)
2137 {
2138 nlohmann::json::object_t iface;
2139 iface["@odata.id"] = boost::urls::format(
2140 "/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2141 BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem);
2142 ifaceArray.push_back(std::move(iface));
2143 }
2144
2145 asyncResp->res.jsonValue["Members@odata.count"] =
2146 ifaceArray.size();
2147 asyncResp->res.jsonValue["@odata.id"] =
2148 boost::urls::format(
2149 "/redfish/v1/Managers/{}/EthernetInterfaces",
Ed Tanous253f11b2024-05-16 09:38:31 -07002150 BMCWEB_REDFISH_MANAGER_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002151 });
2152 });
Johnathan Mantey01784822019-06-18 12:44:21 -07002153
Ed Tanous253f11b2024-05-16 09:38:31 -07002154 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002155 .privileges(redfish::privileges::postEthernetInterfaceCollection)
2156 .methods(boost::beast::http::verb::post)(
2157 [&app](const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002158 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2159 const std::string& managerId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002160 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2161 {
2162 return;
2163 }
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002164
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002165 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2166 {
2167 messages::resourceNotFound(asyncResp->res, "Manager",
2168 managerId);
2169 return;
2170 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002171
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002172 bool vlanEnable = false;
2173 uint32_t vlanId = 0;
2174 std::vector<nlohmann::json::object_t> relatedInterfaces;
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002175
Myung Baeafc474a2024-10-09 00:53:29 -07002176 if (!json_util::readJsonPatch( //
2177 req, asyncResp->res, //
2178 "Links/RelatedInterfaces", relatedInterfaces, //
2179 "VLAN/VLANEnable", vlanEnable, //
2180 "VLAN/VLANId", vlanId //
2181 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002182 {
2183 return;
2184 }
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002185
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002186 if (relatedInterfaces.size() != 1)
2187 {
2188 messages::arraySizeTooLong(asyncResp->res,
2189 "Links/RelatedInterfaces",
2190 relatedInterfaces.size());
2191 return;
2192 }
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002193
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002194 std::string parentInterfaceUri;
2195 if (!json_util::readJsonObject(relatedInterfaces[0],
2196 asyncResp->res, "@odata.id",
2197 parentInterfaceUri))
2198 {
2199 messages::propertyMissing(
2200 asyncResp->res, "Links/RelatedInterfaces/0/@odata.id");
2201 return;
2202 }
2203 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002204
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002205 boost::system::result<boost::urls::url_view> parsedUri =
2206 boost::urls::parse_relative_ref(parentInterfaceUri);
2207 if (!parsedUri)
2208 {
2209 messages::propertyValueFormatError(
2210 asyncResp->res, parentInterfaceUri,
2211 "Links/RelatedInterfaces/0/@odata.id");
2212 return;
2213 }
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002214
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002215 std::string parentInterface;
2216 if (!crow::utility::readUrlSegments(
2217 *parsedUri, "redfish", "v1", "Managers", "bmc",
2218 "EthernetInterfaces", std::ref(parentInterface)))
2219 {
2220 messages::propertyValueNotInList(
2221 asyncResp->res, parentInterfaceUri,
2222 "Links/RelatedInterfaces/0/@odata.id");
2223 return;
2224 }
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002225
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002226 if (!vlanEnable)
2227 {
2228 // In OpenBMC implementation, VLANEnable cannot be false on
2229 // create
2230 messages::propertyValueIncorrect(
2231 asyncResp->res, "VLAN/VLANEnable", "false");
2232 return;
2233 }
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002234
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002235 std::string vlanInterface =
2236 parentInterface + "_" + std::to_string(vlanId);
2237 crow::connections::systemBus->async_method_call(
2238 [asyncResp, parentInterfaceUri,
2239 vlanInterface](const boost::system::error_code& ec,
2240 const sdbusplus::message_t& m) {
2241 afterVlanCreate(asyncResp, parentInterfaceUri,
2242 vlanInterface, ec, m);
2243 },
2244 "xyz.openbmc_project.Network",
2245 "/xyz/openbmc_project/network",
2246 "xyz.openbmc_project.Network.VLAN.Create", "VLAN",
2247 parentInterface, vlanId);
2248 });
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08002249
Ed Tanous253f11b2024-05-16 09:38:31 -07002250 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002251 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07002252 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002253 [&app](const crow::Request& req,
2254 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002255 const std::string& managerId, const std::string& ifaceId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002256 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2257 {
2258 return;
2259 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002260
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002261 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2262 {
2263 messages::resourceNotFound(asyncResp->res, "Manager",
2264 managerId);
2265 return;
2266 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002267
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002268 getEthernetIfaceData(
2269 ifaceId,
2270 [asyncResp, ifaceId](
2271 const bool& success,
2272 const EthernetInterfaceData& ethData,
2273 const std::vector<IPv4AddressData>& ipv4Data,
2274 const std::vector<IPv6AddressData>& ipv6Data,
2275 const std::vector<StaticGatewayData>& ipv6GatewayData) {
2276 if (!success)
2277 {
2278 // TODO(Pawel)consider distinguish between non
2279 // existing object, and other errors
2280 messages::resourceNotFound(
2281 asyncResp->res, "EthernetInterface", ifaceId);
2282 return;
2283 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002284
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002285 asyncResp->res.jsonValue["@odata.type"] =
2286 "#EthernetInterface.v1_9_0.EthernetInterface";
2287 asyncResp->res.jsonValue["Name"] =
2288 "Manager Ethernet Interface";
2289 asyncResp->res.jsonValue["Description"] =
2290 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05302291
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002292 parseInterfaceData(asyncResp, ifaceId, ethData,
2293 ipv4Data, ipv6Data, ipv6GatewayData);
2294 });
2295 });
Johnathan Mantey01784822019-06-18 12:44:21 -07002296
Ed Tanous253f11b2024-05-16 09:38:31 -07002297 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002298 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07002299 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002300 [&app](const crow::Request& req,
2301 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002302 const std::string& managerId, const std::string& ifaceId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002303 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2304 {
2305 return;
2306 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002307
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002308 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2309 {
2310 messages::resourceNotFound(asyncResp->res, "Manager",
2311 managerId);
2312 return;
2313 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002314
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002315 std::optional<std::string> hostname;
2316 std::optional<std::string> fqdn;
2317 std::optional<std::string> macAddress;
2318 std::optional<std::string> ipv6DefaultGateway;
2319 std::optional<std::vector<
2320 std::variant<nlohmann::json::object_t, std::nullptr_t>>>
2321 ipv4StaticAddresses;
2322 std::optional<std::vector<
2323 std::variant<nlohmann::json::object_t, std::nullptr_t>>>
2324 ipv6StaticAddresses;
2325 std::optional<std::vector<
2326 std::variant<nlohmann::json::object_t, std::nullptr_t>>>
2327 ipv6StaticDefaultGateways;
2328 std::optional<std::vector<std::string>> staticNameServers;
2329 std::optional<bool> ipv6AutoConfigEnabled;
2330 std::optional<bool> interfaceEnabled;
2331 std::optional<size_t> mtuSize;
2332 DHCPParameters v4dhcpParms;
2333 DHCPParameters v6dhcpParms;
Myung Baeafc474a2024-10-09 00:53:29 -07002334
2335 if (!json_util::readJsonPatch( //
2336 req, asyncResp->res, //
2337 "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, //
2338 "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, //
2339 "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, //
2340 "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, //
2341 "DHCPv6/OperatingMode",
2342 v6dhcpParms.dhcpv6OperatingMode, //
2343 "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, //
2344 "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, //
2345 "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, //
2346 "FQDN", fqdn, //
2347 "HostName", hostname, //
2348 "InterfaceEnabled", interfaceEnabled, //
2349 "IPv4StaticAddresses", ipv4StaticAddresses, //
2350 "IPv6DefaultGateway", ipv6DefaultGateway, //
2351 "IPv6StaticAddresses", ipv6StaticAddresses, //
2352 "IPv6StaticDefaultGateways",
2353 ipv6StaticDefaultGateways, //
2354 "InterfaceEnabled", interfaceEnabled, //
2355 "MACAddress", macAddress, //
2356 "MTUSize", mtuSize, //
2357 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
2358 ipv6AutoConfigEnabled, //
2359 "StaticNameServers", staticNameServers //
2360 ))
2361 {
2362 return;
2363 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002364
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002365 // Get single eth interface data, and call the below callback
2366 // for JSON preparation
2367 getEthernetIfaceData(
2368 ifaceId,
2369 [asyncResp, ifaceId, hostname = std::move(hostname),
2370 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2371 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2372 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2373 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2374 ipv6StaticDefaultGateway =
2375 std::move(ipv6StaticDefaultGateways),
2376 staticNameServers = std::move(staticNameServers), mtuSize,
2377 ipv6AutoConfigEnabled,
2378 v4dhcpParms = std::move(v4dhcpParms),
2379 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2380 const bool success,
2381 const EthernetInterfaceData& ethData,
2382 const std::vector<IPv4AddressData>& ipv4Data,
2383 const std::vector<IPv6AddressData>& ipv6Data,
2384 const std::vector<StaticGatewayData>&
2385 ipv6GatewayData) mutable {
2386 if (!success)
2387 {
2388 // ... otherwise return error
2389 // TODO(Pawel)consider distinguish between non
2390 // existing object, and other errors
2391 messages::resourceNotFound(
2392 asyncResp->res, "EthernetInterface", ifaceId);
2393 return;
2394 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002395
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002396 handleDHCPPatch(ifaceId, ethData, v4dhcpParms,
2397 v6dhcpParms, asyncResp);
Tejas Patil35fb5312021-09-20 15:35:20 +05302398
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002399 if (hostname)
2400 {
2401 handleHostnamePatch(*hostname, asyncResp);
2402 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002403
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002404 if (ipv6AutoConfigEnabled)
2405 {
2406 handleSLAACAutoConfigPatch(
2407 ifaceId, *ipv6AutoConfigEnabled, asyncResp);
2408 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05002409
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002410 if (fqdn)
2411 {
2412 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2413 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002414
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002415 if (macAddress)
2416 {
2417 handleMACAddressPatch(ifaceId, *macAddress,
2418 asyncResp);
2419 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002420
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002421 if (ipv4StaticAddresses)
2422 {
2423 handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses,
2424 ethData, ipv4Data, asyncResp);
2425 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002426
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002427 if (staticNameServers)
2428 {
2429 handleStaticNameServersPatch(
2430 ifaceId, *staticNameServers, asyncResp);
2431 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002432
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002433 if (ipv6DefaultGateway)
2434 {
2435 messages::propertyNotWritable(asyncResp->res,
2436 "IPv6DefaultGateway");
2437 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002438
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002439 if (ipv6StaticAddresses)
2440 {
2441 handleIPv6StaticAddressesPatch(ifaceId,
2442 *ipv6StaticAddresses,
2443 ipv6Data, asyncResp);
2444 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002445
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002446 if (ipv6StaticDefaultGateway)
2447 {
2448 handleIPv6DefaultGateway(
2449 ifaceId, *ipv6StaticDefaultGateway,
2450 ipv6GatewayData, asyncResp);
2451 }
Sunitha Harishce73d5c2023-04-07 06:46:49 -05002452
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002453 if (interfaceEnabled)
2454 {
2455 setDbusProperty(
2456 asyncResp, "InterfaceEnabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302457 "xyz.openbmc_project.Network",
Ed Tanousd02aad32024-02-13 14:43:34 -08002458 sdbusplus::message::object_path(
2459 "/xyz/openbmc_project/network") /
2460 ifaceId,
2461 "xyz.openbmc_project.Network.EthernetInterface",
Ginu Georgee93abac2024-06-14 17:35:27 +05302462 "NICEnabled", *interfaceEnabled);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002463 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002464
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002465 if (mtuSize)
2466 {
2467 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2468 }
2469 });
2470 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002471
Ed Tanous253f11b2024-05-16 09:38:31 -07002472 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002473 .privileges(redfish::privileges::deleteEthernetInterface)
2474 .methods(boost::beast::http::verb::delete_)(
2475 [&app](const crow::Request& req,
2476 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002477 const std::string& managerId, const std::string& ifaceId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002478 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2479 {
2480 return;
2481 }
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002482
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002483 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2484 {
2485 messages::resourceNotFound(asyncResp->res, "Manager",
2486 managerId);
2487 return;
2488 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002489
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002490 crow::connections::systemBus->async_method_call(
2491 [asyncResp, ifaceId](const boost::system::error_code& ec,
2492 const sdbusplus::message_t& m) {
2493 afterDelete(asyncResp, ifaceId, ec, m);
2494 },
2495 "xyz.openbmc_project.Network",
2496 std::string("/xyz/openbmc_project/network/") + ifaceId,
2497 "xyz.openbmc_project.Object.Delete", "Delete");
2498 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002499}
2500
Ed Tanous1abe55e2018-09-05 08:30:59 -07002501} // namespace redfish