blob: 03b23e14065d98e0ffc580d29cf9f830aa9e31e8 [file] [log] [blame]
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
21#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "error_messages.hpp"
24#include "health.hpp"
Ed Tanous2c5875a2023-05-15 09:56:06 -070025#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "query.hpp"
27#include "registries/privilege_registry.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070028#include "utils/ip_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "utils/json_utils.hpp"
Ed Tanous033f1e42022-08-15 09:47:37 -070030
Ed Tanousef4c65b2023-04-24 15:28:50 -070031#include <boost/url/format.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
George Liu7a1dbc42022-12-07 16:03:22 +080033#include <array>
Ed Tanousa24526d2018-12-10 15:17:59 -080034#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070035#include <ranges>
Joshi-Mansiab6554f2020-03-10 18:33:36 +053036#include <regex>
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <string_view>
Ed Tanous77179532023-02-28 10:45:28 -080038#include <vector>
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010039
Ed Tanous1abe55e2018-09-05 08:30:59 -070040namespace redfish
41{
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010042
Ed Tanous4a0cb852018-10-15 07:55:04 -070043enum class LinkType
44{
45 Local,
46 Global
47};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010048
49/**
50 * Structure for keeping IPv4 data required by Redfish
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010051 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070052struct IPv4AddressData
53{
54 std::string id;
Ed Tanous4a0cb852018-10-15 07:55:04 -070055 std::string address;
56 std::string domain;
57 std::string gateway;
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 std::string netmask;
59 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080060 LinkType linktype{};
61 bool isActive{};
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010062};
63
64/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -050065 * Structure for keeping IPv6 data required by Redfish
66 */
67struct IPv6AddressData
68{
69 std::string id;
70 std::string address;
71 std::string origin;
Ed Tanous77179532023-02-28 10:45:28 -080072 uint8_t prefixLength = 0;
Ravi Tejae48c0fc2019-04-16 08:37:20 -050073};
74/**
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010075 * Structure for keeping basic single Ethernet Interface information
76 * available from DBus
77 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070078struct EthernetInterfaceData
79{
Ed Tanous4a0cb852018-10-15 07:55:04 -070080 uint32_t speed;
Tejas Patil35fb5312021-09-20 15:35:20 +053081 size_t mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080082 bool autoNeg;
Jishnu CMe4588152023-05-11 00:04:40 -050083 bool dnsv4Enabled;
84 bool dnsv6Enabled;
85 bool ntpv4Enabled;
86 bool ntpv6Enabled;
87 bool hostNamev4Enabled;
88 bool hostNamev6Enabled;
Johnathan Manteyaa05fb22020-01-08 12:08:44 -080089 bool linkUp;
Johnathan Manteyeeedda22019-10-29 16:09:52 -070090 bool nicEnabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -050091 bool ipv6AcceptRa;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080092 std::string dhcpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -070093 std::string operatingMode;
Jiaqing Zhao82695a52022-04-14 15:15:59 +080094 std::string hostName;
95 std::string defaultGateway;
96 std::string ipv6DefaultGateway;
97 std::string macAddress;
Jiaqing Zhao17e22022022-04-14 18:58:06 +080098 std::optional<uint32_t> vlanId;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -050099 std::vector<std::string> nameServers;
100 std::vector<std::string> staticNameServers;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800101 std::vector<std::string> domainnames;
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100102};
103
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700104struct DHCPParameters
105{
106 std::optional<bool> dhcpv4Enabled;
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800107 std::optional<bool> useDnsServers;
108 std::optional<bool> useNtpServers;
109 std::optional<bool> useDomainName;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700110 std::optional<std::string> dhcpv6OperatingMode;
111};
112
Ed Tanous4a0cb852018-10-15 07:55:04 -0700113// Helper function that changes bits netmask notation (i.e. /24)
114// into full dot notation
115inline std::string getNetmask(unsigned int bits)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700116{
Ed Tanous4a0cb852018-10-15 07:55:04 -0700117 uint32_t value = 0xffffffff << (32 - bits);
118 std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
119 std::to_string((value >> 16) & 0xff) + "." +
120 std::to_string((value >> 8) & 0xff) + "." +
121 std::to_string(value & 0xff);
122 return netmask;
123}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100124
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800125inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700126 bool isIPv4)
127{
128 if (isIPv4)
129 {
130 return (
131 (inputDHCP ==
132 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
133 (inputDHCP ==
134 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
135 }
136 return ((inputDHCP ==
137 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
138 (inputDHCP ==
139 "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
140}
141
Ed Tanous2c70f802020-09-28 14:29:23 -0700142inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700143{
144 if (isIPv4 && isIPv6)
145 {
146 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
147 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700148 if (isIPv4)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700149 {
150 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
151 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700152 if (isIPv6)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700153 {
154 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
155 }
156 return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
157}
158
Ed Tanous4a0cb852018-10-15 07:55:04 -0700159inline std::string
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500160 translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700161 bool isIPv4)
162{
163 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700165 return "Static";
166 }
167 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
168 {
169 if (isIPv4)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700170 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700171 return "IPv4LinkLocal";
172 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700173 return "LinkLocal";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700174 }
175 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
176 {
177 if (isIPv4)
178 {
179 return "DHCP";
180 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700181 return "DHCPv6";
Ed Tanous4a0cb852018-10-15 07:55:04 -0700182 }
183 if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
184 {
185 return "SLAAC";
186 }
187 return "";
188}
189
Ed Tanous02cad962022-06-30 16:50:15 -0700190inline bool extractEthernetInterfaceData(
191 const std::string& ethifaceId,
192 const dbus::utility::ManagedObjectType& dbusData,
193 EthernetInterfaceData& ethData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700194{
Ed Tanous4c9afe42019-05-03 16:59:57 -0700195 bool idFound = false;
Ed Tanous02cad962022-06-30 16:50:15 -0700196 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700197 {
Ed Tanous02cad962022-06-30 16:50:15 -0700198 for (const auto& ifacePair : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700199 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000200 if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700201 {
Ed Tanous4c9afe42019-05-03 16:59:57 -0700202 idFound = true;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700203 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700204 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500205 for (const auto& propertyPair : ifacePair.second)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 {
Ed Tanous4a0cb852018-10-15 07:55:04 -0700207 if (propertyPair.first == "MACAddress")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500209 const std::string* mac =
Ed Tanousabf2add2019-01-22 16:40:12 -0800210 std::get_if<std::string>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700211 if (mac != nullptr)
212 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800213 ethData.macAddress = *mac;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700214 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700215 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700216 }
217 }
218 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
219 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500220 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700221 {
222 if (propertyPair.first == "Id")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700223 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500224 const uint32_t* id =
Ed Tanousabf2add2019-01-22 16:40:12 -0800225 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700226 if (id != nullptr)
227 {
Jiaqing Zhao17e22022022-04-14 18:58:06 +0800228 ethData.vlanId = *id;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700229 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700230 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700231 }
232 }
233 else if (ifacePair.first ==
234 "xyz.openbmc_project.Network.EthernetInterface")
235 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500236 for (const auto& propertyPair : ifacePair.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700237 {
238 if (propertyPair.first == "AutoNeg")
239 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700240 const bool* autoNeg =
Ed Tanousabf2add2019-01-22 16:40:12 -0800241 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700242 if (autoNeg != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700243 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800244 ethData.autoNeg = *autoNeg;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700245 }
246 }
247 else if (propertyPair.first == "Speed")
248 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500249 const uint32_t* speed =
Ed Tanousabf2add2019-01-22 16:40:12 -0800250 std::get_if<uint32_t>(&propertyPair.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700251 if (speed != nullptr)
252 {
253 ethData.speed = *speed;
254 }
255 }
Tejas Patil35fb5312021-09-20 15:35:20 +0530256 else if (propertyPair.first == "MTU")
257 {
Anthony3e7a8da2023-10-23 14:22:43 +0800258 const size_t* mtuSize =
259 std::get_if<size_t>(&propertyPair.second);
Tejas Patil35fb5312021-09-20 15:35:20 +0530260 if (mtuSize != nullptr)
261 {
262 ethData.mtuSize = *mtuSize;
263 }
264 }
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800265 else if (propertyPair.first == "LinkUp")
266 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500267 const bool* linkUp =
Johnathan Manteyaa05fb22020-01-08 12:08:44 -0800268 std::get_if<bool>(&propertyPair.second);
269 if (linkUp != nullptr)
270 {
271 ethData.linkUp = *linkUp;
272 }
273 }
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700274 else if (propertyPair.first == "NICEnabled")
275 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500276 const bool* nicEnabled =
Johnathan Manteyeeedda22019-10-29 16:09:52 -0700277 std::get_if<bool>(&propertyPair.second);
278 if (nicEnabled != nullptr)
279 {
280 ethData.nicEnabled = *nicEnabled;
281 }
282 }
Ravi Tejab10d8db2022-05-24 09:04:12 -0500283 else if (propertyPair.first == "IPv6AcceptRA")
284 {
285 const bool* ipv6AcceptRa =
286 std::get_if<bool>(&propertyPair.second);
287 if (ipv6AcceptRa != nullptr)
288 {
289 ethData.ipv6AcceptRa = *ipv6AcceptRa;
290 }
291 }
RAJESWARAN THILLAIGOVINDANf85837b2019-04-04 05:18:53 -0500292 else if (propertyPair.first == "Nameservers")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700293 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500294 const std::vector<std::string>* nameservers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500295 std::get_if<std::vector<std::string>>(
Ed Tanous029573d2019-02-01 10:57:49 -0800296 &propertyPair.second);
297 if (nameservers != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700298 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700299 ethData.nameServers = *nameservers;
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500300 }
301 }
302 else if (propertyPair.first == "StaticNameServers")
303 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500304 const std::vector<std::string>* staticNameServers =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500305 std::get_if<std::vector<std::string>>(
manojkiran.eda@gmail.com0f6efdc2019-10-03 04:53:44 -0500306 &propertyPair.second);
307 if (staticNameServers != nullptr)
308 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700309 ethData.staticNameServers = *staticNameServers;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700310 }
311 }
manojkiraneda2a133282019-02-19 13:09:43 +0530312 else if (propertyPair.first == "DHCPEnabled")
313 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700314 const std::string* dhcpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700315 std::get_if<std::string>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700316 if (dhcpEnabled != nullptr)
manojkiraneda2a133282019-02-19 13:09:43 +0530317 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800318 ethData.dhcpEnabled = *dhcpEnabled;
manojkiraneda2a133282019-02-19 13:09:43 +0530319 }
320 }
Jennifer Leed24bfc72019-03-05 13:03:37 -0800321 else if (propertyPair.first == "DomainName")
322 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500323 const std::vector<std::string>* domainNames =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500324 std::get_if<std::vector<std::string>>(
Jennifer Leed24bfc72019-03-05 13:03:37 -0800325 &propertyPair.second);
326 if (domainNames != nullptr)
327 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700328 ethData.domainnames = *domainNames;
Jennifer Leed24bfc72019-03-05 13:03:37 -0800329 }
330 }
Ravi Teja9010ec22019-08-01 23:30:25 -0500331 else if (propertyPair.first == "DefaultGateway")
332 {
333 const std::string* defaultGateway =
334 std::get_if<std::string>(&propertyPair.second);
335 if (defaultGateway != nullptr)
336 {
337 std::string defaultGatewayStr = *defaultGateway;
338 if (defaultGatewayStr.empty())
339 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800340 ethData.defaultGateway = "0.0.0.0";
Ravi Teja9010ec22019-08-01 23:30:25 -0500341 }
342 else
343 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800344 ethData.defaultGateway = defaultGatewayStr;
Ravi Teja9010ec22019-08-01 23:30:25 -0500345 }
346 }
347 }
348 else if (propertyPair.first == "DefaultGateway6")
349 {
350 const std::string* defaultGateway6 =
351 std::get_if<std::string>(&propertyPair.second);
352 if (defaultGateway6 != nullptr)
353 {
354 std::string defaultGateway6Str =
355 *defaultGateway6;
356 if (defaultGateway6Str.empty())
357 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800358 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500359 "0:0:0:0:0:0:0:0";
360 }
361 else
362 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800363 ethData.ipv6DefaultGateway =
Ravi Teja9010ec22019-08-01 23:30:25 -0500364 defaultGateway6Str;
365 }
366 }
367 }
Ed Tanous029573d2019-02-01 10:57:49 -0800368 }
369 }
370 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700371
Jishnu CMe4588152023-05-11 00:04:40 -0500372 sdbusplus::message::object_path path(
373 "/xyz/openbmc_project/network");
374 sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
375 "dhcp4";
376
377 if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700378 {
379 if (ifacePair.first ==
380 "xyz.openbmc_project.Network.DHCPConfiguration")
381 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500382 for (const auto& propertyPair : ifacePair.second)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700383 {
384 if (propertyPair.first == "DNSEnabled")
385 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700386 const bool* dnsEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700387 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700388 if (dnsEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700389 {
Jishnu CMe4588152023-05-11 00:04:40 -0500390 ethData.dnsv4Enabled = *dnsEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700391 }
392 }
393 else if (propertyPair.first == "NTPEnabled")
394 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700395 const bool* ntpEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700396 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700397 if (ntpEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700398 {
Jishnu CMe4588152023-05-11 00:04:40 -0500399 ethData.ntpv4Enabled = *ntpEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700400 }
401 }
402 else if (propertyPair.first == "HostNameEnabled")
403 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700404 const bool* hostNameEnabled =
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700405 std::get_if<bool>(&propertyPair.second);
Ed Tanous2c70f802020-09-28 14:29:23 -0700406 if (hostNameEnabled != nullptr)
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700407 {
Jishnu CMe4588152023-05-11 00:04:40 -0500408 ethData.hostNamev4Enabled = *hostNameEnabled;
409 }
410 }
411 }
412 }
413 }
414
415 sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
416 "dhcp6";
417
418 if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
419 {
420 if (ifacePair.first ==
421 "xyz.openbmc_project.Network.DHCPConfiguration")
422 {
423 for (const auto& propertyPair : ifacePair.second)
424 {
425 if (propertyPair.first == "DNSEnabled")
426 {
427 const bool* dnsEnabled =
428 std::get_if<bool>(&propertyPair.second);
429 if (dnsEnabled != nullptr)
430 {
431 ethData.dnsv6Enabled = *dnsEnabled;
432 }
433 }
434 else if (propertyPair.first == "NTPEnabled")
435 {
436 const bool* ntpEnabled =
437 std::get_if<bool>(&propertyPair.second);
438 if (ntpEnabled != nullptr)
439 {
440 ethData.ntpv6Enabled = *ntpEnabled;
441 }
442 }
443 else if (propertyPair.first == "HostNameEnabled")
444 {
445 const bool* hostNameEnabled =
446 std::get_if<bool>(&propertyPair.second);
447 if (hostNameEnabled != nullptr)
448 {
449 ethData.hostNamev6Enabled = *hostNameEnabled;
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700450 }
451 }
Johnathan Mantey1f8c7b52019-06-18 12:44:21 -0700452 }
453 }
454 }
Ed Tanous029573d2019-02-01 10:57:49 -0800455 // System configuration shows up in the global namespace, so no need
456 // to check eth number
457 if (ifacePair.first ==
458 "xyz.openbmc_project.Network.SystemConfiguration")
459 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500460 for (const auto& propertyPair : ifacePair.second)
Ed Tanous029573d2019-02-01 10:57:49 -0800461 {
462 if (propertyPair.first == "HostName")
463 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500464 const std::string* hostname =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500465 std::get_if<std::string>(&propertyPair.second);
Ed Tanous029573d2019-02-01 10:57:49 -0800466 if (hostname != nullptr)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700467 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +0800468 ethData.hostName = *hostname;
Ed Tanous029573d2019-02-01 10:57:49 -0800469 }
470 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700471 }
472 }
473 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700474 }
Ed Tanous4c9afe42019-05-03 16:59:57 -0700475 return idFound;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700476}
477
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500478// Helper function that extracts data for single ethernet ipv6 address
Ed Tanous77179532023-02-28 10:45:28 -0800479inline void extractIPV6Data(const std::string& ethifaceId,
480 const dbus::utility::ManagedObjectType& dbusData,
481 std::vector<IPv6AddressData>& ipv6Config)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500482{
Patrick Williams89492a12023-05-10 07:51:34 -0500483 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
484 ethifaceId;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500485
486 // Since there might be several IPv6 configurations aligned with
487 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000488 for (const auto& objpath : dbusData)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500489 {
490 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800491 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500492 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800493 for (const auto& interface : objpath.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500494 {
495 if (interface.first == "xyz.openbmc_project.Network.IP")
496 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700497 auto type = std::ranges::find_if(interface.second,
498 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800499 return property.first == "Type";
500 });
501 if (type == interface.second.end())
502 {
503 continue;
504 }
505
506 const std::string* typeStr =
507 std::get_if<std::string>(&type->second);
508
509 if (typeStr == nullptr ||
510 (*typeStr !=
511 "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
512 {
513 continue;
514 }
515
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500516 // Instance IPv6AddressData structure, and set as
517 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800518 IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700519 ipv6Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800520 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800521 for (const auto& property : interface.second)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500522 {
523 if (property.first == "Address")
524 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500525 const std::string* address =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500526 std::get_if<std::string>(&property.second);
527 if (address != nullptr)
528 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700529 ipv6Address.address = *address;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500530 }
531 }
532 else if (property.first == "Origin")
533 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500534 const std::string* origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500535 std::get_if<std::string>(&property.second);
536 if (origin != nullptr)
537 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700538 ipv6Address.origin =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500539 translateAddressOriginDbusToRedfish(*origin,
540 false);
541 }
542 }
543 else if (property.first == "PrefixLength")
544 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500545 const uint8_t* prefix =
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500546 std::get_if<uint8_t>(&property.second);
547 if (prefix != nullptr)
548 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700549 ipv6Address.prefixLength = *prefix;
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500550 }
551 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600552 else if (property.first == "Type" ||
553 property.first == "Gateway")
554 {
555 // Type & Gateway is not used
556 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500557 else
558 {
Ed Tanous62598e32023-07-17 17:06:25 -0700559 BMCWEB_LOG_ERROR(
560 "Got extra property: {} on the {} object",
561 property.first, objpath.first.str);
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500562 }
563 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500564 }
565 }
566 }
567 }
568}
569
Ed Tanous4a0cb852018-10-15 07:55:04 -0700570// Helper function that extracts data for single ethernet ipv4 address
Ed Tanous77179532023-02-28 10:45:28 -0800571inline void extractIPData(const std::string& ethifaceId,
572 const dbus::utility::ManagedObjectType& dbusData,
573 std::vector<IPv4AddressData>& ipv4Config)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700574{
Patrick Williams89492a12023-05-10 07:51:34 -0500575 const std::string ipPathStart = "/xyz/openbmc_project/network/" +
576 ethifaceId;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700577
578 // Since there might be several IPv4 configurations aligned with
579 // single ethernet interface, loop over all of them
Ed Tanous81ce6092020-12-17 16:54:55 +0000580 for (const auto& objpath : dbusData)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700581 {
582 // Check if proper pattern for object path appears
Tony Lee353163e2022-11-23 11:06:10 +0800583 if (objpath.first.str.starts_with(ipPathStart + "/"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700584 {
Ed Tanous9eb808c2022-01-25 10:19:23 -0800585 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700586 {
587 if (interface.first == "xyz.openbmc_project.Network.IP")
588 {
Ed Tanous3544d2a2023-08-06 18:12:20 -0700589 auto type = std::ranges::find_if(interface.second,
590 [](const auto& property) {
Tony Lee353163e2022-11-23 11:06:10 +0800591 return property.first == "Type";
592 });
593 if (type == interface.second.end())
594 {
595 continue;
596 }
597
598 const std::string* typeStr =
599 std::get_if<std::string>(&type->second);
600
601 if (typeStr == nullptr ||
602 (*typeStr !=
603 "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
604 {
605 continue;
606 }
607
Ed Tanous4a0cb852018-10-15 07:55:04 -0700608 // Instance IPv4AddressData structure, and set as
609 // appropriate
Ed Tanous77179532023-02-28 10:45:28 -0800610 IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
Ed Tanous2c70f802020-09-28 14:29:23 -0700611 ipv4Address.id =
Tony Lee353163e2022-11-23 11:06:10 +0800612 objpath.first.str.substr(ipPathStart.size());
Ed Tanous9eb808c2022-01-25 10:19:23 -0800613 for (const auto& property : interface.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700614 {
615 if (property.first == "Address")
616 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500617 const std::string* address =
Ed Tanousabf2add2019-01-22 16:40:12 -0800618 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700619 if (address != nullptr)
620 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700621 ipv4Address.address = *address;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700622 }
623 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700624 else if (property.first == "Origin")
625 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500626 const std::string* origin =
Ed Tanousabf2add2019-01-22 16:40:12 -0800627 std::get_if<std::string>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700628 if (origin != nullptr)
629 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700630 ipv4Address.origin =
Ed Tanous4a0cb852018-10-15 07:55:04 -0700631 translateAddressOriginDbusToRedfish(*origin,
632 true);
633 }
634 }
635 else if (property.first == "PrefixLength")
636 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500637 const uint8_t* mask =
Ed Tanousabf2add2019-01-22 16:40:12 -0800638 std::get_if<uint8_t>(&property.second);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700639 if (mask != nullptr)
640 {
641 // convert it to the string
Ed Tanous2c70f802020-09-28 14:29:23 -0700642 ipv4Address.netmask = getNetmask(*mask);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700643 }
644 }
Asmitha Karunanithi889ff692021-11-29 08:43:30 -0600645 else if (property.first == "Type" ||
646 property.first == "Gateway")
647 {
648 // Type & Gateway is not used
649 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700650 else
651 {
Ed Tanous62598e32023-07-17 17:06:25 -0700652 BMCWEB_LOG_ERROR(
653 "Got extra property: {} on the {} object",
654 property.first, objpath.first.str);
Ed Tanous4a0cb852018-10-15 07:55:04 -0700655 }
656 }
657 // Check if given address is local, or global
Ed Tanous2c70f802020-09-28 14:29:23 -0700658 ipv4Address.linktype =
Ed Tanous11ba3972022-07-11 09:50:41 -0700659 ipv4Address.address.starts_with("169.254.")
Johnathan Mantey18659d12019-06-07 10:26:29 -0700660 ? LinkType::Local
661 : LinkType::Global;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700662 }
663 }
664 }
665 }
666}
667
668/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700669 * @brief Deletes given IPv4 interface
Ed Tanous4a0cb852018-10-15 07:55:04 -0700670 *
671 * @param[in] ifaceId Id of interface whose IP should be deleted
Ed Tanous4a0cb852018-10-15 07:55:04 -0700672 * @param[in] ipHash DBus Hash id of IP that should be deleted
673 * @param[io] asyncResp Response object that will be returned to client
674 *
675 * @return None
676 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600677inline void deleteIPAddress(const std::string& ifaceId,
678 const std::string& ipHash,
679 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700680{
681 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800682 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700683 if (ec)
684 {
685 messages::internalError(asyncResp->res);
686 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500687 },
Ed Tanous4a0cb852018-10-15 07:55:04 -0700688 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600689 "/xyz/openbmc_project/network/" + ifaceId + ipHash,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700690 "xyz.openbmc_project.Object.Delete", "Delete");
691}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700692
Gunnar Mills244b6d52021-04-12 15:44:23 -0500693inline void updateIPv4DefaultGateway(
694 const std::string& ifaceId, const std::string& gateway,
695 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Teja9010ec22019-08-01 23:30:25 -0500696{
George Liu9ae226f2023-06-21 17:56:46 +0800697 sdbusplus::asio::setProperty(
698 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ravi Teja9010ec22019-08-01 23:30:25 -0500699 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9010ec22019-08-01 23:30:25 -0500700 "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
George Liu9ae226f2023-06-21 17:56:46 +0800701 gateway, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -0500702 if (ec)
703 {
704 messages::internalError(asyncResp->res);
705 return;
706 }
707 asyncResp->res.result(boost::beast::http::status::no_content);
708 });
Ravi Teja9010ec22019-08-01 23:30:25 -0500709}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700710/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700711 * @brief Creates a static IPv4 entry
Ed Tanous4a0cb852018-10-15 07:55:04 -0700712 *
Johnathan Mantey01784822019-06-18 12:44:21 -0700713 * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
714 * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
715 * @param[in] gateway IPv4 address of this interfaces gateway
716 * @param[in] address IPv4 address to assign to this interface
717 * @param[io] asyncResp Response object that will be returned to client
Ed Tanous4a0cb852018-10-15 07:55:04 -0700718 *
719 * @return None
720 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000721inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
722 const std::string& gateway, const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800723 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700724{
Patrick Williams5a39f772023-10-20 11:20:21 -0500725 auto createIpHandler = [asyncResp, ifaceId,
726 gateway](const boost::system::error_code& ec) {
Ravi Teja9010ec22019-08-01 23:30:25 -0500727 if (ec)
728 {
729 messages::internalError(asyncResp->res);
730 return;
731 }
732 updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
733 };
734
Ed Tanous4a0cb852018-10-15 07:55:04 -0700735 crow::connections::systemBus->async_method_call(
Ravi Teja9010ec22019-08-01 23:30:25 -0500736 std::move(createIpHandler), "xyz.openbmc_project.Network",
Ed Tanous4a0cb852018-10-15 07:55:04 -0700737 "/xyz/openbmc_project/network/" + ifaceId,
738 "xyz.openbmc_project.Network.IP.Create", "IP",
Johnathan Mantey01784822019-06-18 12:44:21 -0700739 "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
Ed Tanous4a0cb852018-10-15 07:55:04 -0700740 gateway);
741}
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500742
743/**
Johnathan Mantey01784822019-06-18 12:44:21 -0700744 * @brief Deletes the IPv6 entry for this interface and creates a replacement
745 * static IPv6 entry
746 *
747 * @param[in] ifaceId Id of interface upon which to create the IPv6 entry
748 * @param[in] id The unique hash entry identifying the DBus entry
749 * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
750 * @param[in] address IPv6 address to assign to this interface
751 * @param[io] asyncResp Response object that will be returned to client
752 *
753 * @return None
754 */
Ravi Teja9c5e5852023-02-26 21:33:52 -0600755
756enum class IpVersion
757{
758 IpV4,
759 IpV6
760};
761
762inline void deleteAndCreateIPAddress(
763 IpVersion version, const std::string& ifaceId, const std::string& id,
764 uint8_t prefixLength, const std::string& address,
765 const std::string& gateway,
766 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Johnathan Mantey01784822019-06-18 12:44:21 -0700767{
768 crow::connections::systemBus->async_method_call(
Ravi Teja9c5e5852023-02-26 21:33:52 -0600769 [asyncResp, version, ifaceId, address, prefixLength,
770 gateway](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700771 if (ec)
772 {
773 messages::internalError(asyncResp->res);
774 }
Ravi Teja9c5e5852023-02-26 21:33:52 -0600775 std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
776 protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
Ed Tanous002d39b2022-05-31 08:59:27 -0700777 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800778 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700779 if (ec2)
Johnathan Mantey01784822019-06-18 12:44:21 -0700780 {
781 messages::internalError(asyncResp->res);
782 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500783 },
Ed Tanous002d39b2022-05-31 08:59:27 -0700784 "xyz.openbmc_project.Network",
785 "/xyz/openbmc_project/network/" + ifaceId,
Ravi Teja9c5e5852023-02-26 21:33:52 -0600786 "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
787 prefixLength, gateway);
Patrick Williams5a39f772023-10-20 11:20:21 -0500788 },
Johnathan Mantey01784822019-06-18 12:44:21 -0700789 "xyz.openbmc_project.Network",
Ravi Teja9c5e5852023-02-26 21:33:52 -0600790 "/xyz/openbmc_project/network/" + ifaceId + id,
Johnathan Mantey01784822019-06-18 12:44:21 -0700791 "xyz.openbmc_project.Object.Delete", "Delete");
792}
793
794/**
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500795 * @brief Creates IPv6 with given data
796 *
797 * @param[in] ifaceId Id of interface whose IP should be added
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500798 * @param[in] prefixLength Prefix length that needs to be added
799 * @param[in] address IP address that needs to be added
800 * @param[io] asyncResp Response object that will be returned to client
801 *
802 * @return None
803 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500804inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
805 const std::string& address,
zhanghch058d1b46d2021-04-01 11:18:24 +0800806 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500807{
Patrick Williams5a39f772023-10-20 11:20:21 -0500808 auto createIpHandler = [asyncResp,
809 address](const boost::system::error_code& ec) {
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500810 if (ec)
811 {
Nitin Kumar Kotaniafc23ef82023-06-29 04:55:09 -0500812 if (ec == boost::system::errc::io_error)
813 {
814 messages::propertyValueFormatError(asyncResp->res, address,
815 "Address");
816 }
817 else
818 {
819 messages::internalError(asyncResp->res);
820 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500821 }
822 };
823 // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500824 // does not have associated gateway property
Ravi Tejae48c0fc2019-04-16 08:37:20 -0500825 crow::connections::systemBus->async_method_call(
826 std::move(createIpHandler), "xyz.openbmc_project.Network",
827 "/xyz/openbmc_project/network/" + ifaceId,
828 "xyz.openbmc_project.Network.IP.Create", "IP",
829 "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
830 "");
831}
832
Ed Tanous4a0cb852018-10-15 07:55:04 -0700833/**
834 * Function that retrieves all properties for given Ethernet Interface
835 * Object
836 * from EntityManager Network Manager
837 * @param ethiface_id a eth interface id to query on DBus
838 * @param callback a function that shall be called to convert Dbus output
839 * into JSON
840 */
841template <typename CallbackFunc>
Ed Tanous81ce6092020-12-17 16:54:55 +0000842void getEthernetIfaceData(const std::string& ethifaceId,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500843 CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700844{
George Liuf5892d02023-03-01 10:37:08 +0800845 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
846 dbus::utility::getManagedObjects(
847 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800848 [ethifaceId{std::string{ethifaceId}},
849 callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700850 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700851 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700852 EthernetInterfaceData ethData{};
Ed Tanous77179532023-02-28 10:45:28 -0800853 std::vector<IPv4AddressData> ipv4Data;
854 std::vector<IPv6AddressData> ipv6Data;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700855
Ed Tanous8b242752023-06-27 17:17:13 -0700856 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700857 {
858 callback(false, ethData, ipv4Data, ipv6Data);
859 return;
860 }
861
862 bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
863 if (!found)
864 {
865 callback(false, ethData, ipv4Data, ipv6Data);
866 return;
867 }
868
869 extractIPData(ethifaceId, resp, ipv4Data);
870 // Fix global GW
871 for (IPv4AddressData& ipv4 : ipv4Data)
872 {
873 if (((ipv4.linktype == LinkType::Global) &&
874 (ipv4.gateway == "0.0.0.0")) ||
875 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
Ed Tanous4a0cb852018-10-15 07:55:04 -0700876 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700877 ipv4.gateway = ethData.defaultGateway;
Ed Tanous4a0cb852018-10-15 07:55:04 -0700878 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700879 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700880
Ed Tanous002d39b2022-05-31 08:59:27 -0700881 extractIPV6Data(ethifaceId, resp, ipv6Data);
882 // Finally make a callback with useful data
883 callback(true, ethData, ipv4Data, ipv6Data);
Patrick Williams5a39f772023-10-20 11:20:21 -0500884 });
Ed Tanous271584a2019-07-09 16:24:22 -0700885}
Ed Tanous4a0cb852018-10-15 07:55:04 -0700886
887/**
888 * Function that retrieves all Ethernet Interfaces available through Network
889 * Manager
890 * @param callback a function that shall be called to convert Dbus output
891 * into JSON.
892 */
893template <typename CallbackFunc>
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500894void getEthernetIfaceList(CallbackFunc&& callback)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700895{
George Liuf5892d02023-03-01 10:37:08 +0800896 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
897 dbus::utility::getManagedObjects(
898 "xyz.openbmc_project.Network", path,
Ed Tanousf94c4ec2022-01-06 12:44:41 -0800899 [callback{std::forward<CallbackFunc>(callback)}](
Ed Tanous8b242752023-06-27 17:17:13 -0700900 const boost::system::error_code& ec,
George Liuf5892d02023-03-01 10:37:08 +0800901 const dbus::utility::ManagedObjectType& resp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700902 // Callback requires vector<string> to retrieve all available
903 // ethernet interfaces
Ed Tanous77179532023-02-28 10:45:28 -0800904 std::vector<std::string> ifaceList;
Ed Tanous002d39b2022-05-31 08:59:27 -0700905 ifaceList.reserve(resp.size());
Ed Tanous8b242752023-06-27 17:17:13 -0700906 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700907 {
908 callback(false, ifaceList);
909 return;
910 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700911
Ed Tanous002d39b2022-05-31 08:59:27 -0700912 // Iterate over all retrieved ObjectPaths.
913 for (const auto& objpath : resp)
914 {
915 // And all interfaces available for certain ObjectPath.
916 for (const auto& interface : objpath.second)
Ed Tanous4a0cb852018-10-15 07:55:04 -0700917 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700918 // If interface is
919 // xyz.openbmc_project.Network.EthernetInterface, this is
920 // what we're looking for.
921 if (interface.first ==
922 "xyz.openbmc_project.Network.EthernetInterface")
Ed Tanous4a0cb852018-10-15 07:55:04 -0700923 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700924 std::string ifaceId = objpath.first.filename();
925 if (ifaceId.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700926 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700927 continue;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700928 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700929 // and put it into output vector.
Ed Tanous77179532023-02-28 10:45:28 -0800930 ifaceList.emplace_back(ifaceId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700931 }
Ed Tanous4a0cb852018-10-15 07:55:04 -0700932 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700933 }
Ed Tanous2c5875a2023-05-15 09:56:06 -0700934
Ed Tanous3544d2a2023-08-06 18:12:20 -0700935 std::ranges::sort(ifaceList, AlphanumLess<std::string>());
Ed Tanous2c5875a2023-05-15 09:56:06 -0700936
Ed Tanous002d39b2022-05-31 08:59:27 -0700937 // Finally make a callback with useful data
938 callback(true, ifaceList);
Patrick Williams5a39f772023-10-20 11:20:21 -0500939 });
Ed Tanous271584a2019-07-09 16:24:22 -0700940}
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +0100941
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700942inline void
943 handleHostnamePatch(const std::string& hostname,
944 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700945{
Ed Tanousbf648f72021-06-03 15:00:14 -0700946 // SHOULD handle host names of up to 255 characters(RFC 1123)
947 if (hostname.length() > 255)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700948 {
Ed Tanousbf648f72021-06-03 15:00:14 -0700949 messages::propertyValueFormatError(asyncResp->res, hostname,
950 "HostName");
951 return;
952 }
George Liu9ae226f2023-06-21 17:56:46 +0800953 sdbusplus::asio::setProperty(
954 *crow::connections::systemBus, "xyz.openbmc_project.Network",
955 "/xyz/openbmc_project/network/config",
956 "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800957 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700958 if (ec)
959 {
960 messages::internalError(asyncResp->res);
961 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500962 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700963}
964
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700965inline void
Tejas Patil35fb5312021-09-20 15:35:20 +0530966 handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
967 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
968{
Patrick Williams89492a12023-05-10 07:51:34 -0500969 sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
970 ifaceId;
George Liu9ae226f2023-06-21 17:56:46 +0800971 sdbusplus::asio::setProperty(
972 *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
973 "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800974 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700975 if (ec)
976 {
977 messages::internalError(asyncResp->res);
978 }
Patrick Williams5a39f772023-10-20 11:20:21 -0500979 });
Tejas Patil35fb5312021-09-20 15:35:20 +0530980}
981
982inline void
Ed Tanous4f48d5f2021-06-21 08:27:45 -0700983 handleDomainnamePatch(const std::string& ifaceId,
984 const std::string& domainname,
985 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -0700986{
987 std::vector<std::string> vectorDomainname = {domainname};
George Liu9ae226f2023-06-21 17:56:46 +0800988 sdbusplus::asio::setProperty(
989 *crow::connections::systemBus, "xyz.openbmc_project.Network",
Ed Tanousbf648f72021-06-03 15:00:14 -0700990 "/xyz/openbmc_project/network/" + ifaceId,
Ed Tanousbf648f72021-06-03 15:00:14 -0700991 "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
George Liu9ae226f2023-06-21 17:56:46 +0800992 vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
Patrick Williams5a39f772023-10-20 11:20:21 -0500993 if (ec)
994 {
995 messages::internalError(asyncResp->res);
996 }
997 });
Ed Tanousbf648f72021-06-03 15:00:14 -0700998}
999
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001000inline bool isHostnameValid(const std::string& hostname)
Ed Tanousbf648f72021-06-03 15:00:14 -07001001{
1002 // A valid host name can never have the dotted-decimal form (RFC 1123)
Ed Tanous3544d2a2023-08-06 18:12:20 -07001003 if (std::ranges::all_of(hostname, ::isdigit))
Ed Tanousbf648f72021-06-03 15:00:14 -07001004 {
1005 return false;
1006 }
1007 // Each label(hostname/subdomains) within a valid FQDN
1008 // MUST handle host names of up to 63 characters (RFC 1123)
1009 // labels cannot start or end with hyphens (RFC 952)
1010 // labels can start with numbers (RFC 1123)
Ed Tanous4b242742023-05-11 09:51:51 -07001011 const static std::regex pattern(
Ed Tanousbf648f72021-06-03 15:00:14 -07001012 "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1013
1014 return std::regex_match(hostname, pattern);
1015}
1016
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001017inline bool isDomainnameValid(const std::string& domainname)
Ed Tanousbf648f72021-06-03 15:00:14 -07001018{
1019 // Can have multiple subdomains
1020 // Top Level Domain's min length is 2 character
Ed Tanous4b242742023-05-11 09:51:51 -07001021 const static std::regex pattern(
George Liu0fda0f12021-11-16 10:06:17 +08001022 "^([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 -07001023
1024 return std::regex_match(domainname, pattern);
1025}
1026
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001027inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
1028 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001029{
1030 // Total length of FQDN must not exceed 255 characters(RFC 1035)
1031 if (fqdn.length() > 255)
1032 {
1033 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1034 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001035 }
1036
Ed Tanousbf648f72021-06-03 15:00:14 -07001037 size_t pos = fqdn.find('.');
1038 if (pos == std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001039 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001040 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1041 return;
1042 }
zhanghch058d1b46d2021-04-01 11:18:24 +08001043
Ed Tanousbf648f72021-06-03 15:00:14 -07001044 std::string hostname;
1045 std::string domainname;
1046 domainname = (fqdn).substr(pos + 1);
1047 hostname = (fqdn).substr(0, pos);
1048
1049 if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1050 {
1051 messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1052 return;
1053 }
1054
1055 handleHostnamePatch(hostname, asyncResp);
1056 handleDomainnamePatch(ifaceId, domainname, asyncResp);
1057}
1058
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001059inline void
1060 handleMACAddressPatch(const std::string& ifaceId,
1061 const std::string& macAddress,
1062 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001063{
Johnathan Mantey58283f42022-08-15 14:38:36 -07001064 static constexpr std::string_view dbusNotAllowedError =
1065 "xyz.openbmc_project.Common.Error.NotAllowed";
1066
George Liu9ae226f2023-06-21 17:56:46 +08001067 sdbusplus::asio::setProperty(
1068 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1069 "/xyz/openbmc_project/network/" + ifaceId,
1070 "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
1071 [asyncResp](const boost::system::error_code& ec,
1072 const sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001073 if (ec)
1074 {
Johnathan Mantey58283f42022-08-15 14:38:36 -07001075 const sd_bus_error* err = msg.get_error();
1076 if (err == nullptr)
1077 {
1078 messages::internalError(asyncResp->res);
1079 return;
1080 }
1081 if (err->name == dbusNotAllowedError)
1082 {
1083 messages::propertyNotWritable(asyncResp->res, "MACAddress");
1084 return;
1085 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001086 messages::internalError(asyncResp->res);
1087 return;
1088 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001089 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001090}
1091
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001092inline void setDHCPEnabled(const std::string& ifaceId,
1093 const std::string& propertyName, const bool v4Value,
1094 const bool v6Value,
1095 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001096{
1097 const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
George Liu9ae226f2023-06-21 17:56:46 +08001098 sdbusplus::asio::setProperty(
1099 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1100 "/xyz/openbmc_project/network/" + ifaceId,
1101 "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001102 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001103 if (ec)
1104 {
Ed Tanous62598e32023-07-17 17:06:25 -07001105 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001106 messages::internalError(asyncResp->res);
1107 return;
1108 }
1109 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05001110 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001111}
1112
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001113inline void setEthernetInterfaceBoolProperty(
Ed Tanousbf648f72021-06-03 15:00:14 -07001114 const std::string& ifaceId, const std::string& propertyName,
1115 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1116{
George Liu9ae226f2023-06-21 17:56:46 +08001117 sdbusplus::asio::setProperty(
1118 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1119 "/xyz/openbmc_project/network/" + ifaceId,
1120 "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001121 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001122 if (ec)
1123 {
Ed Tanous62598e32023-07-17 17:06:25 -07001124 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001125 messages::internalError(asyncResp->res);
1126 return;
1127 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001128 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001129}
1130
Jishnu CMe4588152023-05-11 00:04:40 -05001131enum class NetworkType
1132{
1133 dhcp4,
1134 dhcp6
1135};
1136
1137inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1138 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1139 const std::string& ethifaceId, NetworkType type)
Ed Tanousbf648f72021-06-03 15:00:14 -07001140{
Ed Tanous62598e32023-07-17 17:06:25 -07001141 BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
Jishnu CMe4588152023-05-11 00:04:40 -05001142 sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1143 path /= ethifaceId;
1144
1145 if (type == NetworkType::dhcp4)
1146 {
1147 path /= "dhcp4";
1148 }
1149 else
1150 {
1151 path /= "dhcp6";
1152 }
1153
George Liu9ae226f2023-06-21 17:56:46 +08001154 sdbusplus::asio::setProperty(
Jishnu CMe4588152023-05-11 00:04:40 -05001155 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
George Liu9ae226f2023-06-21 17:56:46 +08001156 "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001157 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001158 if (ec)
1159 {
Ed Tanous62598e32023-07-17 17:06:25 -07001160 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07001161 messages::internalError(asyncResp->res);
1162 return;
1163 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001164 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001165}
1166
Ravi Tejab10d8db2022-05-24 09:04:12 -05001167inline void handleSLAACAutoConfigPatch(
1168 const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1169 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1170{
1171 sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1172 path /= ifaceId;
1173 sdbusplus::asio::setProperty(
1174 *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1175 "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1176 ipv6AutoConfigEnabled,
1177 [asyncResp](const boost::system::error_code& ec) {
1178 if (ec)
1179 {
1180 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1181 messages::internalError(asyncResp->res);
1182 return;
1183 }
1184 messages::success(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -05001185 });
Ravi Tejab10d8db2022-05-24 09:04:12 -05001186}
1187
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001188inline void handleDHCPPatch(const std::string& ifaceId,
1189 const EthernetInterfaceData& ethData,
1190 const DHCPParameters& v4dhcpParms,
1191 const DHCPParameters& v6dhcpParms,
1192 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001193{
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001194 bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1195 bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
Ed Tanousbf648f72021-06-03 15:00:14 -07001196
1197 bool nextv4DHCPState =
1198 v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
1199
1200 bool nextv6DHCPState{};
1201 if (v6dhcpParms.dhcpv6OperatingMode)
1202 {
Ravi Tejab10d8db2022-05-24 09:04:12 -05001203 if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
Ed Tanousbf648f72021-06-03 15:00:14 -07001204 (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
1205 {
1206 messages::propertyValueFormatError(asyncResp->res,
1207 *v6dhcpParms.dhcpv6OperatingMode,
1208 "OperatingMode");
1209 return;
1210 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05001211 nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
Ed Tanousbf648f72021-06-03 15:00:14 -07001212 }
1213 else
1214 {
1215 nextv6DHCPState = ipv6Active;
1216 }
1217
Jishnu CMe4588152023-05-11 00:04:40 -05001218 bool nextDNSv4 = ethData.dnsv4Enabled;
1219 bool nextDNSv6 = ethData.dnsv6Enabled;
1220 if (v4dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001221 {
Jishnu CMe4588152023-05-11 00:04:40 -05001222 nextDNSv4 = *v4dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001223 }
Jishnu CMe4588152023-05-11 00:04:40 -05001224 if (v6dhcpParms.useDnsServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001225 {
Jishnu CMe4588152023-05-11 00:04:40 -05001226 nextDNSv6 = *v6dhcpParms.useDnsServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001227 }
1228
Jishnu CMe4588152023-05-11 00:04:40 -05001229 bool nextNTPv4 = ethData.ntpv4Enabled;
1230 bool nextNTPv6 = ethData.ntpv6Enabled;
1231 if (v4dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001232 {
Jishnu CMe4588152023-05-11 00:04:40 -05001233 nextNTPv4 = *v4dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001234 }
Jishnu CMe4588152023-05-11 00:04:40 -05001235 if (v6dhcpParms.useNtpServers)
Ed Tanousbf648f72021-06-03 15:00:14 -07001236 {
Jishnu CMe4588152023-05-11 00:04:40 -05001237 nextNTPv6 = *v6dhcpParms.useNtpServers;
Ed Tanousbf648f72021-06-03 15:00:14 -07001238 }
1239
Jishnu CMe4588152023-05-11 00:04:40 -05001240 bool nextUsev4Domain = ethData.hostNamev4Enabled;
1241 bool nextUsev6Domain = ethData.hostNamev6Enabled;
1242 if (v4dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001243 {
Jishnu CMe4588152023-05-11 00:04:40 -05001244 nextUsev4Domain = *v4dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001245 }
Jishnu CMe4588152023-05-11 00:04:40 -05001246 if (v6dhcpParms.useDomainName)
Ed Tanousbf648f72021-06-03 15:00:14 -07001247 {
Jishnu CMe4588152023-05-11 00:04:40 -05001248 nextUsev6Domain = *v6dhcpParms.useDomainName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001249 }
1250
Ed Tanous62598e32023-07-17 17:06:25 -07001251 BMCWEB_LOG_DEBUG("set DHCPEnabled...");
Ed Tanousbf648f72021-06-03 15:00:14 -07001252 setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
1253 asyncResp);
Ed Tanous62598e32023-07-17 17:06:25 -07001254 BMCWEB_LOG_DEBUG("set DNSEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001255 setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1256 NetworkType::dhcp4);
Ed Tanous62598e32023-07-17 17:06:25 -07001257 BMCWEB_LOG_DEBUG("set NTPEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001258 setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1259 NetworkType::dhcp4);
Ed Tanous62598e32023-07-17 17:06:25 -07001260 BMCWEB_LOG_DEBUG("set HostNameEnabled...");
Jishnu CMe4588152023-05-11 00:04:40 -05001261 setDHCPConfig("HostNameEnabled", nextUsev4Domain, asyncResp, ifaceId,
1262 NetworkType::dhcp4);
1263 BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1264 setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1265 NetworkType::dhcp6);
1266 BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1267 setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1268 NetworkType::dhcp6);
1269 BMCWEB_LOG_DEBUG("set HostNameEnabled for dhcp6...");
1270 setDHCPConfig("HostNameEnabled", nextUsev6Domain, asyncResp, ifaceId,
1271 NetworkType::dhcp6);
Ed Tanousbf648f72021-06-03 15:00:14 -07001272}
1273
Ed Tanous77179532023-02-28 10:45:28 -08001274inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
1275 const std::vector<IPv4AddressData>::const_iterator& head,
1276 const std::vector<IPv4AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001277{
1278 return std::find_if(head, end, [](const IPv4AddressData& value) {
1279 return value.origin == "Static";
1280 });
1281}
1282
Ed Tanous77179532023-02-28 10:45:28 -08001283inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
1284 const std::vector<IPv6AddressData>::const_iterator& head,
1285 const std::vector<IPv6AddressData>::const_iterator& end)
Ed Tanousbf648f72021-06-03 15:00:14 -07001286{
1287 return std::find_if(head, end, [](const IPv6AddressData& value) {
1288 return value.origin == "Static";
1289 });
1290}
1291
Ed Tanous77179532023-02-28 10:45:28 -08001292inline void
Ed Tanousddd70dc2023-03-01 16:00:27 -08001293 handleIPv4StaticPatch(const std::string& ifaceId,
1294 nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001295 const std::vector<IPv4AddressData>& ipv4Data,
1296 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanousbf648f72021-06-03 15:00:14 -07001297{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001298 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001299 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001300 messages::propertyValueTypeError(asyncResp->res, input,
1301 "IPv4StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001302 return;
1303 }
1304
1305 unsigned entryIdx = 1;
1306 // Find the first static IP address currently active on the NIC and
1307 // match it to the first JSON element in the IPv4StaticAddresses array.
1308 // Match each subsequent JSON element to the next static IP programmed
1309 // into the NIC.
Ed Tanous77179532023-02-28 10:45:28 -08001310 std::vector<IPv4AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001311 getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
1312
1313 for (nlohmann::json& thisJson : input)
1314 {
Patrick Williams89492a12023-05-10 07:51:34 -05001315 std::string pathString = "IPv4StaticAddresses/" +
1316 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001317
1318 if (!thisJson.is_null() && !thisJson.empty())
1319 {
1320 std::optional<std::string> address;
1321 std::optional<std::string> subnetMask;
1322 std::optional<std::string> gateway;
1323
1324 if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1325 address, "SubnetMask", subnetMask,
1326 "Gateway", gateway))
1327 {
Ed Tanousf818b042022-06-27 13:17:35 -07001328 messages::propertyValueFormatError(asyncResp->res, thisJson,
1329 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001330 return;
1331 }
1332
1333 // Find the address/subnet/gateway values. Any values that are
1334 // not explicitly provided are assumed to be unmodified from the
1335 // current state of the interface. Merge existing state into the
1336 // current request.
Ed Tanousbf648f72021-06-03 15:00:14 -07001337 if (address)
1338 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001339 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
Ed Tanousbf648f72021-06-03 15:00:14 -07001340 {
1341 messages::propertyValueFormatError(asyncResp->res, *address,
1342 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001343 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001344 }
1345 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001346 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001347 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001348 address = (nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001349 }
1350 else
1351 {
1352 messages::propertyMissing(asyncResp->res,
1353 pathString + "/Address");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001354 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001355 }
1356
Ed Tanouse01d0c32023-06-30 13:21:32 -07001357 uint8_t prefixLength = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001358 if (subnetMask)
1359 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001360 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1361 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001362 {
1363 messages::propertyValueFormatError(
1364 asyncResp->res, *subnetMask,
1365 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001366 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001367 }
1368 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001369 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001370 {
Ed Tanous033f1e42022-08-15 09:47:37 -07001371 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
1372 &prefixLength))
Ed Tanousbf648f72021-06-03 15:00:14 -07001373 {
1374 messages::propertyValueFormatError(
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001375 asyncResp->res, nicIpEntry->netmask,
Ed Tanousbf648f72021-06-03 15:00:14 -07001376 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001377 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001378 }
1379 }
1380 else
1381 {
1382 messages::propertyMissing(asyncResp->res,
1383 pathString + "/SubnetMask");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001384 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001385 }
1386
1387 if (gateway)
1388 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001389 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
Ed Tanousbf648f72021-06-03 15:00:14 -07001390 {
1391 messages::propertyValueFormatError(asyncResp->res, *gateway,
1392 pathString + "/Gateway");
Ed Tanouse01d0c32023-06-30 13:21:32 -07001393 return;
Ed Tanousbf648f72021-06-03 15:00:14 -07001394 }
1395 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001396 else if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001397 {
Ed Tanouse01d0c32023-06-30 13:21:32 -07001398 gateway = nicIpEntry->gateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001399 }
1400 else
1401 {
1402 messages::propertyMissing(asyncResp->res,
1403 pathString + "/Gateway");
Ed Tanousbf648f72021-06-03 15:00:14 -07001404 return;
1405 }
1406
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001407 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001408 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001409 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001410 nicIpEntry->id, prefixLength, *address,
1411 *gateway, asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001412 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1413 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001414 }
1415 else
1416 {
1417 createIPv4(ifaceId, prefixLength, *gateway, *address,
1418 asyncResp);
1419 }
1420 entryIdx++;
1421 }
1422 else
1423 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001424 if (nicIpEntry == ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001425 {
1426 // Requesting a DELETE/DO NOT MODIFY action for an item
1427 // that isn't present on the eth(n) interface. Input JSON is
1428 // in error, so bail out.
1429 if (thisJson.is_null())
1430 {
1431 messages::resourceCannotBeDeleted(asyncResp->res);
1432 return;
1433 }
Ed Tanousf818b042022-06-27 13:17:35 -07001434 messages::propertyValueFormatError(asyncResp->res, thisJson,
1435 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001436 return;
1437 }
1438
1439 if (thisJson.is_null())
1440 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001441 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001442 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001443 if (nicIpEntry != ipv4Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001444 {
Patrick Williams89492a12023-05-10 07:51:34 -05001445 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1446 ipv4Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001447 }
1448 entryIdx++;
1449 }
1450 }
1451}
1452
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001453inline void handleStaticNameServersPatch(
Ed Tanousbf648f72021-06-03 15:00:14 -07001454 const std::string& ifaceId,
1455 const std::vector<std::string>& updatedStaticNameServers,
1456 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1457{
George Liu9ae226f2023-06-21 17:56:46 +08001458 sdbusplus::asio::setProperty(
1459 *crow::connections::systemBus, "xyz.openbmc_project.Network",
1460 "/xyz/openbmc_project/network/" + ifaceId,
1461 "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1462 updatedStaticNameServers,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001463 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001464 if (ec)
1465 {
1466 messages::internalError(asyncResp->res);
1467 return;
1468 }
Patrick Williams5a39f772023-10-20 11:20:21 -05001469 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001470}
1471
Ed Tanous4f48d5f2021-06-21 08:27:45 -07001472inline void handleIPv6StaticAddressesPatch(
Ed Tanousddd70dc2023-03-01 16:00:27 -08001473 const std::string& ifaceId, const nlohmann::json::array_t& input,
Ed Tanous77179532023-02-28 10:45:28 -08001474 const std::vector<IPv6AddressData>& ipv6Data,
Ed Tanousbf648f72021-06-03 15:00:14 -07001475 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1476{
Ed Tanousddd70dc2023-03-01 16:00:27 -08001477 if (input.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001478 {
Ed Tanous2e8c4bd2022-06-27 12:59:12 -07001479 messages::propertyValueTypeError(asyncResp->res, input,
1480 "IPv6StaticAddresses");
Ed Tanousbf648f72021-06-03 15:00:14 -07001481 return;
1482 }
1483 size_t entryIdx = 1;
Ed Tanous77179532023-02-28 10:45:28 -08001484 std::vector<IPv6AddressData>::const_iterator nicIpEntry =
Ed Tanousbf648f72021-06-03 15:00:14 -07001485 getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1486 for (const nlohmann::json& thisJson : input)
1487 {
Patrick Williams89492a12023-05-10 07:51:34 -05001488 std::string pathString = "IPv6StaticAddresses/" +
1489 std::to_string(entryIdx);
Ed Tanousbf648f72021-06-03 15:00:14 -07001490
1491 if (!thisJson.is_null() && !thisJson.empty())
1492 {
1493 std::optional<std::string> address;
1494 std::optional<uint8_t> prefixLength;
1495 nlohmann::json thisJsonCopy = thisJson;
1496 if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1497 address, "PrefixLength", prefixLength))
1498 {
Ed Tanousf818b042022-06-27 13:17:35 -07001499 messages::propertyValueFormatError(asyncResp->res, thisJson,
1500 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001501 return;
1502 }
1503
Ed Tanous543f4402022-01-06 13:12:53 -08001504 const std::string* addr = nullptr;
1505 uint8_t prefix = 0;
Ed Tanousbf648f72021-06-03 15:00:14 -07001506
1507 // Find the address and prefixLength values. Any values that are
1508 // not explicitly provided are assumed to be unmodified from the
1509 // current state of the interface. Merge existing state into the
1510 // current request.
1511 if (address)
1512 {
1513 addr = &(*address);
1514 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001515 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001516 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001517 addr = &(nicIpEntry->address);
Ed Tanousbf648f72021-06-03 15:00:14 -07001518 }
1519 else
1520 {
1521 messages::propertyMissing(asyncResp->res,
1522 pathString + "/Address");
1523 return;
1524 }
1525
1526 if (prefixLength)
1527 {
1528 prefix = *prefixLength;
1529 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001530 else if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001531 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001532 prefix = nicIpEntry->prefixLength;
Ed Tanousbf648f72021-06-03 15:00:14 -07001533 }
1534 else
1535 {
1536 messages::propertyMissing(asyncResp->res,
1537 pathString + "/PrefixLength");
1538 return;
1539 }
1540
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001541 if (nicIpEntry != ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001542 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001543 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
Ed Tanous77eb0152023-09-06 10:19:18 -07001544 nicIpEntry->id, prefix, *addr, "",
Ravi Teja9c5e5852023-02-26 21:33:52 -06001545 asyncResp);
Patrick Williams89492a12023-05-10 07:51:34 -05001546 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1547 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001548 }
1549 else
1550 {
1551 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1552 }
1553 entryIdx++;
1554 }
1555 else
1556 {
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001557 if (nicIpEntry == ipv6Data.end())
Ed Tanousbf648f72021-06-03 15:00:14 -07001558 {
1559 // Requesting a DELETE/DO NOT MODIFY action for an item
1560 // that isn't present on the eth(n) interface. Input JSON is
1561 // in error, so bail out.
1562 if (thisJson.is_null())
1563 {
1564 messages::resourceCannotBeDeleted(asyncResp->res);
1565 return;
1566 }
Ed Tanousf818b042022-06-27 13:17:35 -07001567 messages::propertyValueFormatError(asyncResp->res, thisJson,
1568 pathString);
Ed Tanousbf648f72021-06-03 15:00:14 -07001569 return;
1570 }
1571
1572 if (thisJson.is_null())
1573 {
Ravi Teja9c5e5852023-02-26 21:33:52 -06001574 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
Ed Tanousbf648f72021-06-03 15:00:14 -07001575 }
Jiaqing Zhao85ffe862021-12-31 15:41:59 +08001576 if (nicIpEntry != ipv6Data.cend())
Ed Tanousbf648f72021-06-03 15:00:14 -07001577 {
Patrick Williams89492a12023-05-10 07:51:34 -05001578 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1579 ipv6Data.cend());
Ed Tanousbf648f72021-06-03 15:00:14 -07001580 }
1581 entryIdx++;
1582 }
1583 }
1584}
1585
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001586inline std::string extractParentInterfaceName(const std::string& ifaceId)
1587{
1588 std::size_t pos = ifaceId.find('_');
1589 return ifaceId.substr(0, pos);
1590}
1591
Ed Tanous77179532023-02-28 10:45:28 -08001592inline void
1593 parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1594 const std::string& ifaceId,
1595 const EthernetInterfaceData& ethData,
1596 const std::vector<IPv4AddressData>& ipv4Data,
1597 const std::vector<IPv6AddressData>& ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001598{
Ed Tanousbf648f72021-06-03 15:00:14 -07001599 nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
1600 jsonResponse["Id"] = ifaceId;
Ed Tanousef4c65b2023-04-24 15:28:50 -07001601 jsonResponse["@odata.id"] = boost::urls::format(
1602 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
Ed Tanousbf648f72021-06-03 15:00:14 -07001603 jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1604
Willy Tu13451e32023-05-24 16:08:18 -07001605 if constexpr (bmcwebEnableHealthPopulate)
1606 {
1607 constexpr std::array<std::string_view, 1> inventoryForEthernet = {
1608 "xyz.openbmc_project.Inventory.Item.Ethernet"};
1609 auto health = std::make_shared<HealthPopulate>(asyncResp);
1610 dbus::utility::getSubTreePaths(
1611 "/", 0, inventoryForEthernet,
1612 [health](const boost::system::error_code& ec,
1613 const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1614 if (ec)
1615 {
1616 return;
1617 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001618
Willy Tu13451e32023-05-24 16:08:18 -07001619 health->inventory = resp;
Patrick Williams5a39f772023-10-20 11:20:21 -05001620 });
Ed Tanousbf648f72021-06-03 15:00:14 -07001621
Willy Tu13451e32023-05-24 16:08:18 -07001622 health->populate();
1623 }
Ed Tanousbf648f72021-06-03 15:00:14 -07001624
1625 if (ethData.nicEnabled)
1626 {
Johnathan Mantey0ef0e282022-11-15 12:15:02 -08001627 jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
Ed Tanousbf648f72021-06-03 15:00:14 -07001628 jsonResponse["Status"]["State"] = "Enabled";
1629 }
1630 else
1631 {
1632 jsonResponse["LinkStatus"] = "NoLink";
1633 jsonResponse["Status"]["State"] = "Disabled";
1634 }
1635
Ed Tanousbf648f72021-06-03 15:00:14 -07001636 jsonResponse["SpeedMbps"] = ethData.speed;
Tejas Patil35fb5312021-09-20 15:35:20 +05301637 jsonResponse["MTUSize"] = ethData.mtuSize;
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001638 jsonResponse["MACAddress"] = ethData.macAddress;
Ed Tanousbf648f72021-06-03 15:00:14 -07001639 jsonResponse["DHCPv4"]["DHCPEnabled"] =
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001640 translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
Jishnu CMe4588152023-05-11 00:04:40 -05001641 jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1642 jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1643 jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
Ed Tanousbf648f72021-06-03 15:00:14 -07001644 jsonResponse["DHCPv6"]["OperatingMode"] =
Ravi Tejab10d8db2022-05-24 09:04:12 -05001645 translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
Ed Tanousbf648f72021-06-03 15:00:14 -07001646 : "Disabled";
Jishnu CMe4588152023-05-11 00:04:40 -05001647 jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1648 jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1649 jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
Ravi Tejab10d8db2022-05-24 09:04:12 -05001650 jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1651 ethData.ipv6AcceptRa;
Ed Tanousbf648f72021-06-03 15:00:14 -07001652
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001653 if (!ethData.hostName.empty())
Ed Tanousbf648f72021-06-03 15:00:14 -07001654 {
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001655 jsonResponse["HostName"] = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001656
1657 // When domain name is empty then it means, that it is a network
1658 // without domain names, and the host name itself must be treated as
1659 // FQDN
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001660 std::string fqdn = ethData.hostName;
Ed Tanousbf648f72021-06-03 15:00:14 -07001661 if (!ethData.domainnames.empty())
1662 {
1663 fqdn += "." + ethData.domainnames[0];
1664 }
1665 jsonResponse["FQDN"] = fqdn;
1666 }
1667
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001668 if (ethData.vlanId)
1669 {
1670 jsonResponse["EthernetInterfaceType"] = "Virtual";
1671 jsonResponse["VLAN"]["VLANEnable"] = true;
1672 jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
1673 jsonResponse["VLAN"]["Tagged"] = true;
1674
1675 nlohmann::json::array_t relatedInterfaces;
1676 nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
1677 parentInterface["@odata.id"] =
1678 boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
1679 extractParentInterfaceName(ifaceId));
1680 jsonResponse["Links"]["RelatedInterfaces"] =
1681 std::move(relatedInterfaces);
1682 }
1683 else
1684 {
1685 jsonResponse["EthernetInterfaceType"] = "Physical";
1686 }
1687
Ed Tanousbf648f72021-06-03 15:00:14 -07001688 jsonResponse["NameServers"] = ethData.nameServers;
1689 jsonResponse["StaticNameServers"] = ethData.staticNameServers;
1690
1691 nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
1692 nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
1693 ipv4Array = nlohmann::json::array();
1694 ipv4StaticArray = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001695 for (const auto& ipv4Config : ipv4Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001696 {
Ed Tanousbf648f72021-06-03 15:00:14 -07001697 std::string gatewayStr = ipv4Config.gateway;
1698 if (gatewayStr.empty())
1699 {
1700 gatewayStr = "0.0.0.0";
1701 }
Ed Tanous14766872022-03-15 10:44:42 -07001702 nlohmann::json::object_t ipv4;
1703 ipv4["AddressOrigin"] = ipv4Config.origin;
1704 ipv4["SubnetMask"] = ipv4Config.netmask;
1705 ipv4["Address"] = ipv4Config.address;
1706 ipv4["Gateway"] = gatewayStr;
Ed Tanousbf648f72021-06-03 15:00:14 -07001707
Ed Tanousbf648f72021-06-03 15:00:14 -07001708 if (ipv4Config.origin == "Static")
1709 {
Ed Tanous14766872022-03-15 10:44:42 -07001710 ipv4StaticArray.push_back(ipv4);
Ed Tanousbf648f72021-06-03 15:00:14 -07001711 }
Ed Tanous14766872022-03-15 10:44:42 -07001712
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001713 ipv4Array.emplace_back(std::move(ipv4));
Ed Tanousbf648f72021-06-03 15:00:14 -07001714 }
1715
Jiaqing Zhao82695a52022-04-14 15:15:59 +08001716 std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
Ed Tanousbf648f72021-06-03 15:00:14 -07001717 if (ipv6GatewayStr.empty())
1718 {
1719 ipv6GatewayStr = "0:0:0:0:0:0:0:0";
1720 }
1721
1722 jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1723
1724 nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
1725 nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
1726 ipv6Array = nlohmann::json::array();
1727 ipv6StaticArray = nlohmann::json::array();
1728 nlohmann::json& ipv6AddrPolicyTable =
1729 jsonResponse["IPv6AddressPolicyTable"];
1730 ipv6AddrPolicyTable = nlohmann::json::array();
Ed Tanous9eb808c2022-01-25 10:19:23 -08001731 for (const auto& ipv6Config : ipv6Data)
Ed Tanousbf648f72021-06-03 15:00:14 -07001732 {
Ed Tanous14766872022-03-15 10:44:42 -07001733 nlohmann::json::object_t ipv6;
1734 ipv6["Address"] = ipv6Config.address;
1735 ipv6["PrefixLength"] = ipv6Config.prefixLength;
1736 ipv6["AddressOrigin"] = ipv6Config.origin;
Sunitha Harishf8361272023-03-16 03:23:59 -05001737
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001738 ipv6Array.emplace_back(std::move(ipv6));
Ed Tanousbf648f72021-06-03 15:00:14 -07001739 if (ipv6Config.origin == "Static")
1740 {
Ed Tanous14766872022-03-15 10:44:42 -07001741 nlohmann::json::object_t ipv6Static;
1742 ipv6Static["Address"] = ipv6Config.address;
1743 ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001744 ipv6StaticArray.emplace_back(std::move(ipv6Static));
Ed Tanousbf648f72021-06-03 15:00:14 -07001745 }
1746 }
1747}
1748
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001749inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1750 const std::string& ifaceId,
1751 const boost::system::error_code& ec,
1752 const sdbusplus::message_t& m)
1753{
1754 if (!ec)
1755 {
1756 return;
1757 }
1758 const sd_bus_error* dbusError = m.get_error();
1759 if (dbusError == nullptr)
1760 {
1761 messages::internalError(asyncResp->res);
1762 return;
1763 }
Ed Tanous62598e32023-07-17 17:06:25 -07001764 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08001765
1766 if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1767 dbusError->name)
1768 {
1769 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1770 ifaceId);
1771 return;
1772 }
1773 if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1774 dbusError->name)
1775 {
1776 messages::resourceCannotBeDeleted(asyncResp->res);
1777 return;
1778 }
1779 messages::internalError(asyncResp->res);
1780}
1781
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001782inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1783 const std::string& parentInterfaceUri,
1784 const std::string& vlanInterface,
1785 const boost::system::error_code& ec,
1786 const sdbusplus::message_t& m
1787
1788)
1789{
1790 if (ec)
1791 {
1792 const sd_bus_error* dbusError = m.get_error();
1793 if (dbusError == nullptr)
1794 {
1795 messages::internalError(asyncResp->res);
1796 return;
1797 }
Ed Tanous62598e32023-07-17 17:06:25 -07001798 BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001799
1800 if (std::string_view(
1801 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1802 dbusError->name)
1803 {
1804 messages::propertyValueNotInList(
1805 asyncResp->res, parentInterfaceUri,
1806 "Links/RelatedInterfaces/0/@odata.id");
1807 return;
1808 }
1809 if (std::string_view(
1810 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1811 dbusError->name)
1812 {
1813 messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1814 "Id", vlanInterface);
1815 return;
1816 }
1817 messages::internalError(asyncResp->res);
1818 return;
1819 }
1820
1821 const boost::urls::url vlanInterfaceUri = boost::urls::format(
1822 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1823 asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1824}
1825
Ed Tanousbf648f72021-06-03 15:00:14 -07001826inline void requestEthernetInterfacesRoutes(App& app)
1827{
1828 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
Ed Tanoused398212021-06-09 17:05:54 -07001829 .privileges(redfish::privileges::getEthernetInterfaceCollection)
Ed Tanous14766872022-03-15 10:44:42 -07001830 .methods(boost::beast::http::verb::get)(
1831 [&app](const crow::Request& req,
1832 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001833 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001834 {
1835 return;
1836 }
1837
1838 asyncResp->res.jsonValue["@odata.type"] =
1839 "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1840 asyncResp->res.jsonValue["@odata.id"] =
1841 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1842 asyncResp->res.jsonValue["Name"] =
1843 "Ethernet Network Interface Collection";
1844 asyncResp->res.jsonValue["Description"] =
1845 "Collection of EthernetInterfaces for this Manager";
1846
1847 // Get eth interface list, and call the below callback for JSON
1848 // preparation
1849 getEthernetIfaceList(
Ed Tanous77179532023-02-28 10:45:28 -08001850 [asyncResp](const bool& success,
1851 const std::vector<std::string>& ifaceList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001852 if (!success)
1853 {
1854 messages::internalError(asyncResp->res);
1855 return;
1856 }
1857
1858 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1859 ifaceArray = nlohmann::json::array();
Ed Tanous002d39b2022-05-31 08:59:27 -07001860 for (const std::string& ifaceItem : ifaceList)
1861 {
Jiaqing Zhao7857cb82023-03-03 11:23:08 +08001862 nlohmann::json::object_t iface;
1863 iface["@odata.id"] = boost::urls::format(
1864 "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1865 ifaceItem);
1866 ifaceArray.push_back(std::move(iface));
Ed Tanous002d39b2022-05-31 08:59:27 -07001867 }
Jason M. Billsf12894f2018-10-09 12:45:45 -07001868
Ed Tanous002d39b2022-05-31 08:59:27 -07001869 asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1870 asyncResp->res.jsonValue["@odata.id"] =
1871 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1872 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001873 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001874
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001875 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1876 .privileges(redfish::privileges::postEthernetInterfaceCollection)
1877 .methods(boost::beast::http::verb::post)(
1878 [&app](const crow::Request& req,
1879 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1880 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1881 {
1882 return;
1883 }
1884
1885 bool vlanEnable = false;
1886 uint32_t vlanId = 0;
1887 nlohmann::json::array_t relatedInterfaces;
1888
1889 if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1890 vlanEnable, "VLAN/VLANId", vlanId,
1891 "Links/RelatedInterfaces",
1892 relatedInterfaces))
1893 {
1894 return;
1895 }
1896
1897 if (relatedInterfaces.size() != 1)
1898 {
1899 messages::arraySizeTooLong(asyncResp->res,
1900 "Links/RelatedInterfaces",
1901 relatedInterfaces.size());
1902 return;
1903 }
1904
1905 std::string parentInterfaceUri;
1906 if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1907 "@odata.id", parentInterfaceUri))
1908 {
1909 messages::propertyMissing(asyncResp->res,
1910 "Links/RelatedInterfaces/0/@odata.id");
1911 return;
1912 }
Ed Tanous62598e32023-07-17 17:06:25 -07001913 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001914
Ed Tanous6fd29552023-10-04 09:40:14 -07001915 boost::system::result<boost::urls::url_view> parsedUri =
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001916 boost::urls::parse_relative_ref(parentInterfaceUri);
1917 if (!parsedUri)
1918 {
1919 messages::propertyValueFormatError(
1920 asyncResp->res, parentInterfaceUri,
1921 "Links/RelatedInterfaces/0/@odata.id");
1922 return;
1923 }
1924
1925 std::string parentInterface;
1926 if (!crow::utility::readUrlSegments(
1927 *parsedUri, "redfish", "v1", "Managers", "bmc",
1928 "EthernetInterfaces", std::ref(parentInterface)))
1929 {
1930 messages::propertyValueNotInList(
1931 asyncResp->res, parentInterfaceUri,
1932 "Links/RelatedInterfaces/0/@odata.id");
1933 return;
1934 }
1935
1936 if (!vlanEnable)
1937 {
1938 // In OpenBMC implementation, VLANEnable cannot be false on
1939 // create
1940 messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1941 "false");
1942 return;
1943 }
1944
1945 std::string vlanInterface = parentInterface + "_" +
1946 std::to_string(vlanId);
1947 crow::connections::systemBus->async_method_call(
1948 [asyncResp, parentInterfaceUri,
1949 vlanInterface](const boost::system::error_code& ec,
1950 const sdbusplus::message_t& m) {
1951 afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1952 m);
Patrick Williams5a39f772023-10-20 11:20:21 -05001953 },
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001954 "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1955 "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1956 vlanId);
Patrick Williams5a39f772023-10-20 11:20:21 -05001957 });
Jiaqing Zhaob5ca3fd2023-03-08 15:14:58 +08001958
Ed Tanousbf648f72021-06-03 15:00:14 -07001959 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001960 .privileges(redfish::privileges::getEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001961 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001962 [&app](const crow::Request& req,
1963 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1964 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00001965 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001966 {
1967 return;
1968 }
1969 getEthernetIfaceData(
1970 ifaceId,
Ed Tanous77179532023-02-28 10:45:28 -08001971 [asyncResp, ifaceId](const bool& success,
1972 const EthernetInterfaceData& ethData,
1973 const std::vector<IPv4AddressData>& ipv4Data,
1974 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001975 if (!success)
1976 {
1977 // TODO(Pawel)consider distinguish between non
1978 // existing object, and other errors
1979 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1980 ifaceId);
1981 return;
1982 }
Johnathan Mantey01784822019-06-18 12:44:21 -07001983
Ed Tanous002d39b2022-05-31 08:59:27 -07001984 asyncResp->res.jsonValue["@odata.type"] =
Jiaqing Zhao93bbc952023-02-23 14:11:20 +08001985 "#EthernetInterface.v1_9_0.EthernetInterface";
Ed Tanous002d39b2022-05-31 08:59:27 -07001986 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
1987 asyncResp->res.jsonValue["Description"] =
1988 "Management Network Interface";
Ratan Guptaf476acb2019-03-02 16:46:57 +05301989
Ed Tanous002d39b2022-05-31 08:59:27 -07001990 parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
Ed Tanous002d39b2022-05-31 08:59:27 -07001991 });
Patrick Williams5a39f772023-10-20 11:20:21 -05001992 });
Johnathan Mantey01784822019-06-18 12:44:21 -07001993
Ed Tanousbf648f72021-06-03 15:00:14 -07001994 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001995 .privileges(redfish::privileges::patchEthernetInterface)
Ed Tanousbf648f72021-06-03 15:00:14 -07001996 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001997 [&app](const crow::Request& req,
1998 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1999 const std::string& ifaceId) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002000 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002001 {
2002 return;
2003 }
2004 std::optional<std::string> hostname;
2005 std::optional<std::string> fqdn;
2006 std::optional<std::string> macAddress;
2007 std::optional<std::string> ipv6DefaultGateway;
Ed Tanousddd70dc2023-03-01 16:00:27 -08002008 std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2009 std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002010 std::optional<std::vector<std::string>> staticNameServers;
2011 std::optional<nlohmann::json> dhcpv4;
2012 std::optional<nlohmann::json> dhcpv6;
Ravi Tejab10d8db2022-05-24 09:04:12 -05002013 std::optional<bool> ipv6AutoConfigEnabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002014 std::optional<bool> interfaceEnabled;
2015 std::optional<size_t> mtuSize;
2016 DHCPParameters v4dhcpParms;
2017 DHCPParameters v6dhcpParms;
Ravi Tejab10d8db2022-05-24 09:04:12 -05002018 // clang-format off
Ed Tanous002d39b2022-05-31 08:59:27 -07002019 if (!json_util::readJsonPatch(
Ravi Tejab10d8db2022-05-24 09:04:12 -05002020 req, asyncResp->res,
2021 "DHCPv4", dhcpv4,
2022 "DHCPv6", dhcpv6,
2023 "FQDN", fqdn,
2024 "HostName", hostname,
2025 "IPv4StaticAddresses", ipv4StaticAddresses,
2026 "IPv6DefaultGateway", ipv6DefaultGateway,
2027 "IPv6StaticAddresses", ipv6StaticAddresses,
2028 "InterfaceEnabled", interfaceEnabled,
2029 "MACAddress", macAddress,
2030 "MTUSize", mtuSize,
2031 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2032 "StaticNameServers", staticNameServers
2033 )
2034 )
Ed Tanous002d39b2022-05-31 08:59:27 -07002035 {
2036 return;
2037 }
Ravi Tejab10d8db2022-05-24 09:04:12 -05002038 //clang-format on
Ed Tanous002d39b2022-05-31 08:59:27 -07002039 if (dhcpv4)
2040 {
2041 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
2042 v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
2043 v4dhcpParms.useDnsServers, "UseNTPServers",
2044 v4dhcpParms.useNtpServers, "UseDomainName",
2045 v4dhcpParms.useDomainName))
2046 {
2047 return;
2048 }
2049 }
Johnathan Mantey01784822019-06-18 12:44:21 -07002050
Ed Tanous002d39b2022-05-31 08:59:27 -07002051 if (dhcpv6)
2052 {
2053 if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2054 v6dhcpParms.dhcpv6OperatingMode,
2055 "UseDNSServers", v6dhcpParms.useDnsServers,
2056 "UseNTPServers", v6dhcpParms.useNtpServers,
2057 "UseDomainName",
2058 v6dhcpParms.useDomainName))
2059 {
2060 return;
2061 }
2062 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002063
Ed Tanous002d39b2022-05-31 08:59:27 -07002064 // Get single eth interface data, and call the below callback
2065 // for JSON preparation
2066 getEthernetIfaceData(
2067 ifaceId,
2068 [asyncResp, ifaceId, hostname = std::move(hostname),
2069 fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2070 ipv4StaticAddresses = std::move(ipv4StaticAddresses),
2071 ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2072 ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2073 staticNameServers = std::move(staticNameServers),
Ed Tanousbc200892022-06-30 17:49:12 -07002074 dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
Ravi Tejab10d8db2022-05-24 09:04:12 -05002075 ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
Ed Tanous002d39b2022-05-31 08:59:27 -07002076 v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2077 const bool& success, const EthernetInterfaceData& ethData,
Ed Tanous77179532023-02-28 10:45:28 -08002078 const std::vector<IPv4AddressData>& ipv4Data,
2079 const std::vector<IPv6AddressData>& ipv6Data) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002080 if (!success)
2081 {
2082 // ... otherwise return error
2083 // TODO(Pawel)consider distinguish between non
2084 // existing object, and other errors
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +08002085 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
Ed Tanous002d39b2022-05-31 08:59:27 -07002086 ifaceId);
2087 return;
2088 }
Ravi Tejae48c0fc2019-04-16 08:37:20 -05002089
Ed Tanous002d39b2022-05-31 08:59:27 -07002090 if (dhcpv4 || dhcpv6)
2091 {
2092 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
Ed Tanousbf648f72021-06-03 15:00:14 -07002093 asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002094 }
Tejas Patil35fb5312021-09-20 15:35:20 +05302095
Ed Tanous002d39b2022-05-31 08:59:27 -07002096 if (hostname)
2097 {
2098 handleHostnamePatch(*hostname, asyncResp);
2099 }
2100
Ravi Tejab10d8db2022-05-24 09:04:12 -05002101 if (ipv6AutoConfigEnabled)
2102 {
2103 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2104 asyncResp);
2105 }
2106
Ed Tanous002d39b2022-05-31 08:59:27 -07002107 if (fqdn)
2108 {
2109 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2110 }
2111
2112 if (macAddress)
2113 {
2114 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2115 }
2116
2117 if (ipv4StaticAddresses)
2118 {
2119 // TODO(ed) for some reason the capture of
2120 // ipv4Addresses above is returning a const value,
2121 // not a non-const value. This doesn't really work
2122 // for us, as we need to be able to efficiently move
2123 // out the intermedia nlohmann::json objects. This
2124 // makes a copy of the structure, and operates on
2125 // that, but could be done more efficiently
Ed Tanousddd70dc2023-03-01 16:00:27 -08002126 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
Ed Tanous002d39b2022-05-31 08:59:27 -07002127 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
2128 }
2129
2130 if (staticNameServers)
2131 {
2132 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2133 asyncResp);
2134 }
2135
2136 if (ipv6DefaultGateway)
2137 {
2138 messages::propertyNotWritable(asyncResp->res,
2139 "IPv6DefaultGateway");
2140 }
2141
2142 if (ipv6StaticAddresses)
2143 {
Ed Tanousddd70dc2023-03-01 16:00:27 -08002144 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2145 ipv6Data, asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07002146 }
2147
2148 if (interfaceEnabled)
2149 {
2150 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2151 *interfaceEnabled, asyncResp);
2152 }
2153
2154 if (mtuSize)
2155 {
2156 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
2157 }
Ed Tanousbf648f72021-06-03 15:00:14 -07002158 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002159 });
Jiaqing Zhaoe7caf252023-03-09 11:14:44 +08002160
2161 BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2162 .privileges(redfish::privileges::deleteEthernetInterface)
2163 .methods(boost::beast::http::verb::delete_)(
2164 [&app](const crow::Request& req,
2165 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2166 const std::string& ifaceId) {
2167 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2168 {
2169 return;
2170 }
2171
2172 crow::connections::systemBus->async_method_call(
2173 [asyncResp, ifaceId](const boost::system::error_code& ec,
2174 const sdbusplus::message_t& m) {
2175 afterDelete(asyncResp, ifaceId, ec, m);
2176 },
2177 "xyz.openbmc_project.Network",
2178 std::string("/xyz/openbmc_project/network/") + ifaceId,
2179 "xyz.openbmc_project.Object.Delete", "Delete");
2180 });
Ed Tanousbf648f72021-06-03 15:00:14 -07002181}
2182
Ed Tanous1abe55e2018-09-05 08:30:59 -07002183} // namespace redfish