TCP Socket Bind API 99/216599/3
authorKush <kush.agrawal@samsung.com>
Mon, 14 Oct 2019 15:32:34 +0000 (21:02 +0530)
committerPyun DoHyun <dh79.pyun@samsung.com>
Wed, 30 Oct 2019 00:55:59 +0000 (00:55 +0000)
https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/593
https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/588/commits/1f7cb27e719bfd876fd0ff900747eeb3d7210d46
(cherry-picked from 1f7cb27e719bfd876fd0ff900747eeb3d7210d46)

Change-Id: I48954a2caa59d95464a29a257c67b38325b64d12
Signed-off-by: Kush <kush.agrawal@samsung.com>
Signed-off-by: Sudipto <sudipto.bal@samsung.com>
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/api/cautilinterface.h [changed mode: 0644->0755]
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c [changed mode: 0644->0755]
resource/csdk/connectivity/src/tcp_adapter/catcpserver.c [changed mode: 0644->0755]

index c0593e0..002794c 100755 (executable)
@@ -98,6 +98,11 @@ extern "C"
 #define CA_MAX_TOKEN_LEN (8)
 
 /**
+* Max interface name length.
+*/
+#define CA_MAX_INTERFACE_NAME_LEN (16)
+
+/**
  * Max URI length.
  */
 #ifdef ARDUINO
@@ -651,6 +656,7 @@ typedef struct
         int connectionFds[2];   /**< connection pipe */
         bool started;           /**< the TCP adapter has started */
         bool terminate;         /**< the TCP adapter needs to stop */
+        bool bindenabled;       /**< binding of TCP socket enabled */
         bool ipv4tcpenabled;    /**< IPv4 TCP enabled by OCInit flags */
         bool ipv6tcpenabled;    /**< IPv6 TCP enabled by OCInit flags */
     } tcp;
old mode 100644 (file)
new mode 100755 (executable)
index af1f3b0..59e0315
@@ -482,6 +482,18 @@ CAResult_t CAUnSetTCPKeepAlive(const CAEndpoint_t *endpoint);
  * @return             - Direct 'errno' value from kernel
  */
 int CAGetTCPLastErrorCode();
+
+/**
+ * Set the interface to be used for outgoing TCP packets.
+ * Tcp client sockets (before establishing connection) will be bound to the IP address of the given WiFi interface.
+ * Internally, Iotivity reads the IP address assigned to the given interace
+ * and binds it with the TCP client socket before connect().
+ *
+ * @param[in]   ifname     WiFi interface name.
+ *
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CASetTCPServerSocketBindIP(const char* ifname);
 #endif
 
 #ifdef __cplusplus
old mode 100644 (file)
new mode 100755 (executable)
index 4c5b995..83493d3
@@ -360,6 +360,7 @@ static void CAInitializeTCPGlobals()
     caglobals.tcp.selectTimeout = CA_TCP_SELECT_TIMEOUT;
     caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
     caglobals.tcp.svrlist = NULL;
+    caglobals.tcp.bindenabled = false;
 
     CATransportFlags_t flags = 0;
     if (caglobals.client)
old mode 100644 (file)
new mode 100755 (executable)
index 6a2e24c..ad7f8fb
@@ -21,6 +21,9 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
+#if defined(__TIZEN__)
+#include <ifaddrs.h>
+#endif
 #ifdef __TIZENRT__
 #include <tinyara/config.h>
 #include <poll.h>
@@ -144,6 +147,8 @@ static CATCPSessionInfo_t *CAGetSessionInfoFromFDAsOwner(int fd, size_t *index);
 #if defined(__TIZEN__)
 static char g_cloudproxyUri[CA_MAX_URI_LENGTH];
 
+static char g_interfaceName[CA_MAX_INTERFACE_NAME_LEN];
+
 CAResult_t CASetCloudAddressForProxy(const char *uri)
 {
     if (uri == NULL)
@@ -159,6 +164,22 @@ const char *CAGetCloudAddressForProxy()
         return NULL;
     return g_cloudproxyUri;
 }
+
+CAResult_t CASetTCPServerSocketBindIP(const char* ifname)
+{
+    CAResult_t res = CA_STATUS_OK;
+#ifdef TCP_ADAPTER
+    VERIFY_NON_NULL_RET(ifname, TAG, "Interface name is NULL", CA_STATUS_INVALID_PARAM);
+
+    OIC_LOG(DEBUG, TAG, "Setting Socket Bind");
+    caglobals.tcp.bindenabled = true;
+    OICStrcpy(g_interfaceName, sizeof (g_interfaceName), ifname);
+#else
+    OIC_LOG(DEBUG, TAG, "Not supported!");
+    res = CA_NOT_SUPPORTED;
+#endif
+    return res;
+}
 #endif
 
 #define MAX_TCP_SOCK_COUNT 4
@@ -889,6 +910,54 @@ static CAResult_t CATCPConvertNameToAddr(int family, const char *host, uint16_t
 }
 
 #if defined(__TIZEN__)
+static char * CATCPGetInterfaceAddr()
+{
+    struct ifaddrs *ifaddr, *ifa;
+    int family, s, n;
+    char *host = (uint8_t *)OICMalloc(NI_MAXHOST);
+
+    if (getifaddrs(&ifaddr) == -1)
+    {
+        OIC_LOG_V(ERROR, TAG, "getifaddrs failed: errno %s", strerror(errno));
+        OICFree(host);
+        return NULL;
+    }
+
+    for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++)
+    {
+        if (ifa->ifa_addr == NULL)
+            continue;
+
+        family = ifa->ifa_addr->sa_family;
+        OIC_LOG_V(DEBUG, TAG,"Interface name: %s",ifa->ifa_name);
+
+        if ((strncmp(g_interfaceName,ifa->ifa_name,strlen(ifa->ifa_name))==0)
+            && (family == AF_INET || family == AF_INET6))
+        {
+            s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
+                                        host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+            if (s != 0)
+            {
+                OIC_LOG_V(ERROR, TAG, "getnameinfo failed: errno %s", strerror(errno));
+                freeifaddrs(ifaddr);
+                OICFree(host);
+                return NULL;
+            }
+
+            OIC_LOG_V(DEBUG, TAG, "Interface address: %s", host);
+            freeifaddrs(ifaddr);
+            return host;
+        }
+    }
+
+    freeifaddrs(ifaddr);
+    OICFree(host);
+    OIC_LOG(ERROR, TAG, "Interface address not found");
+    return NULL;
+}
+#endif
+
+#if defined(__TIZEN__)
 static int CAGetHTTPStatusCode(char * response) {
     char *resp, *code_plus, *ptrSave;
     int ret = -1;
@@ -945,6 +1014,42 @@ static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem)
         socklen = sizeof(struct sockaddr_in);
     }
 
+#if defined(__TIZEN__)
+    if (caglobals.tcp.bindenabled)
+    {
+        char *host_address = CATCPGetInterfaceAddr();
+        if (host_address)
+        {
+            if (sa.ss_family == AF_INET)
+            {
+                struct sockaddr_in client;
+                memset(&client, 0x00, sizeof(client));
+                inet_pton(AF_INET, host_address, &(client.sin_addr.s_addr));
+                if (-1 == bind(fd, (struct sockaddr *)&client, socklen))
+                {
+                    OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
+                    OICFree(host_address);
+                    return CA_SOCKET_OPERATION_FAILED;
+                }
+            }
+            else
+            {
+                struct sockaddr_in6 client6;
+                memset(&client6, 0x00, sizeof(client6));
+                client6.sin6_family = AF_INET6;
+                inet_pton(AF_INET6, host_address, &client6.sin6_addr.s6_addr);
+                if (-1 == bind(fd, (struct sockaddr *)&client6, socklen))
+                {
+                    OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
+                    OICFree(host_address);
+                    return CA_SOCKET_OPERATION_FAILED;
+                }
+            }
+            OICFree(host_address);
+        }
+    }
+#endif
+
     // #4. connect to remote server device.
     if (connect(fd, (struct sockaddr *)&sa, socklen) < 0)
     {