CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { OIC_LOG(DEBUG, TAG, "IN"); VERIFY_NON_NULL(info, TAG, "info is NULL"); VERIFY_NON_NULL(size, TAG, "size is NULL"); u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG(ERROR, TAG, "get interface info failed"); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t)); if (!eps) { OIC_LOG(ERROR, TAG, "Malloc Failed"); u_arraylist_destroy(iflist); return CA_MEMORY_ALLOC_FAILED; } for (uint32_t i = 0, j = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if(!ifitem) { continue; } unsigned char *addr= (unsigned char *) &(ifitem->ipv4addr); snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); eps[j].flags = CA_IPV4; eps[j].adapter = CA_ADAPTER_IP; eps[j].interface = 0; eps[j].port = caglobals.ip.u4.port; j++; } *info = eps; *size = len; u_arraylist_destroy(iflist); OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; }
CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { OIC_LOG(DEBUG, TAG, "IN"); VERIFY_NON_NULL(info, TAG, "info is NULL"); VERIFY_NON_NULL(size, TAG, "size is NULL"); u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t)); if (!eps) { OIC_LOG(ERROR, TAG, "Malloc Failed"); u_arraylist_destroy(iflist); return CA_MEMORY_ALLOC_FAILED; } for (uint32_t i = 0, j = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if(!ifitem) { continue; } OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name); eps[j].flags = ifitem->family == AF_INET6 ? CA_IPV6 : CA_IPV4; eps[j].adapter = CA_ADAPTER_IP; eps[j].interface = 0; eps[j].port = 0; j++; } *info = eps; *size = len; u_arraylist_destroy(iflist); OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; }
void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, void *userData) { OIC_LOG(DEBUG, TAG, "IN"); if (WIFI_CONNECTION_STATE_ASSOCIATION == state || WIFI_CONNECTION_STATE_CONFIGURATION == state) { OIC_LOG(DEBUG, TAG, "Connection is in Association State"); return; } if (WIFI_CONNECTION_STATE_CONNECTED == state) { CAWakeUpForChange(); } else { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed"); return; } u_arraylist_destroy(iflist); } OIC_LOG(DEBUG, TAG, "OUT"); }
OCStackResult TerminateKeepAlive(OCMode mode) { OIC_LOG(DEBUG, TAG, "TerminateKeepAlive IN"); if (!g_isKeepAliveInitialized) { OIC_LOG(ERROR, TAG, "KeepAlive not initialized"); return OC_STACK_ERROR; } if (OC_CLIENT != mode) { // Delete the KeepAlive Resource[/oic/ping]. OCStackResult result = DeleteKeepAliveResource(); if (OC_STACK_OK != result) { OIC_LOG_V(ERROR, TAG, "DeleteKeepAliveResource failed[%d]", result); return result; } } if (NULL != g_keepAliveConnectionTable) { u_arraylist_destroy(g_keepAliveConnectionTable); g_keepAliveConnectionTable = NULL; } g_isKeepAliveInitialized = false; OIC_LOG(DEBUG, TAG, "TerminateKeepAlive OUT"); return OC_STACK_OK; }
void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen, bool isMulticast) { VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); bool isSecure = (endpoint->flags & CA_SECURE) != 0; if (isMulticast) { endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return; } if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled) { sendMulticastData6(iflist, endpoint, data, datalen); } if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled) { sendMulticastData4(iflist, endpoint, data, datalen); } u_arraylist_destroy(iflist); } else { if (!endpoint->port) // unicast discovery { endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; } int fd; if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6)) { fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd; #ifndef __WITH_DTLS__ fd = caglobals.ip.u6.fd; #endif sendData(fd, endpoint, data, datalen, "unicast", "ipv6"); } if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4)) { fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd; #ifndef __WITH_DTLS__ fd = caglobals.ip.u4.fd; #endif sendData(fd, endpoint, data, datalen, "unicast", "ipv4"); } } }
static void CAHandleNetlink() { #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; struct iovec iov = { buf, sizeof (buf) }; struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) { continue; } int newIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); 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; } if ((int)ifitem->index != newIndex) { continue; } CAProcessNewInterface(ifitem); break; // we found the one we were looking for } u_arraylist_destroy(iflist); } #endif // __linux__ }
static void CAIPDestroyNetworkMonitorList() { if (g_netInterfaceList) { u_arraylist_destroy(g_netInterfaceList); g_netInterfaceList = NULL; } if (g_networkMonitorContextMutex) { ca_mutex_free(g_networkMonitorContextMutex); g_networkMonitorContextMutex = NULL; } }
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { bool result = true; u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { OIC_LOG(ERROR, TAG, "Failed to create iflist"); return NULL; } CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); if (!ifitem) { OIC_LOG(ERROR, TAG, "Malloc failed"); goto exit; } // Since Arduino currently only supports one interface, the next 4 lines are sufficient. OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "WIFI"); ifitem->index = 1; ifitem->family = AF_INET; ifitem->flags = 0; CAArduinoGetInterfaceAddress(ifitem->addr, sizeof(ifitem->addr)); result = u_arraylist_add(iflist, ifitem); if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; } OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family); return iflist; exit: u_arraylist_destroy(iflist); return NULL; }
static void CAApplyInterfaces() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 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); } if (ifitem->family == AF_INET6) { applyMulticastToInterface6(ifitem->index); OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); }
static void CATCPDisconnectAll() { OIC_LOG(DEBUG, TAG, "IN"); ca_mutex_lock(g_mutexObjectList); uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); CATCPServerInfo_t *svritem = NULL; for (size_t i = 0; i < length; i++) { svritem = (CATCPServerInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem && svritem->u4tcp.fd >= 0) { shutdown(svritem->u4tcp.fd, SHUT_RDWR); close(svritem->u4tcp.fd); } } u_arraylist_destroy(caglobals.tcp.svrlist); caglobals.tcp.svrlist = NULL; ca_mutex_unlock(g_mutexObjectList); OIC_LOG(DEBUG, TAG, "OUT"); }
static void applyMulticastToInterface4(struct in_addr inaddr) { if (!caglobals.ip.ipv4enabled) { return; } 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))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) { struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface}; if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticastToInterface6(uint32_t interface) { if (!caglobals.ip.ipv6enabled) { return; } //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface); } CAResult_t CAIPStartListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 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); } if (ifitem->family == AF_INET6) { applyMulticastToInterface6(ifitem->index); OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } CAResult_t CAIPStopListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family == AF_INET) { close(caglobals.ip.m4.fd); close(caglobals.ip.m4s.fd); caglobals.ip.m4.fd = -1; caglobals.ip.m4s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name); } if (ifitem->family == AF_INET6) { close(caglobals.ip.m6.fd); close(caglobals.ip.m6s.fd); caglobals.ip.m6.fd = -1; caglobals.ip.m6s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } static void CAProcessNewInterface(CAInterface_t *ifitem) { if (!ifitem) { OIC_LOG(DEBUG, TAG, "ifitem is null"); return; } applyMulticastToInterface6(ifitem->index); struct in_addr inaddr = { .s_addr = ifitem->ipv4addr }; applyMulticastToInterface4(inaddr); } static void CAHandleNetlink() { #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; struct iovec iov = { buf, sizeof (buf) }; struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) { continue; } int newIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); 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; } if ((int)ifitem->index != newIndex) { continue; } CAProcessNewInterface(ifitem); break; // we found the one we were looking for } u_arraylist_destroy(iflist); } #endif // __linux__ } void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) { g_packetReceivedCallback = callback; } void CAIPSetExceptionCallback(CAIPExceptionCallback callback) { g_exceptionCallback = callback; } static void sendData(int fd, const CAEndpoint_t *endpoint, const void *data, uint32_t dlen, const char *cast, const char *fam) { OIC_LOG(DEBUG, TAG, "IN"); if (!endpoint) { OIC_LOG(DEBUG, TAG, "endpoint is null"); return; } char *secure = (endpoint->flags & CA_SECURE) ? "secure " : ""; (void)secure; // eliminates release warning 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->interface; } socklen = sizeof(struct sockaddr_in6); } else { socklen = sizeof(struct sockaddr_in); } 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); } }
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); 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) { 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; } caglobals.ip.nm.numIfItems = 0; for (size_t i = 0; i < interfaces; i++) { CAResult_t result = CA_STATUS_OK; struct ifreq* item = &ifr[i]; char *name = item->ifr_name; struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; uint32_t ipv4addr = sa4->sin_addr.s_addr; 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; } // Add IPv4 interface result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags); if (CA_STATUS_OK != result) { goto exit; } // Add IPv6 interface result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags); if (CA_STATUS_OK != result) { goto exit; } } return iflist; exit: u_arraylist_destroy(iflist); return NULL; }
CAInterface_t *CAFindInterfaceChange() { CAInterface_t *foundNewInterface = NULL; #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; struct iovec iov = { buf, sizeof (buf) }; struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh != NULL && nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); int ifiIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(ifiIndex); if ((!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))) { bool isFound = CACmpNetworkList(ifiIndex); if (isFound) { CARemoveNetworkMonitorList(ifiIndex); if (g_networkChangeCallback) { g_networkChangeCallback(CA_ADAPTER_IP ,CA_INTERFACE_DOWN); } } continue; } if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return NULL; } 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; } if ((int)ifitem->index != ifiIndex) { continue; } foundNewInterface = CANewInterfaceItem(ifitem->index, ifitem->name, ifitem->family, ifitem->ipv4addr, ifitem->flags); break; // we found the one we were looking for } u_arraylist_destroy(iflist); } #endif return foundNewInterface; }
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { if (desiredIndex < 0) { OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex); return NULL; } u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); return NULL; } struct ifaddrs *ifp = NULL; if (-1 == getifaddrs(&ifp)) { OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); u_arraylist_destroy(iflist); return NULL; } OIC_LOG(DEBUG, TAG, "Got ifaddrs"); struct ifaddrs *ifa = NULL; for (ifa = ifp; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) { continue; } int family = ifa->ifa_addr->sa_family; if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) { continue; } int ifindex = if_nametoindex(ifa->ifa_name); if (desiredIndex && (ifindex != desiredIndex)) { continue; } int length = u_arraylist_length(iflist); int already = false; for (int i = length-1; i >= 0; i--) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (ifitem && (int)ifitem->index == ifindex && ifitem->family == (uint16_t)family) { already = true; break; } } if (already) { continue; } CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); if (!ifitem) { OIC_LOG(ERROR, TAG, "Malloc failed"); goto exit; } OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name); ifitem->index = ifindex; ifitem->family = family; ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; ifitem->flags = ifa->ifa_flags; bool result = u_arraylist_add(iflist, ifitem); if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; } OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, family); } freeifaddrs(ifp); return iflist; exit: freeifaddrs(ifp); u_arraylist_destroy(iflist); return NULL; }
CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { VERIFY_NON_NULL(info, TAG, "info is NULL"); VERIFY_NON_NULL(size, TAG, "size is NULL"); u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); uint32_t length = len; #ifdef __WITH_DTLS__ //If DTLS is supported, each interface can support secure port as well length = len * 2; #endif CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(length, sizeof (CAEndpoint_t)); if (!eps) { OIC_LOG(ERROR, TAG, "Malloc Failed"); u_arraylist_destroy(iflist); return CA_MEMORY_ALLOC_FAILED; } for (uint32_t i = 0, j = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if(!ifitem) { continue; } eps[j].adapter = CA_ADAPTER_IP; eps[j].interface = 0; if (ifitem->family == AF_INET6) { eps[j].flags = CA_IPV6; eps[j].port = caglobals.ip.u6.port; } else { 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); } #ifdef __WITH_DTLS__ j++; eps[j].adapter = CA_ADAPTER_IP; eps[j].interface = 0; if (ifitem->family == AF_INET6) { eps[j].flags = CA_IPV6 | CA_SECURE; eps[j].port = caglobals.ip.u6s.port; } else { eps[j].flags = CA_IPV4 | CA_SECURE; eps[j].port = caglobals.ip.u4s.port; inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA); } #endif j++; } *info = eps; *size = len; u_arraylist_destroy(iflist); return CA_STATUS_OK; }
static void sendMulticastData4(const u_arraylist_t *iflist, CAEndpoint_t *endpoint, const void *data, uint32_t datalen) { VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress, .imr_ifindex = 0 }; OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST); int fd = caglobals.ip.u4.fd; uint32_t len = u_arraylist_length(iflist); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family != AF_INET) { continue; } struct in_addr inaddr; inaddr.s_addr = ifitem->ipv4addr; mreq.imr_address = inaddr; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq))) { OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)", strerror(errno)); } sendData(fd, endpoint, data, datalen, "multicast", "ipv4"); } } void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen, bool isMulticast) { VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); bool isSecure = (endpoint->flags & CA_SECURE) != 0; if (isMulticast) { endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return; } if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled) { sendMulticastData6(iflist, endpoint, data, datalen); } if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled) { sendMulticastData4(iflist, endpoint, data, datalen); } u_arraylist_destroy(iflist); } else { if (!endpoint->port) // unicast discovery { endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; } int fd; if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6)) { fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd; #ifndef __WITH_DTLS__ fd = caglobals.ip.u6.fd; #endif sendData(fd, endpoint, data, datalen, "unicast", "ipv6"); } if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4)) { fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd; #ifndef __WITH_DTLS__ fd = caglobals.ip.u4.fd; #endif sendData(fd, endpoint, data, datalen, "unicast", "ipv4"); } } }
static void applyMulticastToInterface4(struct in_addr inaddr) { if (!caglobals.ip.ipv4enabled) { return; } 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))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) { struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface}; if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticastToInterface6(uint32_t interface) { if (!caglobals.ip.ipv6enabled) { return; } //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface); } CAResult_t CAIPStartListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 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); } if (ifitem->family == AF_INET6) { applyMulticastToInterface6(ifitem->index); OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } CAResult_t CAIPStopListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family == AF_INET) { close(caglobals.ip.m4.fd); close(caglobals.ip.m4s.fd); caglobals.ip.m4.fd = -1; caglobals.ip.m4s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name); } if (ifitem->family == AF_INET6) { close(caglobals.ip.m6.fd); close(caglobals.ip.m6s.fd); caglobals.ip.m6.fd = -1; caglobals.ip.m6s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } static void CAProcessNewInterface(CAInterface_t *ifitem) { if (!ifitem) { 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); } } void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) { g_packetReceivedCallback = callback; } void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) { CAIPSetNetworkMonitorCallback(callback); } static void sendData(int fd, const CAEndpoint_t *endpoint, const void *data, uint32_t dlen, const char *cast, const char *fam) { OIC_LOG(DEBUG, TAG, "IN"); if (!endpoint) { OIC_LOG(DEBUG, TAG, "endpoint is null"); if (g_ipErrorHandler) { g_ipErrorHandler(endpoint, data, dlen, CA_STATUS_INVALID_PARAM); } return; } char *secure = (endpoint->flags & CA_SECURE) ? "secure " : ""; (void)secure; // eliminates release warning 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->interface; } socklen = sizeof(struct sockaddr_in6); } else { socklen = sizeof(struct sockaddr_in); } 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; if (g_ipErrorHandler) { g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED); } 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); } }