From 50c5848e2bf0ba767f47d986d914dd4a70bc154d Mon Sep 17 00:00:00 2001 From: juanlofer-eprosima <88179026+juanlofer-eprosima@users.noreply.github.com> Date: Fri, 29 Nov 2024 08:22:34 +0100 Subject: [PATCH] Allow domain names (DNS) when parsing TCP locators XML elements (#5429) * Refs #21506. Add regression tests Signed-off-by: Juan Lopez Fernandez * Refs #21506. Attempt DNS resolution when setting locator's IP Signed-off-by: Juan Lopez Fernandez * Refs #21506. Fix failing tests and apply suggestions Signed-off-by: Juan Lopez Fernandez * Refs #21506. Apply more suggestions Signed-off-by: Juan Lopez Fernandez --------- Signed-off-by: Juan Lopez Fernandez --- src/cpp/utils/IPLocator.cpp | 116 +++++-- src/cpp/xmlparser/XMLElementParser.cpp | 56 ++-- test/unittest/utils/LocatorTests.cpp | 6 +- test/unittest/xmlparser/CMakeLists.txt | 6 +- .../xmlparser/XMLElementParserTests.cpp | 284 ++++++++++++++++++ 5 files changed, 408 insertions(+), 60 deletions(-) diff --git a/src/cpp/utils/IPLocator.cpp b/src/cpp/utils/IPLocator.cpp index 1ac641efdb2..e5143e78573 100644 --- a/src/cpp/utils/IPLocator.cpp +++ b/src/cpp/utils/IPLocator.cpp @@ -29,8 +29,8 @@ namespace eprosima { namespace fastdds { namespace rtps { -static const std::regex IPv4_REGEX("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}" - "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); +static const std::regex IPv4_REGEX("^(?:(?:0*25[0-5]|0*2[0-4][0-9]|0*[01]?[0-9][0-9]?)\\.){3}" + "(?:0*25[0-5]|0*2[0-4][0-9]|0*[01]?[0-9][0-9]?)$"); static const std::regex IPv6_QUARTET_REGEX("^(?:[A-Fa-f0-9]){0,4}$"); // Factory @@ -106,7 +106,31 @@ bool IPLocator::setIPv4( // This function do not set address to 0 in case it fails // Be careful, do not set all IP to 0 because WAN and LAN could be set beforehand - std::stringstream ss(ipv4); + std::string s(ipv4); + if (!IPLocator::isIPv4(s)) + { + // Attempt DNS resolution + auto response = IPLocator::resolveNameDNS(s); + + // Use the first valid IPv4 address that we can find + if (response.first.size() > 0) + { + s = response.first.begin()->data(); + // Redundant check for extra security (here a custom regex is used instead of asio's verification) + if (!IPLocator::isIPv4(s)) + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, "DNS name [" << ipv4 << "] resolved into wrong IPv4 format: " << s); + return false; + } + } + else + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name"); + return false; + } + } + + std::stringstream ss(s); uint32_t a; uint32_t b; uint32_t c; @@ -127,7 +151,7 @@ bool IPLocator::setIPv4( // If there are more info to read, it fails return ss.rdbuf()->in_avail() == 0; } - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << ipv4 << " error format. Expected X.X.X.X"); + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name"); return false; } @@ -254,14 +278,33 @@ bool IPLocator::setIPv6( return false; } - if (!IPv6isCorrect(ipv6)) + std::string s(ipv6); + if (!IPLocator::isIPv6(s)) { - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << ipv6 << " is not well defined"); - return false; + // Attempt DNS resolution + auto response = IPLocator::resolveNameDNS(s); + + // Use the first valid IPv6 address that we can find + if (response.second.size() > 0) + { + s = response.second.begin()->data(); + // Redundant check for extra security (here a custom regex is used instead of asio's verification) + if (!IPLocator::isIPv6(s)) + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, "DNS name [" << ipv6 << "] resolved into wrong IPv6 format: " << s); + return false; + } + } + else + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, + "IPv6 " << s << " error format. Expected well defined address or valid DNS name"); + return false; + } } LOCATOR_ADDRESS_INVALID(locator.address); - uint16_t count = (uint16_t) std::count_if( ipv6.begin(), ipv6.end(), []( char c ) + uint16_t count = (uint16_t) std::count_if( s.begin(), s.end(), []( char c ) { return c == ':'; }); // C type cast to avoid Windows warnings @@ -274,10 +317,10 @@ bool IPLocator::setIPv6( size_t aux_prev; // This must be size_t as string::npos could change value depending on size_t size // Check whether is a zero block and where - if (ipv6.front() == ':') + if (s.front() == ':') { // First element equal : -> starts with zeros - if (ipv6.back() == ':') + if (s.back() == ':') { // Empty string (correct ipv6 format) initial_zeros = 16; @@ -291,7 +334,7 @@ bool IPLocator::setIPv6( initial_zeros = (7 - (count - 2)) * 2; } } - else if (ipv6.back() == ':') + else if (s.back() == ':') { // Last element equal : -> ends with zeros // It does not start with :: (previous if) @@ -300,8 +343,8 @@ bool IPLocator::setIPv6( else { // It does not starts or ends with zeros, but it could have :: in the middle or not have it - aux_prev = ipv6.size(); // Aux could be 1 so this number must be unreacheable - aux = ipv6.find(':'); // Index of first ':' + aux_prev = s.size(); // Aux could be 1 so this number must be unreacheable + aux = s.find(':'); // Index of first ':' // Look for "::" will loop string twice // Therefore, we use this loop that will go over less or equal once @@ -317,13 +360,13 @@ bool IPLocator::setIPv6( // Not "::" found, keep searching in next ':' position_zeros += 2; // It stores the point where the 0 block is aux_prev = aux; - aux = ipv6.find(':', aux + 1); + aux = s.find(':', aux + 1); } } char punct; std::stringstream ss; - ss << std::hex << ipv6; + ss << std::hex << s; uint16_t i; uint32_t input_aux; // It cannot be uint16_t or we could not find whether the input number is bigger than allowed @@ -343,7 +386,7 @@ bool IPLocator::setIPv6( ss >> punct >> input_aux; if (input_aux >= 65536) { - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << ipv6 << " has values higher than expected (65536)"); + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)"); return false; } locator.address[i++] = octet(input_aux >> 8); @@ -364,7 +407,7 @@ bool IPLocator::setIPv6( ss >> input_aux >> punct; if (input_aux >= 65536) { - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << ipv6 << " has values higher than expected (65536)"); + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)"); return false; } locator.address[i++] = octet(input_aux >> 8); @@ -386,7 +429,7 @@ bool IPLocator::setIPv6( ss >> input_aux >> punct; if (input_aux >= 65536) { - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << ipv6 << " has values higher than expected (65536)"); + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)"); return false; } locator.address[i++] = octet(input_aux >> 8); @@ -403,7 +446,7 @@ bool IPLocator::setIPv6( ss >> punct >> input_aux; if (input_aux >= 65536) { - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << ipv6 << " has values higher than expected (65536)"); + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)"); return false; } locator.address[i++] = octet(input_aux >> 8); @@ -421,7 +464,7 @@ bool IPLocator::setIPv6( ss >> punct >> input_aux; if (input_aux >= 65536) { - EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << ipv6 << " has values higher than expected (65536)"); + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)"); return false; } locator.address[i++] = octet(input_aux >> 8); @@ -671,7 +714,37 @@ bool IPLocator::setWan( Locator_t& locator, const std::string& wan) { - std::stringstream ss(wan); + if (locator.kind != LOCATOR_KIND_TCPv4) + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set WAN address in a non TCP-IPv4 Locator"); + return false; + } + + std::string s(wan); + if (!IPLocator::isIPv4(s)) + { + // Attempt DNS resolution + auto response = IPLocator::resolveNameDNS(s); + + // Use the first valid IPv4 address that we can find + if (response.first.size() > 0) + { + s = response.first.begin()->data(); + // Redundant check for extra security (here a custom regex is used instead of asio's verification) + if (!IPLocator::isIPv4(s)) + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, "DNS name [" << wan << "] resolved into wrong IPv4 format: " << s); + return false; + } + } + else + { + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name"); + return false; + } + } + + std::stringstream ss(s); int a, b, c, d; //to store the 4 ints char ch; //to temporarily store the '.' @@ -683,6 +756,7 @@ bool IPLocator::setWan( locator.address[11] = (octet)d; return true; } + EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name"); return false; } diff --git a/src/cpp/xmlparser/XMLElementParser.cpp b/src/cpp/xmlparser/XMLElementParser.cpp index c9de39f3970..3f49d0741a1 100644 --- a/src/cpp/xmlparser/XMLElementParser.cpp +++ b/src/cpp/xmlparser/XMLElementParser.cpp @@ -3069,24 +3069,11 @@ XMLP_ret XMLParser::getXMLLocatorUDPv4( { return XMLP_ret::XML_ERROR; } - // Check whether the address is IPv4 - if (!IPLocator::isIPv4(s)) + if (!IPLocator::setIPv4(locator, s)) { - auto response = rtps::IPLocator::resolveNameDNS(s); - - // Add the first valid IPv4 address that we can find - if (response.first.size() > 0) - { - s = response.first.begin()->data(); - } - else - { - EPROSIMA_LOG_ERROR(XMLPARSER, - "DNS server did not return any IPv4 address for: '" << s << "'. Name: " << name); - return XMLP_ret::XML_ERROR; - } + EPROSIMA_LOG_ERROR(XMLPARSER, "Failed to parse UDPv4 locator's " << ADDRESS << " tag"); + return XMLP_ret::XML_ERROR; } - IPLocator::setIPv4(locator, s); } else { @@ -3142,24 +3129,11 @@ XMLP_ret XMLParser::getXMLLocatorUDPv6( { return XMLP_ret::XML_ERROR; } - // Check whether the address is IPv6 - if (!IPLocator::isIPv6(s)) + if (!IPLocator::setIPv6(locator, s)) { - auto response = rtps::IPLocator::resolveNameDNS(s); - - // Add the first valid IPv6 address that we can find - if (response.second.size() > 0) - { - s = response.second.begin()->data(); - } - else - { - EPROSIMA_LOG_ERROR(XMLPARSER, - "DNS server did not return any IPv6 address for: '" << s << "'. Name: " << name); - return XMLP_ret::XML_ERROR; - } + EPROSIMA_LOG_ERROR(XMLPARSER, "Failed to parse UDPv6 locator's " << ADDRESS << " tag"); + return XMLP_ret::XML_ERROR; } - IPLocator::setIPv6(locator, s); } else { @@ -3230,7 +3204,11 @@ XMLP_ret XMLParser::getXMLLocatorTCPv4( { return XMLP_ret::XML_ERROR; } - IPLocator::setIPv4(locator, s); + if (!IPLocator::setIPv4(locator, s)) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "Failed to parse TCPv4 locator's " << ADDRESS << " tag"); + return XMLP_ret::XML_ERROR; + } } else if (strcmp(name, WAN_ADDRESS) == 0) { @@ -3240,7 +3218,11 @@ XMLP_ret XMLParser::getXMLLocatorTCPv4( { return XMLP_ret::XML_ERROR; } - IPLocator::setWan(locator, s); + if (!IPLocator::setWan(locator, s)) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "Failed to parse TCPv4 locator's " << WAN_ADDRESS << " tag"); + return XMLP_ret::XML_ERROR; + } } else if (strcmp(name, UNIQUE_LAN_ID) == 0) { @@ -3319,7 +3301,11 @@ XMLP_ret XMLParser::getXMLLocatorTCPv6( { return XMLP_ret::XML_ERROR; } - IPLocator::setIPv6(locator, s); + if (!IPLocator::setIPv6(locator, s)) + { + EPROSIMA_LOG_ERROR(XMLPARSER, "Failed to parse TCPv6 locator's " << ADDRESS << " tag"); + return XMLP_ret::XML_ERROR; + } } else { diff --git a/test/unittest/utils/LocatorTests.cpp b/test/unittest/utils/LocatorTests.cpp index 44425d18684..a4e3958cf94 100644 --- a/test/unittest/utils/LocatorTests.cpp +++ b/test/unittest/utils/LocatorTests.cpp @@ -76,6 +76,7 @@ class IPLocatorTests : public ::testing::Test const std::string ipv4_any = "0.0.0.0"; const std::string ipv4_invalid = "0.0.0.0"; + const std::string ipv4_invalid_format = "192.168.1.256.1"; const std::string ipv6_any = "::"; const std::string ipv6_invalid = "0:0:0:0:0:0:0:0"; @@ -161,7 +162,6 @@ TEST_F(IPLocatorTests, setIPv4_from_string) { // Error cases ASSERT_FALSE(IPLocator::setIPv4(locator, "1.1.1.256")); // Too high number - ASSERT_FALSE(IPLocator::setIPv4(locator, "1.1.1")); // Too few args ASSERT_FALSE(IPLocator::setIPv4(locator, "1.1.1.1.1")); // Too much args // Change to IPv6 @@ -1318,8 +1318,8 @@ TEST_F(IPLocatorTests, setIPv4address) } ASSERT_FALSE(IPLocator::setIPv4address(locator, "1.2.3.4.5.6.7", "9.10.11.12", "13.14.15.16")); - ASSERT_FALSE(IPLocator::setIPv4address(locator, "1.2.3.4.5.6.7.8", "9.10.11", "13.14.15.16")); - ASSERT_FALSE(IPLocator::setIPv4address(locator, "1.2.3.4.5.6.7.8", "9.10.11.12", "13.14.15")); + ASSERT_FALSE(IPLocator::setIPv4address(locator, "1.2.3.4.5.6.7.8", ipv4_invalid_format, "13.14.15.16")); + ASSERT_FALSE(IPLocator::setIPv4address(locator, "1.2.3.4.5.6.7.8", "9.10.11.12", ipv4_invalid_format)); locator.kind = LOCATOR_KIND_TCPv6; ASSERT_FALSE(IPLocator::setIPv4address(locator, "1.2.3.4.5.6.7.8", "9.10.11.12", "13.14.15.16")); diff --git a/test/unittest/xmlparser/CMakeLists.txt b/test/unittest/xmlparser/CMakeLists.txt index 478239642db..0eea2c8b4a8 100644 --- a/test/unittest/xmlparser/CMakeLists.txt +++ b/test/unittest/xmlparser/CMakeLists.txt @@ -254,7 +254,11 @@ target_link_libraries(XMLParserTests if(QNX) target_link_libraries(XMLParserTests socket) endif() -gtest_discover_tests(XMLParserTests) +if(EPROSIMA_TEST_DNS_NOT_SET_UP) + message(STATUS "Ignoring 'getXMLLocatorDNS*'") + set(IGNORE_COMMAND "-getXMLLocatorDNS*") +endif() +gtest_discover_tests(XMLParserTests TEST_FILTER ${IGNORE_COMMAND}) ###################################### XMLParserTests ######################################################## ####################################### XMLTreeTests ######################################################### diff --git a/test/unittest/xmlparser/XMLElementParserTests.cpp b/test/unittest/xmlparser/XMLElementParserTests.cpp index 445ca94562a..4f5643b06b0 100644 --- a/test/unittest/xmlparser/XMLElementParserTests.cpp +++ b/test/unittest/xmlparser/XMLElementParserTests.cpp @@ -307,6 +307,116 @@ TEST_F(XMLParserTests, get_xml_disable_heartbeat_piggyback) XMLParserTest::getXMLWriterQosPolicies_wrapper(titleElement, writer_qos, ident)); } +/* + * This test checks the parsing of a element from a list of locators. + * 1. Correct parsing of a valid element. + * 2. Check an empty definition of . + * 3. Check an empty definition of
. + * 4. Check an bad element as a child xml element. + */ +TEST_F(XMLParserTests, getXMLLocatorUDPv4) +{ + + uint8_t ident = 1; + LocatorList_t list; + tinyxml2::XMLDocument xml_doc; + tinyxml2::XMLElement* titleElement; + + // Parametrized XML + const char* xml_p = + "\ + \ + \ + \ + %s\ +
%s
\ + %s\ +
\ +
\ +
\ + "; + constexpr size_t xml_len {500}; + char xml[xml_len]; + + // Valid XML + snprintf(xml, xml_len, xml_p, "8844", "192.168.1.55", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + EXPECT_EQ(list.begin()->port, 8844u); + EXPECT_EQ(list.begin()->address[12], 192); + EXPECT_EQ(list.begin()->address[13], 168); + EXPECT_EQ(list.begin()->address[14], 1); + EXPECT_EQ(list.begin()->address[15], 55); + EXPECT_EQ(list.begin()->kind, LOCATOR_KIND_UDPv4); + + // Missing data - port + snprintf(xml, xml_len, xml_p, "", "192.168.1.55", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + + // Missing data - address + snprintf(xml, xml_len, xml_p, "8844", "", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + + // Invalid element + snprintf(xml, xml_len, xml_p, "8844", "192.168.1.55", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); +} + +/* + * This test checks the parsing of a element from a list of locators, using DNS resolution. + * 1. Correct parsing of a valid element (with address given by domain). + * 2. Check parsing an element with invalid domain name as address fails. + */ +TEST_F(XMLParserTests, getXMLLocatorDNSUDPv4) +{ + + uint8_t ident = 1; + LocatorList_t list; + tinyxml2::XMLDocument xml_doc; + tinyxml2::XMLElement* titleElement; + + // Parametrized XML + const char* xml_p = + "\ + \ + \ + \ + %s\ +
%s
\ + %s\ +
\ +
\ +
\ + "; + constexpr size_t xml_len {500}; + char xml[xml_len]; + + // Valid XML + snprintf(xml, xml_len, xml_p, "8844", "www.acme.com.test", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + EXPECT_EQ(list.begin()->port, 8844u); + EXPECT_EQ(list.begin()->address[12], 216); + EXPECT_EQ(list.begin()->address[13], 58); + EXPECT_EQ(list.begin()->address[14], 215); + EXPECT_EQ(list.begin()->address[15], 164); + EXPECT_EQ(list.begin()->kind, LOCATOR_KIND_UDPv4); + + // Invalid domain name address + snprintf(xml, xml_len, xml_p, "8844", "hopefully.invalid.domain.name", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); +} + /* * This test checks the parsing of a element from a list of locators. * 1. Correct parsing of a valid element. @@ -366,6 +476,51 @@ TEST_F(XMLParserTests, getXMLLocatorUDPv6) EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); } +/* + * This test checks the parsing of a element from a list of locators, using DNS resolution. + * 1. Correct parsing of a valid element (with address given by domain). + * 2. Check parsing an element with invalid domain name as address fails. + */ +TEST_F(XMLParserTests, getXMLLocatorDNSUDPv6) +{ + + uint8_t ident = 1; + LocatorList_t list; + tinyxml2::XMLDocument xml_doc; + tinyxml2::XMLElement* titleElement; + + // Parametrized XML + const char* xml_p = + "\ + \ + \ + \ + %s\ +
%s
\ + %s\ +
\ +
\ +
\ + "; + constexpr size_t xml_len {500}; + char xml[xml_len]; + + // Valid XML + snprintf(xml, xml_len, xml_p, "8844", "www.acme.com.test", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + Locator_t expected_locator; + IPLocator::createLocator(LOCATOR_KIND_UDPv6, "2a00:1450:400e:803::2004", 8844, expected_locator); + EXPECT_EQ(*list.begin(), expected_locator); + + // Invalid domain name address + snprintf(xml, xml_len, xml_p, "8844", "hopefully.invalid.domain.name", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); +} + /* * This test checks the parsing of a element from a list of locators. * 1. Correct parsing of a valid element. @@ -473,6 +628,86 @@ TEST_F(XMLParserTests, getXMLLocatorTCPv4) EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); } +/* + * This test checks the parsing of a element from a list of locators, using DNS resolution. + * 1. Correct parsing of a valid element (with addresses given by domain). + * 2. Check parsing an element with invalid domain name as wan address fails. + * 3. Check parsing an element with invalid domain name as address fails. + */ +TEST_F(XMLParserTests, getXMLLocatorDNSTCPv4) +{ + + uint8_t ident = 1; + LocatorList_t list; + tinyxml2::XMLDocument xml_doc; + tinyxml2::XMLElement* titleElement; + + // Parametrized XML + const char* xml_p = + "\ + \ + \ + \ + %s\ + %s\ + %s\ + %s\ +
%s
\ + %s\ +
\ +
\ +
\ + "; + constexpr size_t xml_len {1000}; + char xml[xml_len]; + + // Valid XML + snprintf(xml, xml_len, xml_p, "5100", "8844", "192.168.1.1.1.1.2.55", "www.acme.com.test", "localhost", ""); + + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + EXPECT_EQ(IPLocator::getPhysicalPort(list.begin()->port), 5100u); + EXPECT_EQ(IPLocator::getLogicalPort(list.begin()->port), 8844u); + + // + EXPECT_EQ(list.begin()->address[0], 192); + EXPECT_EQ(list.begin()->address[1], 168); + EXPECT_EQ(list.begin()->address[2], 1); + EXPECT_EQ(list.begin()->address[3], 1); + EXPECT_EQ(list.begin()->address[4], 1); + EXPECT_EQ(list.begin()->address[5], 1); + EXPECT_EQ(list.begin()->address[6], 2); + EXPECT_EQ(list.begin()->address[7], 55); + + // + EXPECT_EQ(list.begin()->address[8], 216); + EXPECT_EQ(list.begin()->address[9], 58); + EXPECT_EQ(list.begin()->address[10], 215); + EXPECT_EQ(list.begin()->address[11], 164); + + //
+ EXPECT_EQ(list.begin()->address[12], 127); + EXPECT_EQ(list.begin()->address[13], 0); + EXPECT_EQ(list.begin()->address[14], 0); + EXPECT_EQ(list.begin()->address[15], 1); + EXPECT_EQ(list.begin()->kind, LOCATOR_KIND_TCPv4); + + // Invalid domain name wan address + snprintf(xml, xml_len, xml_p, "5100", "8844", "192.168.1.1.1.1.2.55", "hopefully.invalid.domain.name", "localhost", + ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + + // Invalid domain name address + snprintf(xml, xml_len, xml_p, "5100", "8844", "192.168.1.1.1.1.2.55", "www.acme.com.test", + "hopefully.invalid.domain.name", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); +} + /* * This test checks the parsing of a element from a list of locators. * 1. Correct parsing of a valid element. @@ -542,6 +777,55 @@ TEST_F(XMLParserTests, getXMLLocatorTCPv6) EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); } +/* + * This test checks the parsing of a element from a list of locators, using DNS resolution. + * 1. Correct parsing of a valid element (with address given by domain). + * 2. Check parsing an element with invalid domain name as address fails. + */ +TEST_F(XMLParserTests, getXMLLocatorDNSTCPv6) +{ + + uint8_t ident = 1; + LocatorList_t list; + tinyxml2::XMLDocument xml_doc; + tinyxml2::XMLElement* titleElement; + + // Parametrized XML + const char* xml_p = + "\ + \ + \ + \ + %s\ + %s\ +
%s
\ + %s\ +
\ +
\ +
\ + "; + constexpr size_t xml_len {500}; + char xml[xml_len]; + + // Valid XML + snprintf(xml, xml_len, xml_p, "5100", "8844", "www.acme.com.test", ""); + + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); + Locator_t expected_locator; + IPLocator::createLocator(LOCATOR_KIND_TCPv6, "2a00:1450:400e:803::2004", 0, expected_locator); + IPLocator::setPhysicalPort(expected_locator, 5100u); + IPLocator::setLogicalPort(expected_locator, 8844u); + EXPECT_EQ(*list.begin(), expected_locator); + + // Invalid domain name address + snprintf(xml, xml_len, xml_p, "5100", "8844", "hopefully.invalid.domain.name", ""); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_ERROR, XMLParserTest::getXMLLocatorList_wrapper(titleElement, list, ident)); +} + /* * This test checks the proper parsing of the xml elements to in a vector of pointers to * TransportDescriptorInterface, and negative cases.