%% options copyright owner = Dirk Krause copyright year = 2016-xxxx license = bsd %% module #include "dk4conf.h" #include "dk4types.h" #include "dk4mem.h" #include "dk4sock.h" #include "dk4mai8dus.h" #include "dk4maowd.h" #include "dk4mao8d.h" #include "dk4rec24.h" $!trace-include #if DK4_ON_WINDOWS /** Attempt to convert an IPv4 or IPv6 address from text to address. @param dptr Destination variable. @param str Source text. @return 1 on success, 0 on error. */ static int dk4socket_wc_find_address(dk4_sockaddr_storage_t *dptr, const wchar_t *str) { #if DK4_HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 *in6; #endif struct sockaddr_in *in4; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 IN6_ADDR addr6; #endif IN_ADDR addr4; int back = 0; int res; $? "+ dk4socket_wc_find_address" res = dk4socket_wc_inet_pton(&addr4, sizeof(addr4), AF_INET, str, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { in4 = (struct sockaddr_in *)dptr; in4->sin_family = AF_INET; DK4_MEMCPY(&(in4->sin_addr), &addr4, sizeof(addr4)); back = 1; } else { #if DK4_HAVE_STRUCT_SOCKADDR_IN6 res = dk4socket_wc_inet_pton(&addr6, sizeof(addr6), AF_INET6, str, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { in6 = (struct sockaddr_in6 *)dptr; in6->sin6_family = AF_INET6; DK4_MEMCPY(&(in6->sin6_addr), &addr6, sizeof(addr6)); back = 1; } #endif } $? "- dk4socket_wc_find_address %d", back return back; } /** Find address for one host name. @param dptr Address of destination data structure. @param remhost Remote host name. @param remport Remote port number in host representation. @param ip4 Flag: Prefer IPv4 over IPv6 addresses. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ static int dk4socket_wc_find_host( dk4_sockaddr_storage_t *dptr, const wchar_t *remhost, unsigned short remport, int ip4, dk4_er_t *erp ) { #if DK4_HAVE_GETADDRINFO /* +++ getaddrinfo +++ */ wchar_t buf[16*sizeof(unsigned short)]; ADDRINFOW hints; ADDRINFOW *results = NULL; ADDRINFOW *rptr = NULL; int back = 0; int res = 0; $? "+ dk4socket_wc_find_host (getaddrinfo) \"%!ws\"", TR_LSTR(remhost) res = dk4ma_write_wc_decimal_unsigned( buf, DK4_SIZEOF(buf,wchar_t), (dk4_um_t)remport, 0, NULL ); if (0 != res) { DK4_MEMRES(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_flags = AI_NUMERICSERV; res = GetAddrInfoW(remhost, buf, &hints, &results); if ((0 == res) && (NULL != results)) { $? ". GetAddrInfoW" if (0 != ip4) { rptr = results; while ((NULL != rptr) && (0 == back)) { if ((0 < rptr->ai_addrlen) && (NULL != rptr->ai_addr)) { if (AF_INET == rptr->ai_addr->sa_family) { if (sizeof(dk4_sockaddr_storage_t) >= rptr->ai_addrlen) { DK4_MEMCPY(dptr, rptr->ai_addr, rptr->ai_addrlen); back = 1; $? ". found" } #if TRACE_DEBUG else { $? "! address too large" } #endif } #if TRACE_DEBUG else { $? "! not IPv4" } #endif } #if TRACE_DEBUG else { $? "! no address data" } #endif rptr = rptr->ai_next; } if (0 == back) { rptr = results; while ((NULL != rptr) && (0 == back)) { if ((0 < rptr->ai_addrlen) && (NULL != rptr->ai_addr)) { if (sizeof(dk4_sockaddr_storage_t) >= rptr->ai_addrlen) { DK4_MEMCPY(dptr, rptr->ai_addr, rptr->ai_addrlen); back = 1; $? "- found" } #if TRACE_DEBUG else { $? "! address to large" } #endif } #if TRACE_DEBUG else { $? "! no address data" } #endif rptr = rptr->ai_next; } } } else { $? ". any address fam" rptr = results; while ((NULL != rptr) && (0 == back)) { if ((0 < rptr->ai_addrlen) && (NULL != rptr->ai_addr)) { if (sizeof(dk4_sockaddr_storage_t) >= rptr->ai_addrlen) { DK4_MEMCPY(dptr, rptr->ai_addr, rptr->ai_addrlen); back = 1; $? ". found" } #if TRACE_DEBUG else { $? "! addr too large" } #endif } #if TRACE_DEBUG else { $? "! no address data" } #endif rptr = rptr->ai_next; } } } else { $? "! GetAddrInfoW" } if (NULL != results) { FreeAddrInfoW(results); } } #if TRACE_DEBUG else { $? "! failed to convert port number to text" } #endif $? "- dk4socket_wc_find_host %d", back return back; /* --- getaddrinfo --- */ #else /* +++ ! getaddrinfo +++ */ #if DK4_HAVE_GETHOSTBYNAME /* +++ gethostbyname +++ */ char hona[1040]; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 *sa6; #endif struct sockaddr_in *sa4; struct hostent *hep = NULL; int back = 0; $? "+ dk4socket_wc_find_host (gethostbyname) \"%s\"", TR_LSTR(remhost) if (0 != dk4recode_wchar_t_to_char(hona, sizeof(hona), remhost, erp)) { hep = gethostbyname(hona); if (NULL != hep) { $? ". hep" if (NULL != hep->h_addr_list) { $? ". hep->h_addr_list" if (NULL != *(hep->h_addr_list)) { $? ". *(hep->h_addr_list)" switch (hep->h_addrtype) { case AF_INET : { $? ". IPv4" sa4 = (struct sockaddr_in *)dptr; DK4_MEMRES(sa4, sizeof(struct sockaddr_in)); sa4->sin_family = AF_INET; sa4->sin_port = dk4socket_htons(remport); DK4_MEMCPY(&(sa4->sin_addr),*(hep->h_addr_list),sizeof(IN_ADDR)); back = 1; $? ". found" } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { $? ". IPv6" sa6 = (struct sockaddr_in6 *)dptr; DK4_MEMRES(sa6, sizeof(struct sockaddr_in6)); sa6->sin6_family = AF_INET6; sa6->sin_port = dk4socket_htons(remport); DK4_MEMCPY(&(sa6->sin6_addr),*(hep->h_addr_list),sizeof(IN6_ADDR)); back = 1; $? ". found" } break; #endif #if TRACE_DEBUG default : { $? "! address type" } break; #endif } } #if TRACE_DEBUG else { $? "! *(hep->h_addr_list)" } #endif } #if TRACE_DEBUG else { $? "! hep->h_addr_list" } #endif } #if TRACE_DEBUG else { $? "! not found" } #endif } #if TRACE_DEBUG else { $? "! recode" } #endif $? "- dk4socket_wc_find_host %d", back return back; /* --- gethostbyname --- */ #else /* +++ ! gethostbyname +++ */ dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED); return 0; $? "! not supported" /* --- ! gethostbyname --- */ #endif /* --- ! getaddrinfo --- */ #endif } #endif int dk4socket_wc_udp_addresses_numeric( dk4_sockaddr_storage_t *array, const wchar_t *remhost, unsigned short remport, unsigned short locport, int ip4, dk4_er_t *erp ) { #if DK4_ON_WINDOWS int back = DK4_SOCKET_RESULT_FAILED; $? "+ dk4socket_wc_udp_addresses_numeric DK4_ON_WINDOWS" if ((NULL != array) && (NULL != remhost) && (0 < remport) && (0 < locport)) { DK4_MEMRES(array, (2*sizeof(dk4_sockaddr_storage_t))); if (0 != dk4socket_wc_find_address(array, remhost)) { $? ". address pair found" back = dk4socket_complete_addresses(array, remport, locport); $? ". back = %d", back } if (DK4_SOCKET_RESULT_FAILED == back) { $? ". no pair" if (0 != dk4socket_wc_find_host(array, remhost, remport, ip4, erp)) { back = dk4socket_complete_addresses(array, remport, locport); if (DK4_SOCKET_RESULT_FAILED == back) { $? "! complete" dk4error_set_simple_error_code(erp, DK4_E_BUG); } } else { $? "! not found" dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } } else { $? "! arguments" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4socket_wc_udp_addresses_numeric DK4_ON_WINDOWS %d", back return back; #else dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED); return 0; #endif } int dk4socket_udp_addresses_numeric( dk4_sockaddr_storage_t *array, const dkChar *remhost, unsigned short remport, unsigned short locport, int ip4, dk4_er_t *erp ) { #if DK4_CHAR_SIZE > 1 return ( dk4socket_wc_udp_addresses_numeric( array, remhost, remport, locport, ip4, erp ) ); #else return ( dk4socket_c8_udp_addresses_numeric( array, remhost, remport, locport, ip4, erp ) ); #endif }