Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

SRC/get_ip.c

Go to the documentation of this file.
00001 00006 /* 00007 * Copyright (C) 1999-2001 Internet Software Consortium. 00008 * 00009 * Permission to use, copy, modify, and distribute this software for any 00010 * purpose with or without fee is hereby granted, provided that the above 00011 * copyright notice and this permission notice appear in all copies. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM 00014 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 00015 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 00016 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 00017 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 00018 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00019 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00020 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00021 */ 00022 00023 /* $Id: getipnode.c,v 1.30 2001/07/18 02:37:08 mayer Exp $ */ 00024 00025 /* Originally from ISC's BIND 9.21; lightweigth resolver library (lwres). 00026 * Rewritten an simplified for Watt-32 by <giva@bgnett.no> Nov-2003. 00027 */ 00028 00029 #include "socket.h" 00030 #include "get_xby.h" 00031 #include "udp_dom.h" 00032 00033 #if defined(USE_BSD_API) 00034 00035 static struct hostent *copyandmerge (const struct hostent *he1, 00036 const struct hostent *he2, 00037 int af, int *err); 00038 00039 static __inline void scan_interface (BOOL *have_v4, BOOL *have_v6) 00040 { 00041 if (have_v4) 00042 *have_v4 = TRUE; 00043 00044 if (have_v6) 00045 #if defined(USE_IPV6) 00046 *have_v6 = dns_do_ipv6; 00047 #else 00048 *have_v6 = FALSE; 00049 #endif 00050 } 00051 00052 /* 00053 * AI_V4MAPPED + AF_INET6 00054 * If no IPv6 address then a query for IPv4 and map returned values. 00055 * 00056 * AI_ALL + AI_V4MAPPED + AF_INET6 00057 * Return IPv6 and IPv4 mapped. 00058 * 00059 * AI_ADDRCONFIG 00060 * Only return IPv6 / IPv4 address if there is an interface of that 00061 * type active. 00062 */ 00063 struct hostent * W32_CALL 00064 getipnodebyname (const char *name, int af, int flags, int *error) 00065 { 00066 struct hostent *he1 = NULL; 00067 struct hostent *he2 = NULL; 00068 struct in_addr in4; 00069 struct in6_addr in6; 00070 BOOL have_v4 = TRUE, have_v6 = TRUE; 00071 BOOL v4 = FALSE, v6 = FALSE; 00072 int tmp_err; 00073 00074 SOCK_DEBUGF (("\ngetipnodebyname: %s ", name)); 00075 00076 /* If we care about active interfaces then check. 00077 */ 00078 if (flags & AI_ADDRCONFIG) 00079 scan_interface (&have_v4, &have_v6); 00080 00081 /* Check for literal address. 00082 */ 00083 v4 = inet_pton (AF_INET, name, &in4); 00084 if (!v4) 00085 v6 = inet_pton (AF_INET6, name, &in6); 00086 00087 /* Impossible combination? 00088 */ 00089 if ((af == AF_INET6 && !(flags & AI_V4MAPPED) && v4) || 00090 (af == AF_INET && v6) || 00091 (!have_v4 && v4) || 00092 (!have_v6 && v6) || 00093 (!have_v4 && af == AF_INET) || 00094 ((!have_v6 && af == AF_INET6) && ((flags & AI_V4MAPPED) && have_v4)) || 00095 !(flags & AI_V4MAPPED)) 00096 { 00097 *error = HOST_NOT_FOUND; 00098 return (NULL); 00099 } 00100 00101 /* Literal address? 00102 */ 00103 if (v4 || v6) 00104 { 00105 struct hostent he; 00106 char *addr_list[2]; 00107 char *aliases[1]; 00108 00109 he.h_name = (char*) name; 00110 he.h_addr_list = addr_list; 00111 he.h_addr_list[0] = (v4 ? (char*)&in4 : (char*)&in6); 00112 he.h_addr_list[1] = NULL; 00113 he.h_aliases = aliases; 00114 he.h_aliases[0] = NULL; 00115 he.h_length = (v4 ? INADDRSZ : IN6ADDRSZ); 00116 he.h_addrtype = (v4 ? AF_INET : AF_INET6); 00117 return copyandmerge (&he, NULL, af, error); 00118 } 00119 00120 tmp_err = NO_RECOVERY; 00121 if (have_v6 && af == AF_INET6) 00122 { 00123 #if defined(USE_IPV6) 00124 he1 = gethostbyname6 (name); 00125 #else 00126 he1 = NULL; 00127 #endif 00128 if (!he1) 00129 tmp_err = HOST_NOT_FOUND; 00130 } 00131 00132 if (have_v4 && 00133 (af == AF_INET || 00134 (af == AF_INET6 && 00135 (flags & AI_V4MAPPED) && (!he1 || (flags & AI_ALL))))) 00136 { 00137 SOCK_ENTER_SCOPE(); 00138 he2 = gethostbyname (name); 00139 SOCK_LEAVE_SCOPE(); 00140 if (!he2 || !he1) 00141 { 00142 *error = HOST_NOT_FOUND; 00143 return (NULL); 00144 } 00145 } 00146 else 00147 *error = tmp_err; 00148 00149 return copyandmerge (he1, he2, af, error); 00150 } 00151 00152 struct hostent * W32_CALL 00153 getipnodebyaddr (const void *src, size_t len, int af, int *error) 00154 { 00155 struct hostent *he1, *he2; 00156 const BYTE *cp = (const BYTE*) src; 00157 00158 SOCK_DEBUGF (("\ngetipnodebyaddr: ")); 00159 00160 if (!src) 00161 { 00162 *error = NO_RECOVERY; 00163 return (NULL); 00164 } 00165 00166 switch (af) 00167 { 00168 case AF_INET: 00169 if (len < INADDRSZ) 00170 { 00171 *error = NO_RECOVERY; 00172 return (NULL); 00173 } 00174 break; 00175 #if defined(USE_IPV6) 00176 case AF_INET6: 00177 if (len < IN6ADDRSZ) 00178 { 00179 *error = NO_RECOVERY; 00180 return (NULL); 00181 } 00182 break; 00183 #endif 00184 default: 00185 *error = NO_RECOVERY; 00186 return (NULL); 00187 } 00188 00189 /* Look up IPv4 and IPv4 mapped/compatible addresses. 00190 */ 00191 if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(cp)) || 00192 (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(cp)) || 00193 (af == AF_INET)) 00194 { 00195 if (af == AF_INET6) 00196 cp += 12; 00197 00198 SOCK_ENTER_SCOPE(); 00199 he1 = gethostbyaddr ((const char*)cp, 4, AF_INET); 00200 SOCK_LEAVE_SCOPE(); 00201 00202 if (af == AF_INET) 00203 goto ret_copy; 00204 00205 /* Convert from AF_INET to AF_INET6. 00206 */ 00207 he2 = copyandmerge (he1, NULL, af, error); 00208 if (he2) 00209 { 00210 memcpy (he2->h_addr, src, len); /* Restore original address */ 00211 SOCK_DEBUGF (("%s", af == AF_INET ? 00212 inet_ntoa(*(struct in_addr*)&he2->h_addr) : 00213 _inet6_ntoa(he2->h_addr))); 00214 } 00215 return (he2); 00216 } 00217 00218 he1 = gethostbyaddr (src, len, AF_INET6); /* Lookup IPv6 address */ 00219 00220 ret_copy: 00221 if (!he1) 00222 { 00223 *error = HOST_NOT_FOUND; 00224 return (NULL); 00225 } 00226 return copyandmerge (he1, NULL, af, error); 00227 } 00228 00229 void W32_CALL freehostent (struct hostent *he) 00230 { 00231 char *p; 00232 00233 SOCK_DEBUGF (("\nfreehostent: %s ", he->h_name)); 00234 00235 if (!he->h_name) /* possible double freeing */ 00236 return; 00237 00238 free (he->h_name); 00239 he->h_name = NULL; 00240 00241 for (p = he->h_addr_list[0]; p; p++) 00242 free (p); 00243 00244 for (p = he->h_aliases[0]; p; p++) 00245 free (p); 00246 00247 free (he->h_aliases); 00248 free (he->h_addr_list); 00249 free (he); 00250 } 00251 00252 static struct hostent *copyandmerge (const struct hostent *he1, 00253 const struct hostent *he2, 00254 int af, int *error) 00255 { 00256 struct hostent *he = NULL; 00257 int addresses = 1; /* NULL terminator */ 00258 int names = 1; /* NULL terminator */ 00259 char **cpp, **npp; 00260 00261 /* Work out array sizes. 00262 */ 00263 if (he1) 00264 { 00265 cpp = he1->h_addr_list; 00266 while (*cpp) 00267 { 00268 addresses++; 00269 cpp++; 00270 } 00271 cpp = he1->h_aliases; 00272 while (*cpp) 00273 { 00274 names++; 00275 cpp++; 00276 } 00277 } 00278 00279 if (he2) 00280 { 00281 cpp = he2->h_addr_list; 00282 while (*cpp) 00283 { 00284 addresses++; 00285 cpp++; 00286 } 00287 if (!he1) 00288 { 00289 cpp = he2->h_aliases; 00290 while (*cpp) 00291 { 00292 names++; 00293 cpp++; 00294 } 00295 } 00296 } 00297 00298 if (addresses == 1) 00299 { 00300 *error = NO_ADDRESS; 00301 return (NULL); 00302 } 00303 00304 he = malloc (sizeof(*he)); 00305 if (!he) 00306 { 00307 *error = NO_RECOVERY; 00308 return (NULL); 00309 } 00310 00311 he->h_addr_list = calloc (addresses * sizeof(char*), 1); 00312 if (!he->h_addr_list) 00313 goto cleanup0; 00314 00315 /* Copy addresses. 00316 */ 00317 npp = he->h_addr_list; 00318 if (he1) 00319 { 00320 cpp = he1->h_addr_list; 00321 while (*cpp) 00322 { 00323 *npp = malloc (af == AF_INET ? INADDRSZ : IN6ADDRSZ); 00324 if (!*npp) 00325 goto cleanup1; 00326 00327 /* Convert to mapped if required. 00328 */ 00329 if (af == AF_INET6 && he1->h_addrtype == AF_INET) 00330 { 00331 memcpy (*npp, in6addr_mapped, sizeof(in6addr_mapped)); 00332 memcpy (*npp + sizeof(in6addr_mapped), *cpp, INADDRSZ); 00333 } 00334 else 00335 memcpy (*npp, *cpp, af == AF_INET ? INADDRSZ : IN6ADDRSZ); 00336 cpp++; 00337 npp++; 00338 } 00339 } 00340 00341 if (he2) 00342 { 00343 cpp = he2->h_addr_list; 00344 while (*cpp) 00345 { 00346 *npp = malloc (af == AF_INET ? INADDRSZ : IN6ADDRSZ); 00347 if (!*npp) 00348 goto cleanup1; 00349 00350 /* Convert to mapped if required. 00351 */ 00352 if (af == AF_INET6 && he2->h_addrtype == AF_INET) 00353 { 00354 memcpy (*npp, in6addr_mapped, sizeof(in6addr_mapped)); 00355 memcpy (*npp + sizeof(in6addr_mapped), *cpp, INADDRSZ); 00356 } 00357 else 00358 memcpy (*npp, *cpp, af == AF_INET ? INADDRSZ : IN6ADDRSZ); 00359 cpp++; 00360 npp++; 00361 } 00362 } 00363 00364 he->h_aliases = calloc (names * sizeof(char*), 1); 00365 if (!he->h_aliases) 00366 goto cleanup1; 00367 00368 /* Copy aliases. 00369 */ 00370 npp = he->h_aliases; 00371 cpp = (he1 ? he1->h_aliases : he2->h_aliases); 00372 while (*cpp) 00373 { 00374 *npp = strdup (*cpp); 00375 if (!*npp) 00376 goto cleanup2; 00377 npp++; 00378 cpp++; 00379 } 00380 00381 /* Copy hostname. 00382 */ 00383 if (he1) 00384 he->h_name = strdup (he1->h_name); 00385 else he->h_name = strdup (he2->h_name); 00386 00387 if (!he->h_name) 00388 goto cleanup2; 00389 00390 he->h_addrtype = af; 00391 he->h_length = (af == AF_INET ? INADDRSZ : IN6ADDRSZ); 00392 return (he); 00393 00394 cleanup2: 00395 for (cpp = he->h_aliases; *cpp; *cpp++ = NULL) 00396 free (*cpp); 00397 free (he->h_aliases); 00398 00399 cleanup1: 00400 for (cpp = he->h_addr_list; *cpp; *cpp++ = NULL) 00401 free (*cpp); 00402 free (he->h_addr_list); 00403 00404 cleanup0: 00405 free (he); 00406 *error = NO_RECOVERY; 00407 return (NULL); 00408 } 00409 #endif /* USE_BSD_API */

Generated on Wed Aug 4 08:55:47 2010 for Watt-32 tcp/ip by doxygen 1.3.8