summaryrefslogtreecommitdiff
path: root/redfish-core/lib/ethernet.hpp
diff options
context:
space:
mode:
authorJoshi-Mansi <mansi.joshi@linux.intel.com>2020-03-10 16:03:36 +0300
committermansi.joshi <mansi.joshi@linux.intel.com>2020-04-01 21:45:28 +0300
commitab6554f1d8197753cfb430a72798dde6f4461552 (patch)
tree83a06c79e788526236c1589e4815a8bd59e92129 /redfish-core/lib/ethernet.hpp
parent3c27ed3bb4ce887d2bd691a69314fe71c6a95942 (diff)
downloadbmcweb-ab6554f1d8197753cfb430a72798dde6f4461552.tar.xz
[Redfish-Ethernet Inf] Enable Read/Write for FQDN
Enabling read/write requirement of FQDN in Ethernet Interface Schema to make it OCP compliant. Tested: 1. Tested using PATCH: - https://bmc-ip/redfish/v1/Managers/bmc/EthernetInterfaces/eth-id {"FQDN": "hostname.domainname"} GET Response- "FQDN": "hostname.domainname" //Success - When given invalid hostname/domainname Error Message "propertyValueFormatError" 2. Ran the Redfish validator and no new issues found. Signed-off-by: Joshi-Mansi <mansi.joshi@linux.intel.com> Change-Id: Ief2e94f8b499be59196b0e7073ceffe8d49268ca
Diffstat (limited to 'redfish-core/lib/ethernet.hpp')
-rw-r--r--redfish-core/lib/ethernet.hpp116
1 files changed, 106 insertions, 10 deletions
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 0a2a1858b7..56e1a1508b 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -21,6 +21,7 @@
#include <error_messages.hpp>
#include <node.hpp>
#include <optional>
+#include <regex>
#include <utils/json_utils.hpp>
#include <variant>
@@ -1084,7 +1085,13 @@ class EthernetInterface : public Node
void handleHostnamePatch(const std::string &hostname,
const std::shared_ptr<AsyncResp> asyncResp)
{
- asyncResp->res.jsonValue["HostName"] = hostname;
+ // SHOULD handle host names of up to 255 characters(RFC 1123)
+ if (hostname.length() > 255)
+ {
+ messages::propertyValueFormatError(asyncResp->res, hostname,
+ "HostName");
+ return;
+ }
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code ec) {
if (ec)
@@ -1099,6 +1106,84 @@ class EthernetInterface : public Node
std::variant<std::string>(hostname));
}
+ void handleDomainnamePatch(const std::string &ifaceId,
+ const std::string &domainname,
+ const std::shared_ptr<AsyncResp> asyncResp)
+ {
+ std::vector<std::string> vectorDomainname = {domainname};
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ },
+ "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
+ std::variant<std::vector<std::string>>(vectorDomainname));
+ }
+
+ void handleFqdnPatch(const std::string &ifaceId, const std::string &fqdn,
+ const std::shared_ptr<AsyncResp> asyncResp)
+ {
+ // Total length of FQDN must not exceed 255 characters(RFC 1035)
+ if (fqdn.length() > 255)
+ {
+ messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
+ return;
+ }
+
+ size_t pos = fqdn.find('.');
+ if (pos == std::string::npos)
+ {
+ messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
+ return;
+ }
+
+ std::string hostname;
+ std::string domainname;
+ domainname = (fqdn).substr(pos + 1);
+ hostname = (fqdn).substr(0, pos);
+
+ if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
+ {
+ messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
+ return;
+ }
+
+ handleHostnamePatch(hostname, asyncResp);
+ handleDomainnamePatch(ifaceId, domainname, asyncResp);
+ }
+
+ bool isHostnameValid(const std::string &hostname)
+ {
+ // A valid host name can never have the dotted-decimal form (RFC 1123)
+ if (std::all_of(hostname.begin(), hostname.end(), ::isdigit))
+ {
+ return false;
+ }
+ // Each label(hostname/subdomains) within a valid FQDN
+ // MUST handle host names of up to 63 characters (RFC 1123)
+ // labels cannot start or end with hyphens (RFC 952)
+ // labels can start with numbers (RFC 1123)
+ const std::regex pattern(
+ "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
+
+ return std::regex_match(hostname, pattern);
+ }
+
+ bool isDomainnameValid(const std::string &domainname)
+ {
+ // Can have multiple subdomains
+ // Top Level Domain's min length is 2 character
+ const std::regex pattern("^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]"
+ "{1,30}\\.)*[a-zA-Z]{2,}$");
+
+ return std::regex_match(domainname, pattern);
+ }
+
void handleMACAddressPatch(const std::string &ifaceId,
const std::string &macAddress,
const std::shared_ptr<AsyncResp> &asyncResp)
@@ -1705,11 +1790,16 @@ class EthernetInterface : public Node
if (!ethData.hostname.empty())
{
json_response["HostName"] = ethData.hostname;
+
+ // When domain name is empty then it means, that it is a network
+ // without domain names, and the host name itself must be treated as
+ // FQDN
+ std::string FQDN = std::move(ethData.hostname);
if (!ethData.domainnames.empty())
{
- json_response["FQDN"] =
- ethData.hostname + "." + ethData.domainnames[0];
+ FQDN += "." + ethData.domainnames[0];
}
+ json_response["FQDN"] = FQDN;
}
json_response["VLANs"] = {
@@ -1828,6 +1918,7 @@ class EthernetInterface : public Node
const std::string &iface_id = params[0];
std::optional<std::string> hostname;
+ std::optional<std::string> fqdn;
std::optional<std::string> macAddress;
std::optional<std::string> ipv6DefaultGateway;
std::optional<nlohmann::json> ipv4StaticAddresses;
@@ -1840,12 +1931,12 @@ class EthernetInterface : public Node
DHCPParameters v6dhcpParms;
if (!json_util::readJson(
- req, res, "HostName", hostname, "IPv4StaticAddresses",
- ipv4StaticAddresses, "MACAddress", macAddress,
- "StaticNameServers", staticNameServers, "IPv6DefaultGateway",
- ipv6DefaultGateway, "IPv6StaticAddresses", ipv6StaticAddresses,
- "DHCPv4", dhcpv4, "DHCPv6", dhcpv6, "InterfaceEnabled",
- interfaceEnabled))
+ req, res, "HostName", hostname, "FQDN", fqdn,
+ "IPv4StaticAddresses", ipv4StaticAddresses, "MACAddress",
+ macAddress, "StaticNameServers", staticNameServers,
+ "IPv6DefaultGateway", ipv6DefaultGateway, "IPv6StaticAddresses",
+ ipv6StaticAddresses, "DHCPv4", dhcpv4, "DHCPv6", dhcpv6,
+ "InterfaceEnabled", interfaceEnabled))
{
return;
}
@@ -1879,7 +1970,7 @@ class EthernetInterface : public Node
getEthernetIfaceData(
iface_id,
[this, asyncResp, iface_id, hostname = std::move(hostname),
- macAddress = std::move(macAddress),
+ fqdn = std::move(fqdn), macAddress = std::move(macAddress),
ipv4StaticAddresses = std::move(ipv4StaticAddresses),
ipv6DefaultGateway = std::move(ipv6DefaultGateway),
ipv6StaticAddresses = std::move(ipv6StaticAddresses),
@@ -1912,6 +2003,11 @@ class EthernetInterface : public Node
handleHostnamePatch(*hostname, asyncResp);
}
+ if (fqdn)
+ {
+ handleFqdnPatch(iface_id, *fqdn, asyncResp);
+ }
+
if (macAddress)
{
handleMACAddressPatch(iface_id, *macAddress, asyncResp);