-/*****************************************************************j
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
#include "oic_malloc.h"
#include "oic_string.h"
+#define USE_IP_MREQN
+#if defined(_WIN32)
+#undef USE_IP_MREQN
+#endif
+
/*
* Logging tag for module name
*/
NULL
};
-#if defined (__msys_nt__)
- char* _caips_get_error(){
+#if defined (_WIN32)
+#define IFF_UP_RUNNING_FLAGS (IFF_UP)
+
+ char* caips_get_error(){
static char buffer[32];
snprintf(buffer, 32, "%i", WSAGetLastError());
return buffer;
}
- #define CAIPS_GET_ERROR \
- _caips_get_error()
+#define CAIPS_GET_ERROR \
+ caips_get_error()
#else
- #define CAIPS_GET_ERROR \
- strerror(errno)
+#define IFF_UP_RUNNING_FLAGS (IFF_UP|IFF_RUNNING)
+
+#define CAIPS_GET_ERROR \
+ strerror(errno)
#endif
static CAIPExceptionCallback g_exceptionCallback;
SET(m4, &readFds)
SET(m4s, &readFds)
-#if !defined(__msys_nt__)
+#if !defined(_WIN32)
if (caglobals.ip.shutdownFds[0] != -1)
{
FD_SET(caglobals.ip.shutdownFds[0], &readFds);
else ISSET(m6s, readFds, CA_MULTICAST | CA_IPV6 | CA_SECURE)
else ISSET(m4, readFds, CA_MULTICAST | CA_IPV4)
else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE)
-#if !defined(__msys_nt__)
+#if !defined(_WIN32)
else if (FD_ISSET(caglobals.ip.netlinkFd, readFds))
{
CAInterface_t *ifchanged = CAFindInterfaceChange();
int level, type, namelen;
struct sockaddr_storage srcAddr;
unsigned char *pktinfo = NULL;
-#if !defined(__msys_nt__)
+#if !defined(WSA_CMSG_DATA)
struct cmsghdr *cmp = NULL;
- struct iovec iov = { recvBuffer, sizeof (recvBuffer) };
+ struct iovec iov = { .iov_base = recvBuffer, .iov_len = sizeof (recvBuffer) };
union control
{
struct cmsghdr cmsg;
}
}
}
-#else // if defined(__msys_nt__)
+#else // if defined(WSA_CMSG_DATA)
+ union control
+ {
+ WSACMSGHDR cmsg;
+ uint8_t data[WSA_CMSG_SPACE(sizeof (IN6_PKTINFO))];
+ } cmsg;
+ memset(&cmsg, 0, sizeof(cmsg));
-#endif // !defined(__msys_nt__)
+ if (flags & CA_IPV6)
+ {
+ namelen = sizeof (struct sockaddr_in6);
+ level = IPPROTO_IPV6;
+ type = IPV6_PKTINFO;
+ }
+ else
+ {
+ namelen = sizeof (struct sockaddr_in);
+ level = IPPROTO_IP;
+ type = IP_PKTINFO;
+ }
+
+ WSABUF iov = {.len = sizeof (recvBuffer), .buf = recvBuffer};
+ WSAMSG msg = {.name = &srcAddr,
+ .namelen = namelen,
+ .lpBuffers = &iov,
+ .dwBufferCount = 1,
+ .Control = {.buf = cmsg.data, .len = sizeof (cmsg)}
+ };
+
+ uint32_t recvLen = 0;
+ uint32_t ret = caglobals.ip.wsaRecvMsg(fd, &msg, &recvLen, 0,0);
+ OIC_LOG_V(DEBUG, TAG, "WSARecvMsg recvd %u bytes", recvLen);
+ if (SOCKET_ERROR == ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "WSARecvMsg failed %i", WSAGetLastError());
+ }
+
+ if (flags & CA_MULTICAST)
+ {
+ for (WSACMSGHDR *cmp = WSA_CMSG_FIRSTHDR(&msg); cmp != NULL;
+ cmp = WSA_CMSG_NXTHDR(&msg, cmp))
+ {
+ if (cmp->cmsg_level == level && cmp->cmsg_type == type)
+ {
+ pktinfo = WSA_CMSG_DATA(cmp);
+ }
+ }
+ }
+#endif // !defined(WSA_CMSG_DATA)
CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};
if (flags & CA_IPV6)
{
- sep.endpoint.ifindex = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
- ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0;
-
+ /** @todo figure out correct usage for ifindex, and sin6_scope_id.*/
if ((flags & CA_MULTICAST) && pktinfo)
{
struct in6_addr *addr = &(((struct in6_pktinfo *)pktinfo)->ipi6_addr);
}
}
}
-#if !defined(__msys_nt__)
- CAConvertAddrToName(&srcAddr, msg.msg_namelen, sep.endpoint.addr, &sep.endpoint.port);
-#else
-#endif
+ CAConvertAddrToName(&srcAddr, namelen, sep.endpoint.addr, &sep.endpoint.port);
+
if (flags & CA_SECURE)
{
#ifdef __WITH_DTLS__
return CA_STATUS_OK;
-
}
void CAIPPullData()
static int CACreateSocket(int family, uint16_t *port)
{
-#if !defined(__msys_nt__)
int socktype = SOCK_DGRAM;
#ifdef SOCK_CLOEXEC
socktype |= SOCK_CLOEXEC;
int fd = socket(family, socktype, IPPROTO_UDP);
if (-1 == fd)
{
- OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
+ OIC_LOG_V(ERROR, TAG, "create socket failed: %s", CAIPS_GET_ERROR);
return -1;
}
-#ifndef SOCK_CLOEXEC
+#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
int fl = fcntl(fd, F_GETFD);
if (-1 == fl || -1 == fcntl(fd, F_SETFD, fl|FD_CLOEXEC))
{
return -1;
}
#endif
-#else // defined(__msys_nt__)
-
-#endif
struct sockaddr_storage sa = { .ss_family = family };
socklen_t socklen;
if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
{
- OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno));
+ OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", CAIPS_GET_ERROR);
}
- if (*port) // only do this for multicast ports
+ if (*port) // only do this for multicast ports
{
-#if !defined(__msys_nt__)
+#if defined(IPV6_RECVPKTINFO)
if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof (on)))
#else
-
+ if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof (on)))
#endif
{
OIC_LOG_V(ERROR, TAG, "IPV6_RECVPKTINFO failed: %s",CAIPS_GET_ERROR);
}
else
{
- if (*port) // only do this for multicast ports
+ if (*port) // only do this for multicast ports
{
int on = 1;
if (-1 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &on, sizeof (on)))
socklen = sizeof (struct sockaddr_in);
}
- if (*port) // use the given port
+ if (*port) // use the given port
{
int on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)))
return -1;
}
- if (!*port) // return the assigned port
+ if (!*port) // return the assigned port
{
if (-1 == getsockname(fd, (struct sockaddr *)&sa, &socklen))
{
static void CAInitializePipe()
{
-#if !defined(__msys_nt__)
+#if !defined(_WIN32)
caglobals.ip.selectTimeout = -1;
#ifdef HAVE_PIPE2
int ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC);
caglobals.ip.selectTimeout = SELECT_TIMEOUT; //poll needed for shutdown
}
#else
- //msys stuff here
+ /** @todo Refactor to support Windows-specific inter-thread communication code. */
#endif
}
{
return res;
}
-
+#if defined (_WIN32)
+ WORD wVersionRequested = MAKEWORD(2, 2);
+ WSADATA wsaData ={.wVersion = 0};
+ int err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "WSAStartup failed: %i", err);
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG(DEBUG, TAG, "WSAStartup Succeeded");
+#endif
if (!IPv4MulticastAddress.s_addr)
{
(void)inet_pton(AF_INET, IPv4_MULTICAST, &IPv4MulticastAddress);
caglobals.ip.u6.port, caglobals.ip.u6s.port, caglobals.ip.u4.port,
caglobals.ip.u4s.port, caglobals.ip.m6.port, caglobals.ip.m6s.port,
caglobals.ip.m4.port, caglobals.ip.m4s.port);
+#if defined (_WIN32)
+ caglobals.ip.wsaRecvMsg = NULL;
+ GUID GuidWSARecvMsg = WSAID_WSARECVMSG;
+ DWORD copied = 0;
+ err = WSAIoctl(caglobals.ip.u4.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidWSARecvMsg, sizeof(GuidWSARecvMsg), &(caglobals.ip.wsaRecvMsg), sizeof(caglobals.ip.wsaRecvMsg), &copied, 0, 0);
+ if (0 != err)
+ {
+ OIC_LOG_V(ERROR, TAG, "WSAIoctl failed %i", WSAGetLastError());
+ return CA_STATUS_FAILED;
+ }
+#endif
// create pipe for fast shutdown
CAInitializePipe();
CHECKFD(caglobals.ip.shutdownFds[0]);
{
caglobals.ip.started = false;
caglobals.ip.terminate = true;
-#if !defined(__msys_nt__)
+#if !defined(_WIN32)
if (caglobals.ip.shutdownFds[1] != -1)
{
// receive thread will stop in SELECT_TIMEOUT seconds.
}
#else
- //msys stuff here
+ /** @todo Refactor to support Windows-specific inter-thread communication code. */
#endif
}
void CAWakeUpForChange()
{
-#if !defined(__msys_nt__)
+#if !defined(_WIN32)
if (caglobals.ip.shutdownFds[1] != -1)
{
ssize_t len = 0;
}
}
#else
- //msys stuff here
+ /** @todo Refactor to support Windows-specific inter-thread communication code. */
#endif
}
-static void applyMulticastToInterface4(struct in_addr inaddr)
+static void applyMulticastToInterface4(uint32_t ifindex)
{
if (!caglobals.ip.ipv4enabled)
{
return;
}
+#if defined(USE_IP_MREQN)
struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
- .imr_address = inaddr,
- .imr_ifindex = 0 };
- if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
+ .imr_address.s_addr = htonl(INADDR_ANY),
+ .imr_ifindex = ifindex };
+#else
+ struct ip_mreq mreq = { .imr_multiaddr = IPv4MulticastAddress,
+ .imr_interface.s_addr = htonl(ifindex) };
+#endif
+
+ int ret = setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq));
+ if (-1 == ret)
{
+#if !defined(WSAEINVAL)
if (EADDRINUSE != errno)
+#else
+ if (WSAEINVAL != WSAGetLastError()) // Joining multicast group more than once (IPv4 Flavor)
+#endif
{
- OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
+ OIC_LOG_V(ERROR, TAG, " IPv4 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
}
}
- if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
+ ret = setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq));
+ if (-1 == ret)
{
+#if !defined(WSAEINVAL)
if (EADDRINUSE != errno)
+#else
+ if (WSAEINVAL != WSAGetLastError()) // Joining multicast group more than once (IPv4 Flavor)
+#endif
{
- OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
+ OIC_LOG_V(ERROR, TAG, "SECURE IPv4 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
}
}
}
static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t ifindex)
{
- struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = ifindex};
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq)))
+ struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr,
+ .ipv6mr_interface = ifindex };
+ int ret = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq));
+ if (-1 == ret)
{
- if (EADDRINUSE != errno)
+#if !defined(_WIN32)
+ if (EADDRINUSE != errno)
+#else
+ if (WSAEINVAL != WSAGetLastError()) // Joining multicast group more than once (IPv6 Flavor)
+#endif
{
- OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", CAIPS_GET_ERROR);
+ OIC_LOG_V(ERROR, TAG, "IPv6 IPV6_JOIN_GROUP failed: %s", CAIPS_GET_ERROR);
}
}
}
u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
if (!iflist)
{
- OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+ OIC_LOG_V(ERROR, TAG, "CAIPGetInterfaceInformation() failed: %s", strerror(errno));
return CA_STATUS_FAILED;
}
{
continue;
}
-#if !defined(__msys_nt__)
- if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
-#else
- //IFF_RUNNING is not on msys or win32
-#endif
+ if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
{
continue;
}
if (ifitem->family == AF_INET)
{
- struct in_addr inaddr;
- inaddr.s_addr = ifitem->ipv4addr;
- applyMulticastToInterface4(inaddr);
- OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name);
+ OIC_LOG_V(DEBUG, TAG, "Adding IPv4 interface %i to multicast group", ifitem->index);
+ applyMulticastToInterface4(ifitem->index);
}
if (ifitem->family == AF_INET6)
{
+ OIC_LOG_V(DEBUG, TAG, "Adding IPv6 interface %i to multicast group", ifitem->index);
applyMulticastToInterface6(ifitem->index);
- OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
}
}
{
continue;
}
-#if !defined(__msys_nt__)
- if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
-#else
- //IFF_RUNNING is not on msys or win32
-#endif
+ if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
{
continue;
}
OIC_LOG(DEBUG, TAG, "ifitem is null");
return;
}
+
if (ifitem->family == AF_INET6)
{
applyMulticastToInterface6(ifitem->index);
}
if (ifitem->family == AF_INET)
{
- struct in_addr inaddr = { .s_addr = ifitem->ipv4addr };
- applyMulticastToInterface4(inaddr);
+ applyMulticastToInterface4(ifitem->index);
}
}
}
char *secure = (endpoint->flags & CA_SECURE) ? "secure " : "";
+
(void)secure; // eliminates release warning
+ (void)cast;
+ (void)fam;
+
struct sockaddr_storage sock;
CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);
socklen_t socklen;
if (sock.ss_family == AF_INET6)
{
- struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock;
- if (!sock6->sin6_scope_id)
- {
- sock6->sin6_scope_id = endpoint->ifindex;
- }
+ /** @todo figure out correct usage for ifindex, and sin6_scope_id */
socklen = sizeof(struct sockaddr_in6);
}
else
{
socklen = sizeof(struct sockaddr_in);
}
-#if !defined(__msys_nt__)
+#if !defined(_WIN32)
ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen);
if (-1 == len)
{
- // If logging is not defined/enabled.
- (void)cast;
- (void)fam;
OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
}
else
OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
}
#else
-
+ int err = 0;
+ int len = 0;
+ int sent = 0;
+ do {
+ len = sendto(fd, ((char*)data) + sent, dlen - sent, 0, (struct sockaddr *)&sock, socklen);
+ if (SOCKET_ERROR == len)
+ {
+ err = WSAGetLastError();
+ if ((WSAEWOULDBLOCK != err) && (WSAENOBUFS != err))
+ {
+ OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %i", secure, cast, fam, err);
+ }
+ }
+ else
+ {
+ 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);
+ }
+ else
+ {
+ OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %ld bytes",
+ secure, cast, fam, len);
+ }
+ }
+ } while ((SOCKET_ERROR == len) && ((WSAEWOULDBLOCK == err) || (WSAENOBUFS == err)) || (sent < dlen));
#endif
}
{
continue;
}
-#if !defined(__msys_nt__)
- if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
-#else
-
-#endif
+ if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
{
continue;
}
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof (index)))
{
OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", CAIPS_GET_ERROR);
-
return;
}
sendData(fd, endpoint, data, datalen, "multicast", "ipv6");
{
VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+#if defined(USE_IP_MREQN)
struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
- .imr_ifindex = 0 };
+ .imr_address.s_addr = htonl(INADDR_ANY),
+ .imr_ifindex = 0};
+#else
+ struct ip_mreq mreq = { .imr_multiaddr = IPv4MulticastAddress,
+ .imr_interface = {0}};
+#endif
+
OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST);
int fd = caglobals.ip.u4.fd;
{
continue;
}
-#if !defined(__msys_nt__)
- if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
-#else
-
-#endif
+ if ((ifitem->flags & IFF_UP_RUNNING_FLAGS) != IFF_UP_RUNNING_FLAGS)
{
continue;
}
{
continue;
}
-
- struct in_addr inaddr;
- inaddr.s_addr = ifitem->ipv4addr;
- mreq.imr_address = inaddr;
+#if defined(USE_IP_MREQN)
+ mreq.imr_ifindex = ifitem->index;
+#else
+ mreq.imr_interface.s_addr = htonl(ifitem->index);
+#endif
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq)))
{
OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",
{
eps[j].flags = CA_IPV4;
eps[j].port = caglobals.ip.u4.port;
-
- inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA);
+ /** @todo eps[j].addr not populated with IPv4 address string.
+ * it was using ifitem->ipv4addr to accomplish this.
+ * Need to understand what ipv4addr means to whom*/
}
#ifdef __WITH_DTLS__
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2016 Intel Corporation
+*
+*
+*
+* 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 "caipinterface.h"
+
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <winsock2.h>
+#include <iptypes.h>
+#include <stdbool.h>
+#include "caadapterutils.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+
+#define TAG "IP_MONITOR"
+
+/** @todo Implement network interface monitoring in case the IP changes.
+ * Not critical for win32 bring-up.
+ */
+CAResult_t CAIPStartNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+/** @todo Implement network interface monitoring in case the IP changes.
+ * Not critical for win32 bring-up.
+ */
+CAResult_t CAIPStopNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+/** @todo Implement network interface monitoring.
+ * Not used in win32, but caipserver currently requires this function
+ * be defined. not critical.
+ */
+int CAGetPollingInterval(int interval)
+{
+ return interval;
+}
+
+/** @todo Implement network interface monitoring.
+ * Not critical for win32 bring-up.
+ */
+void CAIPSetNetworkMonitorCallback(CAIPConnectionStateChangeCallback callback)
+{
+ return;
+}
+
+bool IsValidAdapter(PIP_ADAPTER_ADDRESSES pAdapterAddr, int desiredIndex, uint16_t family)
+{
+ bool valid = true;
+
+ // If desiredIndex is non-zero, then only retrieve adapter corresponding to desiredIndex.
+ // If desiredIndex is zero, then retrieve all adapters.
+ if (desiredIndex && (pAdapterAddr->IfIndex != desiredIndex))
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i not interesting.", pAdapterAddr->IfIndex);
+ valid = false;
+ }
+
+ if (pAdapterAddr->IfType & IF_TYPE_SOFTWARE_LOOPBACK)
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i is loopback.", pAdapterAddr->IfIndex);
+ valid = false;
+ }
+
+ // If the adapter must support the requested family
+ if ((family == AF_INET6) && ((pAdapterAddr->Flags & IP_ADAPTER_IPV6_ENABLED) == 0))
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i does not support IPv6", pAdapterAddr->IfIndex);
+ valid = false;
+ }
+ else if ((family == AF_INET) && ((pAdapterAddr->Flags & IP_ADAPTER_IPV4_ENABLED) == 0))
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i does not support IPv4", pAdapterAddr->IfIndex);
+ valid = false;
+ }
+
+ if ((pAdapterAddr->OperStatus & IfOperStatusUp) == 0)
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i is not operational.", pAdapterAddr->IfIndex);
+ valid = false;
+ }
+ return valid;
+
+}
+
+
+bool AddCAInterface(u_arraylist_t *iflist, const char * name, uint32_t index, uint16_t family)
+{
+ bool bSucceeded = false;
+ CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(*ifitem));
+ if (ifitem)
+ {
+ OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
+ ifitem->index = index;
+ ifitem->family = family;
+ ifitem->flags |= IFF_UP;// IsValidAddress() will have filtered out non-operational addresses already.
+
+ if (u_arraylist_add(iflist, ifitem))
+ {
+ bSucceeded = true;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed");
+ OICFree(ifitem);
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Allocating memory for a CAInterface_t failed");
+ }
+ return bSucceeded;
+}
+
+bool AddInterfaces(PIP_ADAPTER_ADDRESSES pAdapterAddr, u_arraylist_t *iflist, int desiredIndex)
+{
+ bool bSucceeded = false;
+ for (PIP_ADAPTER_ADDRESSES pCurAdapterAddr = pAdapterAddr;
+ pCurAdapterAddr != NULL; pCurAdapterAddr = pCurAdapterAddr->Next)
+ {
+ OIC_LOG_V(DEBUG, TAG, "\tInterface Index: %u", pCurAdapterAddr->IfIndex);
+ OIC_LOG_V(DEBUG, TAG, "\tInterface name: %s", pCurAdapterAddr->AdapterName);
+
+ // Prefer IPv6 over IPv4.
+ if (pCurAdapterAddr->Flags & IP_ADAPTER_IPV6_ENABLED)
+ {
+ // Do not add loopback, duplicate, or non-operational adapters
+ if (IsValidAdapter(pCurAdapterAddr, desiredIndex, AF_INET6))
+ {
+ if (AddCAInterface(iflist, pCurAdapterAddr->AdapterName, pCurAdapterAddr->IfIndex, AF_INET6))
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tAdded IPv6 interface %i", pCurAdapterAddr->IfIndex);
+ bSucceeded = true;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "\tAdding IPv6 interface %i failed", pCurAdapterAddr->IfIndex);
+ break;
+ }
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tIPv6 interface %i not valid, skipping...", pCurAdapterAddr->IfIndex);
+ }
+ }
+ else if (pCurAdapterAddr->Flags & IP_ADAPTER_IPV4_ENABLED)
+ {
+ // Do not add loopback, duplicate, or non-operational adapters
+ if (IsValidAdapter(pCurAdapterAddr, desiredIndex, AF_INET))
+ {
+ if (AddCAInterface(iflist, pCurAdapterAddr->AdapterName, pCurAdapterAddr->IfIndex, AF_INET))
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tAdded IPv4 interface %i", pCurAdapterAddr->IfIndex);
+ bSucceeded = true;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "\tAdding IPv4 interface %i failed", pCurAdapterAddr->IfIndex);
+ break;
+ }
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "\t\tIPv6 interface %i not valid, skipping...", pCurAdapterAddr->IfIndex);
+ }
+
+ }
+ }
+ return bSucceeded;
+}
+
+PIP_ADAPTER_ADDRESSES GetAdapters()
+{
+ ULONG ulOutBufLen = sizeof(IP_ADAPTER_ADDRESSES);
+ PIP_ADAPTER_ADDRESSES pAdapterAddr = (IP_ADAPTER_ADDRESSES *) OICMalloc(ulOutBufLen);
+ if (pAdapterAddr != NULL)
+ {
+ ULONG flags = 0;
+ ULONG ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapterAddr, &ulOutBufLen);
+ if (ERROR_BUFFER_OVERFLOW == ret)
+ {
+ // Redo with updated length
+ OICFree(pAdapterAddr);
+ pAdapterAddr = (PIP_ADAPTER_ADDRESSES) OICMalloc(ulOutBufLen);
+ if (pAdapterAddr != NULL) {
+ ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapterAddr, &ulOutBufLen);
+ if (NO_ERROR != ret)
+ {
+ OIC_LOG(ERROR, TAG, "GetAdaptersAddresses() failed");
+ OICFree(pAdapterAddr);
+ pAdapterAddr = NULL;
+ }
+ else
+ {
+ // Succeeded getting adapters
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Second time allocating memory for GetAdaptersAddresses() failed");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Expected GetAdaptersAddresses() to fail on first try, but it didn't.");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "First time allocating memory for GetAdaptersAddresses() failed");
+ }
+ return pAdapterAddr;
+}
+
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
+{
+ u_arraylist_t *iflist = u_arraylist_create();
+ if (iflist)
+ {
+ PIP_ADAPTER_ADDRESSES pAdapterAddr = NULL;
+ pAdapterAddr = GetAdapters();
+ if (pAdapterAddr)
+ {
+ // Cycle through adapters
+ // Add valid adapters to the interface list.
+ bool ret = AddInterfaces(pAdapterAddr, iflist, desiredIndex);
+ if (false == ret)
+ {
+ OIC_LOG(ERROR, TAG, "AddInterfaces() failed");
+ u_arraylist_destroy(iflist);
+ iflist = NULL;
+ }
+
+ // Finished with Adapter List
+ OICFree(pAdapterAddr);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Enumerating Adapters failed");
+ u_arraylist_destroy(iflist);
+ iflist = NULL;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create iflist");
+ }
+ return iflist;
+}