[IOT-3096] Fix for connecting to TCP IPv6 socket 95/26295/7
authorkoushik.girijala <g.koushik@samsung.com>
Tue, 10 Jul 2018 15:02:49 +0000 (20:32 +0530)
committerNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Thu, 26 Jul 2018 14:46:15 +0000 (14:46 +0000)
Change-Id: I90f971ec1f51d7a2b7dd829c3ebd6fbd61f90c77
Signed-off-by: koushik.girijala <g.koushik@samsung.com>
resource/csdk/connectivity/src/tcp_adapter/catcpserver.c
resource/csdk/security/provisioning/src/cloud/cloudresource.c

index 988eaec..b516316 100644 (file)
@@ -570,6 +570,57 @@ static void CASocketEventReturned(CASocketFd_t s, long networkEvents)
 
 #endif // WSA_WAIT_EVENT_0
 
+static CAResult_t CATCPConvertNameToAddr(int family, const char *host, uint16_t port,
+                                         struct sockaddr_storage *sockaddr)
+{
+    VERIFY_NON_NULL_RET(host, TAG, "host is null", CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(sockaddr, TAG, "sockaddr is null", CA_STATUS_INVALID_PARAM);
+
+    struct addrinfo *addrs = NULL;
+    struct addrinfo hints = { .ai_family = family,
+                              .ai_protocol   = IPPROTO_TCP,
+                              .ai_socktype = SOCK_STREAM,
+                              .ai_flags = AI_NUMERICHOST };
+
+    int r = getaddrinfo(host, NULL, &hints, &addrs);
+    if (r)
+    {
+        if (NULL != addrs)
+        {
+            freeaddrinfo(addrs);
+        }
+#if defined(EAI_SYSTEM)
+        if (EAI_SYSTEM == r)
+        {
+            OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: errno %s", strerror(errno));
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: %s", gai_strerror(r));
+        }
+#elif defined(_WIN32)
+        OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: errno %i", WSAGetLastError());
+#else
+        OIC_LOG_V(ERROR, TAG, "getaddrinfo failed: %s", gai_strerror(r));
+#endif
+        return CA_STATUS_FAILED;
+    }
+    // assumption: in this case, getaddrinfo will only return one addrinfo
+    // or first is the one we want.
+    if (addrs[0].ai_family == AF_INET6)
+    {
+        memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
+        ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
+    }
+    else
+    {
+        memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
+        ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
+    }
+    freeaddrinfo(addrs);
+    return CA_STATUS_OK;
+}
+
 static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock)
 {
     VERIFY_NON_NULL_VOID(sock, TAG, "sock is NULL");
@@ -895,8 +946,8 @@ static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem)
 
     // #2. convert address from string to binary.
     struct sockaddr_storage sa = { .ss_family = (short)family };
-    CAResult_t res = CAConvertNameToAddr(svritem->sep.endpoint.addr,
-                                         svritem->sep.endpoint.port, &sa);
+    CAResult_t res = CATCPConvertNameToAddr(family, svritem->sep.endpoint.addr,
+                                            svritem->sep.endpoint.port, &sa);
     if (CA_STATUS_OK != res)
     {
         OIC_LOG(ERROR, TAG, "convert name to sockaddr failed");
@@ -907,6 +958,11 @@ static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem)
     socklen_t socklen = 0;
     if (sa.ss_family == AF_INET6)
     {
+        struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sa;
+        if (!sock6->sin6_scope_id)
+        {
+            sock6->sin6_scope_id = svritem->sep.endpoint.ifindex;
+        }
         socklen = sizeof(struct sockaddr_in6);
     }
     else
index c35935c..cc6ec87 100644 (file)
@@ -38,6 +38,7 @@
 #include "resourcemanager.h"
 #include "cloud/cloudresource.h"
 #include "cloud/auth.h"
+#include "oic_string.h"
 
 #define TAG  "OIC_CLOUD_RESOURCE"
 
@@ -168,6 +169,9 @@ static OCEntityHandlerResult HandleCloudPostRequest(OCEntityHandlerRequest *ehRe
     OCRepPayload *payload = NULL;
     bool isDeviceOwned = false;
     OicCloud_t *xCloud = NULL;
+    char *ipv6End = NULL;
+    char *percentChar = NULL;
+    char *cis = NULL;
 
     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
     VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
@@ -222,6 +226,27 @@ static OCEntityHandlerResult HandleCloudPostRequest(OCEntityHandlerRequest *ehRe
         goto exit;
     }
 
+    // find the IPv6 address end bracket
+    ipv6End = strchr(newCloud->cis, ']');
+    if (NULL != ipv6End)
+    {
+        // find the interface name from UDP address of sender
+        percentChar = strchr(ehRequest->devAddr.addr, '%');
+        size_t ifLen = strlen(percentChar);
+        size_t addrLen = strlen(newCloud->cis);
+        size_t cisLen = addrLen + ifLen + 3;
+
+        // fill the cloud uri with interface name inserted
+        cis = (char *)OICMalloc(sizeof(char) * cisLen);
+        OICStrcpy(cis, ipv6End - newCloud->cis + 1, newCloud->cis);
+        OICStrcat(cis, cisLen, "%25");
+        OICStrcat(cis, cisLen, percentChar + 1);
+        OICStrcat(cis, cisLen, ipv6End);
+
+        OICFree(newCloud->cis);
+        newCloud->cis = cis;
+    }
+
     xCloud = CloudFind(gCloud, newCloud);
     if (xCloud)
     {