From 6493723651bbff959443709767123942ecc2d8a4 Mon Sep 17 00:00:00 2001 From: "jw0213.jung" Date: Fri, 11 Dec 2015 15:58:35 +0900 Subject: [PATCH] MAC address parsing in constructResourceObject() When call the function constructResourceObject(..), the first parameter is a string for a host address of the server. The string could be a IPv4 form or IPv6 or MAC. But there is no parsing logic for MAC address form(xx:xx:xx:xx:xx:xx). Without this, MAC is parsed as IPv4 which does not work properly. (the first block as IP address, the second one is port number, and lasts are ignored) So I added the MAC parsing logic with checking a validity of address. Change-Id: I2fc5a14b400605c9255173bbddc2ff7a4bae0551 Signed-off-by: Jaewook Jung Reviewed-on: https://gerrit.iotivity.org/gerrit/5593 Tested-by: jenkins-iotivity Reviewed-by: Jon A. Cruz (cherry picked from commit 613c5281e662dd8f693477fa001f9f5500fa8f2f) Reviewed-on: https://gerrit.iotivity.org/gerrit/4521 --- resource/csdk/stack/include/octypes.h | 10 ++- resource/src/OCResource.cpp | 133 +++++++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 38 deletions(-) diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index e1758a5..e1ee26c 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -278,10 +278,16 @@ extern "C" { #ifdef RA_ADAPTER #define MAX_ADDR_STR_SIZE (256) #else -/** Max Address could be "coaps://[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:xxxxx */ -#define MAX_ADDR_STR_SIZE (56) +/** Max Address could be "coap+tcp://[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:xxxxx" */ +#define MAX_ADDR_STR_SIZE (59) #endif +/** Length of MAC address */ +#define MAC_ADDR_STR_SIZE (17) + +/** Blocks of MAC address */ +#define MAC_ADDR_BLOCKS (6) + /** Max identity size. */ #define MAX_IDENTITY_SIZE (32) diff --git a/resource/src/OCResource.cpp b/resource/src/OCResource.cpp index 9dd6b46..a3c8ec8 100644 --- a/resource/src/OCResource.cpp +++ b/resource/src/OCResource.cpp @@ -23,6 +23,7 @@ #include #include +#include namespace OC { @@ -133,66 +134,126 @@ void OCResource::setHost(const std::string& host) m_interfaces.empty(), m_clientWrapper.expired(), false, false); } - // removed coap:// or coaps:// or coap+tcp:// + // remove 'coap://' or 'coaps://' or 'coap+tcp://' std::string host_token = host.substr(prefix_len); - if(host_token[0] == '[') + if(host_token[0] == '[') // IPv6 { - m_devAddr.flags = static_cast(m_devAddr.flags & OC_IP_USE_V6); - - size_t found = host_token.find(']'); + size_t bracket = host_token.find(']'); - if(found == std::string::npos || found == 0) + if(bracket == std::string::npos || bracket == 0) { throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), m_interfaces.empty(), m_clientWrapper.expired(), false, false); } - // extract the ipaddress - std::string ip6Addr = host_token.substr(1, found-1); + // extract the ipv6 address + std::string ip6Addr = host_token.substr(1, bracket - 1); - if (ip6Addr.length() >= MAX_ADDR_STR_SIZE) + // address validity check + struct in6_addr buf; + const char *cAddr = ip6Addr.c_str(); + if(0 == inet_pton(AF_INET6, cAddr, &buf)) { - throw std::length_error("host address is too long."); + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); } - ip6Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr)); - m_devAddr.addr[ip6Addr.length()] = '\0'; //skip ']' and ':' characters in host string - host_token = host_token.substr(found + 2); - } - else - { - size_t found = host_token.find(':'); + host_token = host_token.substr(bracket + 2); + int port = std::stoi(host_token); - if(found == std::string::npos || found == 0) + if (0 > port || UINT16_MAX < port) { throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), m_interfaces.empty(), m_clientWrapper.expired(), false, false); } - std::string addrPart = host_token.substr(0, found); - - if (addrPart.length() >= MAX_ADDR_STR_SIZE) - { - throw std::length_error("host address is too long."); - } - - addrPart.copy(m_devAddr.addr, sizeof(m_devAddr.addr)); - m_devAddr.addr[addrPart.length()] = '\0'; - //skip ':' character in host string - host_token = host_token.substr(found + 1); + ip6Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr)); + m_devAddr.addr[ip6Addr.length()] = '\0'; + m_devAddr.port = static_cast(port); + m_devAddr.flags = static_cast(m_devAddr.flags & OC_IP_USE_V6); } - - int port = std::stoi(host_token); - - if( port < 0 || port > UINT16_MAX ) + else if (host_token[0] == ':') { throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), m_interfaces.empty(), m_clientWrapper.expired(), false, false); } - - m_devAddr.port = static_cast(port); - + else + { + size_t dot = host_token.find('.'); + if (std::string::npos == dot) // MAC + { + std::string macAddr = host_token; + + // address validity check + if (MAC_ADDR_STR_SIZE != macAddr.length()) + { + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); + } + + for (size_t blockCnt = 0; blockCnt < MAC_ADDR_BLOCKS; blockCnt++) + { + std::string block = macAddr.substr(blockCnt * 3, 2); + + if (std::string::npos != block.find_first_not_of("0123456789ABCDEFabcdef")) + { + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); + } + + if (MAC_ADDR_BLOCKS - 1 > blockCnt) + { + char delimiter = macAddr[blockCnt * 3 + 2]; + + if (':' != delimiter) + { + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); + } + } + } + + macAddr.copy(m_devAddr.addr, sizeof(m_devAddr.addr)); + m_devAddr.addr[MAC_ADDR_STR_SIZE] = '\0'; + } + else // IPv4 + { + size_t colon = host_token.find(':'); + + if (colon == std::string::npos || colon == 0) + { + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); + } + + // extract the ipv4 address + std::string ip4Addr = host_token.substr(0, colon); + + // address validity check + struct in_addr buf; + const char *cAddr = ip4Addr.c_str(); + if(0 == inet_pton(AF_INET, cAddr, &buf)) + { + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); + } + + //skip ':' characters in host string + host_token = host_token.substr(colon + 1); + int port = std::stoi(host_token); + + if (0 > port || UINT16_MAX < port) + { + throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(), + m_interfaces.empty(), m_clientWrapper.expired(), false, false); + } + + ip4Addr.copy(m_devAddr.addr, sizeof(m_devAddr.addr)); + m_devAddr.addr[ip4Addr.length()] = '\0'; + m_devAddr.port = static_cast(port); + } + } } OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap, -- 2.7.4