00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #include <curl/curl.h>
00026
00027 #ifdef HAVE_NETINET_IN_H
00028 # include <netinet/in.h>
00029 #endif
00030 #ifdef HAVE_NETDB_H
00031 # include <netdb.h>
00032 #endif
00033 #ifdef HAVE_ARPA_INET_H
00034 # include <arpa/inet.h>
00035 #endif
00036 #ifdef HAVE_SYS_UN_H
00037 # include <sys/un.h>
00038 #endif
00039
00040 #ifdef __VMS
00041 # include <in.h>
00042 # include <inet.h>
00043 #endif
00044
00045 #if defined(NETWARE) && defined(__NOVELL_LIBC__)
00046 # undef in_addr_t
00047 # define in_addr_t unsigned long
00048 #endif
00049
00050 #include "curl_addrinfo.h"
00051 #include "inet_pton.h"
00052 #include "warnless.h"
00053
00054 #include "curl_printf.h"
00055 #include "curl_memory.h"
00056 #include "memdebug.h"
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
00068 defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
00069
00070 # define vqualifier volatile
00071 #else
00072 # define vqualifier
00073 #endif
00074
00075 void
00076 Curl_freeaddrinfo(Curl_addrinfo *cahead)
00077 {
00078 Curl_addrinfo *vqualifier canext;
00079 Curl_addrinfo *ca;
00080
00081 for(ca = cahead; ca != NULL; ca = canext) {
00082 free(ca->ai_addr);
00083 free(ca->ai_canonname);
00084 canext = ca->ai_next;
00085
00086 free(ca);
00087 }
00088 }
00089
00090
00091 #ifdef HAVE_GETADDRINFO
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 int
00107 Curl_getaddrinfo_ex(const char *nodename,
00108 const char *servname,
00109 const struct addrinfo *hints,
00110 Curl_addrinfo **result)
00111 {
00112 const struct addrinfo *ai;
00113 struct addrinfo *aihead;
00114 Curl_addrinfo *cafirst = NULL;
00115 Curl_addrinfo *calast = NULL;
00116 Curl_addrinfo *ca;
00117 size_t ss_size;
00118 int error;
00119
00120 *result = NULL;
00121
00122 error = getaddrinfo(nodename, servname, hints, &aihead);
00123 if(error)
00124 return error;
00125
00126
00127
00128 for(ai = aihead; ai != NULL; ai = ai->ai_next) {
00129
00130
00131
00132 if(ai->ai_family == AF_INET)
00133 ss_size = sizeof(struct sockaddr_in);
00134 #ifdef ENABLE_IPV6
00135 else if(ai->ai_family == AF_INET6)
00136 ss_size = sizeof(struct sockaddr_in6);
00137 #endif
00138 else
00139 continue;
00140
00141
00142 if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0))
00143 continue;
00144
00145
00146 if((size_t)ai->ai_addrlen < ss_size)
00147 continue;
00148
00149 ca = malloc(sizeof(Curl_addrinfo));
00150 if(!ca) {
00151 error = EAI_MEMORY;
00152 break;
00153 }
00154
00155
00156
00157
00158 ca->ai_flags = ai->ai_flags;
00159 ca->ai_family = ai->ai_family;
00160 ca->ai_socktype = ai->ai_socktype;
00161 ca->ai_protocol = ai->ai_protocol;
00162 ca->ai_addrlen = (curl_socklen_t)ss_size;
00163 ca->ai_addr = NULL;
00164 ca->ai_canonname = NULL;
00165 ca->ai_next = NULL;
00166
00167 ca->ai_addr = malloc(ss_size);
00168 if(!ca->ai_addr) {
00169 error = EAI_MEMORY;
00170 free(ca);
00171 break;
00172 }
00173 memcpy(ca->ai_addr, ai->ai_addr, ss_size);
00174
00175 if(ai->ai_canonname != NULL) {
00176 ca->ai_canonname = strdup(ai->ai_canonname);
00177 if(!ca->ai_canonname) {
00178 error = EAI_MEMORY;
00179 free(ca->ai_addr);
00180 free(ca);
00181 break;
00182 }
00183 }
00184
00185
00186 if(!cafirst)
00187 cafirst = ca;
00188
00189
00190 if(calast)
00191 calast->ai_next = ca;
00192 calast = ca;
00193
00194 }
00195
00196
00197 if(aihead)
00198 freeaddrinfo(aihead);
00199
00200
00201 if(error) {
00202 Curl_freeaddrinfo(cafirst);
00203 cafirst = NULL;
00204 }
00205 else if(!cafirst) {
00206 #ifdef EAI_NONAME
00207
00208 error = EAI_NONAME;
00209 #else
00210
00211 error = EAI_NODATA;
00212 #endif
00213 #ifdef USE_WINSOCK
00214 SET_SOCKERRNO(error);
00215 #endif
00216 }
00217
00218 *result = cafirst;
00219
00220
00221 return error;
00222 }
00223 #endif
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 Curl_addrinfo *
00268 Curl_he2ai(const struct hostent *he, int port)
00269 {
00270 Curl_addrinfo *ai;
00271 Curl_addrinfo *prevai = NULL;
00272 Curl_addrinfo *firstai = NULL;
00273 struct sockaddr_in *addr;
00274 #ifdef ENABLE_IPV6
00275 struct sockaddr_in6 *addr6;
00276 #endif
00277 CURLcode result = CURLE_OK;
00278 int i;
00279 char *curr;
00280
00281 if(!he)
00282
00283 return NULL;
00284
00285 DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
00286
00287 for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
00288
00289 size_t ss_size;
00290 #ifdef ENABLE_IPV6
00291 if(he->h_addrtype == AF_INET6)
00292 ss_size = sizeof(struct sockaddr_in6);
00293 else
00294 #endif
00295 ss_size = sizeof(struct sockaddr_in);
00296
00297 ai = calloc(1, sizeof(Curl_addrinfo));
00298 if(!ai) {
00299 result = CURLE_OUT_OF_MEMORY;
00300 break;
00301 }
00302 ai->ai_canonname = strdup(he->h_name);
00303 if(!ai->ai_canonname) {
00304 result = CURLE_OUT_OF_MEMORY;
00305 free(ai);
00306 break;
00307 }
00308 ai->ai_addr = calloc(1, ss_size);
00309 if(!ai->ai_addr) {
00310 result = CURLE_OUT_OF_MEMORY;
00311 free(ai->ai_canonname);
00312 free(ai);
00313 break;
00314 }
00315
00316 if(!firstai)
00317
00318 firstai = ai;
00319
00320 if(prevai)
00321
00322 prevai->ai_next = ai;
00323
00324 ai->ai_family = he->h_addrtype;
00325
00326
00327
00328 ai->ai_socktype = SOCK_STREAM;
00329
00330 ai->ai_addrlen = (curl_socklen_t)ss_size;
00331
00332
00333
00334 switch(ai->ai_family) {
00335 case AF_INET:
00336 addr = (void *)ai->ai_addr;
00337
00338 memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
00339 addr->sin_family = (unsigned short)(he->h_addrtype);
00340 addr->sin_port = htons((unsigned short)port);
00341 break;
00342
00343 #ifdef ENABLE_IPV6
00344 case AF_INET6:
00345 addr6 = (void *)ai->ai_addr;
00346
00347 memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
00348 addr6->sin6_family = (unsigned short)(he->h_addrtype);
00349 addr6->sin6_port = htons((unsigned short)port);
00350 break;
00351 #endif
00352 }
00353
00354 prevai = ai;
00355 }
00356
00357 if(result) {
00358 Curl_freeaddrinfo(firstai);
00359 firstai = NULL;
00360 }
00361
00362 return firstai;
00363 }
00364
00365
00366 struct namebuff {
00367 struct hostent hostentry;
00368 union {
00369 struct in_addr ina4;
00370 #ifdef ENABLE_IPV6
00371 struct in6_addr ina6;
00372 #endif
00373 } addrentry;
00374 char *h_addr_list[2];
00375 };
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 Curl_addrinfo *
00388 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
00389 {
00390 Curl_addrinfo *ai;
00391
00392 #if defined(__VMS) && \
00393 defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
00394 #pragma pointer_size save
00395 #pragma pointer_size short
00396 #pragma message disable PTRMISMATCH
00397 #endif
00398
00399 struct hostent *h;
00400 struct namebuff *buf;
00401 char *addrentry;
00402 char *hoststr;
00403 size_t addrsize;
00404
00405 DEBUGASSERT(inaddr && hostname);
00406
00407 buf = malloc(sizeof(struct namebuff));
00408 if(!buf)
00409 return NULL;
00410
00411 hoststr = strdup(hostname);
00412 if(!hoststr) {
00413 free(buf);
00414 return NULL;
00415 }
00416
00417 switch(af) {
00418 case AF_INET:
00419 addrsize = sizeof(struct in_addr);
00420 addrentry = (void *)&buf->addrentry.ina4;
00421 memcpy(addrentry, inaddr, sizeof(struct in_addr));
00422 break;
00423 #ifdef ENABLE_IPV6
00424 case AF_INET6:
00425 addrsize = sizeof(struct in6_addr);
00426 addrentry = (void *)&buf->addrentry.ina6;
00427 memcpy(addrentry, inaddr, sizeof(struct in6_addr));
00428 break;
00429 #endif
00430 default:
00431 free(hoststr);
00432 free(buf);
00433 return NULL;
00434 }
00435
00436 h = &buf->hostentry;
00437 h->h_name = hoststr;
00438 h->h_aliases = NULL;
00439 h->h_addrtype = (short)af;
00440 h->h_length = (short)addrsize;
00441 h->h_addr_list = &buf->h_addr_list[0];
00442 h->h_addr_list[0] = addrentry;
00443 h->h_addr_list[1] = NULL;
00444
00445 #if defined(__VMS) && \
00446 defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
00447 #pragma pointer_size restore
00448 #pragma message enable PTRMISMATCH
00449 #endif
00450
00451 ai = Curl_he2ai(h, port);
00452
00453 free(hoststr);
00454 free(buf);
00455
00456 return ai;
00457 }
00458
00459
00460
00461
00462
00463 Curl_addrinfo *Curl_str2addr(char *address, int port)
00464 {
00465 struct in_addr in;
00466 if(Curl_inet_pton(AF_INET, address, &in) > 0)
00467
00468 return Curl_ip2addr(AF_INET, &in, address, port);
00469 #ifdef ENABLE_IPV6
00470 else {
00471 struct in6_addr in6;
00472 if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
00473
00474 return Curl_ip2addr(AF_INET6, &in6, address, port);
00475 }
00476 #endif
00477 return NULL;
00478 }
00479
00480 #ifdef USE_UNIX_SOCKETS
00481
00486 Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath)
00487 {
00488 Curl_addrinfo *ai;
00489 struct sockaddr_un *sa_un;
00490 size_t path_len;
00491
00492 ai = calloc(1, sizeof(Curl_addrinfo));
00493 if(!ai)
00494 return NULL;
00495 ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
00496 if(!ai->ai_addr) {
00497 free(ai);
00498 *longpath = FALSE;
00499 return NULL;
00500 }
00501
00502 path_len = strlen(path);
00503 if(path_len >= sizeof(sa_un->sun_path)) {
00504 free(ai->ai_addr);
00505 free(ai);
00506 *longpath = TRUE;
00507 return NULL;
00508 }
00509
00510 ai->ai_family = AF_UNIX;
00511 ai->ai_socktype = SOCK_STREAM;
00512 ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un);
00513 sa_un = (void *) ai->ai_addr;
00514 sa_un->sun_family = AF_UNIX;
00515 memcpy(sa_un->sun_path, path, path_len + 1);
00516 return ai;
00517 }
00518 #endif
00519
00520 #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
00521
00522
00523
00524
00525
00526
00527
00528
00529 void
00530 curl_dofreeaddrinfo(struct addrinfo *freethis,
00531 int line, const char *source)
00532 {
00533 #ifdef USE_LWIPSOCK
00534 lwip_freeaddrinfo(freethis);
00535 #else
00536 (freeaddrinfo)(freethis);
00537 #endif
00538 curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
00539 source, line, (void *)freethis);
00540 }
00541 #endif
00542
00543
00544 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
00545
00546
00547
00548
00549
00550
00551
00552
00553 int
00554 curl_dogetaddrinfo(const char *hostname,
00555 const char *service,
00556 const struct addrinfo *hints,
00557 struct addrinfo **result,
00558 int line, const char *source)
00559 {
00560 #ifdef USE_LWIPSOCK
00561 int res=lwip_getaddrinfo(hostname, service, hints, result);
00562 #else
00563 int res=(getaddrinfo)(hostname, service, hints, result);
00564 #endif
00565 if(0 == res)
00566
00567 curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
00568 source, line, (void *)*result);
00569 else
00570 curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
00571 source, line);
00572 return res;
00573 }
00574 #endif
00575
00576 #if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS)
00577
00578
00579
00580
00581 void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
00582 {
00583 Curl_addrinfo *ca;
00584 struct sockaddr_in *addr;
00585 #ifdef ENABLE_IPV6
00586 struct sockaddr_in6 *addr6;
00587 #endif
00588 for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
00589 switch(ca->ai_family) {
00590 case AF_INET:
00591 addr = (void *)ca->ai_addr;
00592 addr->sin_port = htons((unsigned short)port);
00593 break;
00594
00595 #ifdef ENABLE_IPV6
00596 case AF_INET6:
00597 addr6 = (void *)ca->ai_addr;
00598 addr6->sin6_port = htons((unsigned short)port);
00599 break;
00600 #endif
00601 }
00602 }
00603 }
00604 #endif