Changeset 388 for python/vendor/current/Modules/getaddrinfo.c
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Modules/getaddrinfo.c
r2 r388 2 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 3 * All rights reserved. 4 * 4 * 5 5 * Redistribution and use in source and binary forms, with or without 6 6 * modification, are permitted provided that the following conditions … … 14 14 * may be used to endorse or promote products derived from this software 15 15 * without specific prior written permission. 16 * 16 * 17 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 18 * GAI_ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE … … 74 74 static const char in_addrany[] = { 0, 0, 0, 0 }; 75 75 static const char in6_addrany[] = { 76 76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 77 77 }; 78 static const char in_loopback[] = { 127, 0, 0, 1 }; 78 static const char in_loopback[] = { 127, 0, 0, 1 }; 79 79 static const char in6_loopback[] = { 80 80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 81 81 }; 82 82 83 83 struct sockinet { 84 u_charsi_len;85 u_charsi_family;86 u_shortsi_port;84 u_char si_len; 85 u_char si_family; 86 u_short si_port; 87 87 }; 88 88 89 89 static struct gai_afd { 90 91 92 93 94 95 const char *a_loopback; 90 int a_af; 91 int a_addrlen; 92 int a_socklen; 93 int a_off; 94 const char *a_addrany; 95 const char *a_loopback; 96 96 } gai_afdl [] = { 97 97 #ifdef ENABLE_IPV6 98 98 #define N_INET6 0 99 100 101 102 99 {PF_INET6, sizeof(struct in6_addr), 100 sizeof(struct sockaddr_in6), 101 offsetof(struct sockaddr_in6, sin6_addr), 102 in6_addrany, in6_loopback}, 103 103 #define N_INET 1 104 104 #else 105 105 #define N_INET 0 106 106 #endif 107 108 109 110 111 107 {PF_INET, sizeof(struct in_addr), 108 sizeof(struct sockaddr_in), 109 offsetof(struct sockaddr_in, sin_addr), 110 in_addrany, in_loopback}, 111 {0, 0, 0, 0, NULL, NULL}, 112 112 }; 113 113 114 114 #ifdef ENABLE_IPV6 115 #define PTON_MAX 115 #define PTON_MAX 16 116 116 #else 117 #define PTON_MAX 117 #define PTON_MAX 4 118 118 #endif 119 119 120 120 #ifndef IN_MULTICAST 121 #define IN_MULTICAST(i) 121 #define IN_MULTICAST(i) (((i) & 0xf0000000U) == 0xe0000000U) 122 122 #endif 123 123 … … 127 127 128 128 #ifndef IN_LOOPBACKNET 129 #define IN_LOOPBACKNET 129 #define IN_LOOPBACKNET 127 130 130 #endif 131 131 132 132 static int get_name Py_PROTO((const char *, struct gai_afd *, 133 134 133 struct addrinfo **, char *, struct addrinfo *, 134 int)); 135 135 static int get_addr Py_PROTO((const char *, int, struct addrinfo **, 136 136 struct addrinfo *, int)); 137 137 static int str_isnumber Py_PROTO((const char *)); 138 138 139 139 static char *ai_errlist[] = { 140 141 "address family for hostname not supported.",/* EAI_ADDRFAMILY */142 "temporary failure in name resolution.",/* EAI_AGAIN */143 "invalid value for ai_flags.",/* EAI_BADFLAGS */144 "non-recoverable failure in name resolution.",/* EAI_FAIL */145 "ai_family not supported.",/* EAI_FAMILY */146 "memory allocation failure.",/* EAI_MEMORY */147 "no address associated with hostname.",/* EAI_NODATA */148 149 "servname not supported for ai_socktype.",/* EAI_SERVICE */150 "ai_socktype not supported.",/* EAI_SOCKTYPE */151 "system error returned in errno.",/* EAI_SYSTEM */152 "invalid value for hints.", /* EAI_BADHINTS*/153 "resolved protocol is unknown.",/* EAI_PROTOCOL */154 "unknown error.",/* EAI_MAX */140 "success.", 141 "address family for hostname not supported.", /* EAI_ADDRFAMILY */ 142 "temporary failure in name resolution.", /* EAI_AGAIN */ 143 "invalid value for ai_flags.", /* EAI_BADFLAGS */ 144 "non-recoverable failure in name resolution.", /* EAI_FAIL */ 145 "ai_family not supported.", /* EAI_FAMILY */ 146 "memory allocation failure.", /* EAI_MEMORY */ 147 "no address associated with hostname.", /* EAI_NODATA */ 148 "hostname nor servname provided, or not known.",/* EAI_NONAME */ 149 "servname not supported for ai_socktype.", /* EAI_SERVICE */ 150 "ai_socktype not supported.", /* EAI_SOCKTYPE */ 151 "system error returned in errno.", /* EAI_SYSTEM */ 152 "invalid value for hints.", /* EAI_BADHINTS */ 153 "resolved protocol is unknown.", /* EAI_PROTOCOL */ 154 "unknown error.", /* EAI_MAX */ 155 155 }; 156 156 157 157 #define GET_CANONNAME(ai, str) \ 158 158 if (pai->ai_flags & AI_CANONNAME) {\ 159 160 161 162 163 164 159 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\ 160 strcpy((ai)->ai_canonname, (str));\ 161 } else {\ 162 error = EAI_MEMORY;\ 163 goto free;\ 164 }\ 165 165 } 166 166 167 167 #ifdef HAVE_SOCKADDR_SA_LEN 168 168 #define GET_AI(ai, gai_afd, addr, port) {\ 169 170 171 172 173 174 175 176 177 178 179 180 169 char *p;\ 170 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ 171 ((gai_afd)->a_socklen)))\ 172 == NULL) goto free;\ 173 memcpy(ai, pai, sizeof(struct addrinfo));\ 174 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ 175 memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\ 176 (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\ 177 (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\ 178 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\ 179 p = (char *)((ai)->ai_addr);\ 180 memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\ 181 181 } 182 182 #else 183 183 #define GET_AI(ai, gai_afd, addr, port) {\ 184 185 186 187 188 189 190 191 192 193 194 195 184 char *p;\ 185 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ 186 ((gai_afd)->a_socklen)))\ 187 == NULL) goto free;\ 188 memcpy(ai, pai, sizeof(struct addrinfo));\ 189 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ 190 memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\ 191 (ai)->ai_addrlen = (gai_afd)->a_socklen;\ 192 (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\ 193 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\ 194 p = (char *)((ai)->ai_addr);\ 195 memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\ 196 196 } 197 197 #endif … … 202 202 gai_strerror(int ecode) 203 203 { 204 205 206 204 if (ecode < 0 || ecode > EAI_MAX) 205 ecode = EAI_MAX; 206 return ai_errlist[ecode]; 207 207 } 208 208 … … 210 210 freeaddrinfo(struct addrinfo *ai) 211 211 { 212 213 214 215 216 217 218 219 220 212 struct addrinfo *next; 213 214 do { 215 next = ai->ai_next; 216 if (ai->ai_canonname) 217 free(ai->ai_canonname); 218 /* no need to free(ai->ai_addr) */ 219 free(ai); 220 } while ((ai = next) != NULL); 221 221 } 222 222 … … 224 224 str_isnumber(const char *p) 225 225 { 226 227 228 229 230 231 232 226 unsigned char *q = (unsigned char *)p; 227 while (*q) { 228 if (! isdigit(*q)) 229 return NO; 230 q++; 231 } 232 return YES; 233 233 } 234 234 … … 237 237 const struct addrinfo *hints, struct addrinfo **res) 238 238 { 239 240 241 242 243 244 245 246 239 struct addrinfo sentinel; 240 struct addrinfo *top = NULL; 241 struct addrinfo *cur; 242 int i, error = 0; 243 char pton[PTON_MAX]; 244 struct addrinfo ai; 245 struct addrinfo *pai; 246 u_short port; 247 247 248 248 #ifdef FAITH 249 250 251 252 253 254 255 256 257 258 259 260 #endif 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 #ifdef ENABLE_IPV6 289 290 #endif 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 ERR(EAI_BADHINTS);/*xxx*/318 319 320 321 322 323 ERR(EAI_BADHINTS);/*xxx*/324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 ERR(EAI_PROTOCOL);/*xxx*/374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 #ifdef ENABLE_IPV6 418 419 #endif 420 421 422 423 424 425 426 427 428 429 430 431 #ifdef ENABLE_IPV6 432 433 pfx = ((struct in6_addr *)pton)->s6_addr8[0];434 435 436 437 #endif 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 } else 458 ERR(EAI_FAMILY);/*xxx*/459 460 461 462 463 464 465 466 467 468 249 static int firsttime = 1; 250 251 if (firsttime) { 252 /* translator hack */ 253 { 254 char *q = getenv("GAI"); 255 if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) 256 translate = YES; 257 } 258 firsttime = 0; 259 } 260 #endif 261 262 /* initialize file static vars */ 263 sentinel.ai_next = NULL; 264 cur = &sentinel; 265 pai = &ai; 266 pai->ai_flags = 0; 267 pai->ai_family = PF_UNSPEC; 268 pai->ai_socktype = GAI_ANY; 269 pai->ai_protocol = GAI_ANY; 270 pai->ai_addrlen = 0; 271 pai->ai_canonname = NULL; 272 pai->ai_addr = NULL; 273 pai->ai_next = NULL; 274 port = GAI_ANY; 275 276 if (hostname == NULL && servname == NULL) 277 return EAI_NONAME; 278 if (hints) { 279 /* error check for hints */ 280 if (hints->ai_addrlen || hints->ai_canonname || 281 hints->ai_addr || hints->ai_next) 282 ERR(EAI_BADHINTS); /* xxx */ 283 if (hints->ai_flags & ~AI_MASK) 284 ERR(EAI_BADFLAGS); 285 switch (hints->ai_family) { 286 case PF_UNSPEC: 287 case PF_INET: 288 #ifdef ENABLE_IPV6 289 case PF_INET6: 290 #endif 291 break; 292 default: 293 ERR(EAI_FAMILY); 294 } 295 memcpy(pai, hints, sizeof(*pai)); 296 switch (pai->ai_socktype) { 297 case GAI_ANY: 298 switch (pai->ai_protocol) { 299 case GAI_ANY: 300 break; 301 case IPPROTO_UDP: 302 pai->ai_socktype = SOCK_DGRAM; 303 break; 304 case IPPROTO_TCP: 305 pai->ai_socktype = SOCK_STREAM; 306 break; 307 default: 308 pai->ai_socktype = SOCK_RAW; 309 break; 310 } 311 break; 312 case SOCK_RAW: 313 break; 314 case SOCK_DGRAM: 315 if (pai->ai_protocol != IPPROTO_UDP && 316 pai->ai_protocol != GAI_ANY) 317 ERR(EAI_BADHINTS); /*xxx*/ 318 pai->ai_protocol = IPPROTO_UDP; 319 break; 320 case SOCK_STREAM: 321 if (pai->ai_protocol != IPPROTO_TCP && 322 pai->ai_protocol != GAI_ANY) 323 ERR(EAI_BADHINTS); /*xxx*/ 324 pai->ai_protocol = IPPROTO_TCP; 325 break; 326 default: 327 ERR(EAI_SOCKTYPE); 328 /* unreachable */ 329 } 330 } 331 332 /* 333 * service port 334 */ 335 if (servname) { 336 if (str_isnumber(servname)) { 337 if (pai->ai_socktype == GAI_ANY) { 338 /* caller accept *GAI_ANY* socktype */ 339 pai->ai_socktype = SOCK_DGRAM; 340 pai->ai_protocol = IPPROTO_UDP; 341 } 342 port = htons((u_short)atoi(servname)); 343 } else { 344 struct servent *sp; 345 char *proto; 346 347 proto = NULL; 348 switch (pai->ai_socktype) { 349 case GAI_ANY: 350 proto = NULL; 351 break; 352 case SOCK_DGRAM: 353 proto = "udp"; 354 break; 355 case SOCK_STREAM: 356 proto = "tcp"; 357 break; 358 default: 359 fprintf(stderr, "panic!\n"); 360 break; 361 } 362 if ((sp = getservbyname(servname, proto)) == NULL) 363 ERR(EAI_SERVICE); 364 port = sp->s_port; 365 if (pai->ai_socktype == GAI_ANY) { 366 if (strcmp(sp->s_proto, "udp") == 0) { 367 pai->ai_socktype = SOCK_DGRAM; 368 pai->ai_protocol = IPPROTO_UDP; 369 } else if (strcmp(sp->s_proto, "tcp") == 0) { 370 pai->ai_socktype = SOCK_STREAM; 371 pai->ai_protocol = IPPROTO_TCP; 372 } else 373 ERR(EAI_PROTOCOL); /*xxx*/ 374 } 375 } 376 } 377 378 /* 379 * hostname == NULL. 380 * passive socket -> anyaddr (0.0.0.0 or ::) 381 * non-passive socket -> localhost (127.0.0.1 or ::1) 382 */ 383 if (hostname == NULL) { 384 struct gai_afd *gai_afd; 385 386 for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) { 387 if (!(pai->ai_family == PF_UNSPEC 388 || pai->ai_family == gai_afd->a_af)) { 389 continue; 390 } 391 392 if (pai->ai_flags & AI_PASSIVE) { 393 GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port); 394 /* xxx meaningless? 395 * GET_CANONNAME(cur->ai_next, "anyaddr"); 396 */ 397 } else { 398 GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback, 399 port); 400 /* xxx meaningless? 401 * GET_CANONNAME(cur->ai_next, "localhost"); 402 */ 403 } 404 cur = cur->ai_next; 405 } 406 top = sentinel.ai_next; 407 if (top) 408 goto good; 409 else 410 ERR(EAI_FAMILY); 411 } 412 413 /* hostname as numeric name */ 414 for (i = 0; gai_afdl[i].a_af; i++) { 415 if (inet_pton(gai_afdl[i].a_af, hostname, pton)) { 416 u_long v4a; 417 #ifdef ENABLE_IPV6 418 u_char pfx; 419 #endif 420 421 switch (gai_afdl[i].a_af) { 422 case AF_INET: 423 v4a = ((struct in_addr *)pton)->s_addr; 424 v4a = ntohl(v4a); 425 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) 426 pai->ai_flags &= ~AI_CANONNAME; 427 v4a >>= IN_CLASSA_NSHIFT; 428 if (v4a == 0 || v4a == IN_LOOPBACKNET) 429 pai->ai_flags &= ~AI_CANONNAME; 430 break; 431 #ifdef ENABLE_IPV6 432 case AF_INET6: 433 pfx = ((struct in6_addr *)pton)->s6_addr[0]; 434 if (pfx == 0 || pfx == 0xfe || pfx == 0xff) 435 pai->ai_flags &= ~AI_CANONNAME; 436 break; 437 #endif 438 } 439 440 if (pai->ai_family == gai_afdl[i].a_af || 441 pai->ai_family == PF_UNSPEC) { 442 if (! (pai->ai_flags & AI_CANONNAME)) { 443 GET_AI(top, &gai_afdl[i], pton, port); 444 goto good; 445 } 446 /* 447 * if AI_CANONNAME and if reverse lookup 448 * fail, return ai anyway to pacify 449 * calling application. 450 * 451 * XXX getaddrinfo() is a name->address 452 * translation function, and it looks strange 453 * that we do addr->name translation here. 454 */ 455 get_name(pton, &gai_afdl[i], &top, pton, pai, port); 456 goto good; 457 } else 458 ERR(EAI_FAMILY); /*xxx*/ 459 } 460 } 461 462 if (pai->ai_flags & AI_NUMERICHOST) 463 ERR(EAI_NONAME); 464 465 /* hostname as alphabetical name */ 466 error = get_addr(hostname, pai->ai_family, &top, pai, port); 467 if (error == 0) { 468 if (top) { 469 469 good: 470 471 472 473 474 470 *res = top; 471 return SUCCESS; 472 } else 473 error = EAI_FAIL; 474 } 475 475 free: 476 477 476 if (top) 477 freeaddrinfo(top); 478 478 bad: 479 480 479 *res = NULL; 480 return error; 481 481 } 482 482 483 483 static int 484 484 get_name(addr, gai_afd, res, numaddr, pai, port0) 485 486 487 488 489 490 485 const char *addr; 486 struct gai_afd *gai_afd; 487 struct addrinfo **res; 488 char *numaddr; 489 struct addrinfo *pai; 490 int port0; 491 491 { 492 493 494 495 496 #ifdef ENABLE_IPV6 497 498 #endif 499 500 #ifdef ENABLE_IPV6 501 492 u_short port = port0 & 0xffff; 493 struct hostent *hp; 494 struct addrinfo *cur; 495 int error = 0; 496 #ifdef ENABLE_IPV6 497 int h_error; 498 #endif 499 500 #ifdef ENABLE_IPV6 501 hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error); 502 502 #else 503 504 #endif 505 506 507 508 509 510 511 #ifdef ENABLE_IPV6 512 513 514 #endif 515 516 503 hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET); 504 #endif 505 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { 506 GET_AI(cur, gai_afd, hp->h_addr_list[0], port); 507 GET_CANONNAME(cur, hp->h_name); 508 } else 509 GET_AI(cur, gai_afd, numaddr, port); 510 511 #ifdef ENABLE_IPV6 512 if (hp) 513 freehostent(hp); 514 #endif 515 *res = cur; 516 return SUCCESS; 517 517 free: 518 519 520 #ifdef ENABLE_IPV6 521 522 518 if (cur) 519 freeaddrinfo(cur); 520 #ifdef ENABLE_IPV6 521 if (hp) 522 freehostent(hp); 523 523 #endif 524 524 /* bad: */ 525 526 525 *res = NULL; 526 return error; 527 527 } 528 528 529 529 static int 530 530 get_addr(hostname, af, res, pai, port0) 531 532 533 534 535 531 const char *hostname; 532 int af; 533 struct addrinfo **res; 534 struct addrinfo *pai; 535 int port0; 536 536 { 537 538 539 540 541 542 543 544 545 546 547 548 #ifdef ENABLE_IPV6 549 550 551 552 553 537 u_short port = port0 & 0xffff; 538 struct addrinfo sentinel; 539 struct hostent *hp; 540 struct addrinfo *top, *cur; 541 struct gai_afd *gai_afd; 542 int i, error = 0, h_error; 543 char *ap; 544 545 top = NULL; 546 sentinel.ai_next = NULL; 547 cur = &sentinel; 548 #ifdef ENABLE_IPV6 549 if (af == AF_UNSPEC) { 550 hp = getipnodebyname(hostname, AF_INET6, 551 AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error); 552 } else 553 hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error); 554 554 #else 555 556 557 #endif 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 #ifdef ENABLE_IPV6 584 585 586 555 hp = gethostbyname(hostname); 556 h_error = h_errno; 557 #endif 558 if (hp == NULL) { 559 switch (h_error) { 560 case HOST_NOT_FOUND: 561 case NO_DATA: 562 error = EAI_NODATA; 563 break; 564 case TRY_AGAIN: 565 error = EAI_AGAIN; 566 break; 567 case NO_RECOVERY: 568 default: 569 error = EAI_FAIL; 570 break; 571 } 572 goto free; 573 } 574 575 if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || 576 (hp->h_addr_list[0] == NULL)) { 577 error = EAI_FAIL; 578 goto free; 579 } 580 581 for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) { 582 switch (af) { 583 #ifdef ENABLE_IPV6 584 case AF_INET6: 585 gai_afd = &gai_afdl[N_INET6]; 586 break; 587 587 #endif 588 588 #ifndef ENABLE_IPV6 589 default:/* AF_UNSPEC */590 #endif 591 592 593 594 #ifdef ENABLE_IPV6 595 default:/* AF_UNSPEC */596 597 598 599 600 601 602 603 #endif 604 589 default: /* AF_UNSPEC */ 590 #endif 591 case AF_INET: 592 gai_afd = &gai_afdl[N_INET]; 593 break; 594 #ifdef ENABLE_IPV6 595 default: /* AF_UNSPEC */ 596 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { 597 ap += sizeof(struct in6_addr) - 598 sizeof(struct in_addr); 599 gai_afd = &gai_afdl[N_INET]; 600 } else 601 gai_afd = &gai_afdl[N_INET6]; 602 break; 603 #endif 604 } 605 605 #ifdef FAITH 606 607 608 609 610 611 612 613 614 606 if (translate && gai_afd->a_af == AF_INET) { 607 struct in6_addr *in6; 608 609 GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port); 610 in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr; 611 memcpy(&in6->s6_addr32[0], &faith_prefix, 612 sizeof(struct in6_addr) - sizeof(struct in_addr)); 613 memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr)); 614 } else 615 615 #endif /* FAITH */ 616 617 618 619 620 621 622 623 #ifdef ENABLE_IPV6 624 625 #endif 626 627 616 GET_AI(cur->ai_next, gai_afd, ap, port); 617 if (cur == &sentinel) { 618 top = cur->ai_next; 619 GET_CANONNAME(top, hp->h_name); 620 } 621 cur = cur->ai_next; 622 } 623 #ifdef ENABLE_IPV6 624 freehostent(hp); 625 #endif 626 *res = top; 627 return SUCCESS; 628 628 free: 629 630 631 #ifdef ENABLE_IPV6 632 633 629 if (top) 630 freeaddrinfo(top); 631 #ifdef ENABLE_IPV6 632 if (hp) 633 freehostent(hp); 634 634 #endif 635 635 /* bad: */ 636 637 638 } 636 *res = NULL; 637 return error; 638 }
Note:
See TracChangeset
for help on using the changeset viewer.