A version of LWIP, provided for backwards compatibility.
Dependents: AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more
netdb.c
00001 /** 00002 * @file 00003 * API functions for name resolving 00004 * 00005 */ 00006 00007 /* 00008 * Redistribution and use in source and binary forms, with or without modification, 00009 * are permitted provided that the following conditions are met: 00010 * 00011 * 1. Redistributions of source code must retain the above copyright notice, 00012 * this list of conditions and the following disclaimer. 00013 * 2. Redistributions in binary form must reproduce the above copyright notice, 00014 * this list of conditions and the following disclaimer in the documentation 00015 * and/or other materials provided with the distribution. 00016 * 3. The name of the author may not be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00020 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00021 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00022 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00024 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00027 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00028 * OF SUCH DAMAGE. 00029 * 00030 * This file is part of the lwIP TCP/IP stack. 00031 * 00032 * Author: Simon Goldschmidt 00033 * 00034 */ 00035 00036 #include "lwip/netdb.h" 00037 00038 #if LWIP_DNS && LWIP_SOCKET 00039 00040 #include "lwip/err.h" 00041 #include "lwip/mem.h" 00042 #include "lwip/ip_addr.h" 00043 #include "lwip/api.h" 00044 00045 /** helper struct for gethostbyname_r to access the char* buffer */ 00046 struct gethostbyname_r_helper { 00047 struct ip_addr *addrs; 00048 struct ip_addr addr; 00049 char *aliases; 00050 }; 00051 00052 /** h_errno is exported in netdb.h for access by applications. */ 00053 #if LWIP_DNS_API_DECLARE_H_ERRNO 00054 int h_errno; 00055 #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ 00056 00057 /** define "hostent" variables storage: 0 if we use a static (but unprotected) 00058 * set of variables for lwip_gethostbyname, 1 if we use a local storage */ 00059 #ifndef LWIP_DNS_API_HOSTENT_STORAGE 00060 #define LWIP_DNS_API_HOSTENT_STORAGE 0 00061 #endif 00062 00063 /** define "hostent" variables storage */ 00064 #if LWIP_DNS_API_HOSTENT_STORAGE 00065 #define HOSTENT_STORAGE 00066 #else 00067 #define HOSTENT_STORAGE static 00068 #endif /* LWIP_DNS_API_STATIC_HOSTENT */ 00069 00070 /** 00071 * Returns an entry containing addresses of address family AF_INET 00072 * for the host with name name. 00073 * Due to dns_gethostbyname limitations, only one address is returned. 00074 * 00075 * @param name the hostname to resolve 00076 * @return an entry containing addresses of address family AF_INET 00077 * for the host with name name 00078 */ 00079 struct hostent* 00080 lwip_gethostbyname(const char *name) 00081 { 00082 err_t err; 00083 struct ip_addr addr; 00084 00085 /* buffer variables for lwip_gethostbyname() */ 00086 HOSTENT_STORAGE struct hostent s_hostent; 00087 HOSTENT_STORAGE char *s_aliases; 00088 HOSTENT_STORAGE struct ip_addr s_hostent_addr; 00089 HOSTENT_STORAGE struct ip_addr *s_phostent_addr; 00090 00091 /* query host IP address */ 00092 err = netconn_gethostbyname(name, &addr); 00093 if (err != ERR_OK) { 00094 LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); 00095 h_errno = HOST_NOT_FOUND; 00096 return NULL; 00097 } 00098 00099 /* fill hostent */ 00100 s_hostent_addr = addr; 00101 s_phostent_addr = &s_hostent_addr; 00102 s_hostent.h_name = (char*)name; 00103 s_hostent.h_aliases = &s_aliases; 00104 s_hostent.h_addrtype = AF_INET; 00105 s_hostent.h_length = sizeof(struct ip_addr); 00106 s_hostent.h_addr_list = (char**)&s_phostent_addr; 00107 00108 #if DNS_DEBUG 00109 /* dump hostent */ 00110 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); 00111 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == 0x%08lX\n",(u32_t)(s_hostent.h_aliases))); 00112 if (s_hostent.h_aliases != NULL) { 00113 u8_t idx; 00114 for ( idx=0; s_hostent.h_aliases[idx]; idx++) { 00115 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == 0x%08lX\n", idx, s_hostent.h_aliases[idx])); 00116 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx])); 00117 } 00118 } 00119 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %lu\n", (u32_t)(s_hostent.h_addrtype))); 00120 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %lu\n", (u32_t)(s_hostent.h_length))); 00121 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == 0x%08lX\n", s_hostent.h_addr_list)); 00122 if (s_hostent.h_addr_list != NULL) { 00123 u8_t idx; 00124 for ( idx=0; s_hostent.h_addr_list[idx]; idx++) { 00125 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == 0x%08lX\n", idx, s_hostent.h_addr_list[idx])); 00126 LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, inet_ntoa(*((struct in_addr*)(s_hostent.h_addr_list[idx]))))); 00127 } 00128 } 00129 #endif /* DNS_DEBUG */ 00130 00131 #if LWIP_DNS_API_HOSTENT_STORAGE 00132 /* this function should return the "per-thread" hostent after copy from s_hostent */ 00133 return sys_thread_hostent(&s_hostent); 00134 #else 00135 return &s_hostent; 00136 #endif /* LWIP_DNS_API_HOSTENT_STORAGE */ 00137 } 00138 00139 /** 00140 * Thread-safe variant of lwip_gethostbyname: instead of using a static 00141 * buffer, this function takes buffer and errno pointers as arguments 00142 * and uses these for the result. 00143 * 00144 * @param name the hostname to resolve 00145 * @param ret pre-allocated struct where to store the result 00146 * @param buf pre-allocated buffer where to store additional data 00147 * @param buflen the size of buf 00148 * @param result pointer to a hostent pointer that is set to ret on success 00149 * and set to zero on error 00150 * @param h_errnop pointer to an int where to store errors (instead of modifying 00151 * the global h_errno) 00152 * @return 0 on success, non-zero on error, additional error information 00153 * is stored in *h_errnop instead of h_errno to be thread-safe 00154 */ 00155 int 00156 lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, 00157 size_t buflen, struct hostent **result, int *h_errnop) 00158 { 00159 err_t err; 00160 struct gethostbyname_r_helper *h; 00161 char *hostname; 00162 size_t namelen; 00163 int lh_errno; 00164 00165 if (h_errnop == NULL) { 00166 /* ensure h_errnop is never NULL */ 00167 h_errnop = &lh_errno; 00168 } 00169 00170 if (result == NULL) { 00171 /* not all arguments given */ 00172 *h_errnop = EINVAL; 00173 return -1; 00174 } 00175 /* first thing to do: set *result to nothing */ 00176 *result = NULL; 00177 if ((name == NULL) || (ret == NULL) || (buf == 0)) { 00178 /* not all arguments given */ 00179 *h_errnop = EINVAL; 00180 return -1; 00181 } 00182 00183 namelen = strlen(name); 00184 if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { 00185 /* buf can't hold the data needed + a copy of name */ 00186 *h_errnop = ERANGE; 00187 return -1; 00188 } 00189 00190 h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); 00191 hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); 00192 00193 /* query host IP address */ 00194 err = netconn_gethostbyname(name, &(h->addr)); 00195 if (err != ERR_OK) { 00196 LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); 00197 *h_errnop = ENSRNOTFOUND; 00198 return -1; 00199 } 00200 00201 /* copy the hostname into buf */ 00202 MEMCPY(hostname, name, namelen); 00203 hostname[namelen] = 0; 00204 00205 /* fill hostent */ 00206 h->addrs = &(h->addr); 00207 h->aliases = NULL; 00208 ret->h_name = (char*)hostname; 00209 ret->h_aliases = &(h->aliases); 00210 ret->h_addrtype = AF_INET; 00211 ret->h_length = sizeof(struct ip_addr); 00212 ret->h_addr_list = (char**)&(h->addrs); 00213 00214 /* set result != NULL */ 00215 *result = ret; 00216 00217 /* return success */ 00218 return 0; 00219 } 00220 00221 /** 00222 * Frees one or more addrinfo structures returned by getaddrinfo(), along with 00223 * any additional storage associated with those structures. If the ai_next field 00224 * of the structure is not null, the entire list of structures is freed. 00225 * 00226 * @param ai struct addrinfo to free 00227 */ 00228 void 00229 lwip_freeaddrinfo(struct addrinfo *ai) 00230 { 00231 struct addrinfo *next; 00232 00233 while (ai != NULL) { 00234 if (ai->ai_addr != NULL) { 00235 mem_free(ai->ai_addr); 00236 } 00237 if (ai->ai_canonname != NULL) { 00238 mem_free(ai->ai_canonname); 00239 } 00240 next = ai->ai_next; 00241 mem_free(ai); 00242 ai = next; 00243 } 00244 } 00245 00246 /** 00247 * Translates the name of a service location (for example, a host name) and/or 00248 * a service name and returns a set of socket addresses and associated 00249 * information to be used in creating a socket with which to address the 00250 * specified service. 00251 * Memory for the result is allocated internally and must be freed by calling 00252 * lwip_freeaddrinfo()! 00253 * 00254 * Due to a limitation in dns_gethostbyname, only the first address of a 00255 * host is returned. 00256 * Also, service names are not supported (only port numbers)! 00257 * 00258 * @param nodename descriptive name or address string of the host 00259 * (may be NULL -> local address) 00260 * @param servname port number as string of NULL 00261 * @param hints structure containing input values that set socktype and protocol 00262 * @param res pointer to a pointer where to store the result (set to NULL on failure) 00263 * @return 0 on success, non-zero on failure 00264 */ 00265 int 00266 lwip_getaddrinfo(const char *nodename, const char *servname, 00267 const struct addrinfo *hints, struct addrinfo **res) 00268 { 00269 err_t err; 00270 struct ip_addr addr; 00271 struct addrinfo *ai; 00272 struct sockaddr_in *sa = NULL; 00273 int port_nr = 0; 00274 00275 if (res == NULL) { 00276 return EAI_FAIL; 00277 } 00278 *res = NULL; 00279 if ((nodename == NULL) && (servname == NULL)) { 00280 return EAI_NONAME; 00281 } 00282 00283 if (servname != NULL) { 00284 /* service name specified: convert to port number 00285 * @todo?: currently, only ASCII integers (port numbers) are supported! */ 00286 port_nr = atoi(servname); 00287 if ((port_nr <= 0) || (port_nr > 0xffff)) { 00288 return EAI_SERVICE; 00289 } 00290 } 00291 00292 if (nodename != NULL) { 00293 /* service location specified, try to resolve */ 00294 err = netconn_gethostbyname(nodename, &addr); 00295 if (err != ERR_OK) { 00296 return EAI_FAIL; 00297 } 00298 } else { 00299 /* service location specified, use loopback address */ 00300 addr.addr = INADDR_LOOPBACK; 00301 } 00302 00303 ai = mem_malloc(sizeof(struct addrinfo)); 00304 if (ai == NULL) { 00305 goto memerr; 00306 } 00307 memset(ai, 0, sizeof(struct addrinfo)); 00308 sa = mem_malloc(sizeof(struct sockaddr_in)); 00309 if (sa == NULL) { 00310 goto memerr; 00311 } 00312 memset(sa, 0, sizeof(struct sockaddr_in)); 00313 /* set up sockaddr */ 00314 sa->sin_addr.s_addr = addr.addr; 00315 sa->sin_family = AF_INET; 00316 sa->sin_len = sizeof(struct sockaddr_in); 00317 sa->sin_port = htons(port_nr); 00318 00319 /* set up addrinfo */ 00320 ai->ai_family = AF_INET; 00321 if (hints != NULL) { 00322 /* copy socktype & protocol from hints if specified */ 00323 ai->ai_socktype = hints->ai_socktype; 00324 ai->ai_protocol = hints->ai_protocol; 00325 } 00326 if (nodename != NULL) { 00327 /* copy nodename to canonname if specified */ 00328 size_t namelen = strlen(nodename); 00329 ai->ai_canonname = mem_malloc(namelen + 1); 00330 if (ai->ai_canonname == NULL) { 00331 goto memerr; 00332 } 00333 MEMCPY(ai->ai_canonname, nodename, namelen); 00334 ai->ai_canonname[namelen] = 0; 00335 } 00336 ai->ai_addrlen = sizeof(struct sockaddr_in); 00337 ai->ai_addr = (struct sockaddr*)sa; 00338 00339 *res = ai; 00340 00341 return 0; 00342 memerr: 00343 if (ai != NULL) { 00344 mem_free(ai); 00345 } 00346 if (sa != NULL) { 00347 mem_free(sa); 00348 } 00349 return EAI_MEMORY; 00350 } 00351 00352 #endif /* LWIP_DNS && LWIP_SOCKET */
Generated on Tue Jul 12 2022 16:06:18 by 1.7.2