static void CAProcessNewInterface(CAInterface_t *ifitem) { applyMulticastToInterface6(ifitem->index); struct in_addr inaddr; inaddr.s_addr = ifitem->ipv4addr; applyMulticastToInterface4(inaddr); }
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 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); } }
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); } }