1/* 2 * "$Id: http-addrlist.c 11645 2014-02-27 16:35:53Z msweet $" 3 * 4 * HTTP address list routines for CUPS. 5 * 6 * Copyright 2007-2014 by Apple Inc. 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * which should have been included with this file. If this file is 13 * file is missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * This file is subject to the Apple OS-Developed Software exception. 16 */ 17 18/* 19 * Include necessary headers... 20 */ 21 22#include "cups-private.h" 23#ifdef HAVE_RESOLV_H 24# include <resolv.h> 25#endif /* HAVE_RESOLV_H */ 26#ifdef HAVE_POLL 27# include <poll.h> 28#endif /* HAVE_POLL */ 29#ifndef WIN32 30# include <fcntl.h> 31#endif /* WIN32 */ 32 33 34/* 35 * 'httpAddrConnect()' - Connect to any of the addresses in the list. 36 * 37 * @since CUPS 1.2/OS X 10.5@ 38 */ 39 40http_addrlist_t * /* O - Connected address or NULL on failure */ 41httpAddrConnect( 42 http_addrlist_t *addrlist, /* I - List of potential addresses */ 43 int *sock) /* O - Socket */ 44{ 45 DEBUG_printf(("httpAddrConnect(addrlist=%p, sock=%p)", addrlist, sock)); 46 47 return (httpAddrConnect2(addrlist, sock, 30000, NULL)); 48} 49 50 51/* 52 * 'httpAddrConnect2()' - Connect to any of the addresses in the list with a 53 * timeout and optional cancel. 54 * 55 * @since CUPS 1.7/OS X 10.9@ 56 */ 57 58http_addrlist_t * /* O - Connected address or NULL on failure */ 59httpAddrConnect2( 60 http_addrlist_t *addrlist, /* I - List of potential addresses */ 61 int *sock, /* O - Socket */ 62 int msec, /* I - Timeout in milliseconds */ 63 int *cancel) /* I - Pointer to "cancel" variable */ 64{ 65 int val; /* Socket option value */ 66#ifdef O_NONBLOCK 67 socklen_t len; /* Length of value */ 68 http_addr_t peer; /* Peer address */ 69 int flags, /* Socket flags */ 70 remaining; /* Remaining timeout */ 71# ifdef HAVE_POLL 72 struct pollfd pfd; /* Polled file descriptor */ 73# else 74 fd_set input_set, /* select() input set */ 75 output_set; /* select() output set */ 76 struct timeval timeout; /* Timeout */ 77# endif /* HAVE_POLL */ 78 int nfds; /* Result from select()/poll() */ 79#endif /* O_NONBLOCK */ 80#ifdef DEBUG 81 char temp[256]; /* Temporary address string */ 82#endif /* DEBUG */ 83 84 85 DEBUG_printf(("httpAddrConnect2(addrlist=%p, sock=%p, msec=%d, cancel=%p)", 86 addrlist, sock, msec, cancel)); 87 88 if (!sock) 89 { 90 errno = EINVAL; 91 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 92 return (NULL); 93 } 94 95 if (cancel && *cancel) 96 return (NULL); 97 98 if (msec <= 0 || getenv("CUPS_DISABLE_ASYNC_CONNECT")) 99 msec = INT_MAX; 100 101 /* 102 * Loop through each address until we connect or run out of addresses... 103 */ 104 105 while (addrlist) 106 { 107 if (cancel && *cancel) 108 return (NULL); 109 110 /* 111 * Create the socket... 112 */ 113 114 DEBUG_printf(("2httpAddrConnect2: Trying %s:%d...", 115 httpAddrString(&(addrlist->addr), temp, sizeof(temp)), 116 httpAddrPort(&(addrlist->addr)))); 117 118 if ((*sock = (int)socket(httpAddrFamily(&(addrlist->addr)), SOCK_STREAM, 119 0)) < 0) 120 { 121 /* 122 * Don't abort yet, as this could just be an issue with the local 123 * system not being configured with IPv4/IPv6/domain socket enabled... 124 */ 125 126 addrlist = addrlist->next; 127 continue; 128 } 129 130 /* 131 * Set options... 132 */ 133 134 val = 1; 135 setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val)); 136 137#ifdef SO_REUSEPORT 138 val = 1; 139 setsockopt(*sock, SOL_SOCKET, SO_REUSEPORT, CUPS_SOCAST &val, sizeof(val)); 140#endif /* SO_REUSEPORT */ 141 142#ifdef SO_NOSIGPIPE 143 val = 1; 144 setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val)); 145#endif /* SO_NOSIGPIPE */ 146 147 /* 148 * Using TCP_NODELAY improves responsiveness, especially on systems 149 * with a slow loopback interface... 150 */ 151 152 val = 1; 153 setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val)); 154 155#ifdef FD_CLOEXEC 156 /* 157 * Close this socket when starting another process... 158 */ 159 160 fcntl(*sock, F_SETFD, FD_CLOEXEC); 161#endif /* FD_CLOEXEC */ 162 163#ifdef O_NONBLOCK 164 /* 165 * Do an asynchronous connect by setting the socket non-blocking... 166 */ 167 168 DEBUG_printf(("httpAddrConnect2: Setting non-blocking connect()")); 169 170 flags = fcntl(*sock, F_GETFL, 0); 171 if (msec != INT_MAX) 172 { 173 DEBUG_puts("httpAddrConnect2: Setting non-blocking connect()"); 174 175 fcntl(*sock, F_SETFL, flags | O_NONBLOCK); 176 } 177#endif /* O_NONBLOCK */ 178 179 /* 180 * Then connect... 181 */ 182 183 if (!connect(*sock, &(addrlist->addr.addr), (socklen_t)httpAddrLength(&(addrlist->addr)))) 184 { 185 DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", 186 httpAddrString(&(addrlist->addr), temp, sizeof(temp)), 187 httpAddrPort(&(addrlist->addr)))); 188 189#ifdef O_NONBLOCK 190 fcntl(*sock, F_SETFL, flags); 191#endif /* O_NONBLOCK */ 192 193 return (addrlist); 194 } 195 196#ifdef O_NONBLOCK 197# ifdef WIN32 198 if (WSAGetLastError() == WSAEINPROGRESS || 199 WSAGetLastError() == WSAEWOULDBLOCK) 200# else 201 if (errno == EINPROGRESS || errno == EWOULDBLOCK) 202# endif /* WIN32 */ 203 { 204 DEBUG_puts("1httpAddrConnect2: Finishing async connect()"); 205 206 fcntl(*sock, F_SETFL, flags); 207 208 for (remaining = msec; remaining > 0; remaining -= 250) 209 { 210 do 211 { 212 if (cancel && *cancel) 213 { 214 /* 215 * Close this socket and return... 216 */ 217 218 DEBUG_puts("1httpAddrConnect2: Canceled connect()"); 219 220 httpAddrClose(NULL, *sock); 221 222 *sock = -1; 223 224 return (NULL); 225 } 226 227# ifdef HAVE_POLL 228 pfd.fd = *sock; 229 pfd.events = POLLIN | POLLOUT; 230 231 nfds = poll(&pfd, 1, remaining > 250 ? 250 : remaining); 232 233 DEBUG_printf(("1httpAddrConnect2: poll() returned %d (%d)", nfds, 234 errno)); 235 236# else 237 FD_ZERO(&input_set); 238 FD_SET(*sock, &input_set); 239 output_set = input_set; 240 241 timeout.tv_sec = 0; 242 timeout.tv_usec = (remaining > 250 ? 250 : remaining) * 1000; 243 244 nfds = select(*sock + 1, &input_set, &output_set, NULL, &timeout); 245 246 DEBUG_printf(("1httpAddrConnect2: select() returned %d (%d)", nfds, 247 errno)); 248# endif /* HAVE_POLL */ 249 } 250# ifdef WIN32 251 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || 252 WSAGetLastError() == WSAEWOULDBLOCK)); 253# else 254 while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); 255# endif /* WIN32 */ 256 257 if (nfds > 0) 258 { 259 len = sizeof(peer); 260 if (!getpeername(*sock, (struct sockaddr *)&peer, &len)) 261 { 262 DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", 263 httpAddrString(&peer, temp, sizeof(temp)), 264 httpAddrPort(&peer))); 265 266 return (addrlist); 267 } 268 269 break; 270 } 271 } 272 } 273#endif /* O_NONBLOCK */ 274 275 DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s", 276 httpAddrString(&(addrlist->addr), temp, sizeof(temp)), 277 httpAddrPort(&(addrlist->addr)), strerror(errno))); 278 279#ifndef WIN32 280 if (errno == EINPROGRESS) 281 errno = ETIMEDOUT; 282#endif /* !WIN32 */ 283 284 /* 285 * Close this socket and move to the next address... 286 */ 287 288 httpAddrClose(NULL, *sock); 289 290 *sock = -1; 291 addrlist = addrlist->next; 292 } 293 294 if (!addrlist) 295#ifdef WIN32 296 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, "Connection failed", 0); 297#else 298 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, strerror(errno), 0); 299#endif /* WIN32 */ 300 301 return (addrlist); 302} 303 304 305 306/* 307 * 'httpAddrCopyList()' - Copy an address list. 308 * 309 * @since CUPS 1.7/OS X 10.9@ 310 */ 311 312http_addrlist_t * /* O - New address list or @code NULL@ on error */ 313httpAddrCopyList( 314 http_addrlist_t *src) /* I - Source address list */ 315{ 316 http_addrlist_t *dst = NULL, /* First list entry */ 317 *prev = NULL, /* Previous list entry */ 318 *current = NULL;/* Current list entry */ 319 320 321 while (src) 322 { 323 if ((current = malloc(sizeof(http_addrlist_t))) == NULL) 324 { 325 current = dst; 326 327 while (current) 328 { 329 prev = current; 330 current = current->next; 331 332 free(prev); 333 } 334 335 return (NULL); 336 } 337 338 memcpy(current, src, sizeof(http_addrlist_t)); 339 340 current->next = NULL; 341 342 if (prev) 343 prev->next = current; 344 else 345 dst = current; 346 347 prev = current; 348 src = src->next; 349 } 350 351 return (dst); 352} 353 354 355/* 356 * 'httpAddrFreeList()' - Free an address list. 357 * 358 * @since CUPS 1.2/OS X 10.5@ 359 */ 360 361void 362httpAddrFreeList( 363 http_addrlist_t *addrlist) /* I - Address list to free */ 364{ 365 http_addrlist_t *next; /* Next address in list */ 366 367 368 /* 369 * Free each address in the list... 370 */ 371 372 while (addrlist) 373 { 374 next = addrlist->next; 375 376 free(addrlist); 377 378 addrlist = next; 379 } 380} 381 382 383/* 384 * 'httpAddrGetList()' - Get a list of addresses for a hostname. 385 * 386 * @since CUPS 1.2/OS X 10.5@ 387 */ 388 389http_addrlist_t * /* O - List of addresses or NULL */ 390httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for passive listen address */ 391 int family, /* I - Address family or AF_UNSPEC */ 392 const char *service) /* I - Service name or port number */ 393{ 394 http_addrlist_t *first, /* First address in list */ 395 *addr, /* Current address in list */ 396 *temp; /* New address */ 397 _cups_globals_t *cg = _cupsGlobals(); 398 /* Global data */ 399 400 401#ifdef DEBUG 402 _cups_debug_printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, " 403 "service=\"%s\")\n", 404 hostname ? hostname : "(nil)", 405 family == AF_UNSPEC ? "UNSPEC" : 406# ifdef AF_LOCAL 407 family == AF_LOCAL ? "LOCAL" : 408# endif /* AF_LOCAL */ 409# ifdef AF_INET6 410 family == AF_INET6 ? "INET6" : 411# endif /* AF_INET6 */ 412 family == AF_INET ? "INET" : "???", service); 413#endif /* DEBUG */ 414 415#ifdef HAVE_RES_INIT 416 /* 417 * STR #2920: Initialize resolver after failure in cups-polld 418 * 419 * If the previous lookup failed, re-initialize the resolver to prevent 420 * temporary network errors from persisting. This *should* be handled by 421 * the resolver libraries, but apparently the glibc folks do not agree. 422 * 423 * We set a flag at the end of this function if we encounter an error that 424 * requires reinitialization of the resolver functions. We then call 425 * res_init() if the flag is set on the next call here or in httpAddrLookup(). 426 */ 427 428 if (cg->need_res_init) 429 { 430 res_init(); 431 432 cg->need_res_init = 0; 433 } 434#endif /* HAVE_RES_INIT */ 435 436 /* 437 * Lookup the address the best way we can... 438 */ 439 440 first = addr = NULL; 441 442#ifdef AF_LOCAL 443 if (hostname && hostname[0] == '/') 444 { 445 /* 446 * Domain socket address... 447 */ 448 449 if ((first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t))) != NULL) 450 { 451 addr = first; 452 first->addr.un.sun_family = AF_LOCAL; 453 strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path)); 454 } 455 } 456 else 457#endif /* AF_LOCAL */ 458 if (!hostname || _cups_strcasecmp(hostname, "localhost")) 459 { 460#ifdef HAVE_GETADDRINFO 461 struct addrinfo hints, /* Address lookup hints */ 462 *results, /* Address lookup results */ 463 *current; /* Current result */ 464 char ipv6[64], /* IPv6 address */ 465 *ipv6zone; /* Pointer to zone separator */ 466 int ipv6len; /* Length of IPv6 address */ 467 int error; /* getaddrinfo() error */ 468 469 470 /* 471 * Lookup the address as needed... 472 */ 473 474 memset(&hints, 0, sizeof(hints)); 475 hints.ai_family = family; 476 hints.ai_flags = hostname ? 0 : AI_PASSIVE; 477 hints.ai_socktype = SOCK_STREAM; 478 479 if (hostname && *hostname == '[') 480 { 481 /* 482 * Remove brackets from numeric IPv6 address... 483 */ 484 485 if (!strncmp(hostname, "[v1.", 4)) 486 { 487 /* 488 * Copy the newer address format which supports link-local addresses... 489 */ 490 491 strlcpy(ipv6, hostname + 4, sizeof(ipv6)); 492 if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']') 493 { 494 ipv6[ipv6len] = '\0'; 495 hostname = ipv6; 496 497 /* 498 * Convert "+zone" in address to "%zone"... 499 */ 500 501 if ((ipv6zone = strrchr(ipv6, '+')) != NULL) 502 *ipv6zone = '%'; 503 } 504 } 505 else 506 { 507 /* 508 * Copy the regular non-link-local IPv6 address... 509 */ 510 511 strlcpy(ipv6, hostname + 1, sizeof(ipv6)); 512 if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']') 513 { 514 ipv6[ipv6len] = '\0'; 515 hostname = ipv6; 516 } 517 } 518 } 519 520 if ((error = getaddrinfo(hostname, service, &hints, &results)) == 0) 521 { 522 /* 523 * Copy the results to our own address list structure... 524 */ 525 526 for (current = results; current; current = current->ai_next) 527 if (current->ai_family == AF_INET || current->ai_family == AF_INET6) 528 { 529 /* 530 * Copy the address over... 531 */ 532 533 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 534 if (!temp) 535 { 536 httpAddrFreeList(first); 537 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 538 return (NULL); 539 } 540 541 if (current->ai_family == AF_INET6) 542 memcpy(&(temp->addr.ipv6), current->ai_addr, 543 sizeof(temp->addr.ipv6)); 544 else 545 memcpy(&(temp->addr.ipv4), current->ai_addr, 546 sizeof(temp->addr.ipv4)); 547 548 /* 549 * Append the address to the list... 550 */ 551 552 if (!first) 553 first = temp; 554 555 if (addr) 556 addr->next = temp; 557 558 addr = temp; 559 } 560 561 /* 562 * Free the results from getaddrinfo()... 563 */ 564 565 freeaddrinfo(results); 566 } 567 else 568 { 569 if (error == EAI_FAIL) 570 cg->need_res_init = 1; 571 572 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gai_strerror(error), 0); 573 } 574 575#else 576 if (hostname) 577 { 578 int i; /* Looping vars */ 579 unsigned ip[4]; /* IPv4 address components */ 580 const char *ptr; /* Pointer into hostname */ 581 struct hostent *host; /* Result of lookup */ 582 struct servent *port; /* Port number for service */ 583 int portnum; /* Port number */ 584 585 586 /* 587 * Lookup the service... 588 */ 589 590 if (!service) 591 portnum = 0; 592 else if (isdigit(*service & 255)) 593 portnum = atoi(service); 594 else if ((port = getservbyname(service, NULL)) != NULL) 595 portnum = ntohs(port->s_port); 596 else if (!strcmp(service, "http")) 597 portnum = 80; 598 else if (!strcmp(service, "https")) 599 portnum = 443; 600 else if (!strcmp(service, "ipp") || !strcmp(service, "ipps")) 601 portnum = 631; 602 else if (!strcmp(service, "lpd")) 603 portnum = 515; 604 else if (!strcmp(service, "socket")) 605 portnum = 9100; 606 else 607 return (NULL); 608 609 /* 610 * This code is needed because some operating systems have a 611 * buggy implementation of gethostbyname() that does not support 612 * IPv4 addresses. If the hostname string is an IPv4 address, then 613 * sscanf() is used to extract the IPv4 components. We then pack 614 * the components into an IPv4 address manually, since the 615 * inet_aton() function is deprecated. We use the htonl() macro 616 * to get the right byte order for the address. 617 */ 618 619 for (ptr = hostname; isdigit(*ptr & 255) || *ptr == '.'; ptr ++); 620 621 if (!*ptr) 622 { 623 /* 624 * We have an IPv4 address; break it up and create an IPv4 address... 625 */ 626 627 if (sscanf(hostname, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) == 4 && 628 ip[0] <= 255 && ip[1] <= 255 && ip[2] <= 255 && ip[3] <= 255) 629 { 630 first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 631 if (!first) 632 return (NULL); 633 634 first->addr.ipv4.sin_family = AF_INET; 635 first->addr.ipv4.sin_addr.s_addr = htonl((((((((unsigned)ip[0] << 8) | 636 (unsigned)ip[1]) << 8) | 637 (unsigned)ip[2]) << 8) | 638 (unsigned)ip[3])); 639 first->addr.ipv4.sin_port = htons(portnum); 640 } 641 } 642 else if ((host = gethostbyname(hostname)) != NULL && 643# ifdef AF_INET6 644 (host->h_addrtype == AF_INET || host->h_addrtype == AF_INET6)) 645# else 646 host->h_addrtype == AF_INET) 647# endif /* AF_INET6 */ 648 { 649 for (i = 0; host->h_addr_list[i]; i ++) 650 { 651 /* 652 * Copy the address over... 653 */ 654 655 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 656 if (!temp) 657 { 658 httpAddrFreeList(first); 659 return (NULL); 660 } 661 662# ifdef AF_INET6 663 if (host->h_addrtype == AF_INET6) 664 { 665 temp->addr.ipv6.sin6_family = AF_INET6; 666 memcpy(&(temp->addr.ipv6.sin6_addr), host->h_addr_list[i], 667 sizeof(temp->addr.ipv6)); 668 temp->addr.ipv6.sin6_port = htons(portnum); 669 } 670 else 671# endif /* AF_INET6 */ 672 { 673 temp->addr.ipv4.sin_family = AF_INET; 674 memcpy(&(temp->addr.ipv4.sin_addr), host->h_addr_list[i], 675 sizeof(temp->addr.ipv4)); 676 temp->addr.ipv4.sin_port = htons(portnum); 677 } 678 679 /* 680 * Append the address to the list... 681 */ 682 683 if (!first) 684 first = temp; 685 686 if (addr) 687 addr->next = temp; 688 689 addr = temp; 690 } 691 } 692 else 693 { 694 if (h_errno == NO_RECOVERY) 695 cg->need_res_init = 1; 696 697 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, hstrerror(h_errno), 0); 698 } 699 } 700#endif /* HAVE_GETADDRINFO */ 701 } 702 703 /* 704 * Detect some common errors and handle them sanely... 705 */ 706 707 if (!addr && (!hostname || !_cups_strcasecmp(hostname, "localhost"))) 708 { 709 struct servent *port; /* Port number for service */ 710 int portnum; /* Port number */ 711 712 713 /* 714 * Lookup the service... 715 */ 716 717 if (!service) 718 portnum = 0; 719 else if (isdigit(*service & 255)) 720 portnum = atoi(service); 721 else if ((port = getservbyname(service, NULL)) != NULL) 722 portnum = ntohs(port->s_port); 723 else if (!strcmp(service, "http")) 724 portnum = 80; 725 else if (!strcmp(service, "https")) 726 portnum = 443; 727 else if (!strcmp(service, "ipp") || !strcmp(service, "ipps")) 728 portnum = 631; 729 else if (!strcmp(service, "lpd")) 730 portnum = 515; 731 else if (!strcmp(service, "socket")) 732 portnum = 9100; 733 else 734 { 735 httpAddrFreeList(first); 736 737 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown service name."), 1); 738 return (NULL); 739 } 740 741 if (hostname && !_cups_strcasecmp(hostname, "localhost")) 742 { 743 /* 744 * Unfortunately, some users ignore all of the warnings in the 745 * /etc/hosts file and delete "localhost" from it. If we get here 746 * then we were unable to resolve the name, so use the IPv6 and/or 747 * IPv4 loopback interface addresses... 748 */ 749 750#ifdef AF_INET6 751 if (family != AF_INET) 752 { 753 /* 754 * Add [::1] to the address list... 755 */ 756 757 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 758 if (!temp) 759 { 760 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 761 httpAddrFreeList(first); 762 return (NULL); 763 } 764 765 temp->addr.ipv6.sin6_family = AF_INET6; 766 temp->addr.ipv6.sin6_port = htons(portnum); 767# ifdef WIN32 768 temp->addr.ipv6.sin6_addr.u.Byte[15] = 1; 769# else 770 temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1); 771# endif /* WIN32 */ 772 773 if (!first) 774 first = temp; 775 776 addr = temp; 777 } 778 779 if (family != AF_INET6) 780#endif /* AF_INET6 */ 781 { 782 /* 783 * Add 127.0.0.1 to the address list... 784 */ 785 786 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 787 if (!temp) 788 { 789 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 790 httpAddrFreeList(first); 791 return (NULL); 792 } 793 794 temp->addr.ipv4.sin_family = AF_INET; 795 temp->addr.ipv4.sin_port = htons(portnum); 796 temp->addr.ipv4.sin_addr.s_addr = htonl(0x7f000001); 797 798 if (!first) 799 first = temp; 800 801 if (addr) 802 addr->next = temp; 803 } 804 } 805 else if (!hostname) 806 { 807 /* 808 * Provide one or more passive listening addresses... 809 */ 810 811#ifdef AF_INET6 812 if (family != AF_INET) 813 { 814 /* 815 * Add [::] to the address list... 816 */ 817 818 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 819 if (!temp) 820 { 821 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 822 httpAddrFreeList(first); 823 return (NULL); 824 } 825 826 temp->addr.ipv6.sin6_family = AF_INET6; 827 temp->addr.ipv6.sin6_port = htons(portnum); 828 829 if (!first) 830 first = temp; 831 832 addr = temp; 833 } 834 835 if (family != AF_INET6) 836#endif /* AF_INET6 */ 837 { 838 /* 839 * Add 0.0.0.0 to the address list... 840 */ 841 842 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 843 if (!temp) 844 { 845 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 846 httpAddrFreeList(first); 847 return (NULL); 848 } 849 850 temp->addr.ipv4.sin_family = AF_INET; 851 temp->addr.ipv4.sin_port = htons(portnum); 852 853 if (!first) 854 first = temp; 855 856 if (addr) 857 addr->next = temp; 858 } 859 } 860 } 861 862 /* 863 * Return the address list... 864 */ 865 866 return (first); 867} 868 869 870/* 871 * End of "$Id: http-addrlist.c 11645 2014-02-27 16:35:53Z msweet $". 872 */ 873