%% 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 "dk4mao8d.h" $!trace-include /** 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_c8_find_address(dk4_sockaddr_storage_t *dptr, const char *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_c8_find_address" res = dk4socket_c8_inet_pton(&addr4, sizeof(addr4), AF_INET, str, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". IPv4" 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_c8_inet_pton(&addr6, sizeof(addr6), AF_INET6, str, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". IPv6" in6 = (struct sockaddr_in6 *)dptr; in6->sin6_family = AF_INET6; DK4_MEMCPY(&(in6->sin6_addr), &addr6, sizeof(addr6)); back = 1; } #endif } $? "- dk4socket_c8_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. @return 1 on success, 0 on error. */ static int dk4socket_c8_find_host( dk4_sockaddr_storage_t *dptr, const char *remhost, unsigned short remport, int ip4 ) { #if DK4_HAVE_GETADDRINFO char buf[16*sizeof(unsigned short)]; struct addrinfo hints; struct addrinfo *results = NULL; struct addrinfo *rptr = NULL; int back = 0; int res = 0; $? "+ dk4socket_c8_find_host (getaddrinfo) \"%s\"", TR_8STR(remhost) res = dk4ma_write_c8_decimal_unsigned( buf, sizeof(buf), (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 = getaddrinfo(remhost, buf, &hints, &results); if ((0 == res) && (NULL != results)) { $? ". getaddrinfo" if (0 != ip4) { $? ". IPv4 preferred" rptr = results; while ((NULL != rptr) && (0 == back)) { $? ". entry" 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" } else { $? "! address too large" } } else { $? "! not IPv4" } } else { $? "! no address data" } rptr = rptr->ai_next; } if (0 == back) { rptr = results; while ((NULL != rptr) && (0 == back)) { $? ". entry" 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" } else { $? "! address too large" } } else { $? "! no address data" } rptr = rptr->ai_next; } } } else { $? ". any address family" rptr = results; while ((NULL != rptr) && (0 == back)) { $? ". entry" 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" } else { $? "! address too large" } } else { $? "! no address data" } rptr = rptr->ai_next; } } } else { $? "! getaddrinfo" } if (NULL != results) { freeaddrinfo(results); } } else { $? "! failed to convert port no to text" } $? "- dk4socket_c8_find_host %d", back return back; #else #if DK4_HAVE_GETHOSTBYNAME #if DK4_HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 *sa6; #endif struct sockaddr_in *sa4; struct hostent *hep = NULL; int back = 0; $? "+ dk4socket_c8_find_host (gethostbyname) \"%s\"", TR_8STR(remhost) hep = gethostbyname(remhost); if (NULL != hep) { $? ". entry" if (NULL != hep->h_addr_list) { $? ". list" if (NULL != *(hep->h_addr_list)) { $? ". element" 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 } } else { $? "! NULL pointer" } } else { $? "! NULL list" } } else { $? "! not found" } $? "- dk4socket_c8_find_host %d", back return back; #else int back = 0; $? "+ dk4socket_c8_find_host (none) \"%s\"", TR_8STR(remhost) $? "- dk4socket_c8_find_host %d", back return back; #endif #endif } int dk4socket_c8_udp_addresses_numeric( dk4_sockaddr_storage_t *array, const char *remhost, unsigned short remport, unsigned short locport, int ip4, dk4_er_t *erp ) { int back = DK4_SOCKET_RESULT_FAILED; $? "+ dk4socket_c8_udp_addresses_numeric \"%s\"", TR_8STR(remhost) if ((NULL != array) && (NULL != remhost) && (0 < remport) && (0 < locport)) { DK4_MEMRES(array, (2*sizeof(dk4_sockaddr_storage_t))); if (0 != dk4socket_c8_find_address(array, remhost)) { $? ". address found" back = dk4socket_complete_addresses(array, remport, locport); $? ". back = %d", back } if (DK4_SOCKET_RESULT_FAILED == back) { $? ". no addr" if (0 != dk4socket_c8_find_host(array, remhost, remport, ip4)) { back = dk4socket_complete_addresses(array, remport, locport); if (DK4_SOCKET_RESULT_FAILED == back) { $? "! not completed" dk4error_set_simple_error_code(erp, DK4_E_BUG); } } else { $? "! host 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_c8_udp_addresses_numeric %d", back return back; }