diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ce3d178..67db14e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -855,7 +855,8 @@ target_link_libraries( $<$:${MBEDX509_LIBRARY}> $<$:${MBEDCRYPTO_LIBRARY}> $<$:${WOLFSSL_LIBRARY}> - $<$:ws2_32>) + $<$:ws2_32> + $<$:iphlpapi>) target_compile_options( ${COAP_LIBRARY_NAME} diff --git a/src/coap_address.c b/src/coap_address.c index 1393bdf8..c7e8f182 100644 --- a/src/coap_address.c +++ b/src/coap_address.c @@ -173,11 +173,11 @@ coap_is_mcast(const coap_address_t *a) { #define COAP_BCST_REFRESH_SECS 30 #endif /* COAP_BCST_REFRESH_SECS */ -#if COAP_IPV4_SUPPORT && defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__) +#if (COAP_IPV4_SUPPORT && defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__)) || defined(_WIN32) static int bcst_cnt = -1; static coap_tick_t last_refresh; static struct in_addr b_ipv4[COAP_BCST_CNT]; -#endif /* COAP_IPV4_SUPPORT && HAVE_IFADDRS_H && !defined(__ZEPHYR__) */ +#endif /* (COAP_IPV4_SUPPORT && HAVE_IFADDRS_H && !defined(__ZEPHYR__)) || defined(_WIN32) */ int coap_is_bcast(const coap_address_t *a) { @@ -219,7 +219,7 @@ coap_is_bcast(const coap_address_t *a) { if (ipv4.s_addr == INADDR_BROADCAST) return 1; -#if defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__) +#if defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__) && !defined(_WIN32) coap_ticks(&now); if (bcst_cnt == -1 || (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) { @@ -261,9 +261,81 @@ coap_is_bcast(const coap_address_t *a) { if (ipv4.s_addr == b_ipv4[i].s_addr) return 1; } -#endif /* HAVE_IFADDRS_H && !defined(__ZEPHYR__) */ - return 0; +#endif /* HAVE_IFADDRS_H && !defined(__ZEPHYR__) && !defined(_WIN32) */ + +#if defined(_WIN32) + +#include +#if !defined(__MINGW32__) +#pragma comment(lib, "iphlpapi.lib") +#endif /* ! __MINGW32__ */ + + int i; + coap_tick_t now; + + coap_ticks(&now); + if (bcst_cnt == -1 || + (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) { + /* Determine the list of broadcast interfaces */ + + /* Variables used by GetIpAddrTable */ + PMIB_IPADDRTABLE pIPAddrTable; + DWORD dwSize = 0; + DWORD dwRetVal = 0; + + /* Assume just 2 interfaces as a starting point */ + pIPAddrTable = (MIB_IPADDRTABLE *)coap_malloc_type(COAP_STRING, 2 * sizeof(MIB_IPADDRTABLE)); + + if (pIPAddrTable) { + /* Check that 2 interfaces are sufficient */ + if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { + coap_free_type(COAP_STRING, pIPAddrTable); + pIPAddrTable = (MIB_IPADDRTABLE *)coap_malloc_type(COAP_STRING, dwSize); + + } + if (pIPAddrTable == NULL) { + coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n"); + return 0; + } + } + /* Now get the actual data */ + if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) { + coap_log_warn("GetIpAddrTable failed with error %d\n", dwRetVal); + return 0; + } + + bcst_cnt = 0; + last_refresh = now; + + for (i = 0; i < (int)pIPAddrTable->dwNumEntries && bcst_cnt < COAP_BCST_CNT; i++) { + struct in_addr netmask; + + /* Unsafe to use dwBCastAddr */ + netmask.s_addr = (u_long)pIPAddrTable->table[i].dwMask; + if (netmask.s_addr != 0xffffffff) { + b_ipv4[bcst_cnt].s_addr = (u_long)pIPAddrTable->table[i].dwAddr | + ~netmask.s_addr; + bcst_cnt++; + } + } + if (i != (int)pIPAddrTable->dwNumEntries) { + coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n"); + } + + if (pIPAddrTable) { + coap_free_type(COAP_STRING, pIPAddrTable); + pIPAddrTable = NULL; + } + } + + for (i = 0; i < bcst_cnt; i++) { + if (ipv4.s_addr == b_ipv4[i].s_addr) + return 1; + } +#endif /* _WIN32 */ + #endif /* COAP_IPV4_SUPPORT */ + return 0; } #endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */ diff --git a/src/coap_io.c b/src/coap_io.c index c8b7a68b..8bc1caa1 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -627,6 +627,9 @@ coap_win_error_to_errno(void) { case WSAECONNREFUSED: errno = ECONNREFUSED; break; + case WSAEADDRNOTAVAIL: + errno = EADDRNOTAVAIL; + break; default: coap_log_err("WSAGetLastError: %d mapping to errno failed - please fix\n", w_error);