[IOT-1361][Android]Using netlink for get ipaddr instead of ioctl
authorbg.chun <bg.chun@samsung.com>
Thu, 6 Oct 2016 10:23:10 +0000 (19:23 +0900)
committerAshok Babu Channa <ashok.channa@samsung.com>
Wed, 26 Oct 2016 12:53:16 +0000 (12:53 +0000)
Using netlink to support getting ipv6 address in CAGetNetworkInfo()
Remove ioctl code and using netlink.

Change-Id: I94dd5bebd2f8dde95cb589e4f64a44c2a1a428f1
https://jira.iotivity.org/browse/IOT-1361
Signed-off-by: bg.chun <bg.chun@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/12879
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Larry Sachs <larry.j.sachs@intel.com>
Reviewed-by: Dave Thaler <dthaler@microsoft.com>
Reviewed-by: Rick Bell <richard.s.bell@intel.com>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
resource/csdk/connectivity/inc/caipnwmonitor.h
resource/csdk/connectivity/src/ip_adapter/android/SConscript
resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/android/ifaddrs.c [new file with mode: 0644]
resource/csdk/connectivity/src/ip_adapter/android/ifaddrs.h [new file with mode: 0644]
resource/csdk/connectivity/src/ip_adapter/caipserver.c

index e2e7c70..b5a4e29 100644 (file)
@@ -119,6 +119,13 @@ CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
  */
 CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter);
 
+/**
+ * Apply network interface changes.
+ *
+ * @param[in]  ifchanged      Changed interface.
+ */
+void CAProcessNewInterface(CAInterface_t *ifchanged);
+
 #ifdef __cplusplus
 }
 #endif
index b411c2e..b1a6a52 100644 (file)
@@ -7,6 +7,7 @@ import os.path
 
 env.AppendUnique(CPPPATH = [ os.path.join(src_dir, 'android') ])
 
-src_files = [ 'caipnwmonitor.c' ]
+src_files = [ 'caipnwmonitor.c',
+              'ifaddrs.c' ]
 
 Return('src_files')
index 03b7294..3fbc3c8 100644 (file)
@@ -30,6 +30,8 @@
 #include <arpa/inet.h>
 #include <linux/if.h>
 #include <coap/utlist.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
 
 #include "caadapterutils.h"
 #include "caipnwmonitor.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 #include "org_iotivity_ca_CaIpInterface.h"
+#include "ifaddrs.h"
 
 #define TAG "OIC_CA_IP_MONITOR"
 #define NETLINK_MESSAGE_LENGTH  (4096)
-
+#define IFC_LABEL_LOOP          "lo"
+#define IFC_ADDR_LOOP_IPV4      "127.0.0.1"
+#define IFC_ADDR_LOOP_IPV6      "::1"
 /**
  * Used to storing adapter changes callback interface.
  */
@@ -180,147 +185,96 @@ CAResult_t CAIPUnSetNetworkMonitorCallback(CATransportAdapter_t adapter)
 
 u_arraylist_t *CAFindInterfaceChange()
 {
-    // release netlink event
-    char *bufPtr = (char *)OICCalloc(NETLINK_MESSAGE_LENGTH, sizeof (char));
-    if (!bufPtr)
-    {
-        OIC_LOG(ERROR, TAG, "Malloc failed");
-        return NULL;
-    }
-    recv(caglobals.ip.netlinkFd, bufPtr, NETLINK_MESSAGE_LENGTH, 0);
-    OICFree(bufPtr);
-    bufPtr = NULL;
-
-    char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
-    struct ifconf ifc  = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
-
-    int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
-    if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
-    {
-        OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
-        return NULL;
-    }
-
-    u_arraylist_t *iflist = NULL;
-    CAInterface_t *foundNewInterface = NULL;
-
-    struct ifreq* ifr = ifc.ifc_req;
-    size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
-    size_t ifreqsize = ifc.ifc_len;
+    char buf[NETLINK_MESSAGE_LENGTH] = { 0 };
+    struct sockaddr_nl sa = { 0 };
+    struct iovec iov = { .iov_base = buf,
+                         .iov_len = sizeof (buf) };
+    struct msghdr msg = { .msg_name = (void *)&sa,
+                          .msg_namelen = sizeof (sa),
+                          .msg_iov = &iov,
+                          .msg_iovlen = 1 };
+
+    size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
+    return NULL;
+}
 
-    CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize);
-    if (!previous)
+/**
+ * Used to send netlink query to kernel and recv response from kernel.
+ *
+ * @param[in]   idx       desired network interface index, 0 means all interfaces.
+ * @param[out]  iflist    linked list.
+ *
+ */
+static bool CAParsingNetorkInfo(int idx, u_arraylist_t *iflist)
+{
+    if ((idx < 0) || (iflist == NULL))
     {
-        OIC_LOG(ERROR, TAG, "OICMalloc failed");
-        return NULL;
+        return false;
     }
 
-    memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize);
-    size_t numprevious = caglobals.ip.nm.numIfItems;
-
-    if (ifreqsize > caglobals.ip.nm.sizeIfItems)
+    struct ifaddrs *ifp = NULL;
+    CAResult_t ret = CAGetIfaddrsUsingNetlink(&ifp);
+    if (CA_STATUS_OK != ret)
     {
-
-        CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
-        if (!items)
-        {
-            OIC_LOG(ERROR, TAG, "OICRealloc failed");
-            OICFree(previous);
-            return NULL;
-        }
-        caglobals.ip.nm.ifItems = items;
-        caglobals.ip.nm.sizeIfItems = ifreqsize;
+        OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs err code is: %d", ret);
+        return false;
     }
 
-    caglobals.ip.nm.numIfItems = 0;
-    for (size_t i = 0; i < interfaces; i++)
+    struct ifaddrs *ifa = NULL;
+    for (ifa = ifp; ifa; ifa = ifa->ifa_next)
     {
-        struct ifreq* item = &ifr[i];
-        char *name = item->ifr_name;
-
-        if (ioctl(s, SIOCGIFFLAGS, item) < 0)
+        if (!ifa->ifa_addr)
         {
-            OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
             continue;
         }
-        int16_t flags = item->ifr_flags;
-        if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
-        {
-            continue;
-        }
-        if (ioctl(s, SIOCGIFINDEX, item) < 0)
+
+        int family = ifa->ifa_addr->sa_family;
+        if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
         {
-            OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
             continue;
         }
 
-        int ifIndex = item->ifr_ifindex;
-        caglobals.ip.nm.ifItems[i].ifIndex = ifIndex;  // refill interface list
-        caglobals.ip.nm.numIfItems++;
-
-        if (foundNewInterface)
+        int ifindex = if_nametoindex(ifa->ifa_name);
+        if (idx && (ifindex != idx))
         {
-            continue;   // continue updating interface list
+            continue;
         }
 
-        // see if this interface didn't previously exist
-        bool found = false;
-        for (size_t j = 0; j < numprevious; j++)
+        char ipaddr[MAX_ADDR_STR_SIZE_CA] = {0};
+        if (family == AF_INET6)
         {
-            if (ifIndex == previous[j].ifIndex)
-            {
-                found = true;
-                break;
-            }
+            struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa->ifa_addr;
+            inet_ntop(family, (void *)&(in6->sin6_addr), ipaddr, sizeof(ipaddr));
         }
-        if (found)
+        else if (family == AF_INET)
         {
-            OIC_LOG_V(INFO, TAG, "Interface found: %s", name);
-            continue;
+            struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr;
+            inet_ntop(family, (void *)&(in->sin_addr), ipaddr, sizeof(ipaddr));
         }
 
-        // Get address of network interface.
-        char addr[MAX_ADDR_STR_SIZE_CA] = { 0 };
-        struct sockaddr_in *sa = (struct sockaddr_in *)&item->ifr_addr;
-        inet_ntop(AF_INET, (void *)&(sa->sin_addr), addr, sizeof(addr));
-
-        foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, addr, flags);
-    }
-
-    OICFree(previous);
-    // below code is temporary impl for consistency with caipserver.
-    // TODO: whole code which using ioctl will be removed and changed with internal getifaddrs impl.
-    if (foundNewInterface)
-    {
-        iflist = u_arraylist_create();
-
-        if (!iflist)
+        if ((strcmp(ipaddr, IFC_ADDR_LOOP_IPV4) == 0) ||
+            (strcmp(ipaddr, IFC_ADDR_LOOP_IPV6) == 0) ||
+            (strcmp(ifa->ifa_name, IFC_LABEL_LOOP) == 0))
         {
-            OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
-            goto exit;
+            OIC_LOG(DEBUG, TAG, "LOOPBACK continue!!!");
+            continue;
         }
 
-        CAResult_t result = CAAddInterfaceItem(iflist,
-                                               foundNewInterface->index,
-                                               foundNewInterface->name,
-                                               foundNewInterface->family,
-                                               foundNewInterface->addr,
-                                               foundNewInterface->flags);
+        CAResult_t result = CAAddInterfaceItem(iflist, ifindex,
+                                               ifa->ifa_name, family,
+                                               ipaddr, ifa->ifa_flags);
         if (CA_STATUS_OK != result)
         {
+            OIC_LOG(ERROR, TAG, "CAAddInterfaceItem fail");
             goto exit;
         }
-
-        // release foundNewInterface
-        OICFree(foundNewInterface);
-        foundNewInterface = NULL;
     }
-    return iflist;
+    CAFreeIfAddrs(ifp);
+    return true;
+
 exit:
-    OICFree(foundNewInterface);
-    foundNewInterface = NULL;
-    u_arraylist_destroy(iflist);
-    return NULL;
+    CAFreeIfAddrs(ifp);
+    return false;
 }
 
 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
@@ -332,83 +286,11 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
         return NULL;
     }
 
-    char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
-    struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
-
-    int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
-    if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
-    {
-        OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
-        u_arraylist_destroy(iflist);
-        return NULL;
-    }
-
-    struct ifreq* ifr = ifc.ifc_req;
-    size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
-    size_t ifreqsize = ifc.ifc_len;
-
-    if (ifreqsize > caglobals.ip.nm.sizeIfItems)
+    if (!CAParsingNetorkInfo(desiredIndex, iflist))
     {
-        CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
-        if (!items)
-        {
-            OIC_LOG(ERROR, TAG, "OICRealloc failed");
-            goto exit;
-        }
-        caglobals.ip.nm.ifItems = items;
-        caglobals.ip.nm.sizeIfItems = ifreqsize;
+        goto exit;
     }
 
-    caglobals.ip.nm.numIfItems = 0;
-    for (size_t i = 0; i < interfaces; i++)
-    {
-        struct ifreq* item = &ifr[i];
-        char *name = item->ifr_name;
-
-        if (ioctl(s, SIOCGIFFLAGS, item) < 0)
-        {
-            OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
-            continue;
-        }
-        int16_t flags = item->ifr_flags;
-        if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
-        {
-            continue;
-        }
-        if (ioctl(s, SIOCGIFINDEX, item) < 0)
-        {
-            OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
-            continue;
-        }
-
-        int ifindex = item->ifr_ifindex;
-        caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
-        caglobals.ip.nm.numIfItems++;
-
-        if (desiredIndex && (ifindex != desiredIndex))
-        {
-            continue;
-        }
-
-        // Get address of network interface.
-        char addr[MAX_ADDR_STR_SIZE_CA] = { 0 };
-        struct sockaddr_in *sa = (struct sockaddr_in *)&item->ifr_addr;
-        inet_ntop(AF_INET, (void *)&(sa->sin_addr), addr, sizeof(addr));
-
-        // Add IPv4 interface
-        CAResult_t result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, addr, flags);
-        if (CA_STATUS_OK != result)
-        {
-            goto exit;
-        }
-
-        // Add IPv6 interface
-        result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, addr, flags);
-        if (CA_STATUS_OK != result)
-        {
-            goto exit;
-        }
-    }
     return iflist;
 
 exit:
@@ -599,6 +481,28 @@ Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class)
 
     OIC_LOG(DEBUG, TAG, "Wifi is in Activated State");
     CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
+
+    // Apply network interface changes.
+    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
+    if (!iflist)
+    {
+        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+        return;
+    }
+
+    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)
+        {
+            continue;
+        }
+
+        CAProcessNewInterface(ifitem);
+
+    }
+    u_arraylist_destroy(iflist);
 }
 
 JNIEXPORT void JNICALL
diff --git a/resource/csdk/connectivity/src/ip_adapter/android/ifaddrs.c b/resource/csdk/connectivity/src/ip_adapter/android/ifaddrs.c
new file mode 100644 (file)
index 0000000..44e9fb6
--- /dev/null
@@ -0,0 +1,203 @@
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+
+#include "ifaddrs.h"
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include "logger.h"
+#define TAG "OIC_CA_ifaddrs"
+
+#define NETLINK_MESSAGE_LENGTH  (4096)
+#define IFC_LABEL_LOOP          "lo"
+#define IFC_ADDR_LOOP_IPV4      "127.0.0.1"
+#define IFC_ADDR_LOOP_IPV6      "::1"
+
+typedef struct {
+    struct nlmsghdr     msgInfo;
+    struct ifaddrmsg    ifaddrInfo;
+} CANetlintReq_t;
+
+
+static bool CASendNetlinkMessage(int netlinkFd, const void* data, size_t len)
+{
+    ssize_t sentByteCount = TEMP_FAILURE_RETRY(send(netlinkFd, data, len, 0));
+    return (sentByteCount == (ssize_t)(len));
+}
+
+void CAFreeIfAddrs(struct ifaddrs *ifa)
+{
+    struct ifaddrs *cur;
+    while (ifa)
+    {
+        cur = ifa;
+        ifa = ifa->ifa_next;
+        free(cur);
+    }
+}
+
+static struct ifaddrs *CAParsingAddr(struct nlmsghdr *recvMsg)
+{
+    struct ifaddrmsg *ifaddrmsgData = (struct ifaddrmsg*)NLMSG_DATA(recvMsg);
+    if (ifaddrmsgData-> ifa_family != AF_INET && ifaddrmsgData-> ifa_family != AF_INET6)
+    {
+        return NULL;
+    }
+
+    struct rtattr *rtattrData = (struct rtattr*)IFA_RTA(ifaddrmsgData);
+    int ifaddrmsgLen = IFA_PAYLOAD(recvMsg);
+
+    struct ifaddrs *node = (struct ifaddrs *)OICCalloc(1, sizeof(struct ifaddrs));
+    char nameBuf[IFNAMSIZ] = { 0 };
+    node->ifa_next = NULL;
+    if_indextoname(ifaddrmsgData->ifa_index, nameBuf);
+    node->ifa_name = (char *)OICCalloc(strlen(nameBuf)+1, sizeof(char));
+    OICStrcpy(node->ifa_name, strlen(nameBuf)+1, nameBuf);
+    node->ifa_flags = ifaddrmsgData->ifa_flags;
+    node->ifa_flags |= (IFF_UP|IFF_RUNNING);
+    void *dest = NULL;
+    struct sockaddr_storage* ss = NULL;
+
+    for (; RTA_OK(rtattrData, ifaddrmsgLen); rtattrData = RTA_NEXT(rtattrData, ifaddrmsgLen))
+    {
+        switch (rtattrData->rta_type)
+        {
+            case IFA_ADDRESS:
+                ss = (struct sockaddr_storage*)OICCalloc(1, sizeof(struct sockaddr_storage));
+                ss->ss_family = ifaddrmsgData-> ifa_family;
+
+                if (ifaddrmsgData-> ifa_family == AF_INET)
+                {
+                    dest = &((struct sockaddr_in*)ss)->sin_addr;
+                    memcpy(dest, RTA_DATA(rtattrData), RTA_PAYLOAD(rtattrData));
+                }
+                else if (ifaddrmsgData-> ifa_family == AF_INET6)
+                {
+                    dest = &((struct sockaddr_in6*)ss)->sin6_addr;
+                    memcpy(dest, RTA_DATA(rtattrData), RTA_PAYLOAD(rtattrData));
+                }
+
+                node->ifa_addr = (struct sockaddr*)ss;
+                break;
+
+            default :
+                // do nothing
+                break;
+        }
+    }
+
+    return node;
+}
+
+CAResult_t CAGetIfaddrsUsingNetlink(struct ifaddrs **ifap)
+{
+    if (!ifap)
+    {
+        OIC_LOG(ERROR, TAG, "netlink argument error");
+        return CA_STATUS_INVALID_PARAM;
+    }
+    *ifap = NULL;
+
+    int netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
+    int state = -1;
+    if (-1 == netlinkFd)
+    {
+        OIC_LOG_V(ERROR, TAG, "netlink socket failed: %s", strerror(errno));
+        return CA_SOCKET_OPERATION_FAILED;
+    }
+
+    // send request to kernel
+    CANetlintReq_t req;
+    memset(&req, 0, sizeof(req));
+    req.msgInfo.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req)));
+    req.msgInfo.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+    req.msgInfo.nlmsg_type = RTM_GETADDR;
+    req.ifaddrInfo.ifa_family = AF_UNSPEC;
+    req.ifaddrInfo.ifa_index = 0;
+
+    if (!CASendNetlinkMessage(netlinkFd, &req, req.msgInfo.nlmsg_len))
+    {
+        OIC_LOG(ERROR, TAG, "netlink send failed");
+        goto exit;
+    }
+
+    while (1)
+    {
+        char recvBuf[NETLINK_MESSAGE_LENGTH] = {0};
+        int len = recv(netlinkFd, recvBuf, sizeof(recvBuf), 0);
+        struct nlmsghdr *recvMsg = (struct nlmsghdr*)recvBuf;
+        struct ifaddrs *node = NULL;
+        for (; NLMSG_OK(recvMsg, len); recvMsg = NLMSG_NEXT(recvMsg, len))
+        {
+            switch (recvMsg->nlmsg_type)
+            {
+                case NLMSG_DONE:
+                    OIC_LOG(DEBUG, TAG, "NLMSG_DONE");
+                    state = 0;
+                    goto exit;
+
+                case NLMSG_ERROR:
+                    OIC_LOG(ERROR, TAG, "NLMSG is invalid");
+                    state = -1;
+                    goto exit;
+
+                case RTM_NEWADDR:
+                    OIC_LOG(DEBUG, TAG, "RTM_NEWADDR");
+                    node = CAParsingAddr(recvMsg);
+
+                    if (*ifap == NULL)
+                    {
+                        *ifap = node;
+                    }
+                    else
+                    {
+                        node->ifa_next = *ifap;
+                        *ifap = node;
+                    }
+
+                    break;
+
+                case RTM_NEWLINK:
+                default:
+                    OIC_LOG(DEBUG, TAG, "ignore unknown NLMSG");
+                    break;
+            }
+        }
+    }
+
+
+exit:
+    // release all resources
+    close(netlinkFd);
+    if (state == -1)
+    {
+        CAFreeIfAddrs(*ifap);
+        return CA_SOCKET_OPERATION_FAILED;
+    }
+    return CA_STATUS_OK;
+}
\ No newline at end of file
diff --git a/resource/csdk/connectivity/src/ip_adapter/android/ifaddrs.h b/resource/csdk/connectivity/src/ip_adapter/android/ifaddrs.h
new file mode 100644 (file)
index 0000000..cee33c5
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+#include "cacommon.h"
+
+/**
+ * CA partial define for the structure ifaddrs.
+ */
+struct ifaddrs
+{
+    struct ifaddrs     *ifa_next;
+    char               *ifa_name;
+    unsigned int       ifa_flags;
+    struct sockaddr    *ifa_addr;
+};
+
+/**
+ * CA internal definition for getifaddrs.
+ *
+ * @param[out]  ifap    List of ifaddrs.
+ * @return  On success, returns CA_STATUS_OK; on error, CA error code is returned.
+ */
+CAResult_t CAGetIfaddrsUsingNetlink(struct ifaddrs **ifap);
+
+/**
+ * CA internal definition for freeifaddrs
+ *
+ * @param[in]  ifa      List of ifaddrs.
+ */
+void CAFreeIfAddrs(struct ifaddrs *ifa);
+
index 31a9b2d..f27f6d9 100644 (file)
@@ -147,7 +147,7 @@ static void CASelectReturned(fd_set *readFds, int ret);
 #else
 static void CAEventReturned(CASocketFd_t socket);
 #endif
-static void CAProcessNewInterface(CAInterface_t *ifchanged);
+
 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags);
 
 static void CAReceiveHandler(void *data)
@@ -1228,7 +1228,7 @@ CAResult_t CAIPStopListenServer()
     return CA_STATUS_OK;
 }
 
-static void CAProcessNewInterface(CAInterface_t *ifitem)
+void CAProcessNewInterface(CAInterface_t *ifitem)
 {
     if (!ifitem)
     {