blob: 57fe24c431f79e3bd25e65a8eff16a9507a09556 [file] [log] [blame]
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
21#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "error_messages.hpp"
24#include "health.hpp"
Ed Tanous2c5875a2023-05-15 09:56:06 -070025#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "query.hpp"
27#include "registries/privilege_registry.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070028#include "utils/ip_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "utils/json_utils.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070030
Ed Tanous11ba3972022-07-11 09:50:41 -070031#include <boost/algorithm/string/classification.hpp>
32#include <boost/algorithm/string/split.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070033#include <boost/url/format.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050034
George Liu7a1dbc42022-12-07 16:03:22 +080035#include <array>
Ed Tanousa24526d2018-12-10 15:17:59 -080036#include <optional>
Joshi-Mansiab6554f2020-03-10 18:33:36 +053037#include <regex>
George Liu7a1dbc42022-12-07 16:03:22 +080038#include <string_view>
Ed Tanous77179532023-02-28 10:45:28 -080039#include <vector>
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010040
Ed Tanous1abe55e2018-09-05 08:30:59 -070041namespace redfish
42{
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010043
Ed Tanous4a0cb852018-10-15 07:55:04 -070044enum class LinkType
45{
46 Local,
47 Global
48};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010049
50/**
51 * Structure for keeping IPv4 data required by Redfish
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010052 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070053struct IPv4AddressData
54{
55 std::string id;
Ed Tanous4a0cb852018-10-15 07:55:04 -070056 std::string address;
57 std::string domain;
58 std::string gateway;
Ed Tanous1abe55e2018-09-05 08:30:59 -070059 std::string netmask;
60 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080061 LinkType linktype{};
62 bool isActive{};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010063};
64
65/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -050066 * Structure for keeping IPv6 data required by Redfish
67 */
68struct IPv6AddressData
69{
70 std::string id;
71 std::string address;
72 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080073 uint8_t prefixLength = 0;
Ravi Tejae48c0fc2019-04-16 08:37:20 -050074};
75/**
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010076 * Structure for keeping basic single Ethernet Interface information
77 * available from DBus
78 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070079struct EthernetInterfaceData
80{
Ed Tanous4a0cb852018-10-15 07:55:04 -070081 uint32_t speed;
Tejas Patil35fb5312021-09-20 15:35:20 +053082 size_t mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080083 bool autoNeg;
84 bool dnsEnabled;
85 bool ntpEnabled;
86 bool hostNameEnabled;
Johnathan Manteyaa05fb22020-01-08 12:08:44 -080087 bool linkUp;
Johnathan Manteyeeedda22019-10-29 16:09:52 -070088 bool nicEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -050089 bool ipv6AcceptRa;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080090 std::string dhcpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -070091 std::string operatingMode;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080092 std::string hostName;
93 std::string defaultGateway;
94 std::string ipv6DefaultGateway;
95 std::string macAddress;
Jiaqing Zhao17e22022022-04-14 18:58:06 +080096 std::optional<uint32_t> vlanId;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -050097 std::vector<std::string> nameServers;
98 std::vector<std::string> staticNameServers;
Jennifer Leed24bfc72019-03-05 13:03:37 -080099 std::vector<std::string> domainnames;
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100100};
101
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700102struct DHCPParameters
103{
104 std::optional<bool> dhcpv4Enabled;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800105 std::optional<bool> useDnsServers;
106 std::optional<bool> useNtpServers;
107 std::optional<bool> useDomainName;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700108 std::optional<std::string> dhcpv6OperatingMode;
109};
110
Ed Tanous4a0cb852018-10-15 07:55:04 -0700111// Helper function that changes bits netmask notation (i.e. /24)
112// into full dot notation
113inline std::string getNetmask(unsigned int bits)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700114{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700115 uint32_t value = 0xffffffff << (32 - bits);
116 std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
117 std::to_string((value >> 16) & 0xff) + "." +
118 std::to_string((value >> 8) & 0xff) + "." +
119 std::to_string(value & 0xff);
120 return netmask;
121}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100122
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800123inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700124 bool isIPv4)
125{
126 if (isIPv4)
127 {
128 return (
129 (inputDHCP ==
130 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
131 (inputDHCP ==
132 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
133 }
134 return ((inputDHCP ==
135 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
136 (inputDHCP ==
137 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
138}
139
Ed Tanous2c70f802020-09-28 14:29:23 -0700140inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700141{
142 if (isIPv4 && isIPv6)
143 {
144 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
145 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700146 if (isIPv4)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700147 {
148 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
149 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700150 if (isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700151 {
152 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
153 }
154 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
155}
156
Ed Tanous4a0cb852018-10-15 07:55:04 -0700157inline std::string
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500158 translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700159 bool isIPv4)
160{
161 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700162 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700163 return "Static";
164 }
165 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
166 {
167 if (isIPv4)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700168 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700169 return "IPv4LinkLocal";
170 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700171 return "LinkLocal";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700172 }
173 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
174 {
175 if (isIPv4)
176 {
177 return "DHCP";
178 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700179 return "DHCPv6";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700180 }
181 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
182 {
183 return "SLAAC";
184 }
185 return "";
186}
187
Ed Tanous02cad962022-06-30 16:50:15 -0700188inline bool extractEthernetInterfaceData(
189 const std::string& ethifaceId,
190 const dbus::utility::ManagedObjectType& dbusData,
191 EthernetInterfaceData& ethData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700192{
Ed Tanous4c9afe42019-05-03 16:59:57 -0700193 bool idFound = false;
Ed Tanous02cad962022-06-30 16:50:15 -0700194 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700195 {
Ed Tanous02cad962022-06-30 16:50:15 -0700196 for (const auto& ifacePair : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700197 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000198 if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700199 {
Ed Tanous4c9afe42019-05-03 16:59:57 -0700200 idFound = true;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700201 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500203 for (const auto& propertyPair : ifacePair.second)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700204 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700205 if (propertyPair.first == "MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500207 const std::string* mac =
Ed Tanousabf2add2019-01-22 16:40:12 -0800208 std::get_if<std::string>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700209 if (mac != nullptr)
210 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800211 ethData.macAddress = *mac;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700212 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700213 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700214 }
215 }
216 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
217 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500218 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700219 {
220 if (propertyPair.first == "Id")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700221 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500222 const uint32_t* id =
Ed Tanousabf2add2019-01-22 16:40:12 -0800223 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700224 if (id != nullptr)
225 {
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800226 ethData.vlanId = *id;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700227 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700228 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700229 }
230 }
231 else if (ifacePair.first ==
232 "xyz.openbmc_project.Network.EthernetInterface")
233 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500234 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700235 {
236 if (propertyPair.first == "AutoNeg")
237 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700238 const bool* autoNeg =
Ed Tanousabf2add2019-01-22 16:40:12 -0800239 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700240 if (autoNeg != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700241 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800242 ethData.autoNeg = *autoNeg;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700243 }
244 }
245 else if (propertyPair.first == "Speed")
246 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500247 const uint32_t* speed =
Ed Tanousabf2add2019-01-22 16:40:12 -0800248 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700249 if (speed != nullptr)
250 {
251 ethData.speed = *speed;
252 }
253 }
Tejas Patil35fb5312021-09-20 15:35:20 +0530254 else if (propertyPair.first == "MTU")
255 {
256 const uint32_t* mtuSize =
257 std::get_if<uint32_t>(&propertyPair.second);
258 if (mtuSize != nullptr)
259 {
260 ethData.mtuSize = *mtuSize;
261 }
262 }
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800263 else if (propertyPair.first == "LinkUp")
264 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500265 const bool* linkUp =
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800266 std::get_if<bool>(&propertyPair.second);
267 if (linkUp != nullptr)
268 {
269 ethData.linkUp = *linkUp;
270 }
271 }
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700272 else if (propertyPair.first == "NICEnabled")
273 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500274 const bool* nicEnabled =
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700275 std::get_if<bool>(&propertyPair.second);
276 if (nicEnabled != nullptr)
277 {
278 ethData.nicEnabled = *nicEnabled;
279 }
280 }
Ravi Tejab10d8db2022-05-24 09:04:12 -0500281 else if (propertyPair.first == "IPv6AcceptRA")
282 {
283 const bool* ipv6AcceptRa =
284 std::get_if<bool>(&propertyPair.second);
285 if (ipv6AcceptRa != nullptr)
286 {
287 ethData.ipv6AcceptRa = *ipv6AcceptRa;
288 }
289 }
RAJESWARAN THILLAIGOVINDANf85837b2019-04-04 05:18:53 -0500290 else if (propertyPair.first == "Nameservers")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700291 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500292 const std::vector<std::string>* nameservers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500293 std::get_if<std::vector<std::string>>(
Ed Tanous029573d2019-02-01 10:57:49 -0800294 &propertyPair.second);
295 if (nameservers != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700296 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700297 ethData.nameServers = *nameservers;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500298 }
299 }
300 else if (propertyPair.first == "StaticNameServers")
301 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500302 const std::vector<std::string>* staticNameServers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500303 std::get_if<std::vector<std::string>>(
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500304 &propertyPair.second);
305 if (staticNameServers != nullptr)
306 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700307 ethData.staticNameServers = *staticNameServers;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700308 }
309 }
manojkiraneda2a133282019-02-19 13:09:43 +0530310 else if (propertyPair.first == "DHCPEnabled")
311 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700312 const std::string* dhcpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700313 std::get_if<std::string>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700314 if (dhcpEnabled != nullptr)
manojkiraneda2a133282019-02-19 13:09:43 +0530315 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800316 ethData.dhcpEnabled = *dhcpEnabled;
manojkiraneda2a133282019-02-19 13:09:43 +0530317 }
318 }
Jennifer Leed24bfc72019-03-05 13:03:37 -0800319 else if (propertyPair.first == "DomainName")
320 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500321 const std::vector<std::string>* domainNames =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500322 std::get_if<std::vector<std::string>>(
Jennifer Leed24bfc72019-03-05 13:03:37 -0800323 &propertyPair.second);
324 if (domainNames != nullptr)
325 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700326 ethData.domainnames = *domainNames;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800327 }
328 }
Ravi Teja9010ec22019-08-01 23:30:25 -0500329 else if (propertyPair.first == "DefaultGateway")
330 {
331 const std::string* defaultGateway =
332 std::get_if<std::string>(&propertyPair.second);
333 if (defaultGateway != nullptr)
334 {
335 std::string defaultGatewayStr = *defaultGateway;
336 if (defaultGatewayStr.empty())
337 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800338 ethData.defaultGateway = "0.0.0.0";
Ravi Teja9010ec22019-08-01 23:30:25 -0500339 }
340 else
341 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800342 ethData.defaultGateway = defaultGatewayStr;
Ravi Teja9010ec22019-08-01 23:30:25 -0500343 }
344 }
345 }
346 else if (propertyPair.first == "DefaultGateway6")
347 {
348 const std::string* defaultGateway6 =
349 std::get_if<std::string>(&propertyPair.second);
350 if (defaultGateway6 != nullptr)
351 {
352 std::string defaultGateway6Str =
353 *defaultGateway6;
354 if (defaultGateway6Str.empty())
355 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800356 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500357 "0:0:0:0:0:0:0:0";
358 }
359 else
360 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800361 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500362 defaultGateway6Str;
363 }
364 }
365 }
Ed Tanous029573d2019-02-01 10:57:49 -0800366 }
367 }
368 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700369
Jian Zhang1e3f85e2022-12-13 13:50:35 +0800370 if (objpath.first == "/xyz/openbmc_project/network/dhcp")
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700371 {
372 if (ifacePair.first ==
373 "xyz.openbmc_project.Network.DHCPConfiguration")
374 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500375 for (const auto& propertyPair : ifacePair.second)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700376 {
377 if (propertyPair.first == "DNSEnabled")
378 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700379 const bool* dnsEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700380 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700381 if (dnsEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700382 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800383 ethData.dnsEnabled = *dnsEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700384 }
385 }
386 else if (propertyPair.first == "NTPEnabled")
387 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700388 const bool* ntpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700389 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700390 if (ntpEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700391 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800392 ethData.ntpEnabled = *ntpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700393 }
394 }
395 else if (propertyPair.first == "HostNameEnabled")
396 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700397 const bool* hostNameEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700398 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700399 if (hostNameEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700400 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800401 ethData.hostNameEnabled = *hostNameEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700402 }
403 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700404 }
405 }
406 }
Ed Tanous029573d2019-02-01 10:57:49 -0800407 // System configuration shows up in the global namespace, so no need
408 // to check eth number
409 if (ifacePair.first ==
410 "xyz.openbmc_project.Network.SystemConfiguration")
411 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500412 for (const auto& propertyPair : ifacePair.second)
Ed Tanous029573d2019-02-01 10:57:49 -0800413 {
414 if (propertyPair.first == "HostName")
415 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500416 const std::string* hostname =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500417 std::get_if<std::string>(&propertyPair.second);
Ed Tanous029573d2019-02-01 10:57:49 -0800418 if (hostname != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700419 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800420 ethData.hostName = *hostname;
Ed Tanous029573d2019-02-01 10:57:49 -0800421 }
422 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700423 }
424 }
425 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700426 }
Ed Tanous4c9afe42019-05-03 16:59:57 -0700427 return idFound;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700428}
429
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500430// Helper function that extracts data for single ethernet ipv6 address
Ed Tanous77179532023-02-28 10:45:28 -0800431inline void extractIPV6Data(const std::string& ethifaceId,
432 const dbus::utility::ManagedObjectType& dbusData,
433 std::vector<IPv6AddressData>& ipv6Config)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500434{
Patrick Williams89492a12023-05-10 07:51:34 -0500435 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
436 ethifaceId;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500437
438 // Since there might be several IPv6 configurations aligned with
439 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000440 for (const auto& objpath : dbusData)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500441 {
442 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800443 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500444 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800445 for (const auto& interface : objpath.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500446 {
447 if (interface.first == "xyz.openbmc_project.Network.IP")
448 {
Tony Lee353163e2022-11-23 11:06:10 +0800449 auto type = std::find_if(interface.second.begin(),
450 interface.second.end(),
451 [](const auto& property) {
452 return property.first == "Type";
453 });
454 if (type == interface.second.end())
455 {
456 continue;
457 }
458
459 const std::string* typeStr =
460 std::get_if<std::string>(&type->second);
461
462 if (typeStr == nullptr ||
463 (*typeStr !=
464 "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
465 {
466 continue;
467 }
468
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500469 // Instance IPv6AddressData structure, and set as
470 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800471 IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700472 ipv6Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800473 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800474 for (const auto& property : interface.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500475 {
476 if (property.first == "Address")
477 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500478 const std::string* address =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500479 std::get_if<std::string>(&property.second);
480 if (address != nullptr)
481 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700482 ipv6Address.address = *address;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500483 }
484 }
485 else if (property.first == "Origin")
486 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500487 const std::string* origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500488 std::get_if<std::string>(&property.second);
489 if (origin != nullptr)
490 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700491 ipv6Address.origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500492 translateAddressOriginDbusToRedfish(*origin,
493 false);
494 }
495 }
496 else if (property.first == "PrefixLength")
497 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500498 const uint8_t* prefix =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500499 std::get_if<uint8_t>(&property.second);
500 if (prefix != nullptr)
501 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700502 ipv6Address.prefixLength = *prefix;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500503 }
504 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600505 else if (property.first == "Type" ||
506 property.first == "Gateway")
507 {
508 // Type & Gateway is not used
509 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500510 else
511 {
Ed Tanous62598e32023-07-17 17:06:25 -0700512 BMCWEB_LOG_ERROR(
513 "Got extra property: {} on the {} object",
514 property.first, objpath.first.str);
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500515 }
516 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500517 }
518 }
519 }
520 }
521}
522
Ed Tanous4a0cb852018-10-15 07:55:04 -0700523// Helper function that extracts data for single ethernet ipv4 address
Ed Tanous77179532023-02-28 10:45:28 -0800524inline void extractIPData(const std::string& ethifaceId,
525 const dbus::utility::ManagedObjectType& dbusData,
526 std::vector<IPv4AddressData>& ipv4Config)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700527{
Patrick Williams89492a12023-05-10 07:51:34 -0500528 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
529 ethifaceId;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700530
531 // Since there might be several IPv4 configurations aligned with
532 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000533 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700534 {
535 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800536 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700537 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800538 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700539 {
540 if (interface.first == "xyz.openbmc_project.Network.IP")
541 {
Tony Lee353163e2022-11-23 11:06:10 +0800542 auto type = std::find_if(interface.second.begin(),
543 interface.second.end(),
544 [](const auto& property) {
545 return property.first == "Type";
546 });
547 if (type == interface.second.end())
548 {
549 continue;
550 }
551
552 const std::string* typeStr =
553 std::get_if<std::string>(&type->second);
554
555 if (typeStr == nullptr ||
556 (*typeStr !=
557 "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
558 {
559 continue;
560 }
561
Ed Tanous4a0cb852018-10-15 07:55:04 -0700562 // Instance IPv4AddressData structure, and set as
563 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800564 IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700565 ipv4Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800566 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800567 for (const auto& property : interface.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700568 {
569 if (property.first == "Address")
570 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500571 const std::string* address =
Ed Tanousabf2add2019-01-22 16:40:12 -0800572 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700573 if (address != nullptr)
574 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700575 ipv4Address.address = *address;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700576 }
577 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700578 else if (property.first == "Origin")
579 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500580 const std::string* origin =
Ed Tanousabf2add2019-01-22 16:40:12 -0800581 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700582 if (origin != nullptr)
583 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700584 ipv4Address.origin =
Ed Tanous4a0cb852018-10-15 07:55:04 -0700585 translateAddressOriginDbusToRedfish(*origin,
586 true);
587 }
588 }
589 else if (property.first == "PrefixLength")
590 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500591 const uint8_t* mask =
Ed Tanousabf2add2019-01-22 16:40:12 -0800592 std::get_if<uint8_t>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700593 if (mask != nullptr)
594 {
595 // convert it to the string
Ed Tanous2c70f802020-09-28 14:29:23 -0700596 ipv4Address.netmask = getNetmask(*mask);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700597 }
598 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600599 else if (property.first == "Type" ||
600 property.first == "Gateway")
601 {
602 // Type & Gateway is not used
603 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700604 else
605 {
Ed Tanous62598e32023-07-17 17:06:25 -0700606 BMCWEB_LOG_ERROR(
607 "Got extra property: {} on the {} object",
608 property.first, objpath.first.str);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700609 }
610 }
611 // Check if given address is local, or global
Ed Tanous2c70f802020-09-28 14:29:23 -0700612 ipv4Address.linktype =
Ed Tanous11ba3972022-07-11 09:50:41 -0700613 ipv4Address.address.starts_with("169.254.")
Johnathan Mantey18659d12019-06-07 10:26:29 -0700614 ? LinkType::Local
615 : LinkType::Global;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700616 }
617 }
618 }
619 }
620}
621
622/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700623 * @brief Deletes given IPv4 interface
Ed Tanous4a0cb852018-10-15 07:55:04 -0700624 *
625 * @param[in] ifaceId Id of interface whose IP should be deleted
Ed Tanous4a0cb852018-10-15 07:55:04 -0700626 * @param[in] ipHash DBus Hash id of IP that should be deleted
627 * @param[io] asyncResp Response object that will be returned to client
628 *
629 * @return None
630 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600631inline void deleteIPAddress(const std::string& ifaceId,
632 const std::string& ipHash,
633 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700634{
635 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800636 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700637 if (ec)
638 {
639 messages::internalError(asyncResp->res);
640 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700641 },
642 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600643 "/xyz/openbmc_project/network/" + ifaceId + ipHash,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700644 "xyz.openbmc_project.Object.Delete", "Delete");
645}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700646
Gunnar Mills244b6d52021-04-12 15:44:23 -0500647inline void updateIPv4DefaultGateway(
648 const std::string& ifaceId, const std::string& gateway,
649 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Teja9010ec22019-08-01 23:30:25 -0500650{
George Liu9ae226f2023-06-21 17:56:46 +0800651 sdbusplus::asio::setProperty(
652 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ravi Teja9010ec22019-08-01 23:30:25 -0500653 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9010ec22019-08-01 23:30:25 -0500654 "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
George Liu9ae226f2023-06-21 17:56:46 +0800655 gateway, [asyncResp](const boost::system::error_code& ec) {
656 if (ec)
657 {
658 messages::internalError(asyncResp->res);
659 return;
660 }
661 asyncResp->res.result(boost::beast::http::status::no_content);
662 });
Ravi Teja9010ec22019-08-01 23:30:25 -0500663}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700664/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700665 * @brief Creates a static IPv4 entry
Ed Tanous4a0cb852018-10-15 07:55:04 -0700666 *
Johnathan Mantey01784822019-06-18 12:44:21 -0700667 * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
668 * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
669 * @param[in] gateway IPv4 address of this interfaces gateway
670 * @param[in] address IPv4 address to assign to this interface
671 * @param[io] asyncResp Response object that will be returned to client
Ed Tanous4a0cb852018-10-15 07:55:04 -0700672 *
673 * @return None
674 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000675inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
676 const std::string& gateway, const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800677 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700678{
Ed Tanous002d39b2022-05-31 08:59:27 -0700679 auto createIpHandler =
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800680 [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
Ravi Teja9010ec22019-08-01 23:30:25 -0500681 if (ec)
682 {
683 messages::internalError(asyncResp->res);
684 return;
685 }
686 updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
687 };
688
Ed Tanous4a0cb852018-10-15 07:55:04 -0700689 crow::connections::systemBus->async_method_call(
Ravi Teja9010ec22019-08-01 23:30:25 -0500690 std::move(createIpHandler), "xyz.openbmc_project.Network",
Ed Tanous4a0cb852018-10-15 07:55:04 -0700691 "/xyz/openbmc_project/network/" + ifaceId,
692 "xyz.openbmc_project.Network.IP.Create", "IP",
Johnathan Mantey01784822019-06-18 12:44:21 -0700693 "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700694 gateway);
695}
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500696
697/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700698 * @brief Deletes the IPv6 entry for this interface and creates a replacement
699 * static IPv6 entry
700 *
701 * @param[in] ifaceId Id of interface upon which to create the IPv6 entry
702 * @param[in] id The unique hash entry identifying the DBus entry
703 * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
704 * @param[in] address IPv6 address to assign to this interface
705 * @param[io] asyncResp Response object that will be returned to client
706 *
707 * @return None
708 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600709
710enum class IpVersion
711{
712 IpV4,
713 IpV6
714};
715
716inline void deleteAndCreateIPAddress(
717 IpVersion version, const std::string& ifaceId, const std::string& id,
718 uint8_t prefixLength, const std::string& address,
719 const std::string& gateway,
720 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Johnathan Mantey01784822019-06-18 12:44:21 -0700721{
722 crow::connections::systemBus->async_method_call(
Ravi Teja9c5e5852023-02-26 21:33:52 -0600723 [asyncResp, version, ifaceId, address, prefixLength,
724 gateway](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700725 if (ec)
726 {
727 messages::internalError(asyncResp->res);
728 }
Ravi Teja9c5e5852023-02-26 21:33:52 -0600729 std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
730 protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
Ed Tanous002d39b2022-05-31 08:59:27 -0700731 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800732 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700733 if (ec2)
Johnathan Mantey01784822019-06-18 12:44:21 -0700734 {
735 messages::internalError(asyncResp->res);
736 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700737 },
738 "xyz.openbmc_project.Network",
739 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9c5e5852023-02-26 21:33:52 -0600740 "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
741 prefixLength, gateway);
Johnathan Mantey01784822019-06-18 12:44:21 -0700742 },
743 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600744 "/xyz/openbmc_project/network/" + ifaceId + id,
Johnathan Mantey01784822019-06-18 12:44:21 -0700745 "xyz.openbmc_project.Object.Delete", "Delete");
746}
747
748/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500749 * @brief Creates IPv6 with given data
750 *
751 * @param[in] ifaceId Id of interface whose IP should be added
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500752 * @param[in] prefixLength Prefix length that needs to be added
753 * @param[in] address IP address that needs to be added
754 * @param[io] asyncResp Response object that will be returned to client
755 *
756 * @return None
757 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500758inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
759 const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800760 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500761{
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500762 auto createIpHandler =
763 [asyncResp, address](const boost::system::error_code& ec) {
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500764 if (ec)
765 {
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500766 if (ec == boost::system::errc::io_error)
767 {
768 messages::propertyValueFormatError(asyncResp->res, address,
769 "Address");
770 }
771 else
772 {
773 messages::internalError(asyncResp->res);
774 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500775 }
776 };
777 // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500778 // does not have associated gateway property
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500779 crow::connections::systemBus->async_method_call(
780 std::move(createIpHandler), "xyz.openbmc_project.Network",
781 "/xyz/openbmc_project/network/" + ifaceId,
782 "xyz.openbmc_project.Network.IP.Create", "IP",
783 "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
784 "");
785}
786
Ed Tanous4a0cb852018-10-15 07:55:04 -0700787/**
788 * Function that retrieves all properties for given Ethernet Interface
789 * Object
790 * from EntityManager Network Manager
791 * @param ethiface_id a eth interface id to query on DBus
792 * @param callback a function that shall be called to convert Dbus output
793 * into JSON
794 */
795template <typename CallbackFunc>
Ed Tanous81ce6092020-12-17 16:54:55 +0000796void getEthernetIfaceData(const std::string& ethifaceId,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500797 CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700798{
George Liuf5892d02023-03-01 10:37:08 +0800799 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
800 dbus::utility::getManagedObjects(
801 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800802 [ethifaceId{std::string{ethifaceId}},
803 callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700804 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700805 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700806 EthernetInterfaceData ethData{};
Ed Tanous77179532023-02-28 10:45:28 -0800807 std::vector<IPv4AddressData> ipv4Data;
808 std::vector<IPv6AddressData> ipv6Data;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700809
Ed Tanous8b242752023-06-27 17:17:13 -0700810 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700811 {
812 callback(false, ethData, ipv4Data, ipv6Data);
813 return;
814 }
815
816 bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
817 if (!found)
818 {
819 callback(false, ethData, ipv4Data, ipv6Data);
820 return;
821 }
822
823 extractIPData(ethifaceId, resp, ipv4Data);
824 // Fix global GW
825 for (IPv4AddressData& ipv4 : ipv4Data)
826 {
827 if (((ipv4.linktype == LinkType::Global) &&
828 (ipv4.gateway == "0.0.0.0")) ||
829 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700830 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700831 ipv4.gateway = ethData.defaultGateway;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700832 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700833 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700834
Ed Tanous002d39b2022-05-31 08:59:27 -0700835 extractIPV6Data(ethifaceId, resp, ipv6Data);
836 // Finally make a callback with useful data
837 callback(true, ethData, ipv4Data, ipv6Data);
George Liuf5892d02023-03-01 10:37:08 +0800838 });
Ed Tanous271584a2019-07-09 16:24:22 -0700839}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700840
841/**
842 * Function that retrieves all Ethernet Interfaces available through Network
843 * Manager
844 * @param callback a function that shall be called to convert Dbus output
845 * into JSON.
846 */
847template <typename CallbackFunc>
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500848void getEthernetIfaceList(CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700849{
George Liuf5892d02023-03-01 10:37:08 +0800850 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
851 dbus::utility::getManagedObjects(
852 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800853 [callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700854 const boost::system::error_code& ec,
George Liuf5892d02023-03-01 10:37:08 +0800855 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700856 // Callback requires vector<string> to retrieve all available
857 // ethernet interfaces
Ed Tanous77179532023-02-28 10:45:28 -0800858 std::vector<std::string> ifaceList;
Ed Tanous002d39b2022-05-31 08:59:27 -0700859 ifaceList.reserve(resp.size());
Ed Tanous8b242752023-06-27 17:17:13 -0700860 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700861 {
862 callback(false, ifaceList);
863 return;
864 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700865
Ed Tanous002d39b2022-05-31 08:59:27 -0700866 // Iterate over all retrieved ObjectPaths.
867 for (const auto& objpath : resp)
868 {
869 // And all interfaces available for certain ObjectPath.
870 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700871 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700872 // If interface is
873 // xyz.openbmc_project.Network.EthernetInterface, this is
874 // what we're looking for.
875 if (interface.first ==
876 "xyz.openbmc_project.Network.EthernetInterface")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700877 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700878 std::string ifaceId = objpath.first.filename();
879 if (ifaceId.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700880 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700881 continue;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700882 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700883 // and put it into output vector.
Ed Tanous77179532023-02-28 10:45:28 -0800884 ifaceList.emplace_back(ifaceId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700885 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700886 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700887 }
Ed Tanous2c5875a2023-05-15 09:56:06 -0700888
889 std::sort(ifaceList.begin(), ifaceList.end(),
890 AlphanumLess<std::string>());
891
Ed Tanous002d39b2022-05-31 08:59:27 -0700892 // Finally make a callback with useful data
893 callback(true, ifaceList);
George Liuf5892d02023-03-01 10:37:08 +0800894 });
Ed Tanous271584a2019-07-09 16:24:22 -0700895}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100896
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700897inline void
898 handleHostnamePatch(const std::string& hostname,
899 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700900{
Ed Tanousbf648f72021-06-03 15:00:14 -0700901 // SHOULD handle host names of up to 255 characters(RFC 1123)
902 if (hostname.length() > 255)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700903 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700904 messages::propertyValueFormatError(asyncResp->res, hostname,
905 "HostName");
906 return;
907 }
George Liu9ae226f2023-06-21 17:56:46 +0800908 sdbusplus::asio::setProperty(
909 *crow::connections::systemBus, "xyz.openbmc_project.Network",
910 "/xyz/openbmc_project/network/config",
911 "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800912 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700913 if (ec)
914 {
915 messages::internalError(asyncResp->res);
916 }
George Liu9ae226f2023-06-21 17:56:46 +0800917 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700918}
919
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700920inline void
Tejas Patil35fb5312021-09-20 15:35:20 +0530921 handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
922 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
923{
Patrick Williams89492a12023-05-10 07:51:34 -0500924 sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
925 ifaceId;
George Liu9ae226f2023-06-21 17:56:46 +0800926 sdbusplus::asio::setProperty(
927 *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
928 "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800929 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700930 if (ec)
931 {
932 messages::internalError(asyncResp->res);
933 }
George Liu9ae226f2023-06-21 17:56:46 +0800934 });
Tejas Patil35fb5312021-09-20 15:35:20 +0530935}
936
937inline void
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700938 handleDomainnamePatch(const std::string& ifaceId,
939 const std::string& domainname,
940 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700941{
942 std::vector<std::string> vectorDomainname = {domainname};
George Liu9ae226f2023-06-21 17:56:46 +0800943 sdbusplus::asio::setProperty(
944 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ed Tanousbf648f72021-06-03 15:00:14 -0700945 "/xyz/openbmc_project/network/" + ifaceId,
Ed Tanousbf648f72021-06-03 15:00:14 -0700946 "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
George Liu9ae226f2023-06-21 17:56:46 +0800947 vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
948 if (ec)
949 {
950 messages::internalError(asyncResp->res);
951 }
952 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700953}
954
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700955inline bool isHostnameValid(const std::string& hostname)
Ed Tanousbf648f72021-06-03 15:00:14 -0700956{
957 // A valid host name can never have the dotted-decimal form (RFC 1123)
958 if (std::all_of(hostname.begin(), hostname.end(), ::isdigit))
959 {
960 return false;
961 }
962 // Each label(hostname/subdomains) within a valid FQDN
963 // MUST handle host names of up to 63 characters (RFC 1123)
964 // labels cannot start or end with hyphens (RFC 952)
965 // labels can start with numbers (RFC 1123)
Ed Tanous4b242742023-05-11 09:51:51 -0700966 const static std::regex pattern(
Ed Tanousbf648f72021-06-03 15:00:14 -0700967 "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
968
969 return std::regex_match(hostname, pattern);
970}
971
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700972inline bool isDomainnameValid(const std::string& domainname)
Ed Tanousbf648f72021-06-03 15:00:14 -0700973{
974 // Can have multiple subdomains
975 // Top Level Domain's min length is 2 character
Ed Tanous4b242742023-05-11 09:51:51 -0700976 const static std::regex pattern(
George Liu0fda0f12021-11-16 10:06:17 +0800977 "^([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 -0700978
979 return std::regex_match(domainname, pattern);
980}
981
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700982inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
983 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700984{
985 // Total length of FQDN must not exceed 255 characters(RFC 1035)
986 if (fqdn.length() > 255)
987 {
988 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
989 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700990 }
991
Ed Tanousbf648f72021-06-03 15:00:14 -0700992 size_t pos = fqdn.find('.');
993 if (pos == std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700994 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700995 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
996 return;
997 }
zhanghch058d1b46d2021-04-01 11:18:24 +0800998
Ed Tanousbf648f72021-06-03 15:00:14 -0700999 std::string hostname;
1000 std::string domainname;
1001 domainname = (fqdn).substr(pos + 1);
1002 hostname = (fqdn).substr(0, pos);
1003
1004 if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1005 {
1006 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1007 return;
1008 }
1009
1010 handleHostnamePatch(hostname, asyncResp);
1011 handleDomainnamePatch(ifaceId, domainname, asyncResp);
1012}
1013
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001014inline void
1015 handleMACAddressPatch(const std::string& ifaceId,
1016 const std::string& macAddress,
1017 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001018{
Johnathan Mantey58283f42022-08-15 14:38:36 -07001019 static constexpr std::string_view dbusNotAllowedError =
1020 "xyz.openbmc_project.Common.Error.NotAllowed";
1021
George Liu9ae226f2023-06-21 17:56:46 +08001022 sdbusplus::asio::setProperty(
1023 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1024 "/xyz/openbmc_project/network/" + ifaceId,
1025 "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
1026 [asyncResp](const boost::system::error_code& ec,
1027 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001028 if (ec)
1029 {
Johnathan Mantey58283f42022-08-15 14:38:36 -07001030 const sd_bus_error* err = msg.get_error();
1031 if (err == nullptr)
1032 {
1033 messages::internalError(asyncResp->res);
1034 return;
1035 }
1036 if (err->name == dbusNotAllowedError)
1037 {
1038 messages::propertyNotWritable(asyncResp->res, "MACAddress");
1039 return;
1040 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001041 messages::internalError(asyncResp->res);
1042 return;
1043 }
George Liu9ae226f2023-06-21 17:56:46 +08001044 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001045}
1046
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001047inline void setDHCPEnabled(const std::string& ifaceId,
1048 const std::string& propertyName, const bool v4Value,
1049 const bool v6Value,
1050 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001051{
1052 const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
George Liu9ae226f2023-06-21 17:56:46 +08001053 sdbusplus::asio::setProperty(
1054 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1055 "/xyz/openbmc_project/network/" + ifaceId,
1056 "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001057 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001058 if (ec)
1059 {
Ed Tanous62598e32023-07-17 17:06:25 -07001060 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001061 messages::internalError(asyncResp->res);
1062 return;
1063 }
1064 messages::success(asyncResp->res);
George Liu9ae226f2023-06-21 17:56:46 +08001065 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001066}
1067
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001068inline void setEthernetInterfaceBoolProperty(
Ed Tanousbf648f72021-06-03 15:00:14 -07001069 const std::string& ifaceId, const std::string& propertyName,
1070 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1071{
George Liu9ae226f2023-06-21 17:56:46 +08001072 sdbusplus::asio::setProperty(
1073 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1074 "/xyz/openbmc_project/network/" + ifaceId,
1075 "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001076 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001077 if (ec)
1078 {
Ed Tanous62598e32023-07-17 17:06:25 -07001079 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001080 messages::internalError(asyncResp->res);
1081 return;
1082 }
George Liu9ae226f2023-06-21 17:56:46 +08001083 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001084}
1085
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001086inline void setDHCPv4Config(const std::string& propertyName, const bool& value,
1087 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001088{
Ed Tanous62598e32023-07-17 17:06:25 -07001089 BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
George Liu9ae226f2023-06-21 17:56:46 +08001090 sdbusplus::asio::setProperty(
1091 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1092 "/xyz/openbmc_project/network/dhcp",
1093 "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001094 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001095 if (ec)
1096 {
Ed Tanous62598e32023-07-17 17:06:25 -07001097 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001098 messages::internalError(asyncResp->res);
1099 return;
1100 }
George Liu9ae226f2023-06-21 17:56:46 +08001101 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001102}
1103
Ravi Tejab10d8db2022-05-24 09:04:12 -05001104inline void handleSLAACAutoConfigPatch(
1105 const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1106 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1107{
1108 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1109 path /= ifaceId;
1110 sdbusplus::asio::setProperty(
1111 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1112 "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1113 ipv6AutoConfigEnabled,
1114 [asyncResp](const boost::system::error_code& ec) {
1115 if (ec)
1116 {
1117 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1118 messages::internalError(asyncResp->res);
1119 return;
1120 }
1121 messages::success(asyncResp->res);
1122 });
1123}
1124
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001125inline void handleDHCPPatch(const std::string& ifaceId,
1126 const EthernetInterfaceData& ethData,
1127 const DHCPParameters& v4dhcpParms,
1128 const DHCPParameters& v6dhcpParms,
1129 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001130{
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001131 bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1132 bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
Ed Tanousbf648f72021-06-03 15:00:14 -07001133
1134 bool nextv4DHCPState =
1135 v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
1136
1137 bool nextv6DHCPState{};
1138 if (v6dhcpParms.dhcpv6OperatingMode)
1139 {
Ravi Tejab10d8db2022-05-24 09:04:12 -05001140 if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
Ed Tanousbf648f72021-06-03 15:00:14 -07001141 (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
1142 {
1143 messages::propertyValueFormatError(asyncResp->res,
1144 *v6dhcpParms.dhcpv6OperatingMode,
1145 "OperatingMode");
1146 return;
1147 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001148 nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
Ed Tanousbf648f72021-06-03 15:00:14 -07001149 }
1150 else
1151 {
1152 nextv6DHCPState = ipv6Active;
1153 }
1154
1155 bool nextDNS{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001156 if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001157 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001158 if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001159 {
1160 messages::generalError(asyncResp->res);
1161 return;
1162 }
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 (v4dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001166 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001167 nextDNS = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001168 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001169 else if (v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001170 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001171 nextDNS = *v6dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001172 }
1173 else
1174 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001175 nextDNS = ethData.dnsEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001176 }
1177
1178 bool nextNTP{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001179 if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001180 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001181 if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001182 {
1183 messages::generalError(asyncResp->res);
1184 return;
1185 }
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 (v4dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001189 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001190 nextNTP = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001191 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001192 else if (v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001193 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001194 nextNTP = *v6dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001195 }
1196 else
1197 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001198 nextNTP = ethData.ntpEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001199 }
1200
1201 bool nextUseDomain{};
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001202 if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001203 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001204 if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001205 {
1206 messages::generalError(asyncResp->res);
1207 return;
1208 }
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 (v4dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001212 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001213 nextUseDomain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001214 }
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001215 else if (v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001216 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001217 nextUseDomain = *v6dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001218 }
1219 else
1220 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001221 nextUseDomain = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001222 }
1223
Ed Tanous62598e32023-07-17 17:06:25 -07001224 BMCWEB_LOG_DEBUG("set DHCPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001225 setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
1226 asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001227 BMCWEB_LOG_DEBUG("set DNSEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001228 setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001229 BMCWEB_LOG_DEBUG("set NTPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001230 setDHCPv4Config("NTPEnabled", nextNTP, asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001231 BMCWEB_LOG_DEBUG("set HostNameEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001232 setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp);
1233}
1234
Ed Tanous77179532023-02-28 10:45:28 -08001235inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
1236 const std::vector<IPv4AddressData>::const_iterator& head,
1237 const std::vector<IPv4AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001238{
1239 return std::find_if(head, end, [](const IPv4AddressData& value) {
1240 return value.origin == "Static";
1241 });
1242}
1243
Ed Tanous77179532023-02-28 10:45:28 -08001244inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
1245 const std::vector<IPv6AddressData>::const_iterator& head,
1246 const std::vector<IPv6AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001247{
1248 return std::find_if(head, end, [](const IPv6AddressData& value) {
1249 return value.origin == "Static";
1250 });
1251}
1252
Ed Tanous77179532023-02-28 10:45:28 -08001253inline void
Ed Tanousddd70dc2023-03-01 16:00:27 -08001254 handleIPv4StaticPatch(const std::string& ifaceId,
1255 nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001256 const std::vector<IPv4AddressData>& ipv4Data,
1257 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001258{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001259 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001260 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001261 messages::propertyValueTypeError(asyncResp->res, input,
1262 "IPv4StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001263 return;
1264 }
1265
1266 unsigned entryIdx = 1;
1267 // Find the first static IP address currently active on the NIC and
1268 // match it to the first JSON element in the IPv4StaticAddresses array.
1269 // Match each subsequent JSON element to the next static IP programmed
1270 // into the NIC.
Ed Tanous77179532023-02-28 10:45:28 -08001271 std::vector<IPv4AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001272 getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
1273
1274 for (nlohmann::json& thisJson : input)
1275 {
Patrick Williams89492a12023-05-10 07:51:34 -05001276 std::string pathString = "IPv4StaticAddresses/" +
1277 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001278
1279 if (!thisJson.is_null() && !thisJson.empty())
1280 {
1281 std::optional<std::string> address;
1282 std::optional<std::string> subnetMask;
1283 std::optional<std::string> gateway;
1284
1285 if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1286 address, "SubnetMask", subnetMask,
1287 "Gateway", gateway))
1288 {
Ed Tanousf818b042022-06-27 13:17:35 -07001289 messages::propertyValueFormatError(asyncResp->res, thisJson,
1290 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001291 return;
1292 }
1293
1294 // Find the address/subnet/gateway values. Any values that are
1295 // not explicitly provided are assumed to be unmodified from the
1296 // current state of the interface. Merge existing state into the
1297 // current request.
Ed Tanousbf648f72021-06-03 15:00:14 -07001298 if (address)
1299 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001300 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001301 {
1302 messages::propertyValueFormatError(asyncResp->res, *address,
1303 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001304 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001305 }
1306 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001307 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001308 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001309 address = (nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001310 }
1311 else
1312 {
1313 messages::propertyMissing(asyncResp->res,
1314 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001315 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001316 }
1317
Ed Tanouse01d0c32023-06-30 13:21:32 -07001318 uint8_t prefixLength = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001319 if (subnetMask)
1320 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001321 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1322 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001323 {
1324 messages::propertyValueFormatError(
1325 asyncResp->res, *subnetMask,
1326 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001327 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001328 }
1329 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001330 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001331 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001332 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1333 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001334 {
1335 messages::propertyValueFormatError(
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001336 asyncResp->res, nicIpEntry->netmask,
Ed Tanousbf648f72021-06-03 15:00:14 -07001337 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001338 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001339 }
1340 }
1341 else
1342 {
1343 messages::propertyMissing(asyncResp->res,
1344 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001345 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001346 }
1347
1348 if (gateway)
1349 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001350 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001351 {
1352 messages::propertyValueFormatError(asyncResp->res, *gateway,
1353 pathString + "/Gateway");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001354 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001355 }
1356 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001357 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001358 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001359 gateway = nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001360 }
1361 else
1362 {
1363 messages::propertyMissing(asyncResp->res,
1364 pathString + "/Gateway");
Ed Tanousbf648f72021-06-03 15:00:14 -07001365 return;
1366 }
1367
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001368 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001369 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001370 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
Ed Tanouse01d0c32023-06-30 13:21:32 -07001371 nicIpEntry->id, prefixLength, *gateway,
1372 *address, asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001373 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1374 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001375 }
1376 else
1377 {
1378 createIPv4(ifaceId, prefixLength, *gateway, *address,
1379 asyncResp);
1380 }
1381 entryIdx++;
1382 }
1383 else
1384 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001385 if (nicIpEntry == ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001386 {
1387 // Requesting a DELETE/DO NOT MODIFY action for an item
1388 // that isn't present on the eth(n) interface. Input JSON is
1389 // in error, so bail out.
1390 if (thisJson.is_null())
1391 {
1392 messages::resourceCannotBeDeleted(asyncResp->res);
1393 return;
1394 }
Ed Tanousf818b042022-06-27 13:17:35 -07001395 messages::propertyValueFormatError(asyncResp->res, thisJson,
1396 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001397 return;
1398 }
1399
1400 if (thisJson.is_null())
1401 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001402 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001403 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001404 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001405 {
Patrick Williams89492a12023-05-10 07:51:34 -05001406 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1407 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001408 }
1409 entryIdx++;
1410 }
1411 }
1412}
1413
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001414inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001415 const std::string& ifaceId,
1416 const std::vector<std::string>& updatedStaticNameServers,
1417 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1418{
George Liu9ae226f2023-06-21 17:56:46 +08001419 sdbusplus::asio::setProperty(
1420 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1421 "/xyz/openbmc_project/network/" + ifaceId,
1422 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1423 updatedStaticNameServers,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001424 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001425 if (ec)
1426 {
1427 messages::internalError(asyncResp->res);
1428 return;
1429 }
George Liu9ae226f2023-06-21 17:56:46 +08001430 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001431}
1432
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001433inline void handleIPv6StaticAddressesPatch(
Ed Tanousddd70dc2023-03-01 16:00:27 -08001434 const std::string& ifaceId, const nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001435 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001436 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1437{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001438 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001439 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001440 messages::propertyValueTypeError(asyncResp->res, input,
1441 "IPv6StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001442 return;
1443 }
1444 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001445 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001446 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1447 for (const nlohmann::json& thisJson : input)
1448 {
Patrick Williams89492a12023-05-10 07:51:34 -05001449 std::string pathString = "IPv6StaticAddresses/" +
1450 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001451
1452 if (!thisJson.is_null() && !thisJson.empty())
1453 {
1454 std::optional<std::string> address;
1455 std::optional<uint8_t> prefixLength;
1456 nlohmann::json thisJsonCopy = thisJson;
1457 if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1458 address, "PrefixLength", prefixLength))
1459 {
Ed Tanousf818b042022-06-27 13:17:35 -07001460 messages::propertyValueFormatError(asyncResp->res, thisJson,
1461 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001462 return;
1463 }
1464
Ed Tanous543f4402022-01-06 13:12:53 -08001465 const std::string* addr = nullptr;
1466 uint8_t prefix = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001467
1468 // Find the address and prefixLength values. Any values that are
1469 // not explicitly provided are assumed to be unmodified from the
1470 // current state of the interface. Merge existing state into the
1471 // current request.
1472 if (address)
1473 {
1474 addr = &(*address);
1475 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001476 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001477 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001478 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001479 }
1480 else
1481 {
1482 messages::propertyMissing(asyncResp->res,
1483 pathString + "/Address");
1484 return;
1485 }
1486
1487 if (prefixLength)
1488 {
1489 prefix = *prefixLength;
1490 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001491 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001492 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001493 prefix = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001494 }
1495 else
1496 {
1497 messages::propertyMissing(asyncResp->res,
1498 pathString + "/PrefixLength");
1499 return;
1500 }
1501
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001502 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001503 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001504 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1505 nicIpEntry->id, prefix, "", *addr,
1506 asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001507 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1508 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001509 }
1510 else
1511 {
1512 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1513 }
1514 entryIdx++;
1515 }
1516 else
1517 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001518 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001519 {
1520 // Requesting a DELETE/DO NOT MODIFY action for an item
1521 // that isn't present on the eth(n) interface. Input JSON is
1522 // in error, so bail out.
1523 if (thisJson.is_null())
1524 {
1525 messages::resourceCannotBeDeleted(asyncResp->res);
1526 return;
1527 }
Ed Tanousf818b042022-06-27 13:17:35 -07001528 messages::propertyValueFormatError(asyncResp->res, thisJson,
1529 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001530 return;
1531 }
1532
1533 if (thisJson.is_null())
1534 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001535 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001536 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001537 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001538 {
Patrick Williams89492a12023-05-10 07:51:34 -05001539 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1540 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001541 }
1542 entryIdx++;
1543 }
1544 }
1545}
1546
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001547inline std::string extractParentInterfaceName(const std::string& ifaceId)
1548{
1549 std::size_t pos = ifaceId.find('_');
1550 return ifaceId.substr(0, pos);
1551}
1552
Ed Tanous77179532023-02-28 10:45:28 -08001553inline void
1554 parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1555 const std::string& ifaceId,
1556 const EthernetInterfaceData& ethData,
1557 const std::vector<IPv4AddressData>& ipv4Data,
1558 const std::vector<IPv6AddressData>& ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001559{
Ed Tanousbf648f72021-06-03 15:00:14 -07001560 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1561 jsonResponse["Id"] = ifaceId;
Ed Tanousef4c65b2023-04-24 15:28:50 -07001562 jsonResponse["@odata.id"] = boost::urls::format(
1563 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001564 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1565
Willy Tu13451e32023-05-24 16:08:18 -07001566 if constexpr (bmcwebEnableHealthPopulate)
1567 {
1568 constexpr std::array<std::string_view, 1> inventoryForEthernet = {
1569 "xyz.openbmc_project.Inventory.Item.Ethernet"};
1570 auto health = std::make_shared<HealthPopulate>(asyncResp);
1571 dbus::utility::getSubTreePaths(
1572 "/", 0, inventoryForEthernet,
1573 [health](const boost::system::error_code& ec,
1574 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1575 if (ec)
1576 {
1577 return;
1578 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001579
Willy Tu13451e32023-05-24 16:08:18 -07001580 health->inventory = resp;
1581 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001582
Willy Tu13451e32023-05-24 16:08:18 -07001583 health->populate();
1584 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001585
1586 if (ethData.nicEnabled)
1587 {
Johnathan Mantey0ef0e282022-11-15 12:15:02 -08001588 jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
Ed Tanousbf648f72021-06-03 15:00:14 -07001589 jsonResponse["Status"]["State"] = "Enabled";
1590 }
1591 else
1592 {
1593 jsonResponse["LinkStatus"] = "NoLink";
1594 jsonResponse["Status"]["State"] = "Disabled";
1595 }
1596
Ed Tanousbf648f72021-06-03 15:00:14 -07001597 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301598 jsonResponse["MTUSize"] = ethData.mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001599 jsonResponse["MACAddress"] = ethData.macAddress;
Ed Tanousbf648f72021-06-03 15:00:14 -07001600 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001601 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1602 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled;
1603 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled;
1604 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001605
1606 jsonResponse["DHCPv6"]["OperatingMode"] =
Ravi Tejab10d8db2022-05-24 09:04:12 -05001607 translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
Ed Tanousbf648f72021-06-03 15:00:14 -07001608 : "Disabled";
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001609 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled;
1610 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled;
1611 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001612 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1613 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001614
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001615 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001616 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001617 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001618
1619 // When domain name is empty then it means, that it is a network
1620 // without domain names, and the host name itself must be treated as
1621 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001622 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001623 if (!ethData.domainnames.empty())
1624 {
1625 fqdn += "." + ethData.domainnames[0];
1626 }
1627 jsonResponse["FQDN"] = fqdn;
1628 }
1629
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001630 if (ethData.vlanId)
1631 {
1632 jsonResponse["EthernetInterfaceType"] = "Virtual";
1633 jsonResponse["VLAN"]["VLANEnable"] = true;
1634 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1635 jsonResponse["VLAN"]["Tagged"] = true;
1636
1637 nlohmann::json::array_t relatedInterfaces;
1638 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1639 parentInterface["@odata.id"] =
1640 boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
1641 extractParentInterfaceName(ifaceId));
1642 jsonResponse["Links"]["RelatedInterfaces"] =
1643 std::move(relatedInterfaces);
1644 }
1645 else
1646 {
1647 jsonResponse["EthernetInterfaceType"] = "Physical";
1648 }
1649
Ed Tanousbf648f72021-06-03 15:00:14 -07001650 jsonResponse["NameServers"] = ethData.nameServers;
1651 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1652
1653 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1654 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1655 ipv4Array = nlohmann::json::array();
1656 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001657 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001658 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001659 std::string gatewayStr = ipv4Config.gateway;
1660 if (gatewayStr.empty())
1661 {
1662 gatewayStr = "0.0.0.0";
1663 }
Ed Tanous14766872022-03-15 10:44:42 -07001664 nlohmann::json::object_t ipv4;
1665 ipv4["AddressOrigin"] = ipv4Config.origin;
1666 ipv4["SubnetMask"] = ipv4Config.netmask;
1667 ipv4["Address"] = ipv4Config.address;
1668 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001669
Ed Tanousbf648f72021-06-03 15:00:14 -07001670 if (ipv4Config.origin == "Static")
1671 {
Ed Tanous14766872022-03-15 10:44:42 -07001672 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001673 }
Ed Tanous14766872022-03-15 10:44:42 -07001674
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001675 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001676 }
1677
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001678 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001679 if (ipv6GatewayStr.empty())
1680 {
1681 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1682 }
1683
1684 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1685
1686 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1687 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1688 ipv6Array = nlohmann::json::array();
1689 ipv6StaticArray = nlohmann::json::array();
1690 nlohmann::json& ipv6AddrPolicyTable =
1691 jsonResponse["IPv6AddressPolicyTable"];
1692 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001693 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001694 {
Ed Tanous14766872022-03-15 10:44:42 -07001695 nlohmann::json::object_t ipv6;
1696 ipv6["Address"] = ipv6Config.address;
1697 ipv6["PrefixLength"] = ipv6Config.prefixLength;
1698 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05001699
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001700 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07001701 if (ipv6Config.origin == "Static")
1702 {
Ed Tanous14766872022-03-15 10:44:42 -07001703 nlohmann::json::object_t ipv6Static;
1704 ipv6Static["Address"] = ipv6Config.address;
1705 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001706 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07001707 }
1708 }
1709}
1710
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001711inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1712 const std::string& ifaceId,
1713 const boost::system::error_code& ec,
1714 const sdbusplus::message_t& m)
1715{
1716 if (!ec)
1717 {
1718 return;
1719 }
1720 const sd_bus_error* dbusError = m.get_error();
1721 if (dbusError == nullptr)
1722 {
1723 messages::internalError(asyncResp->res);
1724 return;
1725 }
Ed Tanous62598e32023-07-17 17:06:25 -07001726 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001727
1728 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1729 dbusError->name)
1730 {
1731 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1732 ifaceId);
1733 return;
1734 }
1735 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1736 dbusError->name)
1737 {
1738 messages::resourceCannotBeDeleted(asyncResp->res);
1739 return;
1740 }
1741 messages::internalError(asyncResp->res);
1742}
1743
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001744inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1745 const std::string& parentInterfaceUri,
1746 const std::string& vlanInterface,
1747 const boost::system::error_code& ec,
1748 const sdbusplus::message_t& m
1749
1750)
1751{
1752 if (ec)
1753 {
1754 const sd_bus_error* dbusError = m.get_error();
1755 if (dbusError == nullptr)
1756 {
1757 messages::internalError(asyncResp->res);
1758 return;
1759 }
Ed Tanous62598e32023-07-17 17:06:25 -07001760 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001761
1762 if (std::string_view(
1763 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1764 dbusError->name)
1765 {
1766 messages::propertyValueNotInList(
1767 asyncResp->res, parentInterfaceUri,
1768 "Links/RelatedInterfaces/0/@odata.id");
1769 return;
1770 }
1771 if (std::string_view(
1772 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1773 dbusError->name)
1774 {
1775 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1776 "Id", vlanInterface);
1777 return;
1778 }
1779 messages::internalError(asyncResp->res);
1780 return;
1781 }
1782
1783 const boost::urls::url vlanInterfaceUri = boost::urls::format(
1784 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1785 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1786}
1787
Ed Tanousbf648f72021-06-03 15:00:14 -07001788inline void requestEthernetInterfacesRoutes(App& app)
1789{
1790 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07001791 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07001792 .methods(boost::beast::http::verb::get)(
1793 [&app](const crow::Request& req,
1794 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001795 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001796 {
1797 return;
1798 }
1799
1800 asyncResp->res.jsonValue["@odata.type"] =
1801 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1802 asyncResp->res.jsonValue["@odata.id"] =
1803 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1804 asyncResp->res.jsonValue["Name"] =
1805 "Ethernet Network Interface Collection";
1806 asyncResp->res.jsonValue["Description"] =
1807 "Collection of EthernetInterfaces for this Manager";
1808
1809 // Get eth interface list, and call the below callback for JSON
1810 // preparation
1811 getEthernetIfaceList(
Ed Tanous77179532023-02-28 10:45:28 -08001812 [asyncResp](const bool& success,
1813 const std::vector<std::string>& ifaceList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001814 if (!success)
1815 {
1816 messages::internalError(asyncResp->res);
1817 return;
1818 }
1819
1820 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1821 ifaceArray = nlohmann::json::array();
Ed Tanous002d39b2022-05-31 08:59:27 -07001822 for (const std::string& ifaceItem : ifaceList)
1823 {
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001824 nlohmann::json::object_t iface;
1825 iface["@odata.id"] = boost::urls::format(
1826 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1827 ifaceItem);
1828 ifaceArray.push_back(std::move(iface));
Ed Tanous002d39b2022-05-31 08:59:27 -07001829 }
Jason M. Billsf12894f2018-10-09 12:45:45 -07001830
Ed Tanous002d39b2022-05-31 08:59:27 -07001831 asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1832 asyncResp->res.jsonValue["@odata.id"] =
1833 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1834 });
1835 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001836
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001837 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1838 .privileges(redfish::privileges::postEthernetInterfaceCollection)
1839 .methods(boost::beast::http::verb::post)(
1840 [&app](const crow::Request& req,
1841 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1842 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1843 {
1844 return;
1845 }
1846
1847 bool vlanEnable = false;
1848 uint32_t vlanId = 0;
1849 nlohmann::json::array_t relatedInterfaces;
1850
1851 if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1852 vlanEnable, "VLAN/VLANId", vlanId,
1853 "Links/RelatedInterfaces",
1854 relatedInterfaces))
1855 {
1856 return;
1857 }
1858
1859 if (relatedInterfaces.size() != 1)
1860 {
1861 messages::arraySizeTooLong(asyncResp->res,
1862 "Links/RelatedInterfaces",
1863 relatedInterfaces.size());
1864 return;
1865 }
1866
1867 std::string parentInterfaceUri;
1868 if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1869 "@odata.id", parentInterfaceUri))
1870 {
1871 messages::propertyMissing(asyncResp->res,
1872 "Links/RelatedInterfaces/0/@odata.id");
1873 return;
1874 }
Ed Tanous62598e32023-07-17 17:06:25 -07001875 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001876
1877 boost::urls::result<boost::urls::url_view> parsedUri =
1878 boost::urls::parse_relative_ref(parentInterfaceUri);
1879 if (!parsedUri)
1880 {
1881 messages::propertyValueFormatError(
1882 asyncResp->res, parentInterfaceUri,
1883 "Links/RelatedInterfaces/0/@odata.id");
1884 return;
1885 }
1886
1887 std::string parentInterface;
1888 if (!crow::utility::readUrlSegments(
1889 *parsedUri, "redfish", "v1", "Managers", "bmc",
1890 "EthernetInterfaces", std::ref(parentInterface)))
1891 {
1892 messages::propertyValueNotInList(
1893 asyncResp->res, parentInterfaceUri,
1894 "Links/RelatedInterfaces/0/@odata.id");
1895 return;
1896 }
1897
1898 if (!vlanEnable)
1899 {
1900 // In OpenBMC implementation, VLANEnable cannot be false on
1901 // create
1902 messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1903 "false");
1904 return;
1905 }
1906
1907 std::string vlanInterface = parentInterface + "_" +
1908 std::to_string(vlanId);
1909 crow::connections::systemBus->async_method_call(
1910 [asyncResp, parentInterfaceUri,
1911 vlanInterface](const boost::system::error_code& ec,
1912 const sdbusplus::message_t& m) {
1913 afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1914 m);
1915 },
1916 "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1917 "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1918 vlanId);
1919 });
1920
Ed Tanousbf648f72021-06-03 15:00:14 -07001921 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001922 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001923 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001924 [&app](const crow::Request& req,
1925 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1926 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001927 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001928 {
1929 return;
1930 }
1931 getEthernetIfaceData(
1932 ifaceId,
Ed Tanous77179532023-02-28 10:45:28 -08001933 [asyncResp, ifaceId](const bool& success,
1934 const EthernetInterfaceData& ethData,
1935 const std::vector<IPv4AddressData>& ipv4Data,
1936 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001937 if (!success)
1938 {
1939 // TODO(Pawel)consider distinguish between non
1940 // existing object, and other errors
1941 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1942 ifaceId);
1943 return;
1944 }
Johnathan Mantey01784822019-06-18 12:44:21 -07001945
Ed Tanous002d39b2022-05-31 08:59:27 -07001946 asyncResp->res.jsonValue["@odata.type"] =
Jiaqing Zhao93bbc952023-02-23 14:11:20 +08001947 "#EthernetInterface.v1_9_0.EthernetInterface";
Ed Tanous002d39b2022-05-31 08:59:27 -07001948 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
1949 asyncResp->res.jsonValue["Description"] =
1950 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05301951
Ed Tanous002d39b2022-05-31 08:59:27 -07001952 parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
Ed Tanousbf648f72021-06-03 15:00:14 -07001953 });
Ed Tanous002d39b2022-05-31 08:59:27 -07001954 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001955
Ed Tanousbf648f72021-06-03 15:00:14 -07001956 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001957 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001958 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001959 [&app](const crow::Request& req,
1960 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1961 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001962 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001963 {
1964 return;
1965 }
1966 std::optional<std::string> hostname;
1967 std::optional<std::string> fqdn;
1968 std::optional<std::string> macAddress;
1969 std::optional<std::string> ipv6DefaultGateway;
Ed Tanousddd70dc2023-03-01 16:00:27 -08001970 std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
1971 std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07001972 std::optional<std::vector<std::string>> staticNameServers;
1973 std::optional<nlohmann::json> dhcpv4;
1974 std::optional<nlohmann::json> dhcpv6;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001975 std::optional<bool> ipv6AutoConfigEnabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07001976 std::optional<bool> interfaceEnabled;
1977 std::optional<size_t> mtuSize;
1978 DHCPParameters v4dhcpParms;
1979 DHCPParameters v6dhcpParms;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001980 // clang-format off
Ed Tanous002d39b2022-05-31 08:59:27 -07001981 if (!json_util::readJsonPatch(
Ravi Tejab10d8db2022-05-24 09:04:12 -05001982 req, asyncResp->res,
1983 "DHCPv4", dhcpv4,
1984 "DHCPv6", dhcpv6,
1985 "FQDN", fqdn,
1986 "HostName", hostname,
1987 "IPv4StaticAddresses", ipv4StaticAddresses,
1988 "IPv6DefaultGateway", ipv6DefaultGateway,
1989 "IPv6StaticAddresses", ipv6StaticAddresses,
1990 "InterfaceEnabled", interfaceEnabled,
1991 "MACAddress", macAddress,
1992 "MTUSize", mtuSize,
1993 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
1994 "StaticNameServers", staticNameServers
1995 )
1996 )
Ed Tanous002d39b2022-05-31 08:59:27 -07001997 {
1998 return;
1999 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05002000 //clang-format on
Ed Tanous002d39b2022-05-31 08:59:27 -07002001 if (dhcpv4)
2002 {
2003 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
2004 v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
2005 v4dhcpParms.useDnsServers, "UseNTPServers",
2006 v4dhcpParms.useNtpServers, "UseDomainName",
2007 v4dhcpParms.useDomainName))
2008 {
2009 return;
2010 }
2011 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002012
Ed Tanous002d39b2022-05-31 08:59:27 -07002013 if (dhcpv6)
2014 {
2015 if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2016 v6dhcpParms.dhcpv6OperatingMode,
2017 "UseDNSServers", v6dhcpParms.useDnsServers,
2018 "UseNTPServers", v6dhcpParms.useNtpServers,
2019 "UseDomainName",
2020 v6dhcpParms.useDomainName))
2021 {
2022 return;
2023 }
2024 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002025
Ed Tanous002d39b2022-05-31 08:59:27 -07002026 // Get single eth interface data, and call the below callback
2027 // for JSON preparation
2028 getEthernetIfaceData(
2029 ifaceId,
2030 [asyncResp, ifaceId, hostname = std::move(hostname),
2031 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2032 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2033 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2034 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2035 staticNameServers = std::move(staticNameServers),
Ed Tanousbc200892022-06-30 17:49:12 -07002036 dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
Ravi Tejab10d8db2022-05-24 09:04:12 -05002037 ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
Ed Tanous002d39b2022-05-31 08:59:27 -07002038 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2039 const bool& success, const EthernetInterfaceData& ethData,
Ed Tanous77179532023-02-28 10:45:28 -08002040 const std::vector<IPv4AddressData>& ipv4Data,
2041 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002042 if (!success)
2043 {
2044 // ... otherwise return error
2045 // TODO(Pawel)consider distinguish between non
2046 // existing object, and other errors
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +08002047 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
Ed Tanous002d39b2022-05-31 08:59:27 -07002048 ifaceId);
2049 return;
2050 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002051
Ed Tanous002d39b2022-05-31 08:59:27 -07002052 if (dhcpv4 || dhcpv6)
2053 {
2054 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
Ed Tanousbf648f72021-06-03 15:00:14 -07002055 asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002056 }
Tejas Patil35fb5312021-09-20 15:35:20 +05302057
Ed Tanous002d39b2022-05-31 08:59:27 -07002058 if (hostname)
2059 {
2060 handleHostnamePatch(*hostname, asyncResp);
2061 }
2062
Ravi Tejab10d8db2022-05-24 09:04:12 -05002063 if (ipv6AutoConfigEnabled)
2064 {
2065 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2066 asyncResp);
2067 }
2068
Ed Tanous002d39b2022-05-31 08:59:27 -07002069 if (fqdn)
2070 {
2071 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2072 }
2073
2074 if (macAddress)
2075 {
2076 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2077 }
2078
2079 if (ipv4StaticAddresses)
2080 {
2081 // TODO(ed) for some reason the capture of
2082 // ipv4Addresses above is returning a const value,
2083 // not a non-const value. This doesn't really work
2084 // for us, as we need to be able to efficiently move
2085 // out the intermedia nlohmann::json objects. This
2086 // makes a copy of the structure, and operates on
2087 // that, but could be done more efficiently
Ed Tanousddd70dc2023-03-01 16:00:27 -08002088 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002089 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
2090 }
2091
2092 if (staticNameServers)
2093 {
2094 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2095 asyncResp);
2096 }
2097
2098 if (ipv6DefaultGateway)
2099 {
2100 messages::propertyNotWritable(asyncResp->res,
2101 "IPv6DefaultGateway");
2102 }
2103
2104 if (ipv6StaticAddresses)
2105 {
Ed Tanousddd70dc2023-03-01 16:00:27 -08002106 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2107 ipv6Data, asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002108 }
2109
2110 if (interfaceEnabled)
2111 {
2112 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2113 *interfaceEnabled, asyncResp);
2114 }
2115
2116 if (mtuSize)
2117 {
2118 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2119 }
Ed Tanousbf648f72021-06-03 15:00:14 -07002120 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002121 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002122
2123 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2124 .privileges(redfish::privileges::deleteEthernetInterface)
2125 .methods(boost::beast::http::verb::delete_)(
2126 [&app](const crow::Request& req,
2127 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2128 const std::string& ifaceId) {
2129 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2130 {
2131 return;
2132 }
2133
2134 crow::connections::systemBus->async_method_call(
2135 [asyncResp, ifaceId](const boost::system::error_code& ec,
2136 const sdbusplus::message_t& m) {
2137 afterDelete(asyncResp, ifaceId, ec, m);
2138 },
2139 "xyz.openbmc_project.Network",
2140 std::string("/xyz/openbmc_project/network/") + ifaceId,
2141 "xyz.openbmc_project.Object.Delete", "Delete");
2142 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002143}
2144
Ed Tanous1abe55e2018-09-05 08:30:59 -07002145} // namespace redfish