[IOT-1531]PAL API for get link-local zone id from ifindex
authorbg.chun <bg.chun@samsung.com>
Tue, 8 Nov 2016 12:00:56 +0000 (21:00 +0900)
committerAshok Babu Channa <ashok.channa@samsung.com>
Mon, 13 Feb 2017 06:13:54 +0000 (06:13 +0000)
PAL API for get IPv6 link-local zone id from ifindex.
This changes need for mapping zone-id with IPv6 link-local Address
on Endpoint and CAGetNetworkInfo().

Change-Id: Ib5043d3de5747f3e461de775dba2d04e804297dd
Signed-off-by: bg.chun <bg.chun@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/14123
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
16 files changed:
resource/csdk/connectivity/api/cainterface.h
resource/csdk/connectivity/api/cautilinterface.h
resource/csdk/connectivity/inc/caadapterutils.h
resource/csdk/connectivity/inc/caipnwmonitor.h
resource/csdk/connectivity/src/adapter_util/caadapterutils.c
resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/windows/caipnwmonitor.c
resource/csdk/connectivity/test/ca_api_unittest.cpp
resource/csdk/connectivity/util/src/cautilinterface.c
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/octbstack_product.def
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/stacktests.cpp

index 6a4916d..1531ebf 100644 (file)
@@ -250,6 +250,16 @@ CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo);
  */
 CAResult_t CASetProxyUri(const char *uri);
 
+/**
+ * This function return zone id related from ifindex and address.
+ *
+ * @param ifindex[in]     interface index.
+ * @param zoneId[out]     pointer of zoneId string.
+ *
+ * @return  ::CA_STATUS_OK or ::CA_STATUS_INVALID_PARAM
+ */
+CAResult_t CAGetLinkLocalZoneId(uint32_t ifindex, char **zoneId);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index c29d486..4b90ff8 100644 (file)
@@ -224,6 +224,15 @@ CAResult_t CAUtilStopLEAdvertising();
  * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
 CAResult_t CAUtilSetBTConfigure(CAUtilConfig_t config);
+
+/**
+ * return scope level of given ip address.
+ * @param[in]    address  remote address.
+ * @param[out]   scope level of given ip address.
+ * @return      ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAGetIpv6AddrScope(const char *addr, CATransportFlags_t *scopeLevel);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif //__cplusplus
index b3f1f0a..b91581a 100644 (file)
@@ -320,6 +320,14 @@ void CALogAdapterStateInfo(CATransportAdapter_t adapter, CANetworkStatus_t state
  * @param[in]   adapter          transport adapter type.
  */
 void CALogAdapterTypeInfo(CATransportAdapter_t adapter);
+
+/**
+ * return scope level of given ip address.
+ * @param[in]    address    remote address.
+ * @param[out]   scopeLevel scope level of given ip address.
+ * @return      ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAGetIpv6AddrScopeInternal(const char *addr, CATransportFlags_t *scopeLevel);
 #endif
 
 #ifdef __cplusplus
index b5a4e29..f484792 100644 (file)
@@ -126,6 +126,16 @@ CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter);
  */
 void CAProcessNewInterface(CAInterface_t *ifchanged);
 
+/**
+ * This function return link local zone id related from ifindex.
+ *
+ * @param ifindex[in]     interface index.
+ * @param zoneId[out]     pointer of zoneId string, caller should free
+ *                        zoneId using OICFree() when it returned CA_STATUS_OK.
+ * @return  ::CA_STATUS_OK or ::CA_STATUS_INVALID_PARAM
+ */
+CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId);
+
 #ifdef __cplusplus
 }
 #endif
index 37a20bc..8c332f5 100644 (file)
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_IN6ADDR_H
+#include <in6addr.h>
+#endif
 
 #ifdef __JAVA__
 #include <jni.h>
@@ -403,4 +409,48 @@ void CALogAdapterTypeInfo(CATransportAdapter_t adapter)
             break;
     }
 }
+
+CAResult_t CAGetIpv6AddrScopeInternal(const char *addr, CATransportFlags_t *scopeLevel)
+{
+    if (!addr || !scopeLevel)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+    // check addr is ipv6
+    struct in6_addr inAddr6;
+    if (1 == inet_pton(AF_INET6, addr, &inAddr6))
+    {
+        // check addr is multicast
+        if (IN6_IS_ADDR_MULTICAST(&inAddr6))
+        {
+            *scopeLevel = (CATransportFlags_t)(inAddr6.s6_addr[1] & 0xf);
+            return CA_STATUS_OK;
+        }
+        else
+        {
+            // check addr is linklocal or loopback
+            if (IN6_IS_ADDR_LINKLOCAL(&inAddr6) || IN6_IS_ADDR_LOOPBACK(&inAddr6))
+            {
+                *scopeLevel = CA_SCOPE_LINK;
+                return CA_STATUS_OK;
+            }
+            // check addr is sitelocal
+            else if (IN6_IS_ADDR_SITELOCAL(&inAddr6))
+            {
+                *scopeLevel = CA_SCOPE_SITE;
+                return CA_STATUS_OK;
+            }
+            else
+            {
+                *scopeLevel = CA_SCOPE_GLOBAL;
+                return CA_STATUS_OK;
+            }
+        }
+    }
+    else
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed at parse ipv6 address using inet_pton");
+        return CA_STATUS_FAILED;
+    }
+}
 #endif
index 2042826..44965c7 100644 (file)
@@ -515,3 +515,29 @@ Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class)
     OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State");
     CAIPPassNetworkChangesToAdapter(CA_INTERFACE_DOWN);
 }
+
+CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId)
+{
+    if (!zoneId || (*zoneId != NULL))
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    *zoneId = (char *)OICCalloc(IF_NAMESIZE, sizeof(char));
+    if (!(*zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "OICCalloc failed in CAGetLinkLocalZoneIdInternal");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    if (!if_indextoname(ifindex, *zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "if_indextoname failed in CAGetLinkLocalZoneIdInternal");
+        OICFree(*zoneId);
+        *zoneId = NULL;
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Given ifindex is %d parsed zoneId is %s", ifindex, *zoneId);
+    return CA_STATUS_OK;
+}
index afa874c..cde643b 100644 (file)
@@ -1590,3 +1590,8 @@ void CAIPSetErrorHandler(CAIPErrorHandleCallback errorHandleCallback)
 {
     g_ipErrorHandler = errorHandleCallback;
 }
+
+CAResult_t CAGetLinkLocalZoneId(uint32_t ifindex, char **zoneId)
+{
+    return CAGetLinkLocalZoneIdInternal(ifindex, zoneId);
+}
index 26fbef8..d86a854 100644 (file)
@@ -484,3 +484,29 @@ exit:
     u_arraylist_destroy(iflist);
     return NULL;
 }
+
+CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId)
+{
+    if (!zoneId || (*zoneId != NULL))
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    *zoneId = (char *)OICCalloc(IF_NAMESIZE, sizeof(char));
+    if (!(*zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "OICCalloc failed in CAGetLinkLocalZoneIdInternal");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    if (!if_indextoname(ifindex, *zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "if_indextoname failed in CAGetLinkLocalZoneIdInternal");
+        OICFree(*zoneId);
+        *zoneId = NULL;
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Given ifindex is %d parsed zoneId is %s", ifindex, *zoneId);
+    return CA_STATUS_OK;
+}
index 3fb48f6..7f37f78 100644 (file)
@@ -409,3 +409,29 @@ void CAIPConnectionStateChangedCb(connection_type_e type, void* userData)
             break;
     }
 }
+
+CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId)
+{
+    if (!zoneId || (*zoneId != NULL))
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    *zoneId = (char *)OICCalloc(IF_NAMESIZE, sizeof(char));
+    if (!(*zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "OICCalloc failed in CAGetLinkLocalZoneIdInternal");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    if (!if_indextoname(ifindex, *zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "if_indextoname failed in CAGetLinkLocalZoneIdInternal");
+        OICFree(*zoneId);
+        *zoneId = NULL;
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Given ifindex is %d parsed zoneId is %s", ifindex, *zoneId);
+    return CA_STATUS_OK;
+}
index 8f7322c..c0cf28a 100644 (file)
 #define USE_SOCKET_ADDRESS_CHANGE_EVENT
 
 /**
+* Buffer size for PIP_ADAPTER_ADDRESSES
+*/
+#define WORKING_BUFFER_SIZE 15000
+
+/**
  * Mutex for synchronizing access to cached address information.
  */
 static oc_mutex g_CAIPNetworkMonitorMutex = NULL;
@@ -912,3 +917,44 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
 
     return iflist;
 }
+
+CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId)
+{
+    if (!zoneId || (*zoneId != NULL))
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    PIP_ADAPTER_ADDRESSES pAdapters = GetAdapters();
+
+    if (!pAdapters)
+    {
+        OICFree(pAdapters);
+        return CA_STATUS_FAILED;
+    }
+
+    PIP_ADAPTER_ADDRESSES pCurrAdapter = NULL;
+    pCurrAdapter = pAdapters;
+
+    while (pCurrAdapter)
+    {
+        if (ifindex == pCurrAdapter->IfIndex)
+        {
+            OIC_LOG_V(DEBUG, TAG, "Given ifindex is %d parsed zoneId is %d",
+                      ifindex, pCurrAdapter->ZoneIndices[ScopeLevelLink]);
+            *zoneId = (char *)OICCalloc(IF_NAMESIZE, sizeof(char));
+            _ultoa(pCurrAdapter->ZoneIndices[ScopeLevelLink], *zoneId, 10);
+            break;
+        }
+        pCurrAdapter = pCurrAdapter->Next;
+    }
+
+    OICFree(pAdapters);
+
+    if (!*zoneId)
+    {
+        return CA_STATUS_FAILED;
+    }
+
+    return CA_STATUS_OK;
+}
index 791108e..cfbe602 100755 (executable)
@@ -678,3 +678,195 @@ TEST(CAfragmentationTest, DefragmentTest)
     free(data);
 #endif
 }
+
+TEST(Ipv6ScopeLevel, getMulticastScope)
+{
+
+    const char interfaceLocalStart[] = "ff01::";
+    const char linkLocalStart[]      = "ff02::";
+    const char realmLocalStart[]     = "ff03::";
+    const char adminLocalStart[]     = "ff04::";
+    const char siteLocalStart[]      = "ff05::";
+    const char orgLocalStart[]       = "ff08::";
+    const char globalStart[]         = "ff0e::";
+
+    const char interfaceLocalMid[] = "ff81:0000:0000:f000:0000:0000:0000:0000";
+    const char linkLocalMid[]      = "ff82:0000:0000:f000:0000:0000:0000:0000";
+    const char realmLocalMid[]     = "ff83:0000:0000:f000:0000:0000:0000:0000";
+    const char adminLocalMid[]     = "ff84:0000:0000:f000:0000:0000:0000:0000";
+    const char siteLocalMid[]      = "ff85:0000:0000:f000:0000:0000:0000:0000";
+    const char orgLocalMid[]       = "ff88:0000:0000:f000:0000:0000:0000:0000";
+    const char globalMid[]         = "ff8e:0000:0000:f000:0000:0000:0000:0000";
+
+    const char interfaceLocalEnd[] = "fff1:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char linkLocalEnd[]      = "fff2:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char realmLocalEnd[]     = "fff3:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char adminLocalEnd[]     = "fff4:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char siteLocalEnd[]      = "fff5:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char orgLocalEnd[]       = "fff8:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char globalEnd[]         = "fffe:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    // range start
+    CATransportFlags_t scopeLevel = CA_DEFAULT_FLAGS;
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(interfaceLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_INTERFACE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(realmLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_REALM, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(adminLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_ADMIN, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(siteLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_SITE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(orgLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_ORG, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(globalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    // range mid
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(interfaceLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_INTERFACE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(realmLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_REALM, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(adminLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_ADMIN, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(siteLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_SITE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(orgLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_ORG, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(globalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    // range end
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(interfaceLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_INTERFACE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(realmLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_REALM, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(adminLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_ADMIN, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(siteLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_SITE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(orgLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_ORG, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(globalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+}
+
+TEST(Ipv6ScopeLevel, getUnicastScope)
+{
+    const char linkLocalLoopBack[]  = "::1";
+
+    const char linkLocalStart[]     = "fe80::";
+    const char linkLocalMid[]       = "fe80:0000:0000:0000:0f00:0000:0000:0000";
+    const char linkLocalEnd[]       = "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    const char siteLocalStart[]     = "fec0::";
+    const char siteLocalMid[]       = "fec0:0000:0000:0000:0f00:0000:0000:0000";
+    const char siteLocalEnd[]       = "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    const char globalStart[]   = "2000:0000:0000:0000:0000:0000:0000:0000";
+    const char globalMid[]     = "2000:0000:0000:0f00:0000:0000:0000:0000";
+    const char globalEnd[]     = "3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    // loopback
+    CATransportFlags_t scopeLevel = CA_DEFAULT_FLAGS;
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalLoopBack, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    // linklocal
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(linkLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_LINK, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    // sitelocal
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(siteLocalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_SITE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(siteLocalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_SITE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(siteLocalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_SITE, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    // global
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(globalStart, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(globalMid, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+
+    EXPECT_EQ(CA_STATUS_OK, CAGetIpv6AddrScope(globalEnd, &scopeLevel));
+    EXPECT_EQ(CA_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = CA_DEFAULT_FLAGS;
+}
+
+TEST(Ipv6ScopeLevel, invalidAddressTest)
+{
+    const char invalidAddr1[]    = "qqqq";
+    const char invalidAddr2[]    = "ffx7:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char invalidAddr3[]    = "ffx7::::::::::dsds";
+    const char invalidAddr4[]    = "ffx7:ffff:ffff:ff@f:ffff:ffff:ffff:ffff";
+
+    CATransportFlags_t scopeLevel = CA_DEFAULT_FLAGS;
+    EXPECT_EQ(CA_STATUS_FAILED, CAGetIpv6AddrScope(invalidAddr1, &scopeLevel));
+    EXPECT_EQ(CA_STATUS_FAILED, CAGetIpv6AddrScope(invalidAddr2, &scopeLevel));
+    EXPECT_EQ(CA_STATUS_FAILED, CAGetIpv6AddrScope(invalidAddr3, &scopeLevel));
+    EXPECT_EQ(CA_STATUS_FAILED, CAGetIpv6AddrScope(invalidAddr4, &scopeLevel));
+}
\ No newline at end of file
index 2a56b5c..afcf64c 100644 (file)
@@ -349,3 +349,8 @@ CAResult_t CAUtilSetBTConfigure(CAUtilConfig_t config)
     return CA_NOT_SUPPORTED;
 #endif
 }
+
+CAResult_t CAGetIpv6AddrScope(const char *addr, CATransportFlags_t *scopeLevel)
+{
+    return CAGetIpv6AddrScopeInternal(addr, scopeLevel);
+}
index fa8258d..f82ffe5 100644 (file)
@@ -878,6 +878,16 @@ OCStackResult OCGetPropertyValue(OCPayloadType type, const char *propName, void
 */
 OCPersistentStorage *OCGetPersistentStorageHandler();
 
+/**
+* This function return link local zone id related from ifindex.
+*
+* @param ifindex[in]     interface index.
+* @param zoneId[out]     pointer of zoneId string, caller should free
+*                        zoneId using OICFree() when it returned CA_STATUS_OK.
+* @return Returns ::OC_STACK_OK if success.
+*/
+OCStackResult OCGetLinkLocalZoneId(uint32_t ifindex, char **zoneId);
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index ea8cda7..f1a0831 100644 (file)
@@ -57,6 +57,7 @@ OCGetHeaderOption
 OCGetNumberOfResources
 OCGetNumberOfResourceInterfaces
 OCGetNumberOfResourceTypes
+OCGetLinkLocalZoneId
 OCGetPropertyValue
 OCGetResourceHandle
 OCGetResourceHandleAtUri
index bf99983..7744dc2 100644 (file)
@@ -60,6 +60,7 @@
 #include "ocpayload.h"
 #include "ocpayloadcbor.h"
 #include "cautilinterface.h"
+#include "cainterface.h"
 #include "oicgroup.h"
 #include "ocendpoint.h"
 
@@ -5576,3 +5577,8 @@ OCStackResult OCGetDeviceOwnedState(bool *isOwned)
     }
     return ret;
 }
+
+OCStackResult OCGetLinkLocalZoneId(uint32_t ifindex, char **zoneId)
+{
+    return CAResultToOCResult(CAGetLinkLocalZoneId(ifindex, zoneId));
+}
index fac2637..15ecd31 100644 (file)
@@ -2564,3 +2564,28 @@ TEST_F(OCDiscoverTests, DiscoverResourceWithInvalidQueries)
     OC_HIGH_QOS, discoverUnicastRTEmptyCB, NULL, 0));
     discoverUnicastRTEmptyCB.Wait(10);
 }
+
+TEST(StackZoneId, getZoneId)
+{
+    uint32_t tempSize = 0;
+    CAEndpoint_t *tempInfo = NULL;
+    CAGetNetworkInformation(&tempInfo, &tempSize);
+
+    for (uint32_t i = 0; i < tempSize; i++)
+    {
+        char *zoneId = NULL;
+        EXPECT_EQ(OC_STACK_OK, OCGetLinkLocalZoneId(tempInfo[i].ifindex, &zoneId));
+        OICFree(zoneId);
+        zoneId = NULL;
+    }
+
+    OICFree(tempInfo);
+}
+
+TEST(StackZoneId, getZoneIdWithInvalidParams)
+{
+    char *zoneId = NULL;
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, OCGetLinkLocalZoneId(0, NULL));
+    EXPECT_EQ(OC_STACK_ERROR, OCGetLinkLocalZoneId(9999, &zoneId));
+    EXPECT_EQ(OC_STACK_ERROR, OCGetLinkLocalZoneId(-1, &zoneId));
+}