19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 1813451e39SWilly Tu #include "bmcweb_config.h" 1913451e39SWilly Tu 203ccb3adbSEd Tanous #include "app.hpp" 213ccb3adbSEd Tanous #include "dbus_singleton.hpp" 227a1dbc48SGeorge Liu #include "dbus_utility.hpp" 233ccb3adbSEd Tanous #include "error_messages.hpp" 243ccb3adbSEd Tanous #include "health.hpp" 252c5875a2SEd Tanous #include "human_sort.hpp" 263ccb3adbSEd Tanous #include "query.hpp" 273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 28033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 293ccb3adbSEd Tanous #include "utils/json_utils.hpp" 30033f1e4dSEd Tanous 3111ba3979SEd Tanous #include <boost/algorithm/string/classification.hpp> 3211ba3979SEd Tanous #include <boost/algorithm/string/split.hpp> 33ef4c65b7SEd Tanous #include <boost/url/format.hpp> 341214b7e7SGunnar Mills 357a1dbc48SGeorge Liu #include <array> 36a24526dcSEd Tanous #include <optional> 37ab6554f1SJoshi-Mansi #include <regex> 387a1dbc48SGeorge Liu #include <string_view> 3977179532SEd Tanous #include <vector> 409391bb9cSRapkiewicz, Pawel 411abe55efSEd Tanous namespace redfish 421abe55efSEd Tanous { 439391bb9cSRapkiewicz, Pawel 444a0cb85cSEd Tanous enum class LinkType 454a0cb85cSEd Tanous { 464a0cb85cSEd Tanous Local, 474a0cb85cSEd Tanous Global 484a0cb85cSEd Tanous }; 499391bb9cSRapkiewicz, Pawel 509391bb9cSRapkiewicz, Pawel /** 519391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 529391bb9cSRapkiewicz, Pawel */ 531abe55efSEd Tanous struct IPv4AddressData 541abe55efSEd Tanous { 55179db1d7SKowalski, Kamil std::string id; 564a0cb85cSEd Tanous std::string address; 574a0cb85cSEd Tanous std::string domain; 584a0cb85cSEd Tanous std::string gateway; 599391bb9cSRapkiewicz, Pawel std::string netmask; 609391bb9cSRapkiewicz, Pawel std::string origin; 6177179532SEd Tanous LinkType linktype{}; 6277179532SEd Tanous bool isActive{}; 639391bb9cSRapkiewicz, Pawel }; 649391bb9cSRapkiewicz, Pawel 659391bb9cSRapkiewicz, Pawel /** 66e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 67e48c0fc5SRavi Teja */ 68e48c0fc5SRavi Teja struct IPv6AddressData 69e48c0fc5SRavi Teja { 70e48c0fc5SRavi Teja std::string id; 71e48c0fc5SRavi Teja std::string address; 72e48c0fc5SRavi Teja std::string origin; 7377179532SEd Tanous uint8_t prefixLength = 0; 74e48c0fc5SRavi Teja }; 75e48c0fc5SRavi Teja /** 769391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 779391bb9cSRapkiewicz, Pawel * available from DBus 789391bb9cSRapkiewicz, Pawel */ 791abe55efSEd Tanous struct EthernetInterfaceData 801abe55efSEd Tanous { 814a0cb85cSEd Tanous uint32_t speed; 8235fb5311STejas Patil size_t mtuSize; 8382695a5bSJiaqing Zhao bool autoNeg; 8482695a5bSJiaqing Zhao bool dnsEnabled; 8582695a5bSJiaqing Zhao bool ntpEnabled; 8682695a5bSJiaqing Zhao bool hostNameEnabled; 87aa05fb27SJohnathan Mantey bool linkUp; 88eeedda23SJohnathan Mantey bool nicEnabled; 89b10d8db0SRavi Teja bool ipv6AcceptRa; 9082695a5bSJiaqing Zhao std::string dhcpEnabled; 911f8c7b5dSJohnathan Mantey std::string operatingMode; 9282695a5bSJiaqing Zhao std::string hostName; 9382695a5bSJiaqing Zhao std::string defaultGateway; 9482695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 9582695a5bSJiaqing Zhao std::string macAddress; 9617e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 970f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 980f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 99d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1009391bb9cSRapkiewicz, Pawel }; 1019391bb9cSRapkiewicz, Pawel 1021f8c7b5dSJohnathan Mantey struct DHCPParameters 1031f8c7b5dSJohnathan Mantey { 1041f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 10582695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 10682695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 10782695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1081f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1091f8c7b5dSJohnathan Mantey }; 1101f8c7b5dSJohnathan Mantey 1119391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1129391bb9cSRapkiewicz, Pawel // into full dot notation 1131abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1141abe55efSEd Tanous { 1159391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1169391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1179391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1189391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1199391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1209391bb9cSRapkiewicz, Pawel return netmask; 1219391bb9cSRapkiewicz, Pawel } 1229391bb9cSRapkiewicz, Pawel 12382695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1241f8c7b5dSJohnathan Mantey bool isIPv4) 1251f8c7b5dSJohnathan Mantey { 1261f8c7b5dSJohnathan Mantey if (isIPv4) 1271f8c7b5dSJohnathan Mantey { 1281f8c7b5dSJohnathan Mantey return ( 1291f8c7b5dSJohnathan Mantey (inputDHCP == 1301f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1311f8c7b5dSJohnathan Mantey (inputDHCP == 1321f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1331f8c7b5dSJohnathan Mantey } 1341f8c7b5dSJohnathan Mantey return ((inputDHCP == 1351f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1361f8c7b5dSJohnathan Mantey (inputDHCP == 1371f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1381f8c7b5dSJohnathan Mantey } 1391f8c7b5dSJohnathan Mantey 1402c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1411f8c7b5dSJohnathan Mantey { 1421f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1431f8c7b5dSJohnathan Mantey { 1441f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1451f8c7b5dSJohnathan Mantey } 1463174e4dfSEd Tanous if (isIPv4) 1471f8c7b5dSJohnathan Mantey { 1481f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1491f8c7b5dSJohnathan Mantey } 1503174e4dfSEd Tanous if (isIPv6) 1511f8c7b5dSJohnathan Mantey { 1521f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1531f8c7b5dSJohnathan Mantey } 1541f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1551f8c7b5dSJohnathan Mantey } 1561f8c7b5dSJohnathan Mantey 1574a0cb85cSEd Tanous inline std::string 1584a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1594a0cb85cSEd Tanous bool isIPv4) 1601abe55efSEd Tanous { 1614a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1621abe55efSEd Tanous { 1634a0cb85cSEd Tanous return "Static"; 1649391bb9cSRapkiewicz, Pawel } 1654a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1661abe55efSEd Tanous { 1674a0cb85cSEd Tanous if (isIPv4) 1681abe55efSEd Tanous { 1694a0cb85cSEd Tanous return "IPv4LinkLocal"; 1701abe55efSEd Tanous } 1714a0cb85cSEd Tanous return "LinkLocal"; 1729391bb9cSRapkiewicz, Pawel } 1734a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1741abe55efSEd Tanous { 1754a0cb85cSEd Tanous if (isIPv4) 1764a0cb85cSEd Tanous { 1774a0cb85cSEd Tanous return "DHCP"; 1784a0cb85cSEd Tanous } 1794a0cb85cSEd Tanous return "DHCPv6"; 1804a0cb85cSEd Tanous } 1814a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1824a0cb85cSEd Tanous { 1834a0cb85cSEd Tanous return "SLAAC"; 1844a0cb85cSEd Tanous } 1854a0cb85cSEd Tanous return ""; 1864a0cb85cSEd Tanous } 1874a0cb85cSEd Tanous 18802cad96eSEd Tanous inline bool extractEthernetInterfaceData( 18902cad96eSEd Tanous const std::string& ethifaceId, 19002cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 1914a0cb85cSEd Tanous EthernetInterfaceData& ethData) 1924a0cb85cSEd Tanous { 1934c9afe43SEd Tanous bool idFound = false; 19402cad96eSEd Tanous for (const auto& objpath : dbusData) 1954a0cb85cSEd Tanous { 19602cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 1974a0cb85cSEd Tanous { 19881ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 199029573d4SEd Tanous { 2004c9afe43SEd Tanous idFound = true; 2014a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2024a0cb85cSEd Tanous { 2034a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2044a0cb85cSEd Tanous { 2054a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous const std::string* mac = 208abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2094a0cb85cSEd Tanous if (mac != nullptr) 2104a0cb85cSEd Tanous { 21182695a5bSJiaqing Zhao ethData.macAddress = *mac; 2124a0cb85cSEd Tanous } 2134a0cb85cSEd Tanous } 2144a0cb85cSEd Tanous } 2154a0cb85cSEd Tanous } 2164a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2174a0cb85cSEd Tanous { 2184a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2194a0cb85cSEd Tanous { 2204a0cb85cSEd Tanous if (propertyPair.first == "Id") 2214a0cb85cSEd Tanous { 2221b6b96c5SEd Tanous const uint32_t* id = 223abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2244a0cb85cSEd Tanous if (id != nullptr) 2254a0cb85cSEd Tanous { 22617e22024SJiaqing Zhao ethData.vlanId = *id; 2274a0cb85cSEd Tanous } 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous else if (ifacePair.first == 2324a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2334a0cb85cSEd Tanous { 2344a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2354a0cb85cSEd Tanous { 2364a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2374a0cb85cSEd Tanous { 2382c70f800SEd Tanous const bool* autoNeg = 239abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2402c70f800SEd Tanous if (autoNeg != nullptr) 2414a0cb85cSEd Tanous { 24282695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2434a0cb85cSEd Tanous } 2444a0cb85cSEd Tanous } 2454a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2464a0cb85cSEd Tanous { 2474a0cb85cSEd Tanous const uint32_t* speed = 248abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2494a0cb85cSEd Tanous if (speed != nullptr) 2504a0cb85cSEd Tanous { 2514a0cb85cSEd Tanous ethData.speed = *speed; 2524a0cb85cSEd Tanous } 2534a0cb85cSEd Tanous } 25435fb5311STejas Patil else if (propertyPair.first == "MTU") 25535fb5311STejas Patil { 25635fb5311STejas Patil const uint32_t* mtuSize = 25735fb5311STejas Patil std::get_if<uint32_t>(&propertyPair.second); 25835fb5311STejas Patil if (mtuSize != nullptr) 25935fb5311STejas Patil { 26035fb5311STejas Patil ethData.mtuSize = *mtuSize; 26135fb5311STejas Patil } 26235fb5311STejas Patil } 263aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 264aa05fb27SJohnathan Mantey { 265aa05fb27SJohnathan Mantey const bool* linkUp = 266aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 267aa05fb27SJohnathan Mantey if (linkUp != nullptr) 268aa05fb27SJohnathan Mantey { 269aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 270aa05fb27SJohnathan Mantey } 271aa05fb27SJohnathan Mantey } 272eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 273eeedda23SJohnathan Mantey { 274eeedda23SJohnathan Mantey const bool* nicEnabled = 275eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 276eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 277eeedda23SJohnathan Mantey { 278eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 279eeedda23SJohnathan Mantey } 280eeedda23SJohnathan Mantey } 281b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 282b10d8db0SRavi Teja { 283b10d8db0SRavi Teja const bool* ipv6AcceptRa = 284b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 285b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 286b10d8db0SRavi Teja { 287b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 288b10d8db0SRavi Teja } 289b10d8db0SRavi Teja } 290f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 291029573d4SEd Tanous { 292029573d4SEd Tanous const std::vector<std::string>* nameservers = 2938d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 294029573d4SEd Tanous &propertyPair.second); 295029573d4SEd Tanous if (nameservers != nullptr) 296029573d4SEd Tanous { 297f23b7296SEd Tanous ethData.nameServers = *nameservers; 2980f6efdc1Smanojkiran.eda@gmail.com } 2990f6efdc1Smanojkiran.eda@gmail.com } 3000f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3010f6efdc1Smanojkiran.eda@gmail.com { 3020f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3038d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3040f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3050f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3060f6efdc1Smanojkiran.eda@gmail.com { 307f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3084a0cb85cSEd Tanous } 3094a0cb85cSEd Tanous } 3102a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3112a133282Smanojkiraneda { 3122c70f800SEd Tanous const std::string* dhcpEnabled = 3131f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3142c70f800SEd Tanous if (dhcpEnabled != nullptr) 3152a133282Smanojkiraneda { 31682695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3172a133282Smanojkiraneda } 3182a133282Smanojkiraneda } 319d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 320d24bfc7aSJennifer Lee { 321d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3228d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 323d24bfc7aSJennifer Lee &propertyPair.second); 324d24bfc7aSJennifer Lee if (domainNames != nullptr) 325d24bfc7aSJennifer Lee { 326f23b7296SEd Tanous ethData.domainnames = *domainNames; 327d24bfc7aSJennifer Lee } 328d24bfc7aSJennifer Lee } 3299010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3309010ec2eSRavi Teja { 3319010ec2eSRavi Teja const std::string* defaultGateway = 3329010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3339010ec2eSRavi Teja if (defaultGateway != nullptr) 3349010ec2eSRavi Teja { 3359010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3369010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3379010ec2eSRavi Teja { 33882695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3399010ec2eSRavi Teja } 3409010ec2eSRavi Teja else 3419010ec2eSRavi Teja { 34282695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3439010ec2eSRavi Teja } 3449010ec2eSRavi Teja } 3459010ec2eSRavi Teja } 3469010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3479010ec2eSRavi Teja { 3489010ec2eSRavi Teja const std::string* defaultGateway6 = 3499010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3509010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3519010ec2eSRavi Teja { 3529010ec2eSRavi Teja std::string defaultGateway6Str = 3539010ec2eSRavi Teja *defaultGateway6; 3549010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3559010ec2eSRavi Teja { 35682695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3579010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3589010ec2eSRavi Teja } 3599010ec2eSRavi Teja else 3609010ec2eSRavi Teja { 36182695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3629010ec2eSRavi Teja defaultGateway6Str; 3639010ec2eSRavi Teja } 3649010ec2eSRavi Teja } 3659010ec2eSRavi Teja } 366029573d4SEd Tanous } 367029573d4SEd Tanous } 368029573d4SEd Tanous } 3691f8c7b5dSJohnathan Mantey 3701e3f85e6SJian Zhang if (objpath.first == "/xyz/openbmc_project/network/dhcp") 3711f8c7b5dSJohnathan Mantey { 3721f8c7b5dSJohnathan Mantey if (ifacePair.first == 3731f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3741f8c7b5dSJohnathan Mantey { 3751f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 3761f8c7b5dSJohnathan Mantey { 3771f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3781f8c7b5dSJohnathan Mantey { 3792c70f800SEd Tanous const bool* dnsEnabled = 3801f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3812c70f800SEd Tanous if (dnsEnabled != nullptr) 3821f8c7b5dSJohnathan Mantey { 38382695a5bSJiaqing Zhao ethData.dnsEnabled = *dnsEnabled; 3841f8c7b5dSJohnathan Mantey } 3851f8c7b5dSJohnathan Mantey } 3861f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 3871f8c7b5dSJohnathan Mantey { 3882c70f800SEd Tanous const bool* ntpEnabled = 3891f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3902c70f800SEd Tanous if (ntpEnabled != nullptr) 3911f8c7b5dSJohnathan Mantey { 39282695a5bSJiaqing Zhao ethData.ntpEnabled = *ntpEnabled; 3931f8c7b5dSJohnathan Mantey } 3941f8c7b5dSJohnathan Mantey } 3951f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 3961f8c7b5dSJohnathan Mantey { 3972c70f800SEd Tanous const bool* hostNameEnabled = 3981f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3992c70f800SEd Tanous if (hostNameEnabled != nullptr) 4001f8c7b5dSJohnathan Mantey { 40182695a5bSJiaqing Zhao ethData.hostNameEnabled = *hostNameEnabled; 4021f8c7b5dSJohnathan Mantey } 4031f8c7b5dSJohnathan Mantey } 4041f8c7b5dSJohnathan Mantey } 4051f8c7b5dSJohnathan Mantey } 4061f8c7b5dSJohnathan Mantey } 407029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 408029573d4SEd Tanous // to check eth number 409029573d4SEd Tanous if (ifacePair.first == 4104a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4114a0cb85cSEd Tanous { 4124a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4134a0cb85cSEd Tanous { 4144a0cb85cSEd Tanous if (propertyPair.first == "HostName") 4154a0cb85cSEd Tanous { 4164a0cb85cSEd Tanous const std::string* hostname = 4178d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 4184a0cb85cSEd Tanous if (hostname != nullptr) 4194a0cb85cSEd Tanous { 42082695a5bSJiaqing Zhao ethData.hostName = *hostname; 4214a0cb85cSEd Tanous } 4224a0cb85cSEd Tanous } 4234a0cb85cSEd Tanous } 4244a0cb85cSEd Tanous } 4254a0cb85cSEd Tanous } 4264a0cb85cSEd Tanous } 4274c9afe43SEd Tanous return idFound; 4284a0cb85cSEd Tanous } 4294a0cb85cSEd Tanous 430e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 43177179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 432711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 43377179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 434e48c0fc5SRavi Teja { 43589492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 43689492a15SPatrick Williams ethifaceId; 437e48c0fc5SRavi Teja 438e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 439e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 44081ce609eSEd Tanous for (const auto& objpath : dbusData) 441e48c0fc5SRavi Teja { 442e48c0fc5SRavi Teja // Check if proper pattern for object path appears 443353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 444e48c0fc5SRavi Teja { 4459eb808c1SEd Tanous for (const auto& interface : objpath.second) 446e48c0fc5SRavi Teja { 447e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 448e48c0fc5SRavi Teja { 449353163e9STony Lee auto type = std::find_if(interface.second.begin(), 450353163e9STony Lee interface.second.end(), 451353163e9STony Lee [](const auto& property) { 452353163e9STony Lee return property.first == "Type"; 453353163e9STony Lee }); 454353163e9STony Lee if (type == interface.second.end()) 455353163e9STony Lee { 456353163e9STony Lee continue; 457353163e9STony Lee } 458353163e9STony Lee 459353163e9STony Lee const std::string* typeStr = 460353163e9STony Lee std::get_if<std::string>(&type->second); 461353163e9STony Lee 462353163e9STony Lee if (typeStr == nullptr || 463353163e9STony Lee (*typeStr != 464353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 465353163e9STony Lee { 466353163e9STony Lee continue; 467353163e9STony Lee } 468353163e9STony Lee 469e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 470e48c0fc5SRavi Teja // appropriate 47177179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 4722c70f800SEd Tanous ipv6Address.id = 473353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 4749eb808c1SEd Tanous for (const auto& property : interface.second) 475e48c0fc5SRavi Teja { 476e48c0fc5SRavi Teja if (property.first == "Address") 477e48c0fc5SRavi Teja { 478e48c0fc5SRavi Teja const std::string* address = 479e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 480e48c0fc5SRavi Teja if (address != nullptr) 481e48c0fc5SRavi Teja { 4822c70f800SEd Tanous ipv6Address.address = *address; 483e48c0fc5SRavi Teja } 484e48c0fc5SRavi Teja } 485e48c0fc5SRavi Teja else if (property.first == "Origin") 486e48c0fc5SRavi Teja { 487e48c0fc5SRavi Teja const std::string* origin = 488e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 489e48c0fc5SRavi Teja if (origin != nullptr) 490e48c0fc5SRavi Teja { 4912c70f800SEd Tanous ipv6Address.origin = 492e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 493e48c0fc5SRavi Teja false); 494e48c0fc5SRavi Teja } 495e48c0fc5SRavi Teja } 496e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 497e48c0fc5SRavi Teja { 498e48c0fc5SRavi Teja const uint8_t* prefix = 499e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 500e48c0fc5SRavi Teja if (prefix != nullptr) 501e48c0fc5SRavi Teja { 5022c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 503e48c0fc5SRavi Teja } 504e48c0fc5SRavi Teja } 505889ff694SAsmitha Karunanithi else if (property.first == "Type" || 506889ff694SAsmitha Karunanithi property.first == "Gateway") 507889ff694SAsmitha Karunanithi { 508889ff694SAsmitha Karunanithi // Type & Gateway is not used 509889ff694SAsmitha Karunanithi } 510e48c0fc5SRavi Teja else 511e48c0fc5SRavi Teja { 51262598e31SEd Tanous BMCWEB_LOG_ERROR( 51362598e31SEd Tanous "Got extra property: {} on the {} object", 51462598e31SEd Tanous property.first, objpath.first.str); 515e48c0fc5SRavi Teja } 516e48c0fc5SRavi Teja } 517e48c0fc5SRavi Teja } 518e48c0fc5SRavi Teja } 519e48c0fc5SRavi Teja } 520e48c0fc5SRavi Teja } 521e48c0fc5SRavi Teja } 522e48c0fc5SRavi Teja 5234a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 52477179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 525711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 52677179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 5274a0cb85cSEd Tanous { 52889492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 52989492a15SPatrick Williams ethifaceId; 5304a0cb85cSEd Tanous 5314a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 5324a0cb85cSEd Tanous // single ethernet interface, loop over all of them 53381ce609eSEd Tanous for (const auto& objpath : dbusData) 5344a0cb85cSEd Tanous { 5354a0cb85cSEd Tanous // Check if proper pattern for object path appears 536353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 5374a0cb85cSEd Tanous { 5389eb808c1SEd Tanous for (const auto& interface : objpath.second) 5394a0cb85cSEd Tanous { 5404a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 5414a0cb85cSEd Tanous { 542353163e9STony Lee auto type = std::find_if(interface.second.begin(), 543353163e9STony Lee interface.second.end(), 544353163e9STony Lee [](const auto& property) { 545353163e9STony Lee return property.first == "Type"; 546353163e9STony Lee }); 547353163e9STony Lee if (type == interface.second.end()) 548353163e9STony Lee { 549353163e9STony Lee continue; 550353163e9STony Lee } 551353163e9STony Lee 552353163e9STony Lee const std::string* typeStr = 553353163e9STony Lee std::get_if<std::string>(&type->second); 554353163e9STony Lee 555353163e9STony Lee if (typeStr == nullptr || 556353163e9STony Lee (*typeStr != 557353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 558353163e9STony Lee { 559353163e9STony Lee continue; 560353163e9STony Lee } 561353163e9STony Lee 5624a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 5634a0cb85cSEd Tanous // appropriate 56477179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 5652c70f800SEd Tanous ipv4Address.id = 566353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5679eb808c1SEd Tanous for (const auto& property : interface.second) 5684a0cb85cSEd Tanous { 5694a0cb85cSEd Tanous if (property.first == "Address") 5704a0cb85cSEd Tanous { 5714a0cb85cSEd Tanous const std::string* address = 572abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5734a0cb85cSEd Tanous if (address != nullptr) 5744a0cb85cSEd Tanous { 5752c70f800SEd Tanous ipv4Address.address = *address; 5764a0cb85cSEd Tanous } 5774a0cb85cSEd Tanous } 5784a0cb85cSEd Tanous else if (property.first == "Origin") 5794a0cb85cSEd Tanous { 5804a0cb85cSEd Tanous const std::string* origin = 581abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5824a0cb85cSEd Tanous if (origin != nullptr) 5834a0cb85cSEd Tanous { 5842c70f800SEd Tanous ipv4Address.origin = 5854a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 5864a0cb85cSEd Tanous true); 5874a0cb85cSEd Tanous } 5884a0cb85cSEd Tanous } 5894a0cb85cSEd Tanous else if (property.first == "PrefixLength") 5904a0cb85cSEd Tanous { 5914a0cb85cSEd Tanous const uint8_t* mask = 592abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 5934a0cb85cSEd Tanous if (mask != nullptr) 5944a0cb85cSEd Tanous { 5954a0cb85cSEd Tanous // convert it to the string 5962c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 5974a0cb85cSEd Tanous } 5984a0cb85cSEd Tanous } 599889ff694SAsmitha Karunanithi else if (property.first == "Type" || 600889ff694SAsmitha Karunanithi property.first == "Gateway") 601889ff694SAsmitha Karunanithi { 602889ff694SAsmitha Karunanithi // Type & Gateway is not used 603889ff694SAsmitha Karunanithi } 6044a0cb85cSEd Tanous else 6054a0cb85cSEd Tanous { 60662598e31SEd Tanous BMCWEB_LOG_ERROR( 60762598e31SEd Tanous "Got extra property: {} on the {} object", 60862598e31SEd Tanous property.first, objpath.first.str); 6094a0cb85cSEd Tanous } 6104a0cb85cSEd Tanous } 6114a0cb85cSEd Tanous // Check if given address is local, or global 6122c70f800SEd Tanous ipv4Address.linktype = 61311ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 61418659d10SJohnathan Mantey ? LinkType::Local 61518659d10SJohnathan Mantey : LinkType::Global; 6164a0cb85cSEd Tanous } 6174a0cb85cSEd Tanous } 6184a0cb85cSEd Tanous } 6194a0cb85cSEd Tanous } 6204a0cb85cSEd Tanous } 621588c3f0dSKowalski, Kamil 622588c3f0dSKowalski, Kamil /** 62301784826SJohnathan Mantey * @brief Deletes given IPv4 interface 624179db1d7SKowalski, Kamil * 625179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 626179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 627179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 628179db1d7SKowalski, Kamil * 629179db1d7SKowalski, Kamil * @return None 630179db1d7SKowalski, Kamil */ 6319c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 6329c5e585cSRavi Teja const std::string& ipHash, 6338d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6341abe55efSEd Tanous { 63555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 6365e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 6371abe55efSEd Tanous if (ec) 6381abe55efSEd Tanous { 639a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6401abe55efSEd Tanous } 641179db1d7SKowalski, Kamil }, 642179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 6439c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 644179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 645179db1d7SKowalski, Kamil } 646179db1d7SKowalski, Kamil 647244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway( 648244b6d5bSGunnar Mills const std::string& ifaceId, const std::string& gateway, 649244b6d5bSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6509010ec2eSRavi Teja { 6519ae226faSGeorge Liu sdbusplus::asio::setProperty( 6529ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 6539ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 6549ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 6559ae226faSGeorge Liu gateway, [asyncResp](const boost::system::error_code& ec) { 6569010ec2eSRavi Teja if (ec) 6579010ec2eSRavi Teja { 6589010ec2eSRavi Teja messages::internalError(asyncResp->res); 6599010ec2eSRavi Teja return; 6609010ec2eSRavi Teja } 6619010ec2eSRavi Teja asyncResp->res.result(boost::beast::http::status::no_content); 6629ae226faSGeorge Liu }); 6639010ec2eSRavi Teja } 664179db1d7SKowalski, Kamil /** 66501784826SJohnathan Mantey * @brief Creates a static IPv4 entry 666179db1d7SKowalski, Kamil * 66701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 66801784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 66901784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 67001784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 671179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 672179db1d7SKowalski, Kamil * 673179db1d7SKowalski, Kamil * @return None 674179db1d7SKowalski, Kamil */ 675cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 676cb13a392SEd Tanous const std::string& gateway, const std::string& address, 6778d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6781abe55efSEd Tanous { 679002d39b4SEd Tanous auto createIpHandler = 6805e7e2dc5SEd Tanous [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 6811abe55efSEd Tanous if (ec) 6821abe55efSEd Tanous { 683a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6849010ec2eSRavi Teja return; 685179db1d7SKowalski, Kamil } 6869010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 6879010ec2eSRavi Teja }; 6889010ec2eSRavi Teja 6899010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 6909010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 691179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 692179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 69301784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 694179db1d7SKowalski, Kamil gateway); 695179db1d7SKowalski, Kamil } 696e48c0fc5SRavi Teja 697e48c0fc5SRavi Teja /** 69801784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 69901784826SJohnathan Mantey * static IPv6 entry 70001784826SJohnathan Mantey * 70101784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 70201784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 70301784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 70401784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 70501784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 70601784826SJohnathan Mantey * 70701784826SJohnathan Mantey * @return None 70801784826SJohnathan Mantey */ 7099c5e585cSRavi Teja 7109c5e585cSRavi Teja enum class IpVersion 7119c5e585cSRavi Teja { 7129c5e585cSRavi Teja IpV4, 7139c5e585cSRavi Teja IpV6 7149c5e585cSRavi Teja }; 7159c5e585cSRavi Teja 7169c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7179c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7188d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7199c5e585cSRavi Teja const std::string& gateway, 7208d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 72101784826SJohnathan Mantey { 72201784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7239c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 7249c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 72501784826SJohnathan Mantey if (ec) 72601784826SJohnathan Mantey { 72701784826SJohnathan Mantey messages::internalError(asyncResp->res); 72801784826SJohnathan Mantey } 7299c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 7309c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 73101784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7325e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 73323a21a1cSEd Tanous if (ec2) 73401784826SJohnathan Mantey { 73501784826SJohnathan Mantey messages::internalError(asyncResp->res); 73601784826SJohnathan Mantey } 73701784826SJohnathan Mantey }, 73801784826SJohnathan Mantey "xyz.openbmc_project.Network", 73901784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 7409c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 7419c5e585cSRavi Teja prefixLength, gateway); 74201784826SJohnathan Mantey }, 74301784826SJohnathan Mantey "xyz.openbmc_project.Network", 7449c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 74501784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 74601784826SJohnathan Mantey } 74701784826SJohnathan Mantey 74801784826SJohnathan Mantey /** 749e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 750e48c0fc5SRavi Teja * 751e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 752e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 753e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 754e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 755e48c0fc5SRavi Teja * 756e48c0fc5SRavi Teja * @return None 757e48c0fc5SRavi Teja */ 75801784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 75901784826SJohnathan Mantey const std::string& address, 7608d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 761e48c0fc5SRavi Teja { 762fc23ef8aSNitin Kumar Kotania auto createIpHandler = 763fc23ef8aSNitin Kumar Kotania [asyncResp, address](const boost::system::error_code& ec) { 764e48c0fc5SRavi Teja if (ec) 765e48c0fc5SRavi Teja { 766fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 767fc23ef8aSNitin Kumar Kotania { 768fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 769fc23ef8aSNitin Kumar Kotania "Address"); 770fc23ef8aSNitin Kumar Kotania } 771fc23ef8aSNitin Kumar Kotania else 772fc23ef8aSNitin Kumar Kotania { 773e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 774e48c0fc5SRavi Teja } 775fc23ef8aSNitin Kumar Kotania } 776e48c0fc5SRavi Teja }; 777e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 7784e0453b1SGunnar Mills // does not have associated gateway property 779e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 780e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 781e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 782e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 783e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 784e48c0fc5SRavi Teja ""); 785e48c0fc5SRavi Teja } 786e48c0fc5SRavi Teja 787179db1d7SKowalski, Kamil /** 788179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 789179db1d7SKowalski, Kamil * Object 790179db1d7SKowalski, Kamil * from EntityManager Network Manager 7914a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 792179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 793179db1d7SKowalski, Kamil * into JSON 794179db1d7SKowalski, Kamil */ 795179db1d7SKowalski, Kamil template <typename CallbackFunc> 79681ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 7971abe55efSEd Tanous CallbackFunc&& callback) 7981abe55efSEd Tanous { 799f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 800f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 801f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 802f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 803f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 8048b24275dSEd Tanous const boost::system::error_code& ec, 80502cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 80655c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 80777179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 80877179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 809179db1d7SKowalski, Kamil 8108b24275dSEd Tanous if (ec) 8111abe55efSEd Tanous { 81201784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 813179db1d7SKowalski, Kamil return; 814179db1d7SKowalski, Kamil } 815179db1d7SKowalski, Kamil 816002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 8174c9afe43SEd Tanous if (!found) 8184c9afe43SEd Tanous { 81901784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8204c9afe43SEd Tanous return; 8214c9afe43SEd Tanous } 8224c9afe43SEd Tanous 8232c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 824179db1d7SKowalski, Kamil // Fix global GW 8251abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 8261abe55efSEd Tanous { 827c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 828c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 8299010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 8301abe55efSEd Tanous { 83182695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 832179db1d7SKowalski, Kamil } 833179db1d7SKowalski, Kamil } 834179db1d7SKowalski, Kamil 8352c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 8364e0453b1SGunnar Mills // Finally make a callback with useful data 83701784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 838f5892d0dSGeorge Liu }); 839271584abSEd Tanous } 840179db1d7SKowalski, Kamil 841179db1d7SKowalski, Kamil /** 8429391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8439391bb9cSRapkiewicz, Pawel * Manager 8441abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8451abe55efSEd Tanous * into JSON. 8469391bb9cSRapkiewicz, Pawel */ 8479391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8481abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 8491abe55efSEd Tanous { 850f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 851f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 852f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 853f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 8548b24275dSEd Tanous const boost::system::error_code& ec, 855f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 8561abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8571abe55efSEd Tanous // ethernet interfaces 85877179532SEd Tanous std::vector<std::string> ifaceList; 8592c70f800SEd Tanous ifaceList.reserve(resp.size()); 8608b24275dSEd Tanous if (ec) 8611abe55efSEd Tanous { 8622c70f800SEd Tanous callback(false, ifaceList); 8639391bb9cSRapkiewicz, Pawel return; 8649391bb9cSRapkiewicz, Pawel } 8659391bb9cSRapkiewicz, Pawel 8669391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8674a0cb85cSEd Tanous for (const auto& objpath : resp) 8681abe55efSEd Tanous { 8699391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8704a0cb85cSEd Tanous for (const auto& interface : objpath.second) 8711abe55efSEd Tanous { 8721abe55efSEd Tanous // If interface is 8734a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 8744a0cb85cSEd Tanous // what we're looking for. 8759391bb9cSRapkiewicz, Pawel if (interface.first == 8761abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 8771abe55efSEd Tanous { 8782dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 8792dfd18efSEd Tanous if (ifaceId.empty()) 8801abe55efSEd Tanous { 8812dfd18efSEd Tanous continue; 8829391bb9cSRapkiewicz, Pawel } 8832dfd18efSEd Tanous // and put it into output vector. 88477179532SEd Tanous ifaceList.emplace_back(ifaceId); 8859391bb9cSRapkiewicz, Pawel } 8869391bb9cSRapkiewicz, Pawel } 8879391bb9cSRapkiewicz, Pawel } 8882c5875a2SEd Tanous 8892c5875a2SEd Tanous std::sort(ifaceList.begin(), ifaceList.end(), 8902c5875a2SEd Tanous AlphanumLess<std::string>()); 8912c5875a2SEd Tanous 892a434f2bdSEd Tanous // Finally make a callback with useful data 8932c70f800SEd Tanous callback(true, ifaceList); 894f5892d0dSGeorge Liu }); 895271584abSEd Tanous } 8969391bb9cSRapkiewicz, Pawel 8974f48d5f6SEd Tanous inline void 8984f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 8998d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 9001abe55efSEd Tanous { 901ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 902ab6554f1SJoshi-Mansi if (hostname.length() > 255) 903ab6554f1SJoshi-Mansi { 904ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 905ab6554f1SJoshi-Mansi "HostName"); 906ab6554f1SJoshi-Mansi return; 907ab6554f1SJoshi-Mansi } 9089ae226faSGeorge Liu sdbusplus::asio::setProperty( 9099ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9109ae226faSGeorge Liu "/xyz/openbmc_project/network/config", 9119ae226faSGeorge Liu "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname, 9125e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 9134a0cb85cSEd Tanous if (ec) 9144a0cb85cSEd Tanous { 915a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 9161abe55efSEd Tanous } 9179ae226faSGeorge Liu }); 918588c3f0dSKowalski, Kamil } 919588c3f0dSKowalski, Kamil 9204f48d5f6SEd Tanous inline void 92135fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 92235fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 92335fb5311STejas Patil { 92489492a15SPatrick Williams sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" + 92589492a15SPatrick Williams ifaceId; 9269ae226faSGeorge Liu sdbusplus::asio::setProperty( 9279ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath, 9289ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize, 9295e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 93035fb5311STejas Patil if (ec) 93135fb5311STejas Patil { 93235fb5311STejas Patil messages::internalError(asyncResp->res); 93335fb5311STejas Patil } 9349ae226faSGeorge Liu }); 93535fb5311STejas Patil } 93635fb5311STejas Patil 93735fb5311STejas Patil inline void 9384f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 939bf648f77SEd Tanous const std::string& domainname, 9408d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 941ab6554f1SJoshi-Mansi { 942ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 9439ae226faSGeorge Liu sdbusplus::asio::setProperty( 9449ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9459ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 9469ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 9479ae226faSGeorge Liu vectorDomainname, [asyncResp](const boost::system::error_code& ec) { 948ab6554f1SJoshi-Mansi if (ec) 949ab6554f1SJoshi-Mansi { 950ab6554f1SJoshi-Mansi messages::internalError(asyncResp->res); 951ab6554f1SJoshi-Mansi } 9529ae226faSGeorge Liu }); 953ab6554f1SJoshi-Mansi } 954ab6554f1SJoshi-Mansi 9554f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 956bf648f77SEd Tanous { 957bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 958bf648f77SEd Tanous if (std::all_of(hostname.begin(), hostname.end(), ::isdigit)) 959bf648f77SEd Tanous { 960bf648f77SEd Tanous return false; 961bf648f77SEd Tanous } 962bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 963bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 964bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 965bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 9664b242749SEd Tanous const static std::regex pattern( 967bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 968bf648f77SEd Tanous 969bf648f77SEd Tanous return std::regex_match(hostname, pattern); 970bf648f77SEd Tanous } 971bf648f77SEd Tanous 9724f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 973bf648f77SEd Tanous { 974bf648f77SEd Tanous // Can have multiple subdomains 975bf648f77SEd Tanous // Top Level Domain's min length is 2 character 9764b242749SEd Tanous const static std::regex pattern( 9770fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 978bf648f77SEd Tanous 979bf648f77SEd Tanous return std::regex_match(domainname, pattern); 980bf648f77SEd Tanous } 981bf648f77SEd Tanous 9824f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 9838d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 984ab6554f1SJoshi-Mansi { 985ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 986ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 987ab6554f1SJoshi-Mansi { 988ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 989ab6554f1SJoshi-Mansi return; 990ab6554f1SJoshi-Mansi } 991ab6554f1SJoshi-Mansi 992ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 993ab6554f1SJoshi-Mansi if (pos == std::string::npos) 994ab6554f1SJoshi-Mansi { 995ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 996ab6554f1SJoshi-Mansi return; 997ab6554f1SJoshi-Mansi } 998ab6554f1SJoshi-Mansi 999ab6554f1SJoshi-Mansi std::string hostname; 1000ab6554f1SJoshi-Mansi std::string domainname; 1001ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1002ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1003ab6554f1SJoshi-Mansi 1004ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1005ab6554f1SJoshi-Mansi { 1006ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1007ab6554f1SJoshi-Mansi return; 1008ab6554f1SJoshi-Mansi } 1009ab6554f1SJoshi-Mansi 1010ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1011ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1012ab6554f1SJoshi-Mansi } 1013ab6554f1SJoshi-Mansi 10144f48d5f6SEd Tanous inline void 10154f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1016bf648f77SEd Tanous const std::string& macAddress, 10178d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1018d577665bSRatan Gupta { 101958283f41SJohnathan Mantey static constexpr std::string_view dbusNotAllowedError = 102058283f41SJohnathan Mantey "xyz.openbmc_project.Common.Error.NotAllowed"; 102158283f41SJohnathan Mantey 10229ae226faSGeorge Liu sdbusplus::asio::setProperty( 10239ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10249ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10259ae226faSGeorge Liu "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress, 10269ae226faSGeorge Liu [asyncResp](const boost::system::error_code& ec, 10275b378546SPatrick Williams const sdbusplus::message_t& msg) { 1028d577665bSRatan Gupta if (ec) 1029d577665bSRatan Gupta { 103058283f41SJohnathan Mantey const sd_bus_error* err = msg.get_error(); 103158283f41SJohnathan Mantey if (err == nullptr) 103258283f41SJohnathan Mantey { 103358283f41SJohnathan Mantey messages::internalError(asyncResp->res); 103458283f41SJohnathan Mantey return; 103558283f41SJohnathan Mantey } 103658283f41SJohnathan Mantey if (err->name == dbusNotAllowedError) 103758283f41SJohnathan Mantey { 103858283f41SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "MACAddress"); 103958283f41SJohnathan Mantey return; 104058283f41SJohnathan Mantey } 1041d577665bSRatan Gupta messages::internalError(asyncResp->res); 1042d577665bSRatan Gupta return; 1043d577665bSRatan Gupta } 10449ae226faSGeorge Liu }); 1045d577665bSRatan Gupta } 1046286b9118SJohnathan Mantey 10474f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 10484f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 10494f48d5f6SEd Tanous const bool v6Value, 10508d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1051da131a9aSJennifer Lee { 10522c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 10539ae226faSGeorge Liu sdbusplus::asio::setProperty( 10549ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10559ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10569ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp, 10575e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1058da131a9aSJennifer Lee if (ec) 1059da131a9aSJennifer Lee { 106062598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1061da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1062da131a9aSJennifer Lee return; 1063da131a9aSJennifer Lee } 10648f7e9c19SJayaprakash Mutyala messages::success(asyncResp->res); 10659ae226faSGeorge Liu }); 1066da131a9aSJennifer Lee } 10671f8c7b5dSJohnathan Mantey 10684f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty( 1069eeedda23SJohnathan Mantey const std::string& ifaceId, const std::string& propertyName, 10708d1b46d7Szhanghch05 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1071eeedda23SJohnathan Mantey { 10729ae226faSGeorge Liu sdbusplus::asio::setProperty( 10739ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10749ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10759ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, value, 10765e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1077eeedda23SJohnathan Mantey if (ec) 1078eeedda23SJohnathan Mantey { 107962598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1080eeedda23SJohnathan Mantey messages::internalError(asyncResp->res); 1081eeedda23SJohnathan Mantey return; 1082eeedda23SJohnathan Mantey } 10839ae226faSGeorge Liu }); 1084eeedda23SJohnathan Mantey } 1085eeedda23SJohnathan Mantey 10864f48d5f6SEd Tanous inline void setDHCPv4Config(const std::string& propertyName, const bool& value, 10878d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1088da131a9aSJennifer Lee { 108962598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 10909ae226faSGeorge Liu sdbusplus::asio::setProperty( 10919ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10929ae226faSGeorge Liu "/xyz/openbmc_project/network/dhcp", 10939ae226faSGeorge Liu "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value, 10945e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1095da131a9aSJennifer Lee if (ec) 1096da131a9aSJennifer Lee { 109762598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1098da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1099da131a9aSJennifer Lee return; 1100da131a9aSJennifer Lee } 11019ae226faSGeorge Liu }); 1102da131a9aSJennifer Lee } 1103d577665bSRatan Gupta 1104b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1105b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1106b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1107b10d8db0SRavi Teja { 1108b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1109b10d8db0SRavi Teja path /= ifaceId; 1110b10d8db0SRavi Teja sdbusplus::asio::setProperty( 1111b10d8db0SRavi Teja *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 1112b10d8db0SRavi Teja "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA", 1113b10d8db0SRavi Teja ipv6AutoConfigEnabled, 1114b10d8db0SRavi Teja [asyncResp](const boost::system::error_code& ec) { 1115b10d8db0SRavi Teja if (ec) 1116b10d8db0SRavi Teja { 1117b10d8db0SRavi Teja BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1118b10d8db0SRavi Teja messages::internalError(asyncResp->res); 1119b10d8db0SRavi Teja return; 1120b10d8db0SRavi Teja } 1121b10d8db0SRavi Teja messages::success(asyncResp->res); 1122b10d8db0SRavi Teja }); 1123b10d8db0SRavi Teja } 1124b10d8db0SRavi Teja 11254f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 11261f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1127f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1128f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 11298d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1130da131a9aSJennifer Lee { 113182695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 113282695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1133da131a9aSJennifer Lee 11341f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 11351f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 11361f8c7b5dSJohnathan Mantey 11371f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 11381f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1139da131a9aSJennifer Lee { 1140b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 11411f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 11421f8c7b5dSJohnathan Mantey { 1143bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1144bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 11451f8c7b5dSJohnathan Mantey "OperatingMode"); 1146da131a9aSJennifer Lee return; 1147da131a9aSJennifer Lee } 1148b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 11491f8c7b5dSJohnathan Mantey } 11501f8c7b5dSJohnathan Mantey else 1151da131a9aSJennifer Lee { 11521f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 11531f8c7b5dSJohnathan Mantey } 11541f8c7b5dSJohnathan Mantey 11551f8c7b5dSJohnathan Mantey bool nextDNS{}; 115682695a5bSJiaqing Zhao if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers) 11571f8c7b5dSJohnathan Mantey { 115882695a5bSJiaqing Zhao if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers) 11591f8c7b5dSJohnathan Mantey { 11601f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 11611f8c7b5dSJohnathan Mantey return; 11621f8c7b5dSJohnathan Mantey } 116382695a5bSJiaqing Zhao nextDNS = *v4dhcpParms.useDnsServers; 11641f8c7b5dSJohnathan Mantey } 116582695a5bSJiaqing Zhao else if (v4dhcpParms.useDnsServers) 11661f8c7b5dSJohnathan Mantey { 116782695a5bSJiaqing Zhao nextDNS = *v4dhcpParms.useDnsServers; 11681f8c7b5dSJohnathan Mantey } 116982695a5bSJiaqing Zhao else if (v6dhcpParms.useDnsServers) 11701f8c7b5dSJohnathan Mantey { 117182695a5bSJiaqing Zhao nextDNS = *v6dhcpParms.useDnsServers; 11721f8c7b5dSJohnathan Mantey } 11731f8c7b5dSJohnathan Mantey else 11741f8c7b5dSJohnathan Mantey { 117582695a5bSJiaqing Zhao nextDNS = ethData.dnsEnabled; 11761f8c7b5dSJohnathan Mantey } 11771f8c7b5dSJohnathan Mantey 11781f8c7b5dSJohnathan Mantey bool nextNTP{}; 117982695a5bSJiaqing Zhao if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers) 11801f8c7b5dSJohnathan Mantey { 118182695a5bSJiaqing Zhao if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers) 11821f8c7b5dSJohnathan Mantey { 11831f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 11841f8c7b5dSJohnathan Mantey return; 11851f8c7b5dSJohnathan Mantey } 118682695a5bSJiaqing Zhao nextNTP = *v4dhcpParms.useNtpServers; 11871f8c7b5dSJohnathan Mantey } 118882695a5bSJiaqing Zhao else if (v4dhcpParms.useNtpServers) 11891f8c7b5dSJohnathan Mantey { 119082695a5bSJiaqing Zhao nextNTP = *v4dhcpParms.useNtpServers; 11911f8c7b5dSJohnathan Mantey } 119282695a5bSJiaqing Zhao else if (v6dhcpParms.useNtpServers) 11931f8c7b5dSJohnathan Mantey { 119482695a5bSJiaqing Zhao nextNTP = *v6dhcpParms.useNtpServers; 11951f8c7b5dSJohnathan Mantey } 11961f8c7b5dSJohnathan Mantey else 11971f8c7b5dSJohnathan Mantey { 119882695a5bSJiaqing Zhao nextNTP = ethData.ntpEnabled; 11991f8c7b5dSJohnathan Mantey } 12001f8c7b5dSJohnathan Mantey 12011f8c7b5dSJohnathan Mantey bool nextUseDomain{}; 120282695a5bSJiaqing Zhao if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName) 12031f8c7b5dSJohnathan Mantey { 120482695a5bSJiaqing Zhao if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName) 12051f8c7b5dSJohnathan Mantey { 12061f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12071f8c7b5dSJohnathan Mantey return; 12081f8c7b5dSJohnathan Mantey } 120982695a5bSJiaqing Zhao nextUseDomain = *v4dhcpParms.useDomainName; 12101f8c7b5dSJohnathan Mantey } 121182695a5bSJiaqing Zhao else if (v4dhcpParms.useDomainName) 12121f8c7b5dSJohnathan Mantey { 121382695a5bSJiaqing Zhao nextUseDomain = *v4dhcpParms.useDomainName; 12141f8c7b5dSJohnathan Mantey } 121582695a5bSJiaqing Zhao else if (v6dhcpParms.useDomainName) 12161f8c7b5dSJohnathan Mantey { 121782695a5bSJiaqing Zhao nextUseDomain = *v6dhcpParms.useDomainName; 12181f8c7b5dSJohnathan Mantey } 12191f8c7b5dSJohnathan Mantey else 12201f8c7b5dSJohnathan Mantey { 122182695a5bSJiaqing Zhao nextUseDomain = ethData.hostNameEnabled; 12221f8c7b5dSJohnathan Mantey } 12231f8c7b5dSJohnathan Mantey 122462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 12251f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 12261f8c7b5dSJohnathan Mantey asyncResp); 122762598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 12281f8c7b5dSJohnathan Mantey setDHCPv4Config("DNSEnabled", nextDNS, asyncResp); 122962598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 12301f8c7b5dSJohnathan Mantey setDHCPv4Config("NTPEnabled", nextNTP, asyncResp); 123162598e31SEd Tanous BMCWEB_LOG_DEBUG("set HostNameEnabled..."); 12321f8c7b5dSJohnathan Mantey setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp); 1233da131a9aSJennifer Lee } 123401784826SJohnathan Mantey 123577179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 123677179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 123777179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 123801784826SJohnathan Mantey { 123917a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 124017a897dfSManojkiran Eda return value.origin == "Static"; 124117a897dfSManojkiran Eda }); 124201784826SJohnathan Mantey } 124301784826SJohnathan Mantey 124477179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 124577179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 124677179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 124701784826SJohnathan Mantey { 124817a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 124917a897dfSManojkiran Eda return value.origin == "Static"; 125017a897dfSManojkiran Eda }); 125101784826SJohnathan Mantey } 125201784826SJohnathan Mantey 125377179532SEd Tanous inline void 1254ddd70dcaSEd Tanous handleIPv4StaticPatch(const std::string& ifaceId, 1255ddd70dcaSEd Tanous nlohmann::json::array_t& input, 125677179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 12578d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12581abe55efSEd Tanous { 1259ddd70dcaSEd Tanous if (input.empty()) 1260f476acbfSRatan Gupta { 12612e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1262d1d50814SRavi Teja "IPv4StaticAddresses"); 1263f476acbfSRatan Gupta return; 1264f476acbfSRatan Gupta } 1265f476acbfSRatan Gupta 1266271584abSEd Tanous unsigned entryIdx = 1; 126701784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 126801784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 126901784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 127001784826SJohnathan Mantey // into the NIC. 127177179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 12722c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 127301784826SJohnathan Mantey 1274537174c4SEd Tanous for (nlohmann::json& thisJson : input) 12751abe55efSEd Tanous { 127689492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 127789492a15SPatrick Williams std::to_string(entryIdx); 1278179db1d7SKowalski, Kamil 127901784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1280f476acbfSRatan Gupta { 1281537174c4SEd Tanous std::optional<std::string> address; 1282537174c4SEd Tanous std::optional<std::string> subnetMask; 1283537174c4SEd Tanous std::optional<std::string> gateway; 1284537174c4SEd Tanous 1285537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 12867e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 12877e27d832SJohnathan Mantey "Gateway", gateway)) 1288537174c4SEd Tanous { 1289f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 129071f52d96SEd Tanous pathString); 1291537174c4SEd Tanous return; 1292179db1d7SKowalski, Kamil } 1293179db1d7SKowalski, Kamil 129401784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 129501784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 129601784826SJohnathan Mantey // current state of the interface. Merge existing state into the 129701784826SJohnathan Mantey // current request. 1298537174c4SEd Tanous if (address) 12991abe55efSEd Tanous { 1300*e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 130101784826SJohnathan Mantey { 1302bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1303bf648f77SEd Tanous pathString + "/Address"); 1304*e01d0c36SEd Tanous return; 130501784826SJohnathan Mantey } 130601784826SJohnathan Mantey } 130785ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 130801784826SJohnathan Mantey { 1309*e01d0c36SEd Tanous address = (nicIpEntry->address); 131001784826SJohnathan Mantey } 131101784826SJohnathan Mantey else 131201784826SJohnathan Mantey { 131301784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 131401784826SJohnathan Mantey pathString + "/Address"); 1315*e01d0c36SEd Tanous return; 13164a0cb85cSEd Tanous } 13174a0cb85cSEd Tanous 1318*e01d0c36SEd Tanous uint8_t prefixLength = 0; 1319537174c4SEd Tanous if (subnetMask) 13204a0cb85cSEd Tanous { 1321033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1322033f1e4dSEd Tanous &prefixLength)) 13234a0cb85cSEd Tanous { 1324f12894f8SJason M. Bills messages::propertyValueFormatError( 1325537174c4SEd Tanous asyncResp->res, *subnetMask, 13264a0cb85cSEd Tanous pathString + "/SubnetMask"); 1327*e01d0c36SEd Tanous return; 13284a0cb85cSEd Tanous } 13294a0cb85cSEd Tanous } 133085ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 13314a0cb85cSEd Tanous { 1332033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 133301784826SJohnathan Mantey &prefixLength)) 13344a0cb85cSEd Tanous { 133501784826SJohnathan Mantey messages::propertyValueFormatError( 133685ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 133701784826SJohnathan Mantey pathString + "/SubnetMask"); 1338*e01d0c36SEd Tanous return; 13394a0cb85cSEd Tanous } 13404a0cb85cSEd Tanous } 13411abe55efSEd Tanous else 13421abe55efSEd Tanous { 134301784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 134401784826SJohnathan Mantey pathString + "/SubnetMask"); 1345*e01d0c36SEd Tanous return; 134601784826SJohnathan Mantey } 134701784826SJohnathan Mantey 134801784826SJohnathan Mantey if (gateway) 134901784826SJohnathan Mantey { 1350*e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 135101784826SJohnathan Mantey { 1352bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1353bf648f77SEd Tanous pathString + "/Gateway"); 1354*e01d0c36SEd Tanous return; 135501784826SJohnathan Mantey } 135601784826SJohnathan Mantey } 135785ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 135801784826SJohnathan Mantey { 1359*e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 136001784826SJohnathan Mantey } 136101784826SJohnathan Mantey else 13621abe55efSEd Tanous { 1363a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13644a0cb85cSEd Tanous pathString + "/Gateway"); 136501784826SJohnathan Mantey return; 13664a0cb85cSEd Tanous } 13674a0cb85cSEd Tanous 136885ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 13691abe55efSEd Tanous { 13709c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 1371*e01d0c36SEd Tanous nicIpEntry->id, prefixLength, *gateway, 1372*e01d0c36SEd Tanous *address, asyncResp); 137389492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 137489492a15SPatrick Williams ipv4Data.cend()); 1375588c3f0dSKowalski, Kamil } 137601784826SJohnathan Mantey else 137701784826SJohnathan Mantey { 1378cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1379cb13a392SEd Tanous asyncResp); 13804a0cb85cSEd Tanous } 13814a0cb85cSEd Tanous entryIdx++; 13824a0cb85cSEd Tanous } 138301784826SJohnathan Mantey else 138401784826SJohnathan Mantey { 138585ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 138601784826SJohnathan Mantey { 138701784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 138801784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 138901784826SJohnathan Mantey // in error, so bail out. 139001784826SJohnathan Mantey if (thisJson.is_null()) 139101784826SJohnathan Mantey { 139201784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 139301784826SJohnathan Mantey return; 139401784826SJohnathan Mantey } 1395f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 139671f52d96SEd Tanous pathString); 139701784826SJohnathan Mantey return; 139801784826SJohnathan Mantey } 139901784826SJohnathan Mantey 140001784826SJohnathan Mantey if (thisJson.is_null()) 140101784826SJohnathan Mantey { 14029c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 140301784826SJohnathan Mantey } 140485ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 140501784826SJohnathan Mantey { 140689492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 140789492a15SPatrick Williams ipv4Data.cend()); 140801784826SJohnathan Mantey } 140901784826SJohnathan Mantey entryIdx++; 141001784826SJohnathan Mantey } 141101784826SJohnathan Mantey } 14124a0cb85cSEd Tanous } 14134a0cb85cSEd Tanous 14144f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1415f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1416f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 14178d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1418f85837bfSRAJESWARAN THILLAIGOVINDAN { 14199ae226faSGeorge Liu sdbusplus::asio::setProperty( 14209ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 14219ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 14229ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 14239ae226faSGeorge Liu updatedStaticNameServers, 14245e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1425f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1426f85837bfSRAJESWARAN THILLAIGOVINDAN { 1427f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1428f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1429f85837bfSRAJESWARAN THILLAIGOVINDAN } 14309ae226faSGeorge Liu }); 1431f85837bfSRAJESWARAN THILLAIGOVINDAN } 1432f85837bfSRAJESWARAN THILLAIGOVINDAN 14334f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1434ddd70dcaSEd Tanous const std::string& ifaceId, const nlohmann::json::array_t& input, 143577179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 14368d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1437e48c0fc5SRavi Teja { 1438ddd70dcaSEd Tanous if (input.empty()) 1439e48c0fc5SRavi Teja { 14402e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1441e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1442e48c0fc5SRavi Teja return; 1443e48c0fc5SRavi Teja } 1444271584abSEd Tanous size_t entryIdx = 1; 144577179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 14462c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1447f23b7296SEd Tanous for (const nlohmann::json& thisJson : input) 1448e48c0fc5SRavi Teja { 144989492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 145089492a15SPatrick Williams std::to_string(entryIdx); 1451e48c0fc5SRavi Teja 145201784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1453e48c0fc5SRavi Teja { 1454e48c0fc5SRavi Teja std::optional<std::string> address; 1455e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1456f23b7296SEd Tanous nlohmann::json thisJsonCopy = thisJson; 1457bf648f77SEd Tanous if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1458bf648f77SEd Tanous address, "PrefixLength", prefixLength)) 1459e48c0fc5SRavi Teja { 1460f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 146171f52d96SEd Tanous pathString); 1462e48c0fc5SRavi Teja return; 1463e48c0fc5SRavi Teja } 1464e48c0fc5SRavi Teja 1465543f4400SEd Tanous const std::string* addr = nullptr; 1466543f4400SEd Tanous uint8_t prefix = 0; 146701784826SJohnathan Mantey 146801784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 146901784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 147001784826SJohnathan Mantey // current state of the interface. Merge existing state into the 147101784826SJohnathan Mantey // current request. 1472e48c0fc5SRavi Teja if (address) 1473e48c0fc5SRavi Teja { 147401784826SJohnathan Mantey addr = &(*address); 1475e48c0fc5SRavi Teja } 147685ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 147701784826SJohnathan Mantey { 147885ffe86aSJiaqing Zhao addr = &(nicIpEntry->address); 147901784826SJohnathan Mantey } 148001784826SJohnathan Mantey else 148101784826SJohnathan Mantey { 148201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 148301784826SJohnathan Mantey pathString + "/Address"); 148401784826SJohnathan Mantey return; 1485e48c0fc5SRavi Teja } 1486e48c0fc5SRavi Teja 1487e48c0fc5SRavi Teja if (prefixLength) 1488e48c0fc5SRavi Teja { 148901784826SJohnathan Mantey prefix = *prefixLength; 149001784826SJohnathan Mantey } 149185ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 1492e48c0fc5SRavi Teja { 149385ffe86aSJiaqing Zhao prefix = nicIpEntry->prefixLength; 1494e48c0fc5SRavi Teja } 1495e48c0fc5SRavi Teja else 1496e48c0fc5SRavi Teja { 1497e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1498e48c0fc5SRavi Teja pathString + "/PrefixLength"); 149901784826SJohnathan Mantey return; 1500e48c0fc5SRavi Teja } 1501e48c0fc5SRavi Teja 150285ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1503e48c0fc5SRavi Teja { 15049c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 15059c5e585cSRavi Teja nicIpEntry->id, prefix, "", *addr, 1506e48c0fc5SRavi Teja asyncResp); 150789492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 150889492a15SPatrick Williams ipv6Data.cend()); 150901784826SJohnathan Mantey } 151001784826SJohnathan Mantey else 151101784826SJohnathan Mantey { 151201784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1513e48c0fc5SRavi Teja } 1514e48c0fc5SRavi Teja entryIdx++; 1515e48c0fc5SRavi Teja } 151601784826SJohnathan Mantey else 151701784826SJohnathan Mantey { 151885ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 151901784826SJohnathan Mantey { 152001784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 152101784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 152201784826SJohnathan Mantey // in error, so bail out. 152301784826SJohnathan Mantey if (thisJson.is_null()) 152401784826SJohnathan Mantey { 152501784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 152601784826SJohnathan Mantey return; 152701784826SJohnathan Mantey } 1528f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 152971f52d96SEd Tanous pathString); 153001784826SJohnathan Mantey return; 153101784826SJohnathan Mantey } 153201784826SJohnathan Mantey 153301784826SJohnathan Mantey if (thisJson.is_null()) 153401784826SJohnathan Mantey { 15359c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 153601784826SJohnathan Mantey } 153785ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 153801784826SJohnathan Mantey { 153989492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 154089492a15SPatrick Williams ipv6Data.cend()); 154101784826SJohnathan Mantey } 154201784826SJohnathan Mantey entryIdx++; 154301784826SJohnathan Mantey } 154401784826SJohnathan Mantey } 1545e48c0fc5SRavi Teja } 1546e48c0fc5SRavi Teja 15477857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 15487857cb8dSJiaqing Zhao { 15497857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 15507857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 15517857cb8dSJiaqing Zhao } 15527857cb8dSJiaqing Zhao 155377179532SEd Tanous inline void 155477179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 155577179532SEd Tanous const std::string& ifaceId, 155677179532SEd Tanous const EthernetInterfaceData& ethData, 155777179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 155877179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) 15594a0cb85cSEd Tanous { 15602c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 156181ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1562ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1563ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 15642c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1565eeedda23SJohnathan Mantey 156613451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 156713451e39SWilly Tu { 156813451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 156913451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1570eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 15717a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 15727a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 15737a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1574b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1575eeedda23SJohnathan Mantey if (ec) 1576029573d4SEd Tanous { 1577eeedda23SJohnathan Mantey return; 1578eeedda23SJohnathan Mantey } 1579eeedda23SJohnathan Mantey 1580914e2d5dSEd Tanous health->inventory = resp; 15817a1dbc48SGeorge Liu }); 1582eeedda23SJohnathan Mantey 1583eeedda23SJohnathan Mantey health->populate(); 158413451e39SWilly Tu } 1585eeedda23SJohnathan Mantey 1586eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1587eeedda23SJohnathan Mantey { 15880ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 15892c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1590029573d4SEd Tanous } 1591029573d4SEd Tanous else 1592029573d4SEd Tanous { 15932c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 15942c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1595029573d4SEd Tanous } 1596aa05fb27SJohnathan Mantey 15972c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 159835fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 159982695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 16002c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 160182695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 160282695a5bSJiaqing Zhao jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled; 160382695a5bSJiaqing Zhao jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled; 160482695a5bSJiaqing Zhao jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled; 16051f8c7b5dSJohnathan Mantey 16062c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1607b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 16081f8c7b5dSJohnathan Mantey : "Disabled"; 160982695a5bSJiaqing Zhao jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled; 161082695a5bSJiaqing Zhao jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled; 161182695a5bSJiaqing Zhao jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled; 1612b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1613b10d8db0SRavi Teja ethData.ipv6AcceptRa; 16142a133282Smanojkiraneda 161582695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 16164a0cb85cSEd Tanous { 161782695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1618ab6554f1SJoshi-Mansi 1619ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1620ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1621ab6554f1SJoshi-Mansi // FQDN 162282695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1623d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1624d24bfc7aSJennifer Lee { 16252c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1626d24bfc7aSJennifer Lee } 16272c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 16284a0cb85cSEd Tanous } 16294a0cb85cSEd Tanous 16307857cb8dSJiaqing Zhao if (ethData.vlanId) 16317857cb8dSJiaqing Zhao { 16327857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 16337857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 16347857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 16357857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 16367857cb8dSJiaqing Zhao 16377857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 16387857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 16397857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 16407857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 16417857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 16427857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 16437857cb8dSJiaqing Zhao std::move(relatedInterfaces); 16447857cb8dSJiaqing Zhao } 16457857cb8dSJiaqing Zhao else 16467857cb8dSJiaqing Zhao { 16477857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 16487857cb8dSJiaqing Zhao } 16497857cb8dSJiaqing Zhao 16502c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 16512c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 16524a0cb85cSEd Tanous 16532c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 16542c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 16552c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 16562c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 16579eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 16584a0cb85cSEd Tanous { 16592c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1660fa5053a6SGunnar Mills if (gatewayStr.empty()) 1661fa5053a6SGunnar Mills { 1662fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1663fa5053a6SGunnar Mills } 16641476687dSEd Tanous nlohmann::json::object_t ipv4; 16651476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 16661476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 16671476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 16681476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1669fa5053a6SGunnar Mills 16702c70f800SEd Tanous if (ipv4Config.origin == "Static") 1671d1d50814SRavi Teja { 16721476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1673d1d50814SRavi Teja } 16741476687dSEd Tanous 1675b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 167601784826SJohnathan Mantey } 1677d1d50814SRavi Teja 167882695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 16797ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 16807ea79e5eSRavi Teja { 16817ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 16827ea79e5eSRavi Teja } 16837ea79e5eSRavi Teja 16847ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1685e48c0fc5SRavi Teja 16862c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 16872c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 16882c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 16892c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 16907f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 16912c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 16927f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 16939eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1694e48c0fc5SRavi Teja { 16951476687dSEd Tanous nlohmann::json::object_t ipv6; 16961476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 16971476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 16981476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1699f8361275SSunitha Harish 1700b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 17012c70f800SEd Tanous if (ipv6Config.origin == "Static") 1702e48c0fc5SRavi Teja { 17031476687dSEd Tanous nlohmann::json::object_t ipv6Static; 17041476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 17051476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1706b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 170701784826SJohnathan Mantey } 1708e48c0fc5SRavi Teja } 1709588c3f0dSKowalski, Kamil } 1710588c3f0dSKowalski, Kamil 1711e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1712e7caf250SJiaqing Zhao const std::string& ifaceId, 1713e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1714e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1715e7caf250SJiaqing Zhao { 1716e7caf250SJiaqing Zhao if (!ec) 1717e7caf250SJiaqing Zhao { 1718e7caf250SJiaqing Zhao return; 1719e7caf250SJiaqing Zhao } 1720e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1721e7caf250SJiaqing Zhao if (dbusError == nullptr) 1722e7caf250SJiaqing Zhao { 1723e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1724e7caf250SJiaqing Zhao return; 1725e7caf250SJiaqing Zhao } 172662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1727e7caf250SJiaqing Zhao 1728e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 1729e7caf250SJiaqing Zhao dbusError->name) 1730e7caf250SJiaqing Zhao { 1731e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1732e7caf250SJiaqing Zhao ifaceId); 1733e7caf250SJiaqing Zhao return; 1734e7caf250SJiaqing Zhao } 1735e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 1736e7caf250SJiaqing Zhao dbusError->name) 1737e7caf250SJiaqing Zhao { 1738e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 1739e7caf250SJiaqing Zhao return; 1740e7caf250SJiaqing Zhao } 1741e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1742e7caf250SJiaqing Zhao } 1743e7caf250SJiaqing Zhao 1744b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1745b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 1746b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 1747b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 1748b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 1749b5ca3fdcSJiaqing Zhao 1750b5ca3fdcSJiaqing Zhao ) 1751b5ca3fdcSJiaqing Zhao { 1752b5ca3fdcSJiaqing Zhao if (ec) 1753b5ca3fdcSJiaqing Zhao { 1754b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1755b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 1756b5ca3fdcSJiaqing Zhao { 1757b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1758b5ca3fdcSJiaqing Zhao return; 1759b5ca3fdcSJiaqing Zhao } 176062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1761b5ca3fdcSJiaqing Zhao 1762b5ca3fdcSJiaqing Zhao if (std::string_view( 1763b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 1764b5ca3fdcSJiaqing Zhao dbusError->name) 1765b5ca3fdcSJiaqing Zhao { 1766b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1767b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1768b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1769b5ca3fdcSJiaqing Zhao return; 1770b5ca3fdcSJiaqing Zhao } 1771b5ca3fdcSJiaqing Zhao if (std::string_view( 1772b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 1773b5ca3fdcSJiaqing Zhao dbusError->name) 1774b5ca3fdcSJiaqing Zhao { 1775b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 1776b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 1777b5ca3fdcSJiaqing Zhao return; 1778b5ca3fdcSJiaqing Zhao } 1779b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1780b5ca3fdcSJiaqing Zhao return; 1781b5ca3fdcSJiaqing Zhao } 1782b5ca3fdcSJiaqing Zhao 1783b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 1784b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 1785b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 1786b5ca3fdcSJiaqing Zhao } 1787b5ca3fdcSJiaqing Zhao 1788bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 1789bf648f77SEd Tanous { 1790bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1791ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 17921476687dSEd Tanous .methods(boost::beast::http::verb::get)( 17931476687dSEd Tanous [&app](const crow::Request& req, 17941476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 17953ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 179645ca1b86SEd Tanous { 179745ca1b86SEd Tanous return; 179845ca1b86SEd Tanous } 179945ca1b86SEd Tanous 1800bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1801bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 1802bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1803bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1804bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 1805bf648f77SEd Tanous "Ethernet Network Interface Collection"; 1806bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 1807bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 1808bf648f77SEd Tanous 1809bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 1810bf648f77SEd Tanous // preparation 1811002d39b4SEd Tanous getEthernetIfaceList( 181277179532SEd Tanous [asyncResp](const bool& success, 181377179532SEd Tanous const std::vector<std::string>& ifaceList) { 1814bf648f77SEd Tanous if (!success) 18151abe55efSEd Tanous { 1816f12894f8SJason M. Bills messages::internalError(asyncResp->res); 18179391bb9cSRapkiewicz, Pawel return; 18189391bb9cSRapkiewicz, Pawel } 18199391bb9cSRapkiewicz, Pawel 1820002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 1821bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 1822bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 1823bf648f77SEd Tanous { 18241476687dSEd Tanous nlohmann::json::object_t iface; 1825ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 1826ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 1827ef4c65b7SEd Tanous ifaceItem); 18287857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 1829bf648f77SEd Tanous } 1830bf648f77SEd Tanous 1831002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 1832bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1833bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1834bf648f77SEd Tanous }); 1835bf648f77SEd Tanous }); 1836bf648f77SEd Tanous 1837b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1838b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 1839b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 1840b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 1841b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1842b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1843b5ca3fdcSJiaqing Zhao { 1844b5ca3fdcSJiaqing Zhao return; 1845b5ca3fdcSJiaqing Zhao } 1846b5ca3fdcSJiaqing Zhao 1847b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 1848b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 1849b5ca3fdcSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 1850b5ca3fdcSJiaqing Zhao 1851b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 1852b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 1853b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1854b5ca3fdcSJiaqing Zhao relatedInterfaces)) 1855b5ca3fdcSJiaqing Zhao { 1856b5ca3fdcSJiaqing Zhao return; 1857b5ca3fdcSJiaqing Zhao } 1858b5ca3fdcSJiaqing Zhao 1859b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 1860b5ca3fdcSJiaqing Zhao { 1861b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 1862b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1863b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 1864b5ca3fdcSJiaqing Zhao return; 1865b5ca3fdcSJiaqing Zhao } 1866b5ca3fdcSJiaqing Zhao 1867b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 1868b5ca3fdcSJiaqing Zhao if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, 1869b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 1870b5ca3fdcSJiaqing Zhao { 1871b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 1872b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1873b5ca3fdcSJiaqing Zhao return; 1874b5ca3fdcSJiaqing Zhao } 187562598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 1876b5ca3fdcSJiaqing Zhao 1877b5ca3fdcSJiaqing Zhao boost::urls::result<boost::urls::url_view> parsedUri = 1878b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 1879b5ca3fdcSJiaqing Zhao if (!parsedUri) 1880b5ca3fdcSJiaqing Zhao { 1881b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 1882b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1883b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1884b5ca3fdcSJiaqing Zhao return; 1885b5ca3fdcSJiaqing Zhao } 1886b5ca3fdcSJiaqing Zhao 1887b5ca3fdcSJiaqing Zhao std::string parentInterface; 1888b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 1889b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 1890b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 1891b5ca3fdcSJiaqing Zhao { 1892b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1893b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1894b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1895b5ca3fdcSJiaqing Zhao return; 1896b5ca3fdcSJiaqing Zhao } 1897b5ca3fdcSJiaqing Zhao 1898b5ca3fdcSJiaqing Zhao if (!vlanEnable) 1899b5ca3fdcSJiaqing Zhao { 1900b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 1901b5ca3fdcSJiaqing Zhao // create 1902b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 1903b5ca3fdcSJiaqing Zhao "false"); 1904b5ca3fdcSJiaqing Zhao return; 1905b5ca3fdcSJiaqing Zhao } 1906b5ca3fdcSJiaqing Zhao 1907b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 1908b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 1909b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 1910b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 1911b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 1912b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 1913b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 1914b5ca3fdcSJiaqing Zhao m); 1915b5ca3fdcSJiaqing Zhao }, 1916b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 1917b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 1918b5ca3fdcSJiaqing Zhao vlanId); 1919b5ca3fdcSJiaqing Zhao }); 1920b5ca3fdcSJiaqing Zhao 1921bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1922ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 1923bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 192445ca1b86SEd Tanous [&app](const crow::Request& req, 1925bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1926bf648f77SEd Tanous const std::string& ifaceId) { 19273ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 192845ca1b86SEd Tanous { 192945ca1b86SEd Tanous return; 193045ca1b86SEd Tanous } 19314a0cb85cSEd Tanous getEthernetIfaceData( 1932bf648f77SEd Tanous ifaceId, 193377179532SEd Tanous [asyncResp, ifaceId](const bool& success, 193477179532SEd Tanous const EthernetInterfaceData& ethData, 193577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 193677179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 19374a0cb85cSEd Tanous if (!success) 19381abe55efSEd Tanous { 1939bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 1940bf648f77SEd Tanous // existing object, and other errors 1941002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1942002d39b4SEd Tanous ifaceId); 19434a0cb85cSEd Tanous return; 19449391bb9cSRapkiewicz, Pawel } 19454c9afe43SEd Tanous 19460f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 194793bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 1948002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 19490f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 19500f74e643SEd Tanous "Management Network Interface"; 19510f74e643SEd Tanous 1952002d39b4SEd Tanous parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data); 19539391bb9cSRapkiewicz, Pawel }); 1954bf648f77SEd Tanous }); 19559391bb9cSRapkiewicz, Pawel 1956bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1957ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 1958bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 195945ca1b86SEd Tanous [&app](const crow::Request& req, 1960bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1961bf648f77SEd Tanous const std::string& ifaceId) { 19623ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 196345ca1b86SEd Tanous { 196445ca1b86SEd Tanous return; 196545ca1b86SEd Tanous } 1966bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1967ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 1968d577665bSRatan Gupta std::optional<std::string> macAddress; 19699a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1970ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv4StaticAddresses; 1971ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv6StaticAddresses; 1972f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1973da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 19741f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 1975b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 1976eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 197735fb5311STejas Patil std::optional<size_t> mtuSize; 19781f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 19791f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 1980b10d8db0SRavi Teja // clang-format off 198115ed6780SWilly Tu if (!json_util::readJsonPatch( 1982b10d8db0SRavi Teja req, asyncResp->res, 1983b10d8db0SRavi Teja "DHCPv4", dhcpv4, 1984b10d8db0SRavi Teja "DHCPv6", dhcpv6, 1985b10d8db0SRavi Teja "FQDN", fqdn, 1986b10d8db0SRavi Teja "HostName", hostname, 1987b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 1988b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 1989b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 1990b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 1991b10d8db0SRavi Teja "MACAddress", macAddress, 1992b10d8db0SRavi Teja "MTUSize", mtuSize, 1993b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 1994b10d8db0SRavi Teja "StaticNameServers", staticNameServers 1995b10d8db0SRavi Teja ) 1996b10d8db0SRavi Teja ) 19971abe55efSEd Tanous { 1998588c3f0dSKowalski, Kamil return; 1999588c3f0dSKowalski, Kamil } 2000b10d8db0SRavi Teja //clang-format on 2001da131a9aSJennifer Lee if (dhcpv4) 2002da131a9aSJennifer Lee { 2003002d39b4SEd Tanous if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 20041f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 200582695a5bSJiaqing Zhao v4dhcpParms.useDnsServers, "UseNTPServers", 200682695a5bSJiaqing Zhao v4dhcpParms.useNtpServers, "UseDomainName", 200782695a5bSJiaqing Zhao v4dhcpParms.useDomainName)) 20081f8c7b5dSJohnathan Mantey { 20091f8c7b5dSJohnathan Mantey return; 20101f8c7b5dSJohnathan Mantey } 20111f8c7b5dSJohnathan Mantey } 20121f8c7b5dSJohnathan Mantey 20131f8c7b5dSJohnathan Mantey if (dhcpv6) 20141f8c7b5dSJohnathan Mantey { 2015002d39b4SEd Tanous if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", 2016002d39b4SEd Tanous v6dhcpParms.dhcpv6OperatingMode, 2017002d39b4SEd Tanous "UseDNSServers", v6dhcpParms.useDnsServers, 2018002d39b4SEd Tanous "UseNTPServers", v6dhcpParms.useNtpServers, 2019002d39b4SEd Tanous "UseDomainName", 202082695a5bSJiaqing Zhao v6dhcpParms.useDomainName)) 20211f8c7b5dSJohnathan Mantey { 20221f8c7b5dSJohnathan Mantey return; 20231f8c7b5dSJohnathan Mantey } 2024da131a9aSJennifer Lee } 2025da131a9aSJennifer Lee 2026bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2027bf648f77SEd Tanous // for JSON preparation 20284a0cb85cSEd Tanous getEthernetIfaceData( 20292c70f800SEd Tanous ifaceId, 2030bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2031ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2032d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 20339a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2034e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 20351f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 2036bc20089aSEd Tanous dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize, 2037b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2038f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2039002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 204077179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 204177179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 20421abe55efSEd Tanous if (!success) 20431abe55efSEd Tanous { 2044588c3f0dSKowalski, Kamil // ... otherwise return error 2045bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2046bf648f77SEd Tanous // existing object, and other errors 2047002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2048002d39b4SEd Tanous ifaceId); 2049588c3f0dSKowalski, Kamil return; 2050588c3f0dSKowalski, Kamil } 2051588c3f0dSKowalski, Kamil 20521f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 20531f8c7b5dSJohnathan Mantey { 2054002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2055002d39b4SEd Tanous asyncResp); 20561f8c7b5dSJohnathan Mantey } 20571f8c7b5dSJohnathan Mantey 20580627a2c7SEd Tanous if (hostname) 20591abe55efSEd Tanous { 20600627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 20611abe55efSEd Tanous } 20620627a2c7SEd Tanous 2063b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2064b10d8db0SRavi Teja { 2065b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2066b10d8db0SRavi Teja asyncResp); 2067b10d8db0SRavi Teja } 2068b10d8db0SRavi Teja 2069ab6554f1SJoshi-Mansi if (fqdn) 2070ab6554f1SJoshi-Mansi { 20712c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2072ab6554f1SJoshi-Mansi } 2073ab6554f1SJoshi-Mansi 2074d577665bSRatan Gupta if (macAddress) 2075d577665bSRatan Gupta { 2076002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2077d577665bSRatan Gupta } 2078d577665bSRatan Gupta 2079d1d50814SRavi Teja if (ipv4StaticAddresses) 2080d1d50814SRavi Teja { 2081bf648f77SEd Tanous // TODO(ed) for some reason the capture of 2082bf648f77SEd Tanous // ipv4Addresses above is returning a const value, 2083bf648f77SEd Tanous // not a non-const value. This doesn't really work 2084bf648f77SEd Tanous // for us, as we need to be able to efficiently move 2085bf648f77SEd Tanous // out the intermedia nlohmann::json objects. This 2086bf648f77SEd Tanous // makes a copy of the structure, and operates on 2087bf648f77SEd Tanous // that, but could be done more efficiently 2088ddd70dcaSEd Tanous nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses; 2089002d39b4SEd Tanous handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp); 20901abe55efSEd Tanous } 20910627a2c7SEd Tanous 2092f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2093f85837bfSRAJESWARAN THILLAIGOVINDAN { 2094002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2095002d39b4SEd Tanous asyncResp); 2096f85837bfSRAJESWARAN THILLAIGOVINDAN } 20979a6fc6feSRavi Teja 20989a6fc6feSRavi Teja if (ipv6DefaultGateway) 20999a6fc6feSRavi Teja { 21009a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 21019a6fc6feSRavi Teja "IPv6DefaultGateway"); 21029a6fc6feSRavi Teja } 2103e48c0fc5SRavi Teja 2104e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2105e48c0fc5SRavi Teja { 2106ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2107ddd70dcaSEd Tanous ipv6Data, asyncResp); 2108e48c0fc5SRavi Teja } 2109eeedda23SJohnathan Mantey 2110eeedda23SJohnathan Mantey if (interfaceEnabled) 2111eeedda23SJohnathan Mantey { 2112002d39b4SEd Tanous setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled", 2113002d39b4SEd Tanous *interfaceEnabled, asyncResp); 2114eeedda23SJohnathan Mantey } 211535fb5311STejas Patil 211635fb5311STejas Patil if (mtuSize) 211735fb5311STejas Patil { 211835fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 211935fb5311STejas Patil } 2120588c3f0dSKowalski, Kamil }); 2121bf648f77SEd Tanous }); 2122e7caf250SJiaqing Zhao 2123e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2124e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2125e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2126e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2127e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2128e7caf250SJiaqing Zhao const std::string& ifaceId) { 2129e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2130e7caf250SJiaqing Zhao { 2131e7caf250SJiaqing Zhao return; 2132e7caf250SJiaqing Zhao } 2133e7caf250SJiaqing Zhao 2134e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2135e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2136e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2137e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2138e7caf250SJiaqing Zhao }, 2139e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2140e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2141e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2142e7caf250SJiaqing Zhao }); 21434a0cb85cSEd Tanous } 2144bf648f77SEd Tanous 21459391bb9cSRapkiewicz, Pawel } // namespace redfish 2146