diff --git a/ports/win32/bacport.h b/ports/win32/bacport.h index b9e27e74..0348875d 100644 --- a/ports/win32/bacport.h +++ b/ports/win32/bacport.h @@ -70,6 +70,12 @@ and globals in favor of more secure versions. */ #endif #include +#if defined(__BORLANDC__) || defined(_WIN32) +/* seems to not be defined in time.h as specified by The Open Group */ +/* difference from UTC and local standard time */ +long int timezone; +#endif + #ifdef _MSC_VER #define inline __inline #endif @@ -79,6 +85,7 @@ and globals in favor of more secure versions. */ #ifdef _WIN32 #define strncasecmp(x, y, z) _strnicmp(x, y, z) +#define snprintf _snprintf #endif #endif diff --git a/ports/win32/bip6.c b/ports/win32/bip6.c index 336d92eb..7fb2440b 100644 --- a/ports/win32/bip6.c +++ b/ports/win32/bip6.c @@ -67,19 +67,21 @@ static bool BIP6_Debug = false; /** * @brief Print the IPv6 address with debug info * @param str - debug info string - * @param addr - IPv4 address + * @param addr - IPv6 address */ static void debug_print_ipv6(const char *str, const struct in6_addr *addr) { - PRINTF("BIP6: %s " - "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%" - "02x:%02x%02x\n", - str, (int)addr->s6_addr[0], (int)addr->s6_addr[1], - (int)addr->s6_addr[2], (int)addr->s6_addr[3], (int)addr->s6_addr[4], - (int)addr->s6_addr[5], (int)addr->s6_addr[6], (int)addr->s6_addr[7], - (int)addr->s6_addr[8], (int)addr->s6_addr[9], (int)addr->s6_addr[10], - (int)addr->s6_addr[11], (int)addr->s6_addr[12], (int)addr->s6_addr[13], - (int)addr->s6_addr[14], (int)addr->s6_addr[15]); +#if PRINT_ENABLED + char addstr[40] = {}; + BACNET_IP6_ADDRESS bip6_addr = {}; + + if (str && addr) { + memcpy(&bip6_addr.address[0], &addr->s6_addr[0], IP6_ADDRESS_MAX); + bvlc6_address_to_ascii(&bip6_addr, addstr, + sizeof(addstr)); + PRINTF("BIP6: %s %s\n", str, addstr); + } +#endif } /** @@ -111,10 +113,10 @@ void bip6_set_interface(char *ifname) int i, RetVal; struct addrinfo Hints, *AddrInfo, *AI; struct sockaddr_in6 *sin; - struct sockaddr_in6 server; - struct in6_addr broadcast_address; - struct ipv6_mreq join_request; - SOCKET ServSock[FD_SETSIZE]; + struct sockaddr_in6 server = {}; + struct in6_addr broadcast_address = {}; + struct ipv6_mreq join_request = {}; + SOCKET ServSock[FD_SETSIZE] = {}; char port[6] = ""; int sockopt = 0; @@ -126,12 +128,12 @@ void bip6_set_interface(char *ifname) // for that family. // memset(&Hints, 0, sizeof(Hints)); - Hints.ai_family = PF_INET6; + Hints.ai_family = AF_INET6; Hints.ai_socktype = SOCK_DGRAM; Hints.ai_protocol = IPPROTO_UDP; Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE; snprintf(port, sizeof(port), "%u", BIP6_Addr.port); - PRINTF("BIP6: getaddrinfo - IPv6 address %s port %s\n", ifname, port); + PRINTF("BIP6: seeking IPv6 address %s port %s...\n", ifname, port); RetVal = getaddrinfo(ifname, &port[0], &Hints, &AddrInfo); if (RetVal != 0) { fprintf(stderr, "BIP6: getaddrinfo failed with error %d: %s\n", RetVal, @@ -139,6 +141,7 @@ void bip6_set_interface(char *ifname) WSACleanup(); return; } + PRINTF("BIP6: getaddrinfo() succeeded!\n"); // // Find the first matching address getaddrinfo returned so that // we can create a new socket and bind that address to it, @@ -152,8 +155,8 @@ void bip6_set_interface(char *ifname) "use.\n"); break; } - // only support PF_INET6. - if (AI->ai_family != PF_INET6) { + // only support AF_INET6. + if (AI->ai_family != AF_INET6) { continue; } // only support SOCK_DGRAM. @@ -164,13 +167,13 @@ void bip6_set_interface(char *ifname) if (AI->ai_protocol != IPPROTO_UDP) { continue; } - BIP6_Socket = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + BIP6_Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (BIP6_Socket == INVALID_SOCKET) { fprintf(stderr, "BIP6: socket() failed with error %d: %s\n", WSAGetLastError(), PrintError(WSAGetLastError())); continue; } - if ((AI->ai_family == PF_INET6) && IN6_IS_ADDR_LINKLOCAL(AI->ai_addr) && + if ((AI->ai_family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL(AI->ai_addr) && (((SOCKADDR_IN6 *)(AI->ai_addr))->sin6_scope_id == 0)) { fprintf( stderr, "BIP6: IPv6 link local addresses needs a scope ID!\n"); @@ -183,6 +186,9 @@ void bip6_set_interface(char *ifname) if (RetVal < 0) { closesocket(BIP6_Socket); BIP6_Socket = INVALID_SOCKET; + fprintf(stderr, + "BIP6: setsockopt(SO_REUSEADDR) failed with error %d: %s\n", + WSAGetLastError(), PrintError(WSAGetLastError())); continue; } /* allow us to send a broadcast */ @@ -219,7 +225,7 @@ void bip6_set_interface(char *ifname) // that clients know about in advance. // memset(&server, 0, sizeof(server)); - server.sin6_family = PF_INET6; + server.sin6_family = AF_INET6; server.sin6_port = htons(BIP6_Addr.port); server.sin6_addr = in6addr_any; if (bind(BIP6_Socket, (struct sockaddr *)&server, sizeof(server)) == @@ -238,6 +244,7 @@ void bip6_set_interface(char *ifname) ntohs(sin->sin6_addr.s6_addr16[5]), ntohs(sin->sin6_addr.s6_addr16[6]), ntohs(sin->sin6_addr.s6_addr16[7])); + debug_print_ipv6("bind() succeeded!", &sin->sin6_addr); /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx */ } @@ -247,6 +254,9 @@ void bip6_set_interface(char *ifname) } } freeaddrinfo(AddrInfo); + if (BIP6_Socket == INVALID_SOCKET) { + fprintf(stderr, "BIP6: AF_INET6 address not found getaddrinfo()\n"); + } } /** @@ -385,7 +395,7 @@ int bip6_send_mpdu(BACNET_IP6_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len) bvlc_dest.sin6_addr.s6_addr16[6] = htons(addr16[6]); bvlc_dest.sin6_addr.s6_addr16[7] = htons(addr16[7]); bvlc_dest.sin6_port = htons(dest->port); - debug_print_ipv6("BIP6: Sending MPDU->", &bvlc_dest.sin6_addr); + debug_print_ipv6("Sending MPDU->", &bvlc_dest.sin6_addr); /* Send the packet */ return sendto(BIP6_Socket, (char *)mtu, mtu_len, 0, (struct sockaddr *)&bvlc_dest, sizeof(bvlc_dest)); @@ -497,7 +507,7 @@ uint16_t bip6_receive( void bip6_cleanup(void) { if (BIP6_Socket != -1) { - close(BIP6_Socket); + closesocket(BIP6_Socket); } BIP6_Socket = -1; WSACleanup(); diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c index 76f8141b..2d1fa0a9 100644 --- a/src/bacnet/bacapp.c +++ b/src/bacnet/bacapp.c @@ -54,10 +54,6 @@ /** @file bacapp.c Utilities for the BACnet_Application_Data_Value */ -#if defined(_MSC_VER) -#define snprintf _snprintf -#endif - /** @brief Encode application data given by a pointer into the APDU. * Return the number encoded bytes. * diff --git a/src/bacnet/basic/object/gateway/gw_device.c b/src/bacnet/basic/object/gateway/gw_device.c index dff8217e..c8957773 100644 --- a/src/bacnet/basic/object/gateway/gw_device.c +++ b/src/bacnet/basic/object/gateway/gw_device.c @@ -62,12 +62,6 @@ /* os specfic includes */ #include "bacnet/basic/sys/mstimer.h" -#if defined(__BORLANDC__) || defined(_WIN32) -/* seems to not be defined in time.h as specified by The Open Group */ -/* difference from UTC and local standard time */ -long int timezone; -#endif - /* local forward and external prototypes */ extern int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata); extern bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data); diff --git a/src/bacnet/datalink/bvlc6.c b/src/bacnet/datalink/bvlc6.c index f177891d..e1e2a75a 100644 --- a/src/bacnet/datalink/bvlc6.c +++ b/src/bacnet/datalink/bvlc6.c @@ -34,6 +34,7 @@ #include /* for standard integer types uint8_t etc. */ #include /* for the standard bool type. */ +#include #include "bacnet/bacenum.h" #include "bacnet/bacdcode.h" #include "bacnet/bacint.h" @@ -640,6 +641,96 @@ bool bvlc6_address_get(BACNET_IP6_ADDRESS *addr, return status; } +/** Convert IPv6 Address from ASCII + * + * IPv6 addresses are represented as eight groups, separated by colons, + * of four hexadecimal digits. + * + * For convenience, an IPv6 address may be abbreviated to shorter notations + * by application of the following rules according to RFC 5952 [1]: + * - One or more leading zeros from any groups of hexadecimal digits + * are removed; this is usually done to either all or none of the + * leading zeros. For example, the group 0042 is converted to 42. + * - Consecutive sections of zeros are replaced with a double colon (::). + * The double colon may only be used once in an address, as multiple + * use would render the address indeterminate. RFC 5952 requires that + * a double colon not be used to denote an omitted single section of + * zeros. + * + * [1] https://www.rfc-editor.org/rfc/rfc5952 + * + * Adapted from the uIP TCP/IP stack and the Contiki operating system. + * Thank you, Adam Dunkel, and the Swedish Institute of Computer Science. + * + * @param addr - B/IPv6 address that is parsed + * @param buf - B/IPv6 address in 16-bit ASCII hex compressed format + * @param buf_size - B/IPv6 address size in bytes + * + * @return the number of characters which would be generated for the given + * input, excluding the trailing null. + * @note buf and buf_size may be null and zero to return only the size + */ +int bvlc6_address_to_ascii(BACNET_IP6_ADDRESS *addr, char *buf, + size_t buf_size) +{ + uint16_t a; + unsigned int i; + int f = 0; + int len = 0; + int n = 0; + + if (!addr) { + return n; + } + if (!buf) { + return n; + } + for(i = 0; i < IP6_ADDRESS_MAX; i += 2) { + a = (addr->address[i] << 8) + addr->address[i + 1]; + if ((a == 0) && (f >= 0)) { + if (f++ == 0) { + len = snprintf(buf, buf_size, "::"); + if (buf) { + buf += len; + } + if (len > buf_size) { + buf_size = 0; + } else { + buf_size -= len; + } + n += len; + } + } else { + if (f > 0) { + f = -1; + } else if (i > 0) { + len = snprintf(buf, buf_size, ":"); + if (buf) { + buf += len; + } + if (len > buf_size) { + buf_size = 0; + } else { + buf_size -= len; + } + n += len; + } + len = snprintf(buf, buf_size, "%x", a); + if (buf) { + buf += len; + } + if (len > buf_size) { + buf_size = 0; + } else { + buf_size -= len; + } + n += len; + } + } + + return true; +} + /** Convert IPv6 Address from ASCII * * IPv6 addresses are represented as eight groups, separated by colons, @@ -672,7 +763,7 @@ bool bvlc6_address_from_ascii(BACNET_IP6_ADDRESS *addr, const char *addrstr) unsigned int i = 0; char c = 0; - if (!addrstr) { + if (!addr) { return false; } if (!addrstr) { diff --git a/src/bacnet/datalink/bvlc6.h b/src/bacnet/datalink/bvlc6.h index 7ab47215..1789bf9c 100644 --- a/src/bacnet/datalink/bvlc6.h +++ b/src/bacnet/datalink/bvlc6.h @@ -180,6 +180,10 @@ extern "C" { bool bvlc6_address_different( BACNET_IP6_ADDRESS * dst, BACNET_IP6_ADDRESS * src); + + BACNET_STACK_EXPORT + int bvlc6_address_to_ascii(BACNET_IP6_ADDRESS *addr, char *buf, + size_t buf_size); BACNET_STACK_EXPORT bool bvlc6_address_from_ascii( BACNET_IP6_ADDRESS *addr,