1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * API functions for name resolving 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * @defgroup netdbapi NETDB API 6195972f6Sopenharmony_ci * @ingroup socket 7195972f6Sopenharmony_ci */ 8195972f6Sopenharmony_ci 9195972f6Sopenharmony_ci/* 10195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 11195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 12195972f6Sopenharmony_ci * 13195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 14195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 15195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 16195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 17195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 18195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 19195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 20195972f6Sopenharmony_ci * 21195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30195972f6Sopenharmony_ci * OF SUCH DAMAGE. 31195972f6Sopenharmony_ci * 32195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 33195972f6Sopenharmony_ci * 34195972f6Sopenharmony_ci * Author: Simon Goldschmidt 35195972f6Sopenharmony_ci * 36195972f6Sopenharmony_ci */ 37195972f6Sopenharmony_ci 38195972f6Sopenharmony_ci#include "lwip/netdb.h" 39195972f6Sopenharmony_ci 40195972f6Sopenharmony_ci#if LWIP_DNS && LWIP_SOCKET 41195972f6Sopenharmony_ci 42195972f6Sopenharmony_ci#include "lwip/err.h" 43195972f6Sopenharmony_ci#include "lwip/mem.h" 44195972f6Sopenharmony_ci#include "lwip/memp.h" 45195972f6Sopenharmony_ci#include "lwip/ip_addr.h" 46195972f6Sopenharmony_ci#include "lwip/api.h" 47195972f6Sopenharmony_ci#include "lwip/dns.h" 48195972f6Sopenharmony_ci 49195972f6Sopenharmony_ci#include <string.h> /* memset */ 50195972f6Sopenharmony_ci#include <stdlib.h> /* atoi */ 51195972f6Sopenharmony_ci 52195972f6Sopenharmony_ci/** helper struct for gethostbyname_r to access the char* buffer */ 53195972f6Sopenharmony_cistruct gethostbyname_r_helper { 54195972f6Sopenharmony_ci ip_addr_t *addr_list[2]; 55195972f6Sopenharmony_ci ip_addr_t addr; 56195972f6Sopenharmony_ci char *aliases; 57195972f6Sopenharmony_ci}; 58195972f6Sopenharmony_ci 59195972f6Sopenharmony_ci/** h_errno is exported in netdb.h for access by applications. */ 60195972f6Sopenharmony_ci#if LWIP_DNS_API_DECLARE_H_ERRNO 61195972f6Sopenharmony_ciint h_errno; 62195972f6Sopenharmony_ci#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ 63195972f6Sopenharmony_ci 64195972f6Sopenharmony_ci/** define "hostent" variables storage: 0 if we use a static (but unprotected) 65195972f6Sopenharmony_ci * set of variables for lwip_gethostbyname, 1 if we use a local storage */ 66195972f6Sopenharmony_ci#ifndef LWIP_DNS_API_HOSTENT_STORAGE 67195972f6Sopenharmony_ci#define LWIP_DNS_API_HOSTENT_STORAGE 0 68195972f6Sopenharmony_ci#endif 69195972f6Sopenharmony_ci 70195972f6Sopenharmony_ci/** define "hostent" variables storage */ 71195972f6Sopenharmony_ci#if LWIP_DNS_API_HOSTENT_STORAGE 72195972f6Sopenharmony_ci#define HOSTENT_STORAGE 73195972f6Sopenharmony_ci#else 74195972f6Sopenharmony_ci#define HOSTENT_STORAGE static 75195972f6Sopenharmony_ci#endif /* LWIP_DNS_API_STATIC_HOSTENT */ 76195972f6Sopenharmony_ci 77195972f6Sopenharmony_ci/** 78195972f6Sopenharmony_ci * Returns an entry containing addresses of address family AF_INET 79195972f6Sopenharmony_ci * for the host with name name. 80195972f6Sopenharmony_ci * Due to dns_gethostbyname limitations, only one address is returned. 81195972f6Sopenharmony_ci * 82195972f6Sopenharmony_ci * @param name the hostname to resolve 83195972f6Sopenharmony_ci * @return an entry containing addresses of address family AF_INET 84195972f6Sopenharmony_ci * for the host with name name 85195972f6Sopenharmony_ci */ 86195972f6Sopenharmony_cistruct hostent * 87195972f6Sopenharmony_cilwip_gethostbyname(const char *name) 88195972f6Sopenharmony_ci{ 89195972f6Sopenharmony_ci err_t err; 90195972f6Sopenharmony_ci ip_addr_t addr; 91195972f6Sopenharmony_ci 92195972f6Sopenharmony_ci /* buffer variables for lwip_gethostbyname() */ 93195972f6Sopenharmony_ci HOSTENT_STORAGE struct hostent s_hostent; 94195972f6Sopenharmony_ci HOSTENT_STORAGE char *s_aliases; 95195972f6Sopenharmony_ci HOSTENT_STORAGE ip_addr_t s_hostent_addr; 96195972f6Sopenharmony_ci HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; 97195972f6Sopenharmony_ci HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1]; 98195972f6Sopenharmony_ci 99195972f6Sopenharmony_ci /* query host IP address */ 100195972f6Sopenharmony_ci err = netconn_gethostbyname(name, &addr); 101195972f6Sopenharmony_ci if (err != ERR_OK) { 102195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); 103195972f6Sopenharmony_ci h_errno = HOST_NOT_FOUND; 104195972f6Sopenharmony_ci return NULL; 105195972f6Sopenharmony_ci } 106195972f6Sopenharmony_ci 107195972f6Sopenharmony_ci /* fill hostent */ 108195972f6Sopenharmony_ci s_hostent_addr = addr; 109195972f6Sopenharmony_ci s_phostent_addr[0] = &s_hostent_addr; 110195972f6Sopenharmony_ci s_phostent_addr[1] = NULL; 111195972f6Sopenharmony_ci strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); 112195972f6Sopenharmony_ci s_hostname[DNS_MAX_NAME_LENGTH] = 0; 113195972f6Sopenharmony_ci s_hostent.h_name = s_hostname; 114195972f6Sopenharmony_ci s_aliases = NULL; 115195972f6Sopenharmony_ci s_hostent.h_aliases = &s_aliases; 116195972f6Sopenharmony_ci s_hostent.h_addrtype = AF_INET; 117195972f6Sopenharmony_ci s_hostent.h_length = sizeof(ip_addr_t); 118195972f6Sopenharmony_ci s_hostent.h_addr_list = (char **)&s_phostent_addr; 119195972f6Sopenharmony_ci 120195972f6Sopenharmony_ci#if DNS_DEBUG 121195972f6Sopenharmony_ci /* dump hostent */ 122195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); 123195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void *)s_hostent.h_aliases)); 124195972f6Sopenharmony_ci /* h_aliases are always empty */ 125195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); 126195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); 127195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void *)s_hostent.h_addr_list)); 128195972f6Sopenharmony_ci if (s_hostent.h_addr_list != NULL) { 129195972f6Sopenharmony_ci u8_t idx; 130195972f6Sopenharmony_ci for (idx = 0; s_hostent.h_addr_list[idx]; idx++) { 131195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa(s_phostent_addr[idx]))); 132195972f6Sopenharmony_ci } 133195972f6Sopenharmony_ci } 134195972f6Sopenharmony_ci#endif /* DNS_DEBUG */ 135195972f6Sopenharmony_ci 136195972f6Sopenharmony_ci#if LWIP_DNS_API_HOSTENT_STORAGE 137195972f6Sopenharmony_ci /* this function should return the "per-thread" hostent after copy from s_hostent */ 138195972f6Sopenharmony_ci return sys_thread_hostent(&s_hostent); 139195972f6Sopenharmony_ci#else 140195972f6Sopenharmony_ci return &s_hostent; 141195972f6Sopenharmony_ci#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ 142195972f6Sopenharmony_ci} 143195972f6Sopenharmony_ci 144195972f6Sopenharmony_ci/** 145195972f6Sopenharmony_ci * Thread-safe variant of lwip_gethostbyname: instead of using a static 146195972f6Sopenharmony_ci * buffer, this function takes buffer and errno pointers as arguments 147195972f6Sopenharmony_ci * and uses these for the result. 148195972f6Sopenharmony_ci * 149195972f6Sopenharmony_ci * @param name the hostname to resolve 150195972f6Sopenharmony_ci * @param ret pre-allocated struct where to store the result 151195972f6Sopenharmony_ci * @param buf pre-allocated buffer where to store additional data 152195972f6Sopenharmony_ci * @param buflen the size of buf 153195972f6Sopenharmony_ci * @param result pointer to a hostent pointer that is set to ret on success 154195972f6Sopenharmony_ci * and set to zero on error 155195972f6Sopenharmony_ci * @param h_errnop pointer to an int where to store errors (instead of modifying 156195972f6Sopenharmony_ci * the global h_errno) 157195972f6Sopenharmony_ci * @return 0 on success, non-zero on error, additional error information 158195972f6Sopenharmony_ci * is stored in *h_errnop instead of h_errno to be thread-safe 159195972f6Sopenharmony_ci */ 160195972f6Sopenharmony_ciint 161195972f6Sopenharmony_cilwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, 162195972f6Sopenharmony_ci size_t buflen, struct hostent **result, int *h_errnop) 163195972f6Sopenharmony_ci{ 164195972f6Sopenharmony_ci err_t err; 165195972f6Sopenharmony_ci struct gethostbyname_r_helper *h; 166195972f6Sopenharmony_ci char *hostname; 167195972f6Sopenharmony_ci size_t namelen; 168195972f6Sopenharmony_ci int lh_errno; 169195972f6Sopenharmony_ci 170195972f6Sopenharmony_ci if (h_errnop == NULL) { 171195972f6Sopenharmony_ci /* ensure h_errnop is never NULL */ 172195972f6Sopenharmony_ci h_errnop = &lh_errno; 173195972f6Sopenharmony_ci } 174195972f6Sopenharmony_ci 175195972f6Sopenharmony_ci if (result == NULL) { 176195972f6Sopenharmony_ci /* not all arguments given */ 177195972f6Sopenharmony_ci *h_errnop = EINVAL; 178195972f6Sopenharmony_ci return -1; 179195972f6Sopenharmony_ci } 180195972f6Sopenharmony_ci /* first thing to do: set *result to nothing */ 181195972f6Sopenharmony_ci *result = NULL; 182195972f6Sopenharmony_ci if ((name == NULL) || (ret == NULL) || (buf == NULL)) { 183195972f6Sopenharmony_ci /* not all arguments given */ 184195972f6Sopenharmony_ci *h_errnop = EINVAL; 185195972f6Sopenharmony_ci return -1; 186195972f6Sopenharmony_ci } 187195972f6Sopenharmony_ci 188195972f6Sopenharmony_ci namelen = strlen(name); 189195972f6Sopenharmony_ci if (buflen < (sizeof(struct gethostbyname_r_helper) + LWIP_MEM_ALIGN_BUFFER(namelen + 1))) { 190195972f6Sopenharmony_ci /* buf can't hold the data needed + a copy of name */ 191195972f6Sopenharmony_ci *h_errnop = ERANGE; 192195972f6Sopenharmony_ci return -1; 193195972f6Sopenharmony_ci } 194195972f6Sopenharmony_ci 195195972f6Sopenharmony_ci h = (struct gethostbyname_r_helper *)LWIP_MEM_ALIGN(buf); 196195972f6Sopenharmony_ci hostname = ((char *)h) + sizeof(struct gethostbyname_r_helper); 197195972f6Sopenharmony_ci 198195972f6Sopenharmony_ci /* query host IP address */ 199195972f6Sopenharmony_ci err = netconn_gethostbyname(name, &h->addr); 200195972f6Sopenharmony_ci if (err != ERR_OK) { 201195972f6Sopenharmony_ci LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); 202195972f6Sopenharmony_ci *h_errnop = HOST_NOT_FOUND; 203195972f6Sopenharmony_ci return -1; 204195972f6Sopenharmony_ci } 205195972f6Sopenharmony_ci 206195972f6Sopenharmony_ci /* copy the hostname into buf */ 207195972f6Sopenharmony_ci MEMCPY(hostname, name, namelen); 208195972f6Sopenharmony_ci hostname[namelen] = 0; 209195972f6Sopenharmony_ci 210195972f6Sopenharmony_ci /* fill hostent */ 211195972f6Sopenharmony_ci h->addr_list[0] = &h->addr; 212195972f6Sopenharmony_ci h->addr_list[1] = NULL; 213195972f6Sopenharmony_ci h->aliases = NULL; 214195972f6Sopenharmony_ci ret->h_name = hostname; 215195972f6Sopenharmony_ci ret->h_aliases = &h->aliases; 216195972f6Sopenharmony_ci ret->h_addrtype = AF_INET; 217195972f6Sopenharmony_ci ret->h_length = sizeof(ip_addr_t); 218195972f6Sopenharmony_ci ret->h_addr_list = (char **)&h->addr_list; 219195972f6Sopenharmony_ci 220195972f6Sopenharmony_ci /* set result != NULL */ 221195972f6Sopenharmony_ci *result = ret; 222195972f6Sopenharmony_ci 223195972f6Sopenharmony_ci /* return success */ 224195972f6Sopenharmony_ci return 0; 225195972f6Sopenharmony_ci} 226195972f6Sopenharmony_ci 227195972f6Sopenharmony_ci/** 228195972f6Sopenharmony_ci * Frees one or more addrinfo structures returned by getaddrinfo(), along with 229195972f6Sopenharmony_ci * any additional storage associated with those structures. If the ai_next field 230195972f6Sopenharmony_ci * of the structure is not null, the entire list of structures is freed. 231195972f6Sopenharmony_ci * 232195972f6Sopenharmony_ci * @param ai struct addrinfo to free 233195972f6Sopenharmony_ci */ 234195972f6Sopenharmony_civoid 235195972f6Sopenharmony_cilwip_freeaddrinfo(struct addrinfo *ai) 236195972f6Sopenharmony_ci{ 237195972f6Sopenharmony_ci struct addrinfo *next; 238195972f6Sopenharmony_ci 239195972f6Sopenharmony_ci while (ai != NULL) { 240195972f6Sopenharmony_ci next = ai->ai_next; 241195972f6Sopenharmony_ci memp_free(MEMP_NETDB, ai); 242195972f6Sopenharmony_ci ai = next; 243195972f6Sopenharmony_ci } 244195972f6Sopenharmony_ci} 245195972f6Sopenharmony_ci 246195972f6Sopenharmony_ci/** 247195972f6Sopenharmony_ci * Translates the name of a service location (for example, a host name) and/or 248195972f6Sopenharmony_ci * a service name and returns a set of socket addresses and associated 249195972f6Sopenharmony_ci * information to be used in creating a socket with which to address the 250195972f6Sopenharmony_ci * specified service. 251195972f6Sopenharmony_ci * Memory for the result is allocated internally and must be freed by calling 252195972f6Sopenharmony_ci * lwip_freeaddrinfo()! 253195972f6Sopenharmony_ci * 254195972f6Sopenharmony_ci * Due to a limitation in dns_gethostbyname, only the first address of a 255195972f6Sopenharmony_ci * host is returned. 256195972f6Sopenharmony_ci * Also, service names are not supported (only port numbers)! 257195972f6Sopenharmony_ci * 258195972f6Sopenharmony_ci * @param nodename descriptive name or address string of the host 259195972f6Sopenharmony_ci * (may be NULL -> local address) 260195972f6Sopenharmony_ci * @param servname port number as string of NULL 261195972f6Sopenharmony_ci * @param hints structure containing input values that set socktype and protocol 262195972f6Sopenharmony_ci * @param res pointer to a pointer where to store the result (set to NULL on failure) 263195972f6Sopenharmony_ci * @return 0 on success, non-zero on failure 264195972f6Sopenharmony_ci * 265195972f6Sopenharmony_ci * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG 266195972f6Sopenharmony_ci */ 267195972f6Sopenharmony_ciint 268195972f6Sopenharmony_cilwip_getaddrinfo(const char *nodename, const char *servname, 269195972f6Sopenharmony_ci const struct addrinfo *hints, struct addrinfo **res) 270195972f6Sopenharmony_ci{ 271195972f6Sopenharmony_ci err_t err; 272195972f6Sopenharmony_ci ip_addr_t addr; 273195972f6Sopenharmony_ci struct addrinfo *ai; 274195972f6Sopenharmony_ci struct sockaddr_storage *sa = NULL; 275195972f6Sopenharmony_ci int port_nr = 0; 276195972f6Sopenharmony_ci size_t total_size; 277195972f6Sopenharmony_ci size_t namelen = 0; 278195972f6Sopenharmony_ci int ai_family; 279195972f6Sopenharmony_ci 280195972f6Sopenharmony_ci if (res == NULL) { 281195972f6Sopenharmony_ci return EAI_FAIL; 282195972f6Sopenharmony_ci } 283195972f6Sopenharmony_ci *res = NULL; 284195972f6Sopenharmony_ci if ((nodename == NULL) && (servname == NULL)) { 285195972f6Sopenharmony_ci return EAI_NONAME; 286195972f6Sopenharmony_ci } 287195972f6Sopenharmony_ci 288195972f6Sopenharmony_ci if (hints != NULL) { 289195972f6Sopenharmony_ci ai_family = hints->ai_family; 290195972f6Sopenharmony_ci if ((ai_family != AF_UNSPEC) 291195972f6Sopenharmony_ci#if LWIP_IPV4 292195972f6Sopenharmony_ci && (ai_family != AF_INET) 293195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 294195972f6Sopenharmony_ci#if LWIP_IPV6 295195972f6Sopenharmony_ci && (ai_family != AF_INET6) 296195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 297195972f6Sopenharmony_ci ) { 298195972f6Sopenharmony_ci return EAI_FAMILY; 299195972f6Sopenharmony_ci } 300195972f6Sopenharmony_ci } else { 301195972f6Sopenharmony_ci ai_family = AF_UNSPEC; 302195972f6Sopenharmony_ci } 303195972f6Sopenharmony_ci 304195972f6Sopenharmony_ci if (servname != NULL) { 305195972f6Sopenharmony_ci /* service name specified: convert to port number 306195972f6Sopenharmony_ci * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ 307195972f6Sopenharmony_ci port_nr = atoi(servname); 308195972f6Sopenharmony_ci if (port_nr == 0 && (servname[0] != '0')) { 309195972f6Sopenharmony_ci /* atoi failed - service was not numeric */ 310195972f6Sopenharmony_ci return EAI_SERVICE; 311195972f6Sopenharmony_ci } 312195972f6Sopenharmony_ci if ((port_nr < 0) || (port_nr > 0xffff)) { 313195972f6Sopenharmony_ci return EAI_SERVICE; 314195972f6Sopenharmony_ci } 315195972f6Sopenharmony_ci } 316195972f6Sopenharmony_ci 317195972f6Sopenharmony_ci if (nodename != NULL) { 318195972f6Sopenharmony_ci /* service location specified, try to resolve */ 319195972f6Sopenharmony_ci if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { 320195972f6Sopenharmony_ci /* no DNS lookup, just parse for an address string */ 321195972f6Sopenharmony_ci if (!ipaddr_aton(nodename, &addr)) { 322195972f6Sopenharmony_ci return EAI_NONAME; 323195972f6Sopenharmony_ci } 324195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 325195972f6Sopenharmony_ci if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || 326195972f6Sopenharmony_ci (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) { 327195972f6Sopenharmony_ci return EAI_NONAME; 328195972f6Sopenharmony_ci } 329195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 330195972f6Sopenharmony_ci } else { 331195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 332195972f6Sopenharmony_ci /* AF_UNSPEC: prefer IPv4 */ 333195972f6Sopenharmony_ci u8_t type = NETCONN_DNS_IPV4_IPV6; 334195972f6Sopenharmony_ci if (ai_family == AF_INET) { 335195972f6Sopenharmony_ci type = NETCONN_DNS_IPV4; 336195972f6Sopenharmony_ci } else if (ai_family == AF_INET6) { 337195972f6Sopenharmony_ci type = NETCONN_DNS_IPV6; 338195972f6Sopenharmony_ci } 339195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 340195972f6Sopenharmony_ci err = netconn_gethostbyname_addrtype(nodename, &addr, type); 341195972f6Sopenharmony_ci if (err != ERR_OK) { 342195972f6Sopenharmony_ci return EAI_FAIL; 343195972f6Sopenharmony_ci } 344195972f6Sopenharmony_ci } 345195972f6Sopenharmony_ci } else { 346195972f6Sopenharmony_ci /* service location specified, use loopback address */ 347195972f6Sopenharmony_ci if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { 348195972f6Sopenharmony_ci ip_addr_set_any_val(ai_family == AF_INET6, addr); 349195972f6Sopenharmony_ci } else { 350195972f6Sopenharmony_ci ip_addr_set_loopback_val(ai_family == AF_INET6, addr); 351195972f6Sopenharmony_ci } 352195972f6Sopenharmony_ci } 353195972f6Sopenharmony_ci 354195972f6Sopenharmony_ci total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); 355195972f6Sopenharmony_ci if (nodename != NULL) { 356195972f6Sopenharmony_ci namelen = strlen(nodename); 357195972f6Sopenharmony_ci if (namelen > DNS_MAX_NAME_LENGTH) { 358195972f6Sopenharmony_ci /* invalid name length */ 359195972f6Sopenharmony_ci return EAI_FAIL; 360195972f6Sopenharmony_ci } 361195972f6Sopenharmony_ci LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); 362195972f6Sopenharmony_ci total_size += namelen + 1; 363195972f6Sopenharmony_ci } 364195972f6Sopenharmony_ci /* If this fails, please report to lwip-devel! :-) */ 365195972f6Sopenharmony_ci LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", 366195972f6Sopenharmony_ci total_size <= NETDB_ELEM_SIZE); 367195972f6Sopenharmony_ci ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); 368195972f6Sopenharmony_ci if (ai == NULL) { 369195972f6Sopenharmony_ci return EAI_MEMORY; 370195972f6Sopenharmony_ci } 371195972f6Sopenharmony_ci memset(ai, 0, total_size); 372195972f6Sopenharmony_ci /* cast through void* to get rid of alignment warnings */ 373195972f6Sopenharmony_ci sa = (struct sockaddr_storage *)(void *)((u8_t *)ai + sizeof(struct addrinfo)); 374195972f6Sopenharmony_ci if (IP_IS_V6_VAL(addr)) { 375195972f6Sopenharmony_ci#if LWIP_IPV6 376195972f6Sopenharmony_ci struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 377195972f6Sopenharmony_ci /* set up sockaddr */ 378195972f6Sopenharmony_ci inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); 379195972f6Sopenharmony_ci sa6->sin6_family = AF_INET6; 380195972f6Sopenharmony_ci sa6->sin6_len = sizeof(struct sockaddr_in6); 381195972f6Sopenharmony_ci sa6->sin6_port = lwip_htons((u16_t)port_nr); 382195972f6Sopenharmony_ci sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); 383195972f6Sopenharmony_ci ai->ai_family = AF_INET6; 384195972f6Sopenharmony_ci ai->ai_addrlen = sizeof(struct sockaddr_in6); 385195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 386195972f6Sopenharmony_ci } else { 387195972f6Sopenharmony_ci#if LWIP_IPV4 388195972f6Sopenharmony_ci struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; 389195972f6Sopenharmony_ci /* set up sockaddr */ 390195972f6Sopenharmony_ci inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); 391195972f6Sopenharmony_ci sa4->sin_family = AF_INET; 392195972f6Sopenharmony_ci sa4->sin_len = sizeof(struct sockaddr_in); 393195972f6Sopenharmony_ci sa4->sin_port = lwip_htons((u16_t)port_nr); 394195972f6Sopenharmony_ci ai->ai_family = AF_INET; 395195972f6Sopenharmony_ci ai->ai_addrlen = sizeof(struct sockaddr_in); 396195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 397195972f6Sopenharmony_ci } 398195972f6Sopenharmony_ci 399195972f6Sopenharmony_ci /* set up addrinfo */ 400195972f6Sopenharmony_ci if (hints != NULL) { 401195972f6Sopenharmony_ci /* copy socktype & protocol from hints if specified */ 402195972f6Sopenharmony_ci ai->ai_socktype = hints->ai_socktype; 403195972f6Sopenharmony_ci ai->ai_protocol = hints->ai_protocol; 404195972f6Sopenharmony_ci } 405195972f6Sopenharmony_ci if (nodename != NULL) { 406195972f6Sopenharmony_ci /* copy nodename to canonname if specified */ 407195972f6Sopenharmony_ci ai->ai_canonname = ((char *)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); 408195972f6Sopenharmony_ci MEMCPY(ai->ai_canonname, nodename, namelen); 409195972f6Sopenharmony_ci ai->ai_canonname[namelen] = 0; 410195972f6Sopenharmony_ci } 411195972f6Sopenharmony_ci ai->ai_addr = (struct sockaddr *)sa; 412195972f6Sopenharmony_ci 413195972f6Sopenharmony_ci *res = ai; 414195972f6Sopenharmony_ci 415195972f6Sopenharmony_ci return 0; 416195972f6Sopenharmony_ci} 417195972f6Sopenharmony_ci 418195972f6Sopenharmony_ci#endif /* LWIP_DNS && LWIP_SOCKET */ 419