blob: 390efbcc36b5e5ea74a78950376febc9226c6d7d [file] [log] [blame]
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
21#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "error_messages.hpp"
24#include "health.hpp"
Ed Tanous2c5875a2023-05-15 09:56:06 -070025#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "query.hpp"
27#include "registries/privilege_registry.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070028#include "utils/ip_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "utils/json_utils.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070030
Ed Tanousef4c65b2023-04-24 15:28:50 -070031#include <boost/url/format.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
George Liu7a1dbc42022-12-07 16:03:22 +080033#include <array>
Ed Tanousa24526d2018-12-10 15:17:59 -080034#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070035#include <ranges>
Joshi-Mansiab6554f2020-03-10 18:33:36 +053036#include <regex>
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <string_view>
Ed Tanous77179532023-02-28 10:45:28 -080038#include <vector>
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010039
Ed Tanous1abe55e2018-09-05 08:30:59 -070040namespace redfish
41{
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010042
Ed Tanous4a0cb852018-10-15 07:55:04 -070043enum class LinkType
44{
45 Local,
46 Global
47};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010048
49/**
50 * Structure for keeping IPv4 data required by Redfish
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010051 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070052struct IPv4AddressData
53{
54 std::string id;
Ed Tanous4a0cb852018-10-15 07:55:04 -070055 std::string address;
56 std::string domain;
57 std::string gateway;
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 std::string netmask;
59 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080060 LinkType linktype{};
61 bool isActive{};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010062};
63
64/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -050065 * Structure for keeping IPv6 data required by Redfish
66 */
67struct IPv6AddressData
68{
69 std::string id;
70 std::string address;
71 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080072 uint8_t prefixLength = 0;
Ravi Tejae48c0fc2019-04-16 08:37:20 -050073};
74/**
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010075 * Structure for keeping basic single Ethernet Interface information
76 * available from DBus
77 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070078struct EthernetInterfaceData
79{
Ed Tanous4a0cb852018-10-15 07:55:04 -070080 uint32_t speed;
Tejas Patil35fb5312021-09-20 15:35:20 +053081 size_t mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080082 bool autoNeg;
83 bool dnsEnabled;
84 bool ntpEnabled;
85 bool hostNameEnabled;
Johnathan Manteyaa05fb22020-01-08 12:08:44 -080086 bool linkUp;
Johnathan Manteyeeedda22019-10-29 16:09:52 -070087 bool nicEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -050088 bool ipv6AcceptRa;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080089 std::string dhcpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -070090 std::string operatingMode;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080091 std::string hostName;
92 std::string defaultGateway;
93 std::string ipv6DefaultGateway;
94 std::string macAddress;
Jiaqing Zhao17e22022022-04-14 18:58:06 +080095 std::optional<uint32_t> vlanId;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -050096 std::vector<std::string> nameServers;
97 std::vector<std::string> staticNameServers;
Jennifer Leed24bfc72019-03-05 13:03:37 -080098 std::vector<std::string> domainnames;
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010099};
100
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700101struct DHCPParameters
102{
103 std::optional<bool> dhcpv4Enabled;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800104 std::optional<bool> useDnsServers;
105 std::optional<bool> useNtpServers;
106 std::optional<bool> useDomainName;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700107 std::optional<std::string> dhcpv6OperatingMode;
108};
109
Ed Tanous4a0cb852018-10-15 07:55:04 -0700110// Helper function that changes bits netmask notation (i.e. /24)
111// into full dot notation
112inline std::string getNetmask(unsigned int bits)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700113{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700114 uint32_t value = 0xffffffff << (32 - bits);
115 std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
116 std::to_string((value >> 16) & 0xff) + "." +
117 std::to_string((value >> 8) & 0xff) + "." +
118 std::to_string(value & 0xff);
119 return netmask;
120}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100121
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800122inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700123 bool isIPv4)
124{
125 if (isIPv4)
126 {
127 return (
128 (inputDHCP ==
129 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
130 (inputDHCP ==
131 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
132 }
133 return ((inputDHCP ==
134 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
135 (inputDHCP ==
136 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
137}
138
Ed Tanous2c70f802020-09-28 14:29:23 -0700139inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700140{
141 if (isIPv4 && isIPv6)
142 {
143 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
144 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700145 if (isIPv4)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700146 {
147 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
148 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700149 if (isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700150 {
151 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
152 }
153 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
154}
155
Ed Tanous4a0cb852018-10-15 07:55:04 -0700156inline std::string
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500157 translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700158 bool isIPv4)
159{
160 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700161 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700162 return "Static";
163 }
164 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
165 {
166 if (isIPv4)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700167 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700168 return "IPv4LinkLocal";
169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700170 return "LinkLocal";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700171 }
172 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
173 {
174 if (isIPv4)
175 {
176 return "DHCP";
177 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700178 return "DHCPv6";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700179 }
180 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
181 {
182 return "SLAAC";
183 }
184 return "";
185}
186
Ed Tanous02cad962022-06-30 16:50:15 -0700187inline bool extractEthernetInterfaceData(
188 const std::string& ethifaceId,
189 const dbus::utility::ManagedObjectType& dbusData,
190 EthernetInterfaceData& ethData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700191{
Ed Tanous4c9afe42019-05-03 16:59:57 -0700192 bool idFound = false;
Ed Tanous02cad962022-06-30 16:50:15 -0700193 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700194 {
Ed Tanous02cad962022-06-30 16:50:15 -0700195 for (const auto& ifacePair : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700196 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000197 if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700198 {
Ed Tanous4c9afe42019-05-03 16:59:57 -0700199 idFound = true;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700200 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700201 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500202 for (const auto& propertyPair : ifacePair.second)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700203 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700204 if (propertyPair.first == "MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700205 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500206 const std::string* mac =
Ed Tanousabf2add2019-01-22 16:40:12 -0800207 std::get_if<std::string>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700208 if (mac != nullptr)
209 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800210 ethData.macAddress = *mac;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700211 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700212 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700213 }
214 }
215 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
216 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500217 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700218 {
219 if (propertyPair.first == "Id")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700220 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500221 const uint32_t* id =
Ed Tanousabf2add2019-01-22 16:40:12 -0800222 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700223 if (id != nullptr)
224 {
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800225 ethData.vlanId = *id;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700226 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700228 }
229 }
230 else if (ifacePair.first ==
231 "xyz.openbmc_project.Network.EthernetInterface")
232 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500233 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700234 {
235 if (propertyPair.first == "AutoNeg")
236 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700237 const bool* autoNeg =
Ed Tanousabf2add2019-01-22 16:40:12 -0800238 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700239 if (autoNeg != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700240 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800241 ethData.autoNeg = *autoNeg;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700242 }
243 }
244 else if (propertyPair.first == "Speed")
245 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500246 const uint32_t* speed =
Ed Tanousabf2add2019-01-22 16:40:12 -0800247 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700248 if (speed != nullptr)
249 {
250 ethData.speed = *speed;
251 }
252 }
Tejas Patil35fb5312021-09-20 15:35:20 +0530253 else if (propertyPair.first == "MTU")
254 {
Anthony3e7a8da2023-10-23 14:22:43 +0800255 const size_t* mtuSize =
256 std::get_if<size_t>(&propertyPair.second);
Tejas Patil35fb5312021-09-20 15:35:20 +0530257 if (mtuSize != nullptr)
258 {
259 ethData.mtuSize = *mtuSize;
260 }
261 }
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800262 else if (propertyPair.first == "LinkUp")
263 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500264 const bool* linkUp =
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800265 std::get_if<bool>(&propertyPair.second);
266 if (linkUp != nullptr)
267 {
268 ethData.linkUp = *linkUp;
269 }
270 }
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700271 else if (propertyPair.first == "NICEnabled")
272 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500273 const bool* nicEnabled =
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700274 std::get_if<bool>(&propertyPair.second);
275 if (nicEnabled != nullptr)
276 {
277 ethData.nicEnabled = *nicEnabled;
278 }
279 }
Ravi Tejab10d8db2022-05-24 09:04:12 -0500280 else if (propertyPair.first == "IPv6AcceptRA")
281 {
282 const bool* ipv6AcceptRa =
283 std::get_if<bool>(&propertyPair.second);
284 if (ipv6AcceptRa != nullptr)
285 {
286 ethData.ipv6AcceptRa = *ipv6AcceptRa;
287 }
288 }
RAJESWARAN THILLAIGOVINDANf85837b2019-04-04 05:18:53 -0500289 else if (propertyPair.first == "Nameservers")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700290 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500291 const std::vector<std::string>* nameservers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500292 std::get_if<std::vector<std::string>>(
Ed Tanous029573d2019-02-01 10:57:49 -0800293 &propertyPair.second);
294 if (nameservers != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700295 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700296 ethData.nameServers = *nameservers;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500297 }
298 }
299 else if (propertyPair.first == "StaticNameServers")
300 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500301 const std::vector<std::string>* staticNameServers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500302 std::get_if<std::vector<std::string>>(
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500303 &propertyPair.second);
304 if (staticNameServers != nullptr)
305 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700306 ethData.staticNameServers = *staticNameServers;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700307 }
308 }
manojkiraneda2a133282019-02-19 13:09:43 +0530309 else if (propertyPair.first == "DHCPEnabled")
310 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700311 const std::string* dhcpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700312 std::get_if<std::string>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700313 if (dhcpEnabled != nullptr)
manojkiraneda2a133282019-02-19 13:09:43 +0530314 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800315 ethData.dhcpEnabled = *dhcpEnabled;
manojkiraneda2a133282019-02-19 13:09:43 +0530316 }
317 }
Jennifer Leed24bfc72019-03-05 13:03:37 -0800318 else if (propertyPair.first == "DomainName")
319 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500320 const std::vector<std::string>* domainNames =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500321 std::get_if<std::vector<std::string>>(
Jennifer Leed24bfc72019-03-05 13:03:37 -0800322 &propertyPair.second);
323 if (domainNames != nullptr)
324 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700325 ethData.domainnames = *domainNames;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800326 }
327 }
Ravi Teja9010ec22019-08-01 23:30:25 -0500328 else if (propertyPair.first == "DefaultGateway")
329 {
330 const std::string* defaultGateway =
331 std::get_if<std::string>(&propertyPair.second);
332 if (defaultGateway != nullptr)
333 {
334 std::string defaultGatewayStr = *defaultGateway;
335 if (defaultGatewayStr.empty())
336 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800337 ethData.defaultGateway = "0.0.0.0";
Ravi Teja9010ec22019-08-01 23:30:25 -0500338 }
339 else
340 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800341 ethData.defaultGateway = defaultGatewayStr;
Ravi Teja9010ec22019-08-01 23:30:25 -0500342 }
343 }
344 }
345 else if (propertyPair.first == "DefaultGateway6")
346 {
347 const std::string* defaultGateway6 =
348 std::get_if<std::string>(&propertyPair.second);
349 if (defaultGateway6 != nullptr)
350 {
351 std::string defaultGateway6Str =
352 *defaultGateway6;
353 if (defaultGateway6Str.empty())
354 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800355 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500356 "0:0:0:0:0:0:0:0";
357 }
358 else
359 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800360 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500361 defaultGateway6Str;
362 }
363 }
364 }
Ed Tanous029573d2019-02-01 10:57:49 -0800365 }
366 }
367 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700368
Jian Zhang1e3f85e2022-12-13 13:50:35 +0800369 if (objpath.first == "/xyz/openbmc_project/network/dhcp")
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700370 {
371 if (ifacePair.first ==
372 "xyz.openbmc_project.Network.DHCPConfiguration")
373 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500374 for (const auto& propertyPair : ifacePair.second)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700375 {
376 if (propertyPair.first == "DNSEnabled")
377 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700378 const bool* dnsEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700379 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700380 if (dnsEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700381 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800382 ethData.dnsEnabled = *dnsEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700383 }
384 }
385 else if (propertyPair.first == "NTPEnabled")
386 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700387 const bool* ntpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700388 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700389 if (ntpEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700390 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800391 ethData.ntpEnabled = *ntpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700392 }
393 }
394 else if (propertyPair.first == "HostNameEnabled")
395 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700396 const bool* hostNameEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700397 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700398 if (hostNameEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700399 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800400 ethData.hostNameEnabled = *hostNameEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700401 }
402 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700403 }
404 }
405 }
Ed Tanous029573d2019-02-01 10:57:49 -0800406 // System configuration shows up in the global namespace, so no need
407 // to check eth number
408 if (ifacePair.first ==
409 "xyz.openbmc_project.Network.SystemConfiguration")
410 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500411 for (const auto& propertyPair : ifacePair.second)
Ed Tanous029573d2019-02-01 10:57:49 -0800412 {
413 if (propertyPair.first == "HostName")
414 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500415 const std::string* hostname =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500416 std::get_if<std::string>(&propertyPair.second);
Ed Tanous029573d2019-02-01 10:57:49 -0800417 if (hostname != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700418 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800419 ethData.hostName = *hostname;
Ed Tanous029573d2019-02-01 10:57:49 -0800420 }
421 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700422 }
423 }
424 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700425 }
Ed Tanous4c9afe42019-05-03 16:59:57 -0700426 return idFound;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700427}
428
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500429// Helper function that extracts data for single ethernet ipv6 address
Ed Tanous77179532023-02-28 10:45:28 -0800430inline void extractIPV6Data(const std::string& ethifaceId,
431 const dbus::utility::ManagedObjectType& dbusData,
432 std::vector<IPv6AddressData>& ipv6Config)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500433{
Patrick Williams89492a12023-05-10 07:51:34 -0500434 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
435 ethifaceId;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500436
437 // Since there might be several IPv6 configurations aligned with
438 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000439 for (const auto& objpath : dbusData)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500440 {
441 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800442 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500443 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800444 for (const auto& interface : objpath.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500445 {
446 if (interface.first == "xyz.openbmc_project.Network.IP")
447 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700448 auto type = std::ranges::find_if(interface.second,
449 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800450 return property.first == "Type";
451 });
452 if (type == interface.second.end())
453 {
454 continue;
455 }
456
457 const std::string* typeStr =
458 std::get_if<std::string>(&type->second);
459
460 if (typeStr == nullptr ||
461 (*typeStr !=
462 "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
463 {
464 continue;
465 }
466
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500467 // Instance IPv6AddressData structure, and set as
468 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800469 IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700470 ipv6Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800471 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800472 for (const auto& property : interface.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500473 {
474 if (property.first == "Address")
475 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500476 const std::string* address =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500477 std::get_if<std::string>(&property.second);
478 if (address != nullptr)
479 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700480 ipv6Address.address = *address;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500481 }
482 }
483 else if (property.first == "Origin")
484 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500485 const std::string* origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500486 std::get_if<std::string>(&property.second);
487 if (origin != nullptr)
488 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700489 ipv6Address.origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500490 translateAddressOriginDbusToRedfish(*origin,
491 false);
492 }
493 }
494 else if (property.first == "PrefixLength")
495 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500496 const uint8_t* prefix =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500497 std::get_if<uint8_t>(&property.second);
498 if (prefix != nullptr)
499 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700500 ipv6Address.prefixLength = *prefix;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500501 }
502 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600503 else if (property.first == "Type" ||
504 property.first == "Gateway")
505 {
506 // Type & Gateway is not used
507 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500508 else
509 {
Ed Tanous62598e32023-07-17 17:06:25 -0700510 BMCWEB_LOG_ERROR(
511 "Got extra property: {} on the {} object",
512 property.first, objpath.first.str);
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500513 }
514 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500515 }
516 }
517 }
518 }
519}
520
Ed Tanous4a0cb852018-10-15 07:55:04 -0700521// Helper function that extracts data for single ethernet ipv4 address
Ed Tanous77179532023-02-28 10:45:28 -0800522inline void extractIPData(const std::string& ethifaceId,
523 const dbus::utility::ManagedObjectType& dbusData,
524 std::vector<IPv4AddressData>& ipv4Config)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700525{
Patrick Williams89492a12023-05-10 07:51:34 -0500526 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
527 ethifaceId;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700528
529 // Since there might be several IPv4 configurations aligned with
530 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000531 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700532 {
533 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800534 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700535 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800536 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700537 {
538 if (interface.first == "xyz.openbmc_project.Network.IP")
539 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700540 auto type = std::ranges::find_if(interface.second,
541 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800542 return property.first == "Type";
543 });
544 if (type == interface.second.end())
545 {
546 continue;
547 }
548
549 const std::string* typeStr =
550 std::get_if<std::string>(&type->second);
551
552 if (typeStr == nullptr ||
553 (*typeStr !=
554 "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
555 {
556 continue;
557 }
558
Ed Tanous4a0cb852018-10-15 07:55:04 -0700559 // Instance IPv4AddressData structure, and set as
560 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800561 IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700562 ipv4Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800563 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800564 for (const auto& property : interface.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700565 {
566 if (property.first == "Address")
567 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500568 const std::string* address =
Ed Tanousabf2add2019-01-22 16:40:12 -0800569 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700570 if (address != nullptr)
571 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700572 ipv4Address.address = *address;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700573 }
574 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700575 else if (property.first == "Origin")
576 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500577 const std::string* origin =
Ed Tanousabf2add2019-01-22 16:40:12 -0800578 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700579 if (origin != nullptr)
580 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700581 ipv4Address.origin =
Ed Tanous4a0cb852018-10-15 07:55:04 -0700582 translateAddressOriginDbusToRedfish(*origin,
583 true);
584 }
585 }
586 else if (property.first == "PrefixLength")
587 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500588 const uint8_t* mask =
Ed Tanousabf2add2019-01-22 16:40:12 -0800589 std::get_if<uint8_t>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700590 if (mask != nullptr)
591 {
592 // convert it to the string
Ed Tanous2c70f802020-09-28 14:29:23 -0700593 ipv4Address.netmask = getNetmask(*mask);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700594 }
595 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600596 else if (property.first == "Type" ||
597 property.first == "Gateway")
598 {
599 // Type & Gateway is not used
600 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700601 else
602 {
Ed Tanous62598e32023-07-17 17:06:25 -0700603 BMCWEB_LOG_ERROR(
604 "Got extra property: {} on the {} object",
605 property.first, objpath.first.str);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700606 }
607 }
608 // Check if given address is local, or global
Ed Tanous2c70f802020-09-28 14:29:23 -0700609 ipv4Address.linktype =
Ed Tanous11ba3972022-07-11 09:50:41 -0700610 ipv4Address.address.starts_with("169.254.")
Johnathan Mantey18659d12019-06-07 10:26:29 -0700611 ? LinkType::Local
612 : LinkType::Global;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700613 }
614 }
615 }
616 }
617}
618
619/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700620 * @brief Deletes given IPv4 interface
Ed Tanous4a0cb852018-10-15 07:55:04 -0700621 *
622 * @param[in] ifaceId Id of interface whose IP should be deleted
Ed Tanous4a0cb852018-10-15 07:55:04 -0700623 * @param[in] ipHash DBus Hash id of IP that should be deleted
624 * @param[io] asyncResp Response object that will be returned to client
625 *
626 * @return None
627 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600628inline void deleteIPAddress(const std::string& ifaceId,
629 const std::string& ipHash,
630 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700631{
632 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800633 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700634 if (ec)
635 {
636 messages::internalError(asyncResp->res);
637 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500638 },
Ed Tanous4a0cb852018-10-15 07:55:04 -0700639 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600640 "/xyz/openbmc_project/network/" + ifaceId + ipHash,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700641 "xyz.openbmc_project.Object.Delete", "Delete");
642}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700643
Gunnar Mills244b6d52021-04-12 15:44:23 -0500644inline void updateIPv4DefaultGateway(
645 const std::string& ifaceId, const std::string& gateway,
646 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Teja9010ec22019-08-01 23:30:25 -0500647{
George Liu9ae226f2023-06-21 17:56:46 +0800648 sdbusplus::asio::setProperty(
649 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ravi Teja9010ec22019-08-01 23:30:25 -0500650 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9010ec22019-08-01 23:30:25 -0500651 "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
George Liu9ae226f2023-06-21 17:56:46 +0800652 gateway, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -0500653 if (ec)
654 {
655 messages::internalError(asyncResp->res);
656 return;
657 }
658 asyncResp->res.result(boost::beast::http::status::no_content);
659 });
Ravi Teja9010ec22019-08-01 23:30:25 -0500660}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700661/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700662 * @brief Creates a static IPv4 entry
Ed Tanous4a0cb852018-10-15 07:55:04 -0700663 *
Johnathan Mantey01784822019-06-18 12:44:21 -0700664 * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
665 * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
666 * @param[in] gateway IPv4 address of this interfaces gateway
667 * @param[in] address IPv4 address to assign to this interface
668 * @param[io] asyncResp Response object that will be returned to client
Ed Tanous4a0cb852018-10-15 07:55:04 -0700669 *
670 * @return None
671 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000672inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
673 const std::string& gateway, const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800674 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700675{
Patrick Williams5a39f772023-10-20 11:20:21 -0500676 auto createIpHandler = [asyncResp, ifaceId,
677 gateway](const boost::system::error_code& ec) {
Ravi Teja9010ec22019-08-01 23:30:25 -0500678 if (ec)
679 {
680 messages::internalError(asyncResp->res);
681 return;
682 }
683 updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
684 };
685
Ed Tanous4a0cb852018-10-15 07:55:04 -0700686 crow::connections::systemBus->async_method_call(
Ravi Teja9010ec22019-08-01 23:30:25 -0500687 std::move(createIpHandler), "xyz.openbmc_project.Network",
Ed Tanous4a0cb852018-10-15 07:55:04 -0700688 "/xyz/openbmc_project/network/" + ifaceId,
689 "xyz.openbmc_project.Network.IP.Create", "IP",
Johnathan Mantey01784822019-06-18 12:44:21 -0700690 "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700691 gateway);
692}
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500693
694/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700695 * @brief Deletes the IPv6 entry for this interface and creates a replacement
696 * static IPv6 entry
697 *
698 * @param[in] ifaceId Id of interface upon which to create the IPv6 entry
699 * @param[in] id The unique hash entry identifying the DBus entry
700 * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
701 * @param[in] address IPv6 address to assign to this interface
702 * @param[io] asyncResp Response object that will be returned to client
703 *
704 * @return None
705 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600706
707enum class IpVersion
708{
709 IpV4,
710 IpV6
711};
712
713inline void deleteAndCreateIPAddress(
714 IpVersion version, const std::string& ifaceId, const std::string& id,
715 uint8_t prefixLength, const std::string& address,
716 const std::string& gateway,
717 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Johnathan Mantey01784822019-06-18 12:44:21 -0700718{
719 crow::connections::systemBus->async_method_call(
Ravi Teja9c5e5852023-02-26 21:33:52 -0600720 [asyncResp, version, ifaceId, address, prefixLength,
721 gateway](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700722 if (ec)
723 {
724 messages::internalError(asyncResp->res);
725 }
Ravi Teja9c5e5852023-02-26 21:33:52 -0600726 std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
727 protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
Ed Tanous002d39b2022-05-31 08:59:27 -0700728 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800729 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700730 if (ec2)
Johnathan Mantey01784822019-06-18 12:44:21 -0700731 {
732 messages::internalError(asyncResp->res);
733 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500734 },
Ed Tanous002d39b2022-05-31 08:59:27 -0700735 "xyz.openbmc_project.Network",
736 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9c5e5852023-02-26 21:33:52 -0600737 "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
738 prefixLength, gateway);
Patrick Williams5a39f772023-10-20 11:20:21 -0500739 },
Johnathan Mantey01784822019-06-18 12:44:21 -0700740 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600741 "/xyz/openbmc_project/network/" + ifaceId + id,
Johnathan Mantey01784822019-06-18 12:44:21 -0700742 "xyz.openbmc_project.Object.Delete", "Delete");
743}
744
745/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500746 * @brief Creates IPv6 with given data
747 *
748 * @param[in] ifaceId Id of interface whose IP should be added
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500749 * @param[in] prefixLength Prefix length that needs to be added
750 * @param[in] address IP address that needs to be added
751 * @param[io] asyncResp Response object that will be returned to client
752 *
753 * @return None
754 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500755inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
756 const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800757 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500758{
Patrick Williams5a39f772023-10-20 11:20:21 -0500759 auto createIpHandler = [asyncResp,
760 address](const boost::system::error_code& ec) {
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500761 if (ec)
762 {
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500763 if (ec == boost::system::errc::io_error)
764 {
765 messages::propertyValueFormatError(asyncResp->res, address,
766 "Address");
767 }
768 else
769 {
770 messages::internalError(asyncResp->res);
771 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500772 }
773 };
774 // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500775 // does not have associated gateway property
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500776 crow::connections::systemBus->async_method_call(
777 std::move(createIpHandler), "xyz.openbmc_project.Network",
778 "/xyz/openbmc_project/network/" + ifaceId,
779 "xyz.openbmc_project.Network.IP.Create", "IP",
780 "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
781 "");
782}
783
Ed Tanous4a0cb852018-10-15 07:55:04 -0700784/**
785 * Function that retrieves all properties for given Ethernet Interface
786 * Object
787 * from EntityManager Network Manager
788 * @param ethiface_id a eth interface id to query on DBus
789 * @param callback a function that shall be called to convert Dbus output
790 * into JSON
791 */
792template <typename CallbackFunc>
Ed Tanous81ce6092020-12-17 16:54:55 +0000793void getEthernetIfaceData(const std::string& ethifaceId,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500794 CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700795{
George Liuf5892d02023-03-01 10:37:08 +0800796 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
797 dbus::utility::getManagedObjects(
798 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800799 [ethifaceId{std::string{ethifaceId}},
800 callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700801 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700802 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700803 EthernetInterfaceData ethData{};
Ed Tanous77179532023-02-28 10:45:28 -0800804 std::vector<IPv4AddressData> ipv4Data;
805 std::vector<IPv6AddressData> ipv6Data;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700806
Ed Tanous8b242752023-06-27 17:17:13 -0700807 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700808 {
809 callback(false, ethData, ipv4Data, ipv6Data);
810 return;
811 }
812
813 bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
814 if (!found)
815 {
816 callback(false, ethData, ipv4Data, ipv6Data);
817 return;
818 }
819
820 extractIPData(ethifaceId, resp, ipv4Data);
821 // Fix global GW
822 for (IPv4AddressData& ipv4 : ipv4Data)
823 {
824 if (((ipv4.linktype == LinkType::Global) &&
825 (ipv4.gateway == "0.0.0.0")) ||
826 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700827 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700828 ipv4.gateway = ethData.defaultGateway;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700829 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700830 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700831
Ed Tanous002d39b2022-05-31 08:59:27 -0700832 extractIPV6Data(ethifaceId, resp, ipv6Data);
833 // Finally make a callback with useful data
834 callback(true, ethData, ipv4Data, ipv6Data);
Patrick Williams5a39f772023-10-20 11:20:21 -0500835 });
Ed Tanous271584a2019-07-09 16:24:22 -0700836}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700837
838/**
839 * Function that retrieves all Ethernet Interfaces available through Network
840 * Manager
841 * @param callback a function that shall be called to convert Dbus output
842 * into JSON.
843 */
844template <typename CallbackFunc>
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500845void getEthernetIfaceList(CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700846{
George Liuf5892d02023-03-01 10:37:08 +0800847 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
848 dbus::utility::getManagedObjects(
849 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800850 [callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700851 const boost::system::error_code& ec,
George Liuf5892d02023-03-01 10:37:08 +0800852 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 // Callback requires vector<string> to retrieve all available
854 // ethernet interfaces
Ed Tanous77179532023-02-28 10:45:28 -0800855 std::vector<std::string> ifaceList;
Ed Tanous002d39b2022-05-31 08:59:27 -0700856 ifaceList.reserve(resp.size());
Ed Tanous8b242752023-06-27 17:17:13 -0700857 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700858 {
859 callback(false, ifaceList);
860 return;
861 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700862
Ed Tanous002d39b2022-05-31 08:59:27 -0700863 // Iterate over all retrieved ObjectPaths.
864 for (const auto& objpath : resp)
865 {
866 // And all interfaces available for certain ObjectPath.
867 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700868 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700869 // If interface is
870 // xyz.openbmc_project.Network.EthernetInterface, this is
871 // what we're looking for.
872 if (interface.first ==
873 "xyz.openbmc_project.Network.EthernetInterface")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700874 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700875 std::string ifaceId = objpath.first.filename();
876 if (ifaceId.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700877 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700878 continue;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700879 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700880 // and put it into output vector.
Ed Tanous77179532023-02-28 10:45:28 -0800881 ifaceList.emplace_back(ifaceId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700882 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700883 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700884 }
Ed Tanous2c5875a2023-05-15 09:56:06 -0700885
Ed Tanous3544d2a2023-08-06 18:12:20 -0700886 std::ranges::sort(ifaceList, AlphanumLess<std::string>());
Ed Tanous2c5875a2023-05-15 09:56:06 -0700887
Ed Tanous002d39b2022-05-31 08:59:27 -0700888 // Finally make a callback with useful data
889 callback(true, ifaceList);
Patrick Williams5a39f772023-10-20 11:20:21 -0500890 });
Ed Tanous271584a2019-07-09 16:24:22 -0700891}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100892
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700893inline void
894 handleHostnamePatch(const std::string& hostname,
895 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700896{
Ed Tanousbf648f72021-06-03 15:00:14 -0700897 // SHOULD handle host names of up to 255 characters(RFC 1123)
898 if (hostname.length() > 255)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700899 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700900 messages::propertyValueFormatError(asyncResp->res, hostname,
901 "HostName");
902 return;
903 }
George Liu9ae226f2023-06-21 17:56:46 +0800904 sdbusplus::asio::setProperty(
905 *crow::connections::systemBus, "xyz.openbmc_project.Network",
906 "/xyz/openbmc_project/network/config",
907 "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800908 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700909 if (ec)
910 {
911 messages::internalError(asyncResp->res);
912 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500913 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700914}
915
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700916inline void
Tejas Patil35fb5312021-09-20 15:35:20 +0530917 handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
918 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
919{
Patrick Williams89492a12023-05-10 07:51:34 -0500920 sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
921 ifaceId;
George Liu9ae226f2023-06-21 17:56:46 +0800922 sdbusplus::asio::setProperty(
923 *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
924 "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800925 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700926 if (ec)
927 {
928 messages::internalError(asyncResp->res);
929 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500930 });
Tejas Patil35fb5312021-09-20 15:35:20 +0530931}
932
933inline void
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700934 handleDomainnamePatch(const std::string& ifaceId,
935 const std::string& domainname,
936 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700937{
938 std::vector<std::string> vectorDomainname = {domainname};
George Liu9ae226f2023-06-21 17:56:46 +0800939 sdbusplus::asio::setProperty(
940 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ed Tanousbf648f72021-06-03 15:00:14 -0700941 "/xyz/openbmc_project/network/" + ifaceId,
Ed Tanousbf648f72021-06-03 15:00:14 -0700942 "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
George Liu9ae226f2023-06-21 17:56:46 +0800943 vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -0500944 if (ec)
945 {
946 messages::internalError(asyncResp->res);
947 }
948 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700949}
950
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700951inline bool isHostnameValid(const std::string& hostname)
Ed Tanousbf648f72021-06-03 15:00:14 -0700952{
953 // A valid host name can never have the dotted-decimal form (RFC 1123)
Ed Tanous3544d2a2023-08-06 18:12:20 -0700954 if (std::ranges::all_of(hostname, ::isdigit))
Ed Tanousbf648f72021-06-03 15:00:14 -0700955 {
956 return false;
957 }
958 // Each label(hostname/subdomains) within a valid FQDN
959 // MUST handle host names of up to 63 characters (RFC 1123)
960 // labels cannot start or end with hyphens (RFC 952)
961 // labels can start with numbers (RFC 1123)
Ed Tanous4b242742023-05-11 09:51:51 -0700962 const static std::regex pattern(
Ed Tanousbf648f72021-06-03 15:00:14 -0700963 "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
964
965 return std::regex_match(hostname, pattern);
966}
967
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700968inline bool isDomainnameValid(const std::string& domainname)
Ed Tanousbf648f72021-06-03 15:00:14 -0700969{
970 // Can have multiple subdomains
971 // Top Level Domain's min length is 2 character
Ed Tanous4b242742023-05-11 09:51:51 -0700972 const static std::regex pattern(
George Liu0fda0f12021-11-16 10:06:17 +0800973 "^([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 -0700974
975 return std::regex_match(domainname, pattern);
976}
977
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700978inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
979 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700980{
981 // Total length of FQDN must not exceed 255 characters(RFC 1035)
982 if (fqdn.length() > 255)
983 {
984 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
985 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700986 }
987
Ed Tanousbf648f72021-06-03 15:00:14 -0700988 size_t pos = fqdn.find('.');
989 if (pos == std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700990 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700991 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
992 return;
993 }
zhanghch058d1b46d2021-04-01 11:18:24 +0800994
Ed Tanousbf648f72021-06-03 15:00:14 -0700995 std::string hostname;
996 std::string domainname;
997 domainname = (fqdn).substr(pos + 1);
998 hostname = (fqdn).substr(0, pos);
999
1000 if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1001 {
1002 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1003 return;
1004 }
1005
1006 handleHostnamePatch(hostname, asyncResp);
1007 handleDomainnamePatch(ifaceId, domainname, asyncResp);
1008}
1009
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001010inline void
1011 handleMACAddressPatch(const std::string& ifaceId,
1012 const std::string& macAddress,
1013 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001014{
Johnathan Mantey58283f42022-08-15 14:38:36 -07001015 static constexpr std::string_view dbusNotAllowedError =
1016 "xyz.openbmc_project.Common.Error.NotAllowed";
1017
George Liu9ae226f2023-06-21 17:56:46 +08001018 sdbusplus::asio::setProperty(
1019 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1020 "/xyz/openbmc_project/network/" + ifaceId,
1021 "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
1022 [asyncResp](const boost::system::error_code& ec,
1023 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001024 if (ec)
1025 {
Johnathan Mantey58283f42022-08-15 14:38:36 -07001026 const sd_bus_error* err = msg.get_error();
1027 if (err == nullptr)
1028 {
1029 messages::internalError(asyncResp->res);
1030 return;
1031 }
1032 if (err->name == dbusNotAllowedError)
1033 {
1034 messages::propertyNotWritable(asyncResp->res, "MACAddress");
1035 return;
1036 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001037 messages::internalError(asyncResp->res);
1038 return;
1039 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001040 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001041}
1042
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001043inline void setDHCPEnabled(const std::string& ifaceId,
1044 const std::string& propertyName, const bool v4Value,
1045 const bool v6Value,
1046 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001047{
1048 const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
George Liu9ae226f2023-06-21 17:56:46 +08001049 sdbusplus::asio::setProperty(
1050 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1051 "/xyz/openbmc_project/network/" + ifaceId,
1052 "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001053 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001054 if (ec)
1055 {
Ed Tanous62598e32023-07-17 17:06:25 -07001056 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001057 messages::internalError(asyncResp->res);
1058 return;
1059 }
1060 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05001061 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001062}
1063
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001064inline void setEthernetInterfaceBoolProperty(
Ed Tanousbf648f72021-06-03 15:00:14 -07001065 const std::string& ifaceId, const std::string& propertyName,
1066 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1067{
George Liu9ae226f2023-06-21 17:56:46 +08001068 sdbusplus::asio::setProperty(
1069 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1070 "/xyz/openbmc_project/network/" + ifaceId,
1071 "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001072 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001073 if (ec)
1074 {
Ed Tanous62598e32023-07-17 17:06:25 -07001075 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001076 messages::internalError(asyncResp->res);
1077 return;
1078 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001079 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001080}
1081
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001082inline void setDHCPv4Config(const std::string& propertyName, const bool& value,
1083 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001084{
Ed Tanous62598e32023-07-17 17:06:25 -07001085 BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
George Liu9ae226f2023-06-21 17:56:46 +08001086 sdbusplus::asio::setProperty(
1087 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1088 "/xyz/openbmc_project/network/dhcp",
1089 "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001090 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001091 if (ec)
1092 {
Ed Tanous62598e32023-07-17 17:06:25 -07001093 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001094 messages::internalError(asyncResp->res);
1095 return;
1096 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001097 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001098}
1099
Ravi Tejab10d8db2022-05-24 09:04:12 -05001100inline void handleSLAACAutoConfigPatch(
1101 const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1102 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1103{
1104 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1105 path /= ifaceId;
1106 sdbusplus::asio::setProperty(
1107 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1108 "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1109 ipv6AutoConfigEnabled,
1110 [asyncResp](const boost::system::error_code& ec) {
1111 if (ec)
1112 {
1113 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1114 messages::internalError(asyncResp->res);
1115 return;
1116 }
1117 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05001118 });
Ravi Tejab10d8db2022-05-24 09:04:12 -05001119}
1120
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001121inline void handleDHCPPatch(const std::string& ifaceId,
1122 const EthernetInterfaceData& ethData,
1123 const DHCPParameters& v4dhcpParms,
1124 const DHCPParameters& v6dhcpParms,
1125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001126{
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001127 bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1128 bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
Ed Tanousbf648f72021-06-03 15:00:14 -07001129
1130 bool nextv4DHCPState =
1131 v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
1132
1133 bool nextv6DHCPState{};
1134 if (v6dhcpParms.dhcpv6OperatingMode)
1135 {
Ravi Tejab10d8db2022-05-24 09:04:12 -05001136 if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
Ed Tanousbf648f72021-06-03 15:00:14 -07001137 (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
1138 {
1139 messages::propertyValueFormatError(asyncResp->res,
1140 *v6dhcpParms.dhcpv6OperatingMode,
1141 "OperatingMode");
1142 return;
1143 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001144 nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
Ed Tanousbf648f72021-06-03 15:00:14 -07001145 }
1146 else
1147 {
1148 nextv6DHCPState = ipv6Active;
1149 }
1150
1151 bool nextDNS{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001152 if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001153 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001154 if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001155 {
1156 messages::generalError(asyncResp->res);
1157 return;
1158 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001159 nextDNS = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001160 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001161 else if (v4dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001162 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001163 nextDNS = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001164 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001165 else if (v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001166 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001167 nextDNS = *v6dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001168 }
1169 else
1170 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001171 nextDNS = ethData.dnsEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001172 }
1173
1174 bool nextNTP{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001175 if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001176 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001177 if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001178 {
1179 messages::generalError(asyncResp->res);
1180 return;
1181 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001182 nextNTP = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001183 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001184 else if (v4dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001185 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001186 nextNTP = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001187 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001188 else if (v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001189 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001190 nextNTP = *v6dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001191 }
1192 else
1193 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001194 nextNTP = ethData.ntpEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001195 }
1196
1197 bool nextUseDomain{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001198 if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001199 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001200 if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001201 {
1202 messages::generalError(asyncResp->res);
1203 return;
1204 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001205 nextUseDomain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001206 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001207 else if (v4dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001208 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001209 nextUseDomain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001210 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001211 else if (v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001212 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001213 nextUseDomain = *v6dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001214 }
1215 else
1216 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001217 nextUseDomain = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001218 }
1219
Ed Tanous62598e32023-07-17 17:06:25 -07001220 BMCWEB_LOG_DEBUG("set DHCPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001221 setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
1222 asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001223 BMCWEB_LOG_DEBUG("set DNSEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001224 setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001225 BMCWEB_LOG_DEBUG("set NTPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001226 setDHCPv4Config("NTPEnabled", nextNTP, asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001227 BMCWEB_LOG_DEBUG("set HostNameEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001228 setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp);
1229}
1230
Ed Tanous77179532023-02-28 10:45:28 -08001231inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
1232 const std::vector<IPv4AddressData>::const_iterator& head,
1233 const std::vector<IPv4AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001234{
1235 return std::find_if(head, end, [](const IPv4AddressData& value) {
1236 return value.origin == "Static";
1237 });
1238}
1239
Ed Tanous77179532023-02-28 10:45:28 -08001240inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
1241 const std::vector<IPv6AddressData>::const_iterator& head,
1242 const std::vector<IPv6AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001243{
1244 return std::find_if(head, end, [](const IPv6AddressData& value) {
1245 return value.origin == "Static";
1246 });
1247}
1248
Ed Tanous77179532023-02-28 10:45:28 -08001249inline void
Ed Tanousddd70dc2023-03-01 16:00:27 -08001250 handleIPv4StaticPatch(const std::string& ifaceId,
1251 nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001252 const std::vector<IPv4AddressData>& ipv4Data,
1253 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001254{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001255 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001256 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001257 messages::propertyValueTypeError(asyncResp->res, input,
1258 "IPv4StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001259 return;
1260 }
1261
1262 unsigned entryIdx = 1;
1263 // Find the first static IP address currently active on the NIC and
1264 // match it to the first JSON element in the IPv4StaticAddresses array.
1265 // Match each subsequent JSON element to the next static IP programmed
1266 // into the NIC.
Ed Tanous77179532023-02-28 10:45:28 -08001267 std::vector<IPv4AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001268 getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
1269
1270 for (nlohmann::json& thisJson : input)
1271 {
Patrick Williams89492a12023-05-10 07:51:34 -05001272 std::string pathString = "IPv4StaticAddresses/" +
1273 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001274
1275 if (!thisJson.is_null() && !thisJson.empty())
1276 {
1277 std::optional<std::string> address;
1278 std::optional<std::string> subnetMask;
1279 std::optional<std::string> gateway;
1280
1281 if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1282 address, "SubnetMask", subnetMask,
1283 "Gateway", gateway))
1284 {
Ed Tanousf818b042022-06-27 13:17:35 -07001285 messages::propertyValueFormatError(asyncResp->res, thisJson,
1286 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001287 return;
1288 }
1289
1290 // Find the address/subnet/gateway values. Any values that are
1291 // not explicitly provided are assumed to be unmodified from the
1292 // current state of the interface. Merge existing state into the
1293 // current request.
Ed Tanousbf648f72021-06-03 15:00:14 -07001294 if (address)
1295 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001296 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001297 {
1298 messages::propertyValueFormatError(asyncResp->res, *address,
1299 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001300 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001301 }
1302 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001303 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001304 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001305 address = (nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001306 }
1307 else
1308 {
1309 messages::propertyMissing(asyncResp->res,
1310 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001311 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001312 }
1313
Ed Tanouse01d0c32023-06-30 13:21:32 -07001314 uint8_t prefixLength = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001315 if (subnetMask)
1316 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001317 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1318 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001319 {
1320 messages::propertyValueFormatError(
1321 asyncResp->res, *subnetMask,
1322 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001323 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001324 }
1325 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001326 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001327 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001328 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1329 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001330 {
1331 messages::propertyValueFormatError(
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001332 asyncResp->res, nicIpEntry->netmask,
Ed Tanousbf648f72021-06-03 15:00:14 -07001333 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001334 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001335 }
1336 }
1337 else
1338 {
1339 messages::propertyMissing(asyncResp->res,
1340 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001341 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001342 }
1343
1344 if (gateway)
1345 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001346 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001347 {
1348 messages::propertyValueFormatError(asyncResp->res, *gateway,
1349 pathString + "/Gateway");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001350 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001351 }
1352 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001353 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001354 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001355 gateway = nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001356 }
1357 else
1358 {
1359 messages::propertyMissing(asyncResp->res,
1360 pathString + "/Gateway");
Ed Tanousbf648f72021-06-03 15:00:14 -07001361 return;
1362 }
1363
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001364 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001365 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001366 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001367 nicIpEntry->id, prefixLength, *address,
1368 *gateway, asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001369 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1370 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001371 }
1372 else
1373 {
1374 createIPv4(ifaceId, prefixLength, *gateway, *address,
1375 asyncResp);
1376 }
1377 entryIdx++;
1378 }
1379 else
1380 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001381 if (nicIpEntry == ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001382 {
1383 // Requesting a DELETE/DO NOT MODIFY action for an item
1384 // that isn't present on the eth(n) interface. Input JSON is
1385 // in error, so bail out.
1386 if (thisJson.is_null())
1387 {
1388 messages::resourceCannotBeDeleted(asyncResp->res);
1389 return;
1390 }
Ed Tanousf818b042022-06-27 13:17:35 -07001391 messages::propertyValueFormatError(asyncResp->res, thisJson,
1392 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001393 return;
1394 }
1395
1396 if (thisJson.is_null())
1397 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001398 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001399 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001400 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001401 {
Patrick Williams89492a12023-05-10 07:51:34 -05001402 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1403 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001404 }
1405 entryIdx++;
1406 }
1407 }
1408}
1409
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001410inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001411 const std::string& ifaceId,
1412 const std::vector<std::string>& updatedStaticNameServers,
1413 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1414{
George Liu9ae226f2023-06-21 17:56:46 +08001415 sdbusplus::asio::setProperty(
1416 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1417 "/xyz/openbmc_project/network/" + ifaceId,
1418 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1419 updatedStaticNameServers,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001420 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001421 if (ec)
1422 {
1423 messages::internalError(asyncResp->res);
1424 return;
1425 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001426 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001427}
1428
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001429inline void handleIPv6StaticAddressesPatch(
Ed Tanousddd70dc2023-03-01 16:00:27 -08001430 const std::string& ifaceId, const nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001431 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001432 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1433{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001434 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001435 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001436 messages::propertyValueTypeError(asyncResp->res, input,
1437 "IPv6StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001438 return;
1439 }
1440 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001441 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001442 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1443 for (const nlohmann::json& thisJson : input)
1444 {
Patrick Williams89492a12023-05-10 07:51:34 -05001445 std::string pathString = "IPv6StaticAddresses/" +
1446 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001447
1448 if (!thisJson.is_null() && !thisJson.empty())
1449 {
1450 std::optional<std::string> address;
1451 std::optional<uint8_t> prefixLength;
1452 nlohmann::json thisJsonCopy = thisJson;
1453 if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1454 address, "PrefixLength", prefixLength))
1455 {
Ed Tanousf818b042022-06-27 13:17:35 -07001456 messages::propertyValueFormatError(asyncResp->res, thisJson,
1457 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001458 return;
1459 }
1460
Ed Tanous543f4402022-01-06 13:12:53 -08001461 const std::string* addr = nullptr;
1462 uint8_t prefix = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001463
1464 // Find the address and prefixLength values. Any values that are
1465 // not explicitly provided are assumed to be unmodified from the
1466 // current state of the interface. Merge existing state into the
1467 // current request.
1468 if (address)
1469 {
1470 addr = &(*address);
1471 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001472 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001473 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001474 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001475 }
1476 else
1477 {
1478 messages::propertyMissing(asyncResp->res,
1479 pathString + "/Address");
1480 return;
1481 }
1482
1483 if (prefixLength)
1484 {
1485 prefix = *prefixLength;
1486 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001487 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001488 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001489 prefix = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001490 }
1491 else
1492 {
1493 messages::propertyMissing(asyncResp->res,
1494 pathString + "/PrefixLength");
1495 return;
1496 }
1497
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001498 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001499 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001500 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001501 nicIpEntry->id, prefix, *addr, "",
Ravi Teja9c5e5852023-02-26 21:33:52 -06001502 asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001503 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1504 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001505 }
1506 else
1507 {
1508 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1509 }
1510 entryIdx++;
1511 }
1512 else
1513 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001514 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001515 {
1516 // Requesting a DELETE/DO NOT MODIFY action for an item
1517 // that isn't present on the eth(n) interface. Input JSON is
1518 // in error, so bail out.
1519 if (thisJson.is_null())
1520 {
1521 messages::resourceCannotBeDeleted(asyncResp->res);
1522 return;
1523 }
Ed Tanousf818b042022-06-27 13:17:35 -07001524 messages::propertyValueFormatError(asyncResp->res, thisJson,
1525 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001526 return;
1527 }
1528
1529 if (thisJson.is_null())
1530 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001531 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001532 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001533 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001534 {
Patrick Williams89492a12023-05-10 07:51:34 -05001535 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1536 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001537 }
1538 entryIdx++;
1539 }
1540 }
1541}
1542
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001543inline std::string extractParentInterfaceName(const std::string& ifaceId)
1544{
1545 std::size_t pos = ifaceId.find('_');
1546 return ifaceId.substr(0, pos);
1547}
1548
Ed Tanous77179532023-02-28 10:45:28 -08001549inline void
1550 parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1551 const std::string& ifaceId,
1552 const EthernetInterfaceData& ethData,
1553 const std::vector<IPv4AddressData>& ipv4Data,
1554 const std::vector<IPv6AddressData>& ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001555{
Ed Tanousbf648f72021-06-03 15:00:14 -07001556 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1557 jsonResponse["Id"] = ifaceId;
Ed Tanousef4c65b2023-04-24 15:28:50 -07001558 jsonResponse["@odata.id"] = boost::urls::format(
1559 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001560 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1561
Willy Tu13451e32023-05-24 16:08:18 -07001562 if constexpr (bmcwebEnableHealthPopulate)
1563 {
1564 constexpr std::array<std::string_view, 1> inventoryForEthernet = {
1565 "xyz.openbmc_project.Inventory.Item.Ethernet"};
1566 auto health = std::make_shared<HealthPopulate>(asyncResp);
1567 dbus::utility::getSubTreePaths(
1568 "/", 0, inventoryForEthernet,
1569 [health](const boost::system::error_code& ec,
1570 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1571 if (ec)
1572 {
1573 return;
1574 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001575
Willy Tu13451e32023-05-24 16:08:18 -07001576 health->inventory = resp;
Patrick Williams5a39f772023-10-20 11:20:21 -05001577 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001578
Willy Tu13451e32023-05-24 16:08:18 -07001579 health->populate();
1580 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001581
1582 if (ethData.nicEnabled)
1583 {
Johnathan Mantey0ef0e282022-11-15 12:15:02 -08001584 jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
Ed Tanousbf648f72021-06-03 15:00:14 -07001585 jsonResponse["Status"]["State"] = "Enabled";
1586 }
1587 else
1588 {
1589 jsonResponse["LinkStatus"] = "NoLink";
1590 jsonResponse["Status"]["State"] = "Disabled";
1591 }
1592
Ed Tanousbf648f72021-06-03 15:00:14 -07001593 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301594 jsonResponse["MTUSize"] = ethData.mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001595 jsonResponse["MACAddress"] = ethData.macAddress;
Ed Tanousbf648f72021-06-03 15:00:14 -07001596 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001597 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1598 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled;
1599 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled;
1600 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001601
1602 jsonResponse["DHCPv6"]["OperatingMode"] =
Ravi Tejab10d8db2022-05-24 09:04:12 -05001603 translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
Ed Tanousbf648f72021-06-03 15:00:14 -07001604 : "Disabled";
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001605 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled;
1606 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled;
1607 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001608 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1609 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001610
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001611 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001612 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001613 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001614
1615 // When domain name is empty then it means, that it is a network
1616 // without domain names, and the host name itself must be treated as
1617 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001618 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001619 if (!ethData.domainnames.empty())
1620 {
1621 fqdn += "." + ethData.domainnames[0];
1622 }
1623 jsonResponse["FQDN"] = fqdn;
1624 }
1625
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001626 if (ethData.vlanId)
1627 {
1628 jsonResponse["EthernetInterfaceType"] = "Virtual";
1629 jsonResponse["VLAN"]["VLANEnable"] = true;
1630 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1631 jsonResponse["VLAN"]["Tagged"] = true;
1632
1633 nlohmann::json::array_t relatedInterfaces;
1634 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1635 parentInterface["@odata.id"] =
1636 boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
1637 extractParentInterfaceName(ifaceId));
1638 jsonResponse["Links"]["RelatedInterfaces"] =
1639 std::move(relatedInterfaces);
1640 }
1641 else
1642 {
1643 jsonResponse["EthernetInterfaceType"] = "Physical";
1644 }
1645
Ed Tanousbf648f72021-06-03 15:00:14 -07001646 jsonResponse["NameServers"] = ethData.nameServers;
1647 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1648
1649 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1650 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1651 ipv4Array = nlohmann::json::array();
1652 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001653 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001654 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001655 std::string gatewayStr = ipv4Config.gateway;
1656 if (gatewayStr.empty())
1657 {
1658 gatewayStr = "0.0.0.0";
1659 }
Ed Tanous14766872022-03-15 10:44:42 -07001660 nlohmann::json::object_t ipv4;
1661 ipv4["AddressOrigin"] = ipv4Config.origin;
1662 ipv4["SubnetMask"] = ipv4Config.netmask;
1663 ipv4["Address"] = ipv4Config.address;
1664 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001665
Ed Tanousbf648f72021-06-03 15:00:14 -07001666 if (ipv4Config.origin == "Static")
1667 {
Ed Tanous14766872022-03-15 10:44:42 -07001668 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001669 }
Ed Tanous14766872022-03-15 10:44:42 -07001670
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001671 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001672 }
1673
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001674 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001675 if (ipv6GatewayStr.empty())
1676 {
1677 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1678 }
1679
1680 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1681
1682 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1683 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1684 ipv6Array = nlohmann::json::array();
1685 ipv6StaticArray = nlohmann::json::array();
1686 nlohmann::json& ipv6AddrPolicyTable =
1687 jsonResponse["IPv6AddressPolicyTable"];
1688 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001689 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001690 {
Ed Tanous14766872022-03-15 10:44:42 -07001691 nlohmann::json::object_t ipv6;
1692 ipv6["Address"] = ipv6Config.address;
1693 ipv6["PrefixLength"] = ipv6Config.prefixLength;
1694 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05001695
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001696 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07001697 if (ipv6Config.origin == "Static")
1698 {
Ed Tanous14766872022-03-15 10:44:42 -07001699 nlohmann::json::object_t ipv6Static;
1700 ipv6Static["Address"] = ipv6Config.address;
1701 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001702 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07001703 }
1704 }
1705}
1706
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001707inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1708 const std::string& ifaceId,
1709 const boost::system::error_code& ec,
1710 const sdbusplus::message_t& m)
1711{
1712 if (!ec)
1713 {
1714 return;
1715 }
1716 const sd_bus_error* dbusError = m.get_error();
1717 if (dbusError == nullptr)
1718 {
1719 messages::internalError(asyncResp->res);
1720 return;
1721 }
Ed Tanous62598e32023-07-17 17:06:25 -07001722 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001723
1724 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1725 dbusError->name)
1726 {
1727 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1728 ifaceId);
1729 return;
1730 }
1731 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1732 dbusError->name)
1733 {
1734 messages::resourceCannotBeDeleted(asyncResp->res);
1735 return;
1736 }
1737 messages::internalError(asyncResp->res);
1738}
1739
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001740inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1741 const std::string& parentInterfaceUri,
1742 const std::string& vlanInterface,
1743 const boost::system::error_code& ec,
1744 const sdbusplus::message_t& m
1745
1746)
1747{
1748 if (ec)
1749 {
1750 const sd_bus_error* dbusError = m.get_error();
1751 if (dbusError == nullptr)
1752 {
1753 messages::internalError(asyncResp->res);
1754 return;
1755 }
Ed Tanous62598e32023-07-17 17:06:25 -07001756 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001757
1758 if (std::string_view(
1759 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1760 dbusError->name)
1761 {
1762 messages::propertyValueNotInList(
1763 asyncResp->res, parentInterfaceUri,
1764 "Links/RelatedInterfaces/0/@odata.id");
1765 return;
1766 }
1767 if (std::string_view(
1768 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1769 dbusError->name)
1770 {
1771 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1772 "Id", vlanInterface);
1773 return;
1774 }
1775 messages::internalError(asyncResp->res);
1776 return;
1777 }
1778
1779 const boost::urls::url vlanInterfaceUri = boost::urls::format(
1780 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1781 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1782}
1783
Ed Tanousbf648f72021-06-03 15:00:14 -07001784inline void requestEthernetInterfacesRoutes(App& app)
1785{
1786 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07001787 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07001788 .methods(boost::beast::http::verb::get)(
1789 [&app](const crow::Request& req,
1790 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001791 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001792 {
1793 return;
1794 }
1795
1796 asyncResp->res.jsonValue["@odata.type"] =
1797 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1798 asyncResp->res.jsonValue["@odata.id"] =
1799 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1800 asyncResp->res.jsonValue["Name"] =
1801 "Ethernet Network Interface Collection";
1802 asyncResp->res.jsonValue["Description"] =
1803 "Collection of EthernetInterfaces for this Manager";
1804
1805 // Get eth interface list, and call the below callback for JSON
1806 // preparation
1807 getEthernetIfaceList(
Ed Tanous77179532023-02-28 10:45:28 -08001808 [asyncResp](const bool& success,
1809 const std::vector<std::string>& ifaceList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001810 if (!success)
1811 {
1812 messages::internalError(asyncResp->res);
1813 return;
1814 }
1815
1816 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1817 ifaceArray = nlohmann::json::array();
Ed Tanous002d39b2022-05-31 08:59:27 -07001818 for (const std::string& ifaceItem : ifaceList)
1819 {
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001820 nlohmann::json::object_t iface;
1821 iface["@odata.id"] = boost::urls::format(
1822 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1823 ifaceItem);
1824 ifaceArray.push_back(std::move(iface));
Ed Tanous002d39b2022-05-31 08:59:27 -07001825 }
Jason M. Billsf12894f2018-10-09 12:45:45 -07001826
Ed Tanous002d39b2022-05-31 08:59:27 -07001827 asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1828 asyncResp->res.jsonValue["@odata.id"] =
1829 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1830 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001831 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001832
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001833 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1834 .privileges(redfish::privileges::postEthernetInterfaceCollection)
1835 .methods(boost::beast::http::verb::post)(
1836 [&app](const crow::Request& req,
1837 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1838 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1839 {
1840 return;
1841 }
1842
1843 bool vlanEnable = false;
1844 uint32_t vlanId = 0;
1845 nlohmann::json::array_t relatedInterfaces;
1846
1847 if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1848 vlanEnable, "VLAN/VLANId", vlanId,
1849 "Links/RelatedInterfaces",
1850 relatedInterfaces))
1851 {
1852 return;
1853 }
1854
1855 if (relatedInterfaces.size() != 1)
1856 {
1857 messages::arraySizeTooLong(asyncResp->res,
1858 "Links/RelatedInterfaces",
1859 relatedInterfaces.size());
1860 return;
1861 }
1862
1863 std::string parentInterfaceUri;
1864 if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1865 "@odata.id", parentInterfaceUri))
1866 {
1867 messages::propertyMissing(asyncResp->res,
1868 "Links/RelatedInterfaces/0/@odata.id");
1869 return;
1870 }
Ed Tanous62598e32023-07-17 17:06:25 -07001871 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001872
Ed Tanous6fd29552023-10-04 09:40:14 -07001873 boost::system::result<boost::urls::url_view> parsedUri =
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001874 boost::urls::parse_relative_ref(parentInterfaceUri);
1875 if (!parsedUri)
1876 {
1877 messages::propertyValueFormatError(
1878 asyncResp->res, parentInterfaceUri,
1879 "Links/RelatedInterfaces/0/@odata.id");
1880 return;
1881 }
1882
1883 std::string parentInterface;
1884 if (!crow::utility::readUrlSegments(
1885 *parsedUri, "redfish", "v1", "Managers", "bmc",
1886 "EthernetInterfaces", std::ref(parentInterface)))
1887 {
1888 messages::propertyValueNotInList(
1889 asyncResp->res, parentInterfaceUri,
1890 "Links/RelatedInterfaces/0/@odata.id");
1891 return;
1892 }
1893
1894 if (!vlanEnable)
1895 {
1896 // In OpenBMC implementation, VLANEnable cannot be false on
1897 // create
1898 messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1899 "false");
1900 return;
1901 }
1902
1903 std::string vlanInterface = parentInterface + "_" +
1904 std::to_string(vlanId);
1905 crow::connections::systemBus->async_method_call(
1906 [asyncResp, parentInterfaceUri,
1907 vlanInterface](const boost::system::error_code& ec,
1908 const sdbusplus::message_t& m) {
1909 afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1910 m);
Patrick Williams5a39f772023-10-20 11:20:21 -05001911 },
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001912 "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1913 "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1914 vlanId);
Patrick Williams5a39f772023-10-20 11:20:21 -05001915 });
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001916
Ed Tanousbf648f72021-06-03 15:00:14 -07001917 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001918 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001919 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001920 [&app](const crow::Request& req,
1921 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1922 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001923 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001924 {
1925 return;
1926 }
1927 getEthernetIfaceData(
1928 ifaceId,
Ed Tanous77179532023-02-28 10:45:28 -08001929 [asyncResp, ifaceId](const bool& success,
1930 const EthernetInterfaceData& ethData,
1931 const std::vector<IPv4AddressData>& ipv4Data,
1932 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001933 if (!success)
1934 {
1935 // TODO(Pawel)consider distinguish between non
1936 // existing object, and other errors
1937 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1938 ifaceId);
1939 return;
1940 }
Johnathan Mantey01784822019-06-18 12:44:21 -07001941
Ed Tanous002d39b2022-05-31 08:59:27 -07001942 asyncResp->res.jsonValue["@odata.type"] =
Jiaqing Zhao93bbc952023-02-23 14:11:20 +08001943 "#EthernetInterface.v1_9_0.EthernetInterface";
Ed Tanous002d39b2022-05-31 08:59:27 -07001944 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
1945 asyncResp->res.jsonValue["Description"] =
1946 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05301947
Ed Tanous002d39b2022-05-31 08:59:27 -07001948 parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
Ed Tanous002d39b2022-05-31 08:59:27 -07001949 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001950 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001951
Ed Tanousbf648f72021-06-03 15:00:14 -07001952 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001953 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001954 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001955 [&app](const crow::Request& req,
1956 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1957 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001958 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001959 {
1960 return;
1961 }
1962 std::optional<std::string> hostname;
1963 std::optional<std::string> fqdn;
1964 std::optional<std::string> macAddress;
1965 std::optional<std::string> ipv6DefaultGateway;
Ed Tanousddd70dc2023-03-01 16:00:27 -08001966 std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
1967 std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07001968 std::optional<std::vector<std::string>> staticNameServers;
1969 std::optional<nlohmann::json> dhcpv4;
1970 std::optional<nlohmann::json> dhcpv6;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001971 std::optional<bool> ipv6AutoConfigEnabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07001972 std::optional<bool> interfaceEnabled;
1973 std::optional<size_t> mtuSize;
1974 DHCPParameters v4dhcpParms;
1975 DHCPParameters v6dhcpParms;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001976 // clang-format off
Ed Tanous002d39b2022-05-31 08:59:27 -07001977 if (!json_util::readJsonPatch(
Ravi Tejab10d8db2022-05-24 09:04:12 -05001978 req, asyncResp->res,
1979 "DHCPv4", dhcpv4,
1980 "DHCPv6", dhcpv6,
1981 "FQDN", fqdn,
1982 "HostName", hostname,
1983 "IPv4StaticAddresses", ipv4StaticAddresses,
1984 "IPv6DefaultGateway", ipv6DefaultGateway,
1985 "IPv6StaticAddresses", ipv6StaticAddresses,
1986 "InterfaceEnabled", interfaceEnabled,
1987 "MACAddress", macAddress,
1988 "MTUSize", mtuSize,
1989 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
1990 "StaticNameServers", staticNameServers
1991 )
1992 )
Ed Tanous002d39b2022-05-31 08:59:27 -07001993 {
1994 return;
1995 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001996 //clang-format on
Ed Tanous002d39b2022-05-31 08:59:27 -07001997 if (dhcpv4)
1998 {
1999 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
2000 v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
2001 v4dhcpParms.useDnsServers, "UseNTPServers",
2002 v4dhcpParms.useNtpServers, "UseDomainName",
2003 v4dhcpParms.useDomainName))
2004 {
2005 return;
2006 }
2007 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002008
Ed Tanous002d39b2022-05-31 08:59:27 -07002009 if (dhcpv6)
2010 {
2011 if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2012 v6dhcpParms.dhcpv6OperatingMode,
2013 "UseDNSServers", v6dhcpParms.useDnsServers,
2014 "UseNTPServers", v6dhcpParms.useNtpServers,
2015 "UseDomainName",
2016 v6dhcpParms.useDomainName))
2017 {
2018 return;
2019 }
2020 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002021
Ed Tanous002d39b2022-05-31 08:59:27 -07002022 // Get single eth interface data, and call the below callback
2023 // for JSON preparation
2024 getEthernetIfaceData(
2025 ifaceId,
2026 [asyncResp, ifaceId, hostname = std::move(hostname),
2027 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2028 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2029 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2030 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2031 staticNameServers = std::move(staticNameServers),
Ed Tanousbc200892022-06-30 17:49:12 -07002032 dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
Ravi Tejab10d8db2022-05-24 09:04:12 -05002033 ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
Ed Tanous002d39b2022-05-31 08:59:27 -07002034 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2035 const bool& success, const EthernetInterfaceData& ethData,
Ed Tanous77179532023-02-28 10:45:28 -08002036 const std::vector<IPv4AddressData>& ipv4Data,
2037 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002038 if (!success)
2039 {
2040 // ... otherwise return error
2041 // TODO(Pawel)consider distinguish between non
2042 // existing object, and other errors
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +08002043 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
Ed Tanous002d39b2022-05-31 08:59:27 -07002044 ifaceId);
2045 return;
2046 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002047
Ed Tanous002d39b2022-05-31 08:59:27 -07002048 if (dhcpv4 || dhcpv6)
2049 {
2050 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
Ed Tanousbf648f72021-06-03 15:00:14 -07002051 asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002052 }
Tejas Patil35fb5312021-09-20 15:35:20 +05302053
Ed Tanous002d39b2022-05-31 08:59:27 -07002054 if (hostname)
2055 {
2056 handleHostnamePatch(*hostname, asyncResp);
2057 }
2058
Ravi Tejab10d8db2022-05-24 09:04:12 -05002059 if (ipv6AutoConfigEnabled)
2060 {
2061 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2062 asyncResp);
2063 }
2064
Ed Tanous002d39b2022-05-31 08:59:27 -07002065 if (fqdn)
2066 {
2067 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2068 }
2069
2070 if (macAddress)
2071 {
2072 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2073 }
2074
2075 if (ipv4StaticAddresses)
2076 {
2077 // TODO(ed) for some reason the capture of
2078 // ipv4Addresses above is returning a const value,
2079 // not a non-const value. This doesn't really work
2080 // for us, as we need to be able to efficiently move
2081 // out the intermedia nlohmann::json objects. This
2082 // makes a copy of the structure, and operates on
2083 // that, but could be done more efficiently
Ed Tanousddd70dc2023-03-01 16:00:27 -08002084 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002085 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
2086 }
2087
2088 if (staticNameServers)
2089 {
2090 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2091 asyncResp);
2092 }
2093
2094 if (ipv6DefaultGateway)
2095 {
2096 messages::propertyNotWritable(asyncResp->res,
2097 "IPv6DefaultGateway");
2098 }
2099
2100 if (ipv6StaticAddresses)
2101 {
Ed Tanousddd70dc2023-03-01 16:00:27 -08002102 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2103 ipv6Data, asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002104 }
2105
2106 if (interfaceEnabled)
2107 {
2108 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2109 *interfaceEnabled, asyncResp);
2110 }
2111
2112 if (mtuSize)
2113 {
2114 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2115 }
Ed Tanousbf648f72021-06-03 15:00:14 -07002116 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002117 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002118
2119 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2120 .privileges(redfish::privileges::deleteEthernetInterface)
2121 .methods(boost::beast::http::verb::delete_)(
2122 [&app](const crow::Request& req,
2123 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2124 const std::string& ifaceId) {
2125 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2126 {
2127 return;
2128 }
2129
2130 crow::connections::systemBus->async_method_call(
2131 [asyncResp, ifaceId](const boost::system::error_code& ec,
2132 const sdbusplus::message_t& m) {
2133 afterDelete(asyncResp, ifaceId, ec, m);
2134 },
2135 "xyz.openbmc_project.Network",
2136 std::string("/xyz/openbmc_project/network/") + ifaceId,
2137 "xyz.openbmc_project.Object.Delete", "Delete");
2138 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002139}
2140
Ed Tanous1abe55e2018-09-05 08:30:59 -07002141} // namespace redfish