blob: 7783e7cfa45277e86c532c3f635bce8d1e7a271b [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.
1298 const std::string* addr = nullptr;
1299 const std::string* gw = nullptr;
1300 uint8_t prefixLength = 0;
1301 bool errorInEntry = false;
1302 if (address)
1303 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001304 if (ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001305 {
1306 addr = &(*address);
1307 }
1308 else
1309 {
1310 messages::propertyValueFormatError(asyncResp->res, *address,
1311 pathString + "/Address");
1312 errorInEntry = true;
1313 }
1314 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001315 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001316 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001317 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001318 }
1319 else
1320 {
1321 messages::propertyMissing(asyncResp->res,
1322 pathString + "/Address");
1323 errorInEntry = true;
1324 }
1325
1326 if (subnetMask)
1327 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001328 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1329 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001330 {
1331 messages::propertyValueFormatError(
1332 asyncResp->res, *subnetMask,
1333 pathString + "/SubnetMask");
1334 errorInEntry = true;
1335 }
1336 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001337 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001338 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001339 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1340 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001341 {
1342 messages::propertyValueFormatError(
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001343 asyncResp->res, nicIpEntry->netmask,
Ed Tanousbf648f72021-06-03 15:00:14 -07001344 pathString + "/SubnetMask");
1345 errorInEntry = true;
1346 }
1347 }
1348 else
1349 {
1350 messages::propertyMissing(asyncResp->res,
1351 pathString + "/SubnetMask");
1352 errorInEntry = true;
1353 }
1354
1355 if (gateway)
1356 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001357 if (ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001358 {
1359 gw = &(*gateway);
1360 }
1361 else
1362 {
1363 messages::propertyValueFormatError(asyncResp->res, *gateway,
1364 pathString + "/Gateway");
1365 errorInEntry = true;
1366 }
1367 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001368 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001369 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001370 gw = &nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001371 }
1372 else
1373 {
1374 messages::propertyMissing(asyncResp->res,
1375 pathString + "/Gateway");
1376 errorInEntry = true;
1377 }
1378
1379 if (errorInEntry)
1380 {
1381 return;
1382 }
1383
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001384 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001385 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001386 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
1387 nicIpEntry->id, prefixLength, *gw,
1388 *addr, asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001389 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1390 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001391 }
1392 else
1393 {
1394 createIPv4(ifaceId, prefixLength, *gateway, *address,
1395 asyncResp);
1396 }
1397 entryIdx++;
1398 }
1399 else
1400 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001401 if (nicIpEntry == ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001402 {
1403 // Requesting a DELETE/DO NOT MODIFY action for an item
1404 // that isn't present on the eth(n) interface. Input JSON is
1405 // in error, so bail out.
1406 if (thisJson.is_null())
1407 {
1408 messages::resourceCannotBeDeleted(asyncResp->res);
1409 return;
1410 }
Ed Tanousf818b042022-06-27 13:17:35 -07001411 messages::propertyValueFormatError(asyncResp->res, thisJson,
1412 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001413 return;
1414 }
1415
1416 if (thisJson.is_null())
1417 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001418 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001419 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001420 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001421 {
Patrick Williams89492a12023-05-10 07:51:34 -05001422 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1423 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001424 }
1425 entryIdx++;
1426 }
1427 }
1428}
1429
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001430inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001431 const std::string& ifaceId,
1432 const std::vector<std::string>& updatedStaticNameServers,
1433 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1434{
George Liu9ae226f2023-06-21 17:56:46 +08001435 sdbusplus::asio::setProperty(
1436 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1437 "/xyz/openbmc_project/network/" + ifaceId,
1438 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1439 updatedStaticNameServers,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001440 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001441 if (ec)
1442 {
1443 messages::internalError(asyncResp->res);
1444 return;
1445 }
George Liu9ae226f2023-06-21 17:56:46 +08001446 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001447}
1448
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001449inline void handleIPv6StaticAddressesPatch(
Ed Tanousddd70dc2023-03-01 16:00:27 -08001450 const std::string& ifaceId, const nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001451 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001452 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1453{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001454 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001455 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001456 messages::propertyValueTypeError(asyncResp->res, input,
1457 "IPv6StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001458 return;
1459 }
1460 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001461 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001462 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1463 for (const nlohmann::json& thisJson : input)
1464 {
Patrick Williams89492a12023-05-10 07:51:34 -05001465 std::string pathString = "IPv6StaticAddresses/" +
1466 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001467
1468 if (!thisJson.is_null() && !thisJson.empty())
1469 {
1470 std::optional<std::string> address;
1471 std::optional<uint8_t> prefixLength;
1472 nlohmann::json thisJsonCopy = thisJson;
1473 if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1474 address, "PrefixLength", prefixLength))
1475 {
Ed Tanousf818b042022-06-27 13:17:35 -07001476 messages::propertyValueFormatError(asyncResp->res, thisJson,
1477 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001478 return;
1479 }
1480
Ed Tanous543f4402022-01-06 13:12:53 -08001481 const std::string* addr = nullptr;
1482 uint8_t prefix = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001483
1484 // Find the address and prefixLength values. Any values that are
1485 // not explicitly provided are assumed to be unmodified from the
1486 // current state of the interface. Merge existing state into the
1487 // current request.
1488 if (address)
1489 {
1490 addr = &(*address);
1491 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001492 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001493 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001494 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001495 }
1496 else
1497 {
1498 messages::propertyMissing(asyncResp->res,
1499 pathString + "/Address");
1500 return;
1501 }
1502
1503 if (prefixLength)
1504 {
1505 prefix = *prefixLength;
1506 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001507 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001508 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001509 prefix = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001510 }
1511 else
1512 {
1513 messages::propertyMissing(asyncResp->res,
1514 pathString + "/PrefixLength");
1515 return;
1516 }
1517
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001518 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001519 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001520 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1521 nicIpEntry->id, prefix, "", *addr,
1522 asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001523 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1524 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001525 }
1526 else
1527 {
1528 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1529 }
1530 entryIdx++;
1531 }
1532 else
1533 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001534 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001535 {
1536 // Requesting a DELETE/DO NOT MODIFY action for an item
1537 // that isn't present on the eth(n) interface. Input JSON is
1538 // in error, so bail out.
1539 if (thisJson.is_null())
1540 {
1541 messages::resourceCannotBeDeleted(asyncResp->res);
1542 return;
1543 }
Ed Tanousf818b042022-06-27 13:17:35 -07001544 messages::propertyValueFormatError(asyncResp->res, thisJson,
1545 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001546 return;
1547 }
1548
1549 if (thisJson.is_null())
1550 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001551 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001552 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001553 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001554 {
Patrick Williams89492a12023-05-10 07:51:34 -05001555 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1556 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001557 }
1558 entryIdx++;
1559 }
1560 }
1561}
1562
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001563inline std::string extractParentInterfaceName(const std::string& ifaceId)
1564{
1565 std::size_t pos = ifaceId.find('_');
1566 return ifaceId.substr(0, pos);
1567}
1568
Ed Tanous77179532023-02-28 10:45:28 -08001569inline void
1570 parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1571 const std::string& ifaceId,
1572 const EthernetInterfaceData& ethData,
1573 const std::vector<IPv4AddressData>& ipv4Data,
1574 const std::vector<IPv6AddressData>& ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001575{
Ed Tanousbf648f72021-06-03 15:00:14 -07001576 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1577 jsonResponse["Id"] = ifaceId;
Ed Tanousef4c65b2023-04-24 15:28:50 -07001578 jsonResponse["@odata.id"] = boost::urls::format(
1579 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001580 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1581
Willy Tu13451e32023-05-24 16:08:18 -07001582 if constexpr (bmcwebEnableHealthPopulate)
1583 {
1584 constexpr std::array<std::string_view, 1> inventoryForEthernet = {
1585 "xyz.openbmc_project.Inventory.Item.Ethernet"};
1586 auto health = std::make_shared<HealthPopulate>(asyncResp);
1587 dbus::utility::getSubTreePaths(
1588 "/", 0, inventoryForEthernet,
1589 [health](const boost::system::error_code& ec,
1590 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1591 if (ec)
1592 {
1593 return;
1594 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001595
Willy Tu13451e32023-05-24 16:08:18 -07001596 health->inventory = resp;
1597 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001598
Willy Tu13451e32023-05-24 16:08:18 -07001599 health->populate();
1600 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001601
1602 if (ethData.nicEnabled)
1603 {
Johnathan Mantey0ef0e282022-11-15 12:15:02 -08001604 jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
Ed Tanousbf648f72021-06-03 15:00:14 -07001605 jsonResponse["Status"]["State"] = "Enabled";
1606 }
1607 else
1608 {
1609 jsonResponse["LinkStatus"] = "NoLink";
1610 jsonResponse["Status"]["State"] = "Disabled";
1611 }
1612
Ed Tanousbf648f72021-06-03 15:00:14 -07001613 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301614 jsonResponse["MTUSize"] = ethData.mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001615 jsonResponse["MACAddress"] = ethData.macAddress;
Ed Tanousbf648f72021-06-03 15:00:14 -07001616 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001617 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1618 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled;
1619 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled;
1620 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001621
1622 jsonResponse["DHCPv6"]["OperatingMode"] =
Ravi Tejab10d8db2022-05-24 09:04:12 -05001623 translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
Ed Tanousbf648f72021-06-03 15:00:14 -07001624 : "Disabled";
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001625 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled;
1626 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled;
1627 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001628 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1629 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001630
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001631 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001632 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001633 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001634
1635 // When domain name is empty then it means, that it is a network
1636 // without domain names, and the host name itself must be treated as
1637 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001638 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001639 if (!ethData.domainnames.empty())
1640 {
1641 fqdn += "." + ethData.domainnames[0];
1642 }
1643 jsonResponse["FQDN"] = fqdn;
1644 }
1645
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001646 if (ethData.vlanId)
1647 {
1648 jsonResponse["EthernetInterfaceType"] = "Virtual";
1649 jsonResponse["VLAN"]["VLANEnable"] = true;
1650 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1651 jsonResponse["VLAN"]["Tagged"] = true;
1652
1653 nlohmann::json::array_t relatedInterfaces;
1654 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1655 parentInterface["@odata.id"] =
1656 boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
1657 extractParentInterfaceName(ifaceId));
1658 jsonResponse["Links"]["RelatedInterfaces"] =
1659 std::move(relatedInterfaces);
1660 }
1661 else
1662 {
1663 jsonResponse["EthernetInterfaceType"] = "Physical";
1664 }
1665
Ed Tanousbf648f72021-06-03 15:00:14 -07001666 jsonResponse["NameServers"] = ethData.nameServers;
1667 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1668
1669 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1670 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1671 ipv4Array = nlohmann::json::array();
1672 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001673 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001674 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001675 std::string gatewayStr = ipv4Config.gateway;
1676 if (gatewayStr.empty())
1677 {
1678 gatewayStr = "0.0.0.0";
1679 }
Ed Tanous14766872022-03-15 10:44:42 -07001680 nlohmann::json::object_t ipv4;
1681 ipv4["AddressOrigin"] = ipv4Config.origin;
1682 ipv4["SubnetMask"] = ipv4Config.netmask;
1683 ipv4["Address"] = ipv4Config.address;
1684 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001685
Ed Tanousbf648f72021-06-03 15:00:14 -07001686 if (ipv4Config.origin == "Static")
1687 {
Ed Tanous14766872022-03-15 10:44:42 -07001688 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001689 }
Ed Tanous14766872022-03-15 10:44:42 -07001690
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001691 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001692 }
1693
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001694 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001695 if (ipv6GatewayStr.empty())
1696 {
1697 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1698 }
1699
1700 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1701
1702 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1703 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1704 ipv6Array = nlohmann::json::array();
1705 ipv6StaticArray = nlohmann::json::array();
1706 nlohmann::json& ipv6AddrPolicyTable =
1707 jsonResponse["IPv6AddressPolicyTable"];
1708 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001709 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001710 {
Ed Tanous14766872022-03-15 10:44:42 -07001711 nlohmann::json::object_t ipv6;
1712 ipv6["Address"] = ipv6Config.address;
1713 ipv6["PrefixLength"] = ipv6Config.prefixLength;
1714 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05001715
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001716 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07001717 if (ipv6Config.origin == "Static")
1718 {
Ed Tanous14766872022-03-15 10:44:42 -07001719 nlohmann::json::object_t ipv6Static;
1720 ipv6Static["Address"] = ipv6Config.address;
1721 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001722 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07001723 }
1724 }
1725}
1726
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001727inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1728 const std::string& ifaceId,
1729 const boost::system::error_code& ec,
1730 const sdbusplus::message_t& m)
1731{
1732 if (!ec)
1733 {
1734 return;
1735 }
1736 const sd_bus_error* dbusError = m.get_error();
1737 if (dbusError == nullptr)
1738 {
1739 messages::internalError(asyncResp->res);
1740 return;
1741 }
Ed Tanous62598e32023-07-17 17:06:25 -07001742 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001743
1744 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1745 dbusError->name)
1746 {
1747 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1748 ifaceId);
1749 return;
1750 }
1751 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1752 dbusError->name)
1753 {
1754 messages::resourceCannotBeDeleted(asyncResp->res);
1755 return;
1756 }
1757 messages::internalError(asyncResp->res);
1758}
1759
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001760inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1761 const std::string& parentInterfaceUri,
1762 const std::string& vlanInterface,
1763 const boost::system::error_code& ec,
1764 const sdbusplus::message_t& m
1765
1766)
1767{
1768 if (ec)
1769 {
1770 const sd_bus_error* dbusError = m.get_error();
1771 if (dbusError == nullptr)
1772 {
1773 messages::internalError(asyncResp->res);
1774 return;
1775 }
Ed Tanous62598e32023-07-17 17:06:25 -07001776 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001777
1778 if (std::string_view(
1779 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1780 dbusError->name)
1781 {
1782 messages::propertyValueNotInList(
1783 asyncResp->res, parentInterfaceUri,
1784 "Links/RelatedInterfaces/0/@odata.id");
1785 return;
1786 }
1787 if (std::string_view(
1788 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1789 dbusError->name)
1790 {
1791 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1792 "Id", vlanInterface);
1793 return;
1794 }
1795 messages::internalError(asyncResp->res);
1796 return;
1797 }
1798
1799 const boost::urls::url vlanInterfaceUri = boost::urls::format(
1800 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1801 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1802}
1803
Ed Tanousbf648f72021-06-03 15:00:14 -07001804inline void requestEthernetInterfacesRoutes(App& app)
1805{
1806 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07001807 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07001808 .methods(boost::beast::http::verb::get)(
1809 [&app](const crow::Request& req,
1810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001811 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001812 {
1813 return;
1814 }
1815
1816 asyncResp->res.jsonValue["@odata.type"] =
1817 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1818 asyncResp->res.jsonValue["@odata.id"] =
1819 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1820 asyncResp->res.jsonValue["Name"] =
1821 "Ethernet Network Interface Collection";
1822 asyncResp->res.jsonValue["Description"] =
1823 "Collection of EthernetInterfaces for this Manager";
1824
1825 // Get eth interface list, and call the below callback for JSON
1826 // preparation
1827 getEthernetIfaceList(
Ed Tanous77179532023-02-28 10:45:28 -08001828 [asyncResp](const bool& success,
1829 const std::vector<std::string>& ifaceList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001830 if (!success)
1831 {
1832 messages::internalError(asyncResp->res);
1833 return;
1834 }
1835
1836 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1837 ifaceArray = nlohmann::json::array();
Ed Tanous002d39b2022-05-31 08:59:27 -07001838 for (const std::string& ifaceItem : ifaceList)
1839 {
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001840 nlohmann::json::object_t iface;
1841 iface["@odata.id"] = boost::urls::format(
1842 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1843 ifaceItem);
1844 ifaceArray.push_back(std::move(iface));
Ed Tanous002d39b2022-05-31 08:59:27 -07001845 }
Jason M. Billsf12894f2018-10-09 12:45:45 -07001846
Ed Tanous002d39b2022-05-31 08:59:27 -07001847 asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1848 asyncResp->res.jsonValue["@odata.id"] =
1849 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1850 });
1851 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001852
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001853 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1854 .privileges(redfish::privileges::postEthernetInterfaceCollection)
1855 .methods(boost::beast::http::verb::post)(
1856 [&app](const crow::Request& req,
1857 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1858 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1859 {
1860 return;
1861 }
1862
1863 bool vlanEnable = false;
1864 uint32_t vlanId = 0;
1865 nlohmann::json::array_t relatedInterfaces;
1866
1867 if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1868 vlanEnable, "VLAN/VLANId", vlanId,
1869 "Links/RelatedInterfaces",
1870 relatedInterfaces))
1871 {
1872 return;
1873 }
1874
1875 if (relatedInterfaces.size() != 1)
1876 {
1877 messages::arraySizeTooLong(asyncResp->res,
1878 "Links/RelatedInterfaces",
1879 relatedInterfaces.size());
1880 return;
1881 }
1882
1883 std::string parentInterfaceUri;
1884 if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1885 "@odata.id", parentInterfaceUri))
1886 {
1887 messages::propertyMissing(asyncResp->res,
1888 "Links/RelatedInterfaces/0/@odata.id");
1889 return;
1890 }
Ed Tanous62598e32023-07-17 17:06:25 -07001891 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001892
1893 boost::urls::result<boost::urls::url_view> parsedUri =
1894 boost::urls::parse_relative_ref(parentInterfaceUri);
1895 if (!parsedUri)
1896 {
1897 messages::propertyValueFormatError(
1898 asyncResp->res, parentInterfaceUri,
1899 "Links/RelatedInterfaces/0/@odata.id");
1900 return;
1901 }
1902
1903 std::string parentInterface;
1904 if (!crow::utility::readUrlSegments(
1905 *parsedUri, "redfish", "v1", "Managers", "bmc",
1906 "EthernetInterfaces", std::ref(parentInterface)))
1907 {
1908 messages::propertyValueNotInList(
1909 asyncResp->res, parentInterfaceUri,
1910 "Links/RelatedInterfaces/0/@odata.id");
1911 return;
1912 }
1913
1914 if (!vlanEnable)
1915 {
1916 // In OpenBMC implementation, VLANEnable cannot be false on
1917 // create
1918 messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1919 "false");
1920 return;
1921 }
1922
1923 std::string vlanInterface = parentInterface + "_" +
1924 std::to_string(vlanId);
1925 crow::connections::systemBus->async_method_call(
1926 [asyncResp, parentInterfaceUri,
1927 vlanInterface](const boost::system::error_code& ec,
1928 const sdbusplus::message_t& m) {
1929 afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1930 m);
1931 },
1932 "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1933 "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1934 vlanId);
1935 });
1936
Ed Tanousbf648f72021-06-03 15:00:14 -07001937 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001938 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001939 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001940 [&app](const crow::Request& req,
1941 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1942 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001943 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001944 {
1945 return;
1946 }
1947 getEthernetIfaceData(
1948 ifaceId,
Ed Tanous77179532023-02-28 10:45:28 -08001949 [asyncResp, ifaceId](const bool& success,
1950 const EthernetInterfaceData& ethData,
1951 const std::vector<IPv4AddressData>& ipv4Data,
1952 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001953 if (!success)
1954 {
1955 // TODO(Pawel)consider distinguish between non
1956 // existing object, and other errors
1957 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1958 ifaceId);
1959 return;
1960 }
Johnathan Mantey01784822019-06-18 12:44:21 -07001961
Ed Tanous002d39b2022-05-31 08:59:27 -07001962 asyncResp->res.jsonValue["@odata.type"] =
Jiaqing Zhao93bbc952023-02-23 14:11:20 +08001963 "#EthernetInterface.v1_9_0.EthernetInterface";
Ed Tanous002d39b2022-05-31 08:59:27 -07001964 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
1965 asyncResp->res.jsonValue["Description"] =
1966 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05301967
Ed Tanous002d39b2022-05-31 08:59:27 -07001968 parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
Ed Tanousbf648f72021-06-03 15:00:14 -07001969 });
Ed Tanous002d39b2022-05-31 08:59:27 -07001970 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001971
Ed Tanousbf648f72021-06-03 15:00:14 -07001972 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001973 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001974 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001975 [&app](const crow::Request& req,
1976 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1977 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001978 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001979 {
1980 return;
1981 }
1982 std::optional<std::string> hostname;
1983 std::optional<std::string> fqdn;
1984 std::optional<std::string> macAddress;
1985 std::optional<std::string> ipv6DefaultGateway;
Ed Tanousddd70dc2023-03-01 16:00:27 -08001986 std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
1987 std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07001988 std::optional<std::vector<std::string>> staticNameServers;
1989 std::optional<nlohmann::json> dhcpv4;
1990 std::optional<nlohmann::json> dhcpv6;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001991 std::optional<bool> ipv6AutoConfigEnabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07001992 std::optional<bool> interfaceEnabled;
1993 std::optional<size_t> mtuSize;
1994 DHCPParameters v4dhcpParms;
1995 DHCPParameters v6dhcpParms;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001996 // clang-format off
Ed Tanous002d39b2022-05-31 08:59:27 -07001997 if (!json_util::readJsonPatch(
Ravi Tejab10d8db2022-05-24 09:04:12 -05001998 req, asyncResp->res,
1999 "DHCPv4", dhcpv4,
2000 "DHCPv6", dhcpv6,
2001 "FQDN", fqdn,
2002 "HostName", hostname,
2003 "IPv4StaticAddresses", ipv4StaticAddresses,
2004 "IPv6DefaultGateway", ipv6DefaultGateway,
2005 "IPv6StaticAddresses", ipv6StaticAddresses,
2006 "InterfaceEnabled", interfaceEnabled,
2007 "MACAddress", macAddress,
2008 "MTUSize", mtuSize,
2009 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2010 "StaticNameServers", staticNameServers
2011 )
2012 )
Ed Tanous002d39b2022-05-31 08:59:27 -07002013 {
2014 return;
2015 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05002016 //clang-format on
Ed Tanous002d39b2022-05-31 08:59:27 -07002017 if (dhcpv4)
2018 {
2019 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
2020 v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
2021 v4dhcpParms.useDnsServers, "UseNTPServers",
2022 v4dhcpParms.useNtpServers, "UseDomainName",
2023 v4dhcpParms.useDomainName))
2024 {
2025 return;
2026 }
2027 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002028
Ed Tanous002d39b2022-05-31 08:59:27 -07002029 if (dhcpv6)
2030 {
2031 if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2032 v6dhcpParms.dhcpv6OperatingMode,
2033 "UseDNSServers", v6dhcpParms.useDnsServers,
2034 "UseNTPServers", v6dhcpParms.useNtpServers,
2035 "UseDomainName",
2036 v6dhcpParms.useDomainName))
2037 {
2038 return;
2039 }
2040 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002041
Ed Tanous002d39b2022-05-31 08:59:27 -07002042 // Get single eth interface data, and call the below callback
2043 // for JSON preparation
2044 getEthernetIfaceData(
2045 ifaceId,
2046 [asyncResp, ifaceId, hostname = std::move(hostname),
2047 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2048 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2049 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2050 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2051 staticNameServers = std::move(staticNameServers),
Ed Tanousbc200892022-06-30 17:49:12 -07002052 dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
Ravi Tejab10d8db2022-05-24 09:04:12 -05002053 ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
Ed Tanous002d39b2022-05-31 08:59:27 -07002054 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2055 const bool& success, const EthernetInterfaceData& ethData,
Ed Tanous77179532023-02-28 10:45:28 -08002056 const std::vector<IPv4AddressData>& ipv4Data,
2057 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002058 if (!success)
2059 {
2060 // ... otherwise return error
2061 // TODO(Pawel)consider distinguish between non
2062 // existing object, and other errors
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +08002063 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
Ed Tanous002d39b2022-05-31 08:59:27 -07002064 ifaceId);
2065 return;
2066 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002067
Ed Tanous002d39b2022-05-31 08:59:27 -07002068 if (dhcpv4 || dhcpv6)
2069 {
2070 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
Ed Tanousbf648f72021-06-03 15:00:14 -07002071 asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002072 }
Tejas Patil35fb5312021-09-20 15:35:20 +05302073
Ed Tanous002d39b2022-05-31 08:59:27 -07002074 if (hostname)
2075 {
2076 handleHostnamePatch(*hostname, asyncResp);
2077 }
2078
Ravi Tejab10d8db2022-05-24 09:04:12 -05002079 if (ipv6AutoConfigEnabled)
2080 {
2081 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2082 asyncResp);
2083 }
2084
Ed Tanous002d39b2022-05-31 08:59:27 -07002085 if (fqdn)
2086 {
2087 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2088 }
2089
2090 if (macAddress)
2091 {
2092 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2093 }
2094
2095 if (ipv4StaticAddresses)
2096 {
2097 // TODO(ed) for some reason the capture of
2098 // ipv4Addresses above is returning a const value,
2099 // not a non-const value. This doesn't really work
2100 // for us, as we need to be able to efficiently move
2101 // out the intermedia nlohmann::json objects. This
2102 // makes a copy of the structure, and operates on
2103 // that, but could be done more efficiently
Ed Tanousddd70dc2023-03-01 16:00:27 -08002104 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002105 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
2106 }
2107
2108 if (staticNameServers)
2109 {
2110 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2111 asyncResp);
2112 }
2113
2114 if (ipv6DefaultGateway)
2115 {
2116 messages::propertyNotWritable(asyncResp->res,
2117 "IPv6DefaultGateway");
2118 }
2119
2120 if (ipv6StaticAddresses)
2121 {
Ed Tanousddd70dc2023-03-01 16:00:27 -08002122 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2123 ipv6Data, asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002124 }
2125
2126 if (interfaceEnabled)
2127 {
2128 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2129 *interfaceEnabled, asyncResp);
2130 }
2131
2132 if (mtuSize)
2133 {
2134 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2135 }
Ed Tanousbf648f72021-06-03 15:00:14 -07002136 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002137 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002138
2139 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2140 .privileges(redfish::privileges::deleteEthernetInterface)
2141 .methods(boost::beast::http::verb::delete_)(
2142 [&app](const crow::Request& req,
2143 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2144 const std::string& ifaceId) {
2145 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2146 {
2147 return;
2148 }
2149
2150 crow::connections::systemBus->async_method_call(
2151 [asyncResp, ifaceId](const boost::system::error_code& ec,
2152 const sdbusplus::message_t& m) {
2153 afterDelete(asyncResp, ifaceId, ec, m);
2154 },
2155 "xyz.openbmc_project.Network",
2156 std::string("/xyz/openbmc_project/network/") + ifaceId,
2157 "xyz.openbmc_project.Object.Delete", "Delete");
2158 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002159}
2160
Ed Tanous1abe55e2018-09-05 08:30:59 -07002161} // namespace redfish