Update snapshot(2017-12-06)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipserver.c
index 84a0af7..87afa90 100644 (file)
 #define _GNU_SOURCE // for in6_pktinfo
 #endif
 
+#ifdef __TIZENRT__
+#include <tinyara/config.h>
+#include <uio.h>
+#endif
+
 #include "iotivity_config.h"
 #include <sys/types.h>
 #if !defined(_WIN32)
@@ -40,6 +45,7 @@
 #endif
 
 #include <stdio.h>
+#include <string.h>
 #if !defined(_MSC_VER)
 #include <unistd.h>
 #endif //!defined(_MSC_VER)
 #include <linux/rtnetlink.h>
 #endif
 
+#ifdef __TIZENRT__
+#include <uio.h>
+#include <mqueue.h>
+#endif
+
 #include <coap/pdu.h>
 #include "caipinterface.h"
 #include "caipnwmonitor.h"
@@ -64,7 +75,7 @@
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 #include "ca_adapter_net_ssl.h"
 #endif
-#include "camutex.h"
+#include "octhread.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 
 #undef USE_IP_MREQN
 #endif
 
+#ifdef __TIZEN__
+#include <pthread.h>
+#endif
+
 /*
  * Logging tag for module name
  */
-#define TAG "OIC_CA_IP_SERVER"
+//#define TAG "OIC_CA_IP_SERVER"
+#define TAG IP_SERVER_TAG
 
+#ifdef __TIZENRT__
+mqd_t g_nwevent_mqfd;
+#ifdef CONFIG_NET_LWIP
+#define SOCK_CLOEXEC 0
+#else
+#define SOCK_CLOEXEC 1
+#endif
+#endif
 #define SELECT_TIMEOUT 1     // select() seconds (and termination latency)
 
 #define IPv4_MULTICAST     "224.0.1.187"
 static struct in_addr IPv4MulticastAddress = { 0 };
 
 #define IPv6_DOMAINS       16
+#define MOBILE_INTERFACES  2
 #define IPv6_MULTICAST_INT "ff01::158"
 static struct in6_addr IPv6MulticastAddressInt;
 #define IPv6_MULTICAST_LNK "ff02::158"
@@ -99,6 +124,11 @@ static struct in6_addr IPv6MulticastAddressOrg;
 #define IPv6_MULTICAST_GLB "ff0e::158"
 static struct in6_addr IPv6MulticastAddressGlb;
 
+/*
+ * Buffer size for the receive message buffer
+ */
+#define RECV_MSG_BUF_LEN 16384
+
 static char *ipv6mcnames[IPv6_DOMAINS] = {
     NULL,
     IPv6_MULTICAST_INT,
@@ -118,6 +148,41 @@ static char *ipv6mcnames[IPv6_DOMAINS] = {
     NULL
 };
 
+// Samsung Mobile
+static char *mobileinferfaces[MOBILE_INTERFACES] = {
+    "rmnet", "pdp"
+};
+
+#ifdef __TIZENRT__
+struct in6_pktinfo {
+        struct in6_addr ipi6_addr;
+        int             ipi6_ifindex;
+};
+
+struct in_pktinfo
+{
+  unsigned int   ipi_ifindex;  /* Interface index */
+  struct in_addr ipi_spec_dst; /* Local address */
+  struct in_addr ipi_addr;     /* Header Destination
+                                    address */
+};
+
+
+#define RTMGRP_LINK 1
+#define IP_PKTINFO         8
+#define IPV6_PKTINFO            50
+#define IPV6_MULTICAST_IF 9
+#define IPV6_V6ONLY 27
+#define IPV6_RECVPKTINFO       50
+#define IPV6_JOIN_GROUP 12
+#endif
+
+/**
+ * By default, IP multicast datagrams are sent with a time-to-live (TTL) of 1.
+ * An application can choose an initial TTL.
+ */
+static size_t multicastTTL = 1;
+
 #if defined (_WIN32)
 #define IFF_UP_RUNNING_FLAGS  (IFF_UP)
 
@@ -147,15 +212,58 @@ static void CAEventReturned(CASocketFd_t socket);
 
 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags);
 
+#ifdef __TIZEN__
+static int cleanup_pop_arg = 1;
+
+static void CAIPCleanupHandler(void *arg)
+{
+    (void)arg;
+
+    OIC_LOG(DEBUG, TAG, "Called clean-up handler");
+
+    if (caglobals.ip.shutdownFds[0] != OC_INVALID_SOCKET)
+    {
+        close(caglobals.ip.shutdownFds[0]);
+        caglobals.ip.shutdownFds[0] = OC_INVALID_SOCKET;
+    }
+}
+
 static void CAReceiveHandler(void *data)
 {
     (void)data;
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler");
+
+    pthread_cleanup_push(CAIPCleanupHandler, NULL);
 
     while (!caglobals.ip.terminate)
     {
         CAFindReadyMessage();
     }
+
+    pthread_cleanup_pop(cleanup_pop_arg);
+
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
 }
+#else
+static void CAReceiveHandler(void *data)
+{
+    (void)data;
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler");
+
+    while (!caglobals.ip.terminate)
+    {
+        CAFindReadyMessage();
+    }
+#ifndef __TIZENRT__
+    if (caglobals.ip.shutdownFds[0] != OC_INVALID_SOCKET)
+    {
+        close(caglobals.ip.shutdownFds[0]);
+        caglobals.ip.shutdownFds[0] = OC_INVALID_SOCKET;
+    }
+#endif
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
+}
+#endif
 
 #if !defined(WSA_WAIT_EVENT_0)
 
@@ -198,11 +306,12 @@ static void CAFindReadyMessage()
     SET(m6s, &readFds)
     SET(m4,  &readFds)
     SET(m4s, &readFds)
-
+#ifndef __TIZENRT__
     if (caglobals.ip.shutdownFds[0] != -1)
     {
         FD_SET(caglobals.ip.shutdownFds[0], &readFds);
     }
+#endif
     if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
     {
         FD_SET(caglobals.ip.netlinkFd, &readFds);
@@ -212,10 +321,25 @@ static void CAFindReadyMessage()
 
     if (caglobals.ip.terminate)
     {
-        OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received.");
+        OIC_LOG_V(INFO, TAG, "Packet receiver Stop request received.");
         return;
     }
-
+#ifdef __TIZENRT__
+    u_arraylist_t *iflist = CAFindInterfaceChange();
+    if (iflist)
+    {
+        uint32_t listLength = u_arraylist_length(iflist);
+        for (uint32_t i = 0; i < listLength; i++)
+        {
+            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+            if (ifitem)
+            {
+                CAProcessNewInterface(ifitem);
+            }
+        }
+        u_arraylist_destroy(iflist);
+    }
+#endif
     if (0 < ret)
     {
         CASelectReturned(&readFds, ret);
@@ -244,6 +368,7 @@ static void CASelectReturned(fd_set *readFds, int ret)
         else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE)
         else if ((caglobals.ip.netlinkFd != OC_INVALID_SOCKET) && FD_ISSET(caglobals.ip.netlinkFd, readFds))
         {
+#ifndef __TIZENRT__
             u_arraylist_t *iflist = CAFindInterfaceChange();
             if (iflist)
             {
@@ -259,7 +384,9 @@ static void CASelectReturned(fd_set *readFds, int ret)
                 u_arraylist_destroy(iflist);
             }
             break;
+#endif
         }
+#ifndef __TIZENRT__
         else if (FD_ISSET(caglobals.ip.shutdownFds[0], readFds))
         {
             char buf[10] = {0};
@@ -270,6 +397,7 @@ static void CASelectReturned(fd_set *readFds, int ret)
             }
             break;
         }
+#endif
         else
         {
             break;
@@ -468,14 +596,7 @@ static void CAEventReturned(CASocketFd_t socket)
 
 void CADeInitializeIPGlobals()
 {
-    CLOSE_SOCKET(u6);
-    CLOSE_SOCKET(u6s);
-    CLOSE_SOCKET(u4);
-    CLOSE_SOCKET(u4s);
-    CLOSE_SOCKET(m6);
-    CLOSE_SOCKET(m6s);
-    CLOSE_SOCKET(m4);
-    CLOSE_SOCKET(m4s);
+    CloseMulticastSocket();
 
     if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
     {
@@ -490,7 +611,8 @@ void CADeInitializeIPGlobals()
 
 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
 {
-    char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveMessage");
+    char recvBuffer[RECV_MSG_BUF_LEN] = {0};
 
     size_t len = 0;
     int level = 0;
@@ -535,6 +657,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
         OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
         return CA_STATUS_FAILED;
     }
+    OIC_LOG_V(DEBUG, TAG, "recvd %u bytes from recvmsg", recvLen);
 
     if (flags & CA_MULTICAST)
     {
@@ -597,6 +720,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
 #endif // !defined(WSA_CMSG_DATA)
     CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};
 
+#ifndef __TIZENRT__
     if (flags & CA_IPV6)
     {
         /** @todo figure out correct usage for ifindex, and sin6_scope_id.*/
@@ -611,6 +735,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
         }
     }
     else
+#endif
     {
         if ((flags & CA_MULTICAST) && pktinfo)
         {
@@ -630,7 +755,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
     {
 #ifdef __WITH_DTLS__
         int ret = CAdecryptSsl(&sep, (uint8_t *)recvBuffer, recvLen);
-        OIC_LOG_V(DEBUG, TAG, "CAdecryptSsl returns [%d]", ret);
+        OIC_LOG_V(INFO, TAG, "CAdecryptSsl returns [%d]", ret);
 #else
         OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
 #endif
@@ -639,10 +764,12 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
     {
         if (g_packetReceivedCallback)
         {
+            OIC_LOG(DEBUG, TAG, "call receivedCB");
             g_packetReceivedCallback(&sep, recvBuffer, recvLen);
         }
     }
 
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveMessage");
     return CA_STATUS_OK;
 
 }
@@ -767,20 +894,64 @@ static CASocketFd_t CACreateSocket(int family, uint16_t *port, bool isMulticast)
     if (FD > caglobals.ip.maxfd) \
         caglobals.ip.maxfd = FD;
 #define NEWSOCKET(FAMILY, NAME, MULTICAST) \
-    caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
     if (caglobals.ip.NAME.fd == OC_INVALID_SOCKET) \
     {   \
-        caglobals.ip.NAME.port = 0; \
         caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
+        if (caglobals.ip.NAME.fd == OC_INVALID_SOCKET) \
+        {   \
+            caglobals.ip.NAME.port = 0; \
+            caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
+        }   \
+        CHECKFD(caglobals.ip.NAME.fd)   \
     }   \
-    CHECKFD(caglobals.ip.NAME.fd)
+
+void CreateMulticastSocket()
+{
+    OIC_LOG_V(INFO, TAG, "In %s", __func__);
+
+    if (caglobals.ip.ipv6enabled)
+    {
+        NEWSOCKET(AF_INET6, u6, false)
+        NEWSOCKET(AF_INET6, u6s, false)
+        NEWSOCKET(AF_INET6, m6, true)
+        NEWSOCKET(AF_INET6, m6s, true)
+        OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
+    }
+    if (caglobals.ip.ipv4enabled)
+    {
+        NEWSOCKET(AF_INET, u4, false)
+        NEWSOCKET(AF_INET, u4s, false)
+        NEWSOCKET(AF_INET, m4, true)
+        NEWSOCKET(AF_INET, m4s, true)
+        OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
+    }
+
+    OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+}
+
+void CloseMulticastSocket()
+{
+    OIC_LOG_V(INFO, TAG, "In %s", __func__);
+
+    CLOSE_SOCKET(u6);
+    CLOSE_SOCKET(u6s);
+    CLOSE_SOCKET(u4);
+    CLOSE_SOCKET(u4s);
+    CLOSE_SOCKET(m6);
+    CLOSE_SOCKET(m6s);
+    CLOSE_SOCKET(m4);
+    CLOSE_SOCKET(m4s);
+
+    OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+}
 
 static void CAInitializeNetlink()
 {
     caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
 #ifdef __linux__
     // create NETLINK fd for interface change notifications
-    struct sockaddr_nl sa = { AF_NETLINK, 0, 0, RTMGRP_LINK };
+    struct sockaddr_nl sa = { AF_NETLINK, 0, 0,
+                              RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR };
 
     caglobals.ip.netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
     if (caglobals.ip.netlinkFd == OC_INVALID_SOCKET)
@@ -801,6 +972,17 @@ static void CAInitializeNetlink()
             CHECKFD(caglobals.ip.netlinkFd);
         }
     }
+#elif defined (__TIZENRT__) // pkmsgq
+       struct mq_attr lq_attr;
+       lq_attr.mq_maxmsg = 10;
+       lq_attr.mq_msgsize = 4;
+       lq_attr.mq_flags = 0;
+       g_nwevent_mqfd = mq_open("netlink_evtq", O_RDWR | O_NONBLOCK | O_CREAT, 0666, &lq_attr);
+       if (g_nwevent_mqfd == (mqd_t) - 1)
+       {
+               OIC_LOG_V(ERROR, TAG,"RECV mq_open failed\n");
+               return ;
+       }
 #endif
 }
 
@@ -815,10 +997,13 @@ static void CAInitializeFastShutdownMechanism()
         ret = 0;
     }
 #elif defined(HAVE_PIPE2)
+#ifndef __TIZENRT__
     ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC);
     CHECKFD(caglobals.ip.shutdownFds[0]);
     CHECKFD(caglobals.ip.shutdownFds[1]);
+#endif
 #else
+#ifndef __TIZENRT__
     ret = pipe(caglobals.ip.shutdownFds);
     if (-1 != ret)
     {
@@ -846,6 +1031,7 @@ static void CAInitializeFastShutdownMechanism()
     CHECKFD(caglobals.ip.shutdownFds[0]);
     CHECKFD(caglobals.ip.shutdownFds[1]);
 #endif
+#endif
     if (-1 == ret)
     {
         OIC_LOG_V(ERROR, TAG, "fast shutdown mechanism init failed: %s", CAIPS_GET_ERROR);
@@ -889,29 +1075,14 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
         caglobals.ip.ipv4enabled = true;  // only needed to run CA tests
     }
 
-    if (caglobals.ip.ipv6enabled)
-    {
-        NEWSOCKET(AF_INET6, u6, false)
-        NEWSOCKET(AF_INET6, u6s, false)
-        NEWSOCKET(AF_INET6, m6, true)
-        NEWSOCKET(AF_INET6, m6s, true)
-        OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
-    }
-    if (caglobals.ip.ipv4enabled)
-    {
-        NEWSOCKET(AF_INET, u4, false)
-        NEWSOCKET(AF_INET, u4s, false)
-        NEWSOCKET(AF_INET, m4, true)
-        NEWSOCKET(AF_INET, m4s, true)
-        OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
-    }
+    CreateMulticastSocket();
 
-    OIC_LOG_V(DEBUG, TAG,
+    OIC_LOG_V(INFO, TAG,
               "socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d",
               caglobals.ip.u6.fd, caglobals.ip.u6s.fd, caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
               caglobals.ip.m6.fd, caglobals.ip.m6s.fd, caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
 
-    OIC_LOG_V(DEBUG, TAG,
+    OIC_LOG_V(INFO, TAG,
               "port summary: u6 port=%d, u6s port=%d, u4 port=%d, u4s port=%d, m6 port=%d,"
               "m6s port=%d, m4 port=%d, m4s port=%d",
               caglobals.ip.u6.port, caglobals.ip.u6s.port, caglobals.ip.u4.port,
@@ -944,13 +1115,19 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
     }
 
     caglobals.ip.terminate = false;
-    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
+#ifndef __TIZENRT__
+    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL, NULL);
+#else
+    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL, NULL, "IoT_ReceiveHandler",
+                                  CONFIG_IOTIVITY_RECEIVEHANDLER_PTHREAD_STACKSIZE);
+#endif
     if (CA_STATUS_OK != res)
     {
         OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+        CAIPStopServer();
         return res;
     }
-    OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
+    OIC_LOG(INFO, TAG, "CAReceiveHandler thread started successfully.");
 
     caglobals.ip.started = true;
     return CA_STATUS_OK;
@@ -961,7 +1138,10 @@ void CAIPStopServer()
     caglobals.ip.started = false;
     caglobals.ip.terminate = true;
 
+    CADeInitializeIPGlobals();
+
 #if !defined(WSA_WAIT_EVENT_0)
+#ifndef __TIZENRT__
     if (caglobals.ip.shutdownFds[1] != -1)
     {
         close(caglobals.ip.shutdownFds[1]);
@@ -971,6 +1151,7 @@ void CAIPStopServer()
     {
         // receive thread will stop in SELECT_TIMEOUT seconds.
     }
+#endif
 #else
     // receive thread will stop immediately.
     if (!WSASetEvent(caglobals.ip.shutdownEvent))
@@ -978,29 +1159,8 @@ void CAIPStopServer()
         OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %#08X", GetLastError());
     }
 #endif
-}
 
-void CAWakeUpForChange()
-{
-#if !defined(WSA_WAIT_EVENT_0)
-    if (caglobals.ip.shutdownFds[1] != -1)
-    {
-        ssize_t len = 0;
-        do
-        {
-            len = write(caglobals.ip.shutdownFds[1], "w", 1);
-        } while ((len == -1) && (errno == EINTR));
-        if ((len == -1) && (errno != EINTR) && (errno != EPIPE))
-        {
-            OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno));
-        }
-    }
-#else
-    if (!WSASetEvent(caglobals.ip.shutdownEvent))
-    {
-        OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %#08X", GetLastError());
-    }
-#endif
+    OIC_LOG(INFO, TAG, "Adapter terminated successfully");
 }
 
 static void applyMulticastToInterface4(uint32_t ifindex)
@@ -1047,7 +1207,8 @@ static void applyMulticastToInterface4(uint32_t ifindex)
 
 static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t ifindex)
 {
-    struct ipv6_mreq mreq = {.ipv6mr_multiaddr = {0},
+#ifndef __TIZENRT__
+    struct ipv6_mreq mreq = {.ipv6mr_multiaddr = {{{0}}},
                              .ipv6mr_interface = ifindex };
 
     // VS2013 has problems with struct copies inside struct initializers, so copy separately.
@@ -1065,6 +1226,7 @@ static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t ifindex)
             OIC_LOG_V(ERROR, TAG, "IPv6 IPV6_JOIN_GROUP failed: %s", CAIPS_GET_ERROR);
         }
     }
+#endif
 }
 
 static void applyMulticastToInterface6(uint32_t ifindex)
@@ -1242,10 +1404,14 @@ static void sendData(int fd, const CAEndpoint_t *endpoint,
             g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
         }
         OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
+        CALogSendStateInfo(endpoint->adapter, endpoint->addr, endpoint->port,
+                           len, false, strerror(errno));
     }
     else
     {
         OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
+        CALogSendStateInfo(endpoint->adapter, endpoint->addr, endpoint->port,
+                           len, true, NULL);
     }
 #else
     int err = 0;
@@ -1272,11 +1438,11 @@ static void sendData(int fd, const CAEndpoint_t *endpoint,
             sent += len;
             if (sent != len)
             {
-                OIC_LOG_V(DEBUG, TAG, "%s%s %s sendTo (Partial Send) is successful: "
-                                      "currently sent: %ld bytes, "
-                                      "total sent: %ld bytes, "
-                                      "remaining: %ld bytes",
-                                      secure, cast, fam, len, sent, dlen-sent);
+                OIC_LOG_V(INFO, TAG, "%s%s %s sendTo (Partial Send) is successful: "
+                          "currently sent: %ld bytes, "
+                          "total sent: %ld bytes, "
+                          "remaining: %ld bytes",
+                          secure, cast, fam, len, sent, dlen-sent);
             }
             else
             {
@@ -1325,12 +1491,34 @@ static void sendMulticastData6(const u_arraylist_t *iflist,
             continue;
         }
 
+        bool isMobile = false;
+        for (uint32_t j = 0; j < MOBILE_INTERFACES; j++)
+        {
+            if (strstr(ifitem->name, mobileinferfaces[j]))
+            {
+                isMobile = true;
+                break;
+            }
+        }
+        if (isMobile)
+        {
+            continue;
+        }
+
         int index = ifitem->index;
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, OPTVAL_T(&index), sizeof (index)))
         {
             OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", CAIPS_GET_ERROR);
             return;
         }
+
+#ifndef __TIZENRT__
+        // Set multicast packet TTL; default TTL is 1
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &multicastTTL, sizeof(multicastTTL)))
+        {
+            OIC_LOG_V(ERROR, TAG, "IPV6_MULTICAST_HOPS failed: %s", CAIPS_GET_ERROR);
+        }
+#endif
         sendData(fd, endpoint, data, datalen, "multicast", "ipv6");
     }
 }
@@ -1369,6 +1557,21 @@ static void sendMulticastData4(const u_arraylist_t *iflist,
         {
             continue;
         }
+
+        bool isMobile = false;
+        for (uint32_t j = 0; j < MOBILE_INTERFACES; j++)
+        {
+            if (strstr(ifitem->name, mobileinferfaces[j]))
+            {
+                isMobile = true;
+                break;
+            }
+        }
+        if (isMobile)
+        {
+            continue;
+        }
+
 #if defined(USE_IP_MREQN)
         mreq.imr_ifindex = ifitem->index;
 #else
@@ -1379,6 +1582,12 @@ static void sendMulticastData4(const u_arraylist_t *iflist,
             OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",
                     CAIPS_GET_ERROR);
         }
+
+        // Set multicast packet TTL; default TTL is 1
+        if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &multicastTTL, sizeof(multicastTTL)))
+        {
+            OIC_LOG_V(ERROR, TAG, "IP_MULTICAST_TTL failed: %s", CAIPS_GET_ERROR);
+        }
         sendData(fd, endpoint, data, datalen, "multicast", "ipv4");
     }
 }
@@ -1524,3 +1733,17 @@ void CAIPSetErrorHandler(CAIPErrorHandleCallback errorHandleCallback)
 {
     g_ipErrorHandler = errorHandleCallback;
 }
+
+CAResult_t CAIPSetMulticastTTL(size_t ttl)
+{
+    multicastTTL = ttl;
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAIPGetMulticastTTL(size_t *ttl)
+{
+    VERIFY_NON_NULL(ttl, TAG, "ttl is NULL");
+
+    *ttl = multicastTTL;
+    return CA_STATUS_OK;
+}