1/* 2 * "$Id: http-addrlist.c 11693 2014-03-11 01:24:45Z msweet $" 3 * 4 * HTTP address list routines for CUPS. 5 * 6 * Copyright 2007-2013 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), 184 httpAddrLength(&(addrlist->addr)))) 185 { 186 DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", 187 httpAddrString(&(addrlist->addr), temp, sizeof(temp)), 188 httpAddrPort(&(addrlist->addr)))); 189 190#ifdef O_NONBLOCK 191 fcntl(*sock, F_SETFL, flags); 192#endif /* O_NONBLOCK */ 193 194 return (addrlist); 195 } 196 197#ifdef O_NONBLOCK 198# ifdef WIN32 199 if (WSAGetLastError() == WSAEINPROGRESS || 200 WSAGetLastError() == WSAEWOULDBLOCK) 201# else 202 if (errno == EINPROGRESS || errno == EWOULDBLOCK) 203# endif /* WIN32 */ 204 { 205 DEBUG_puts("1httpAddrConnect2: Finishing async connect()"); 206 207 fcntl(*sock, F_SETFL, flags); 208 209 for (remaining = msec; remaining > 0; remaining -= 250) 210 { 211 do 212 { 213 if (cancel && *cancel) 214 { 215 /* 216 * Close this socket and return... 217 */ 218 219 DEBUG_puts("1httpAddrConnect2: Canceled connect()"); 220 221# ifdef WIN32 222 closesocket(*sock); 223# else 224 close(*sock); 225# endif /* WIN32 */ 226 227 *sock = -1; 228 229 return (NULL); 230 } 231 232# ifdef HAVE_POLL 233 pfd.fd = *sock; 234 pfd.events = POLLIN | POLLOUT; 235 236 nfds = poll(&pfd, 1, remaining > 250 ? 250 : remaining); 237 238 DEBUG_printf(("1httpAddrConnect2: poll() returned %d (%d)", nfds, 239 errno)); 240 241# else 242 FD_ZERO(&input_set); 243 FD_SET(*sock, &input_set); 244 output_set = input_set; 245 246 timeout.tv_sec = 0; 247 timeout.tv_usec = (remaining > 250 ? 250 : remaining) * 1000; 248 249 nfds = select(*sock + 1, &input_set, &output_set, NULL, &timeout); 250 251 DEBUG_printf(("1httpAddrConnect2: select() returned %d (%d)", nfds, 252 errno)); 253# endif /* HAVE_POLL */ 254 } 255# ifdef WIN32 256 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || 257 WSAGetLastError() == WSAEWOULDBLOCK)); 258# else 259 while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); 260# endif /* WIN32 */ 261 262 if (nfds > 0) 263 { 264 len = sizeof(peer); 265 if (!getpeername(*sock, (struct sockaddr *)&peer, &len)) 266 { 267 DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", 268 httpAddrString(&peer, temp, sizeof(temp)), 269 httpAddrPort(&peer))); 270 271 return (addrlist); 272 } 273 274 break; 275 } 276 } 277 } 278#endif /* O_NONBLOCK */ 279 280 DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s", 281 httpAddrString(&(addrlist->addr), temp, sizeof(temp)), 282 httpAddrPort(&(addrlist->addr)), strerror(errno))); 283 284#ifndef WIN32 285 if (errno == EINPROGRESS) 286 errno = ETIMEDOUT; 287#endif /* !WIN32 */ 288 289 /* 290 * Close this socket and move to the next address... 291 */ 292 293#ifdef WIN32 294 closesocket(*sock); 295#else 296 close(*sock); 297#endif /* WIN32 */ 298 299 *sock = -1; 300 addrlist = addrlist->next; 301 } 302 303 if (!addrlist) 304#ifdef WIN32 305 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, "Connection failed", 0); 306#else 307 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, strerror(errno), 0); 308#endif /* WIN32 */ 309 310 return (addrlist); 311} 312 313 314 315/* 316 * 'httpAddrCopyList()' - Copy an address list. 317 * 318 * @since CUPS 1.7/OS X 10.9@ 319 */ 320 321http_addrlist_t * /* O - New address list or @code NULL@ on error */ 322httpAddrCopyList( 323 http_addrlist_t *src) /* I - Source address list */ 324{ 325 http_addrlist_t *dst = NULL, /* First list entry */ 326 *prev = NULL, /* Previous list entry */ 327 *current = NULL;/* Current list entry */ 328 329 330 while (src) 331 { 332 if ((current = malloc(sizeof(http_addrlist_t))) == NULL) 333 { 334 current = dst; 335 336 while (current) 337 { 338 prev = current; 339 current = current->next; 340 341 free(prev); 342 } 343 344 return (NULL); 345 } 346 347 memcpy(current, src, sizeof(http_addrlist_t)); 348 349 current->next = NULL; 350 351 if (prev) 352 prev->next = current; 353 else 354 dst = current; 355 356 prev = current; 357 src = src->next; 358 } 359 360 return (dst); 361} 362 363 364/* 365 * 'httpAddrFreeList()' - Free an address list. 366 * 367 * @since CUPS 1.2/OS X 10.5@ 368 */ 369 370void 371httpAddrFreeList( 372 http_addrlist_t *addrlist) /* I - Address list to free */ 373{ 374 http_addrlist_t *next; /* Next address in list */ 375 376 377 /* 378 * Free each address in the list... 379 */ 380 381 while (addrlist) 382 { 383 next = addrlist->next; 384 385 free(addrlist); 386 387 addrlist = next; 388 } 389} 390 391 392/* 393 * 'httpAddrGetList()' - Get a list of addresses for a hostname. 394 * 395 * @since CUPS 1.2/OS X 10.5@ 396 */ 397 398http_addrlist_t * /* O - List of addresses or NULL */ 399httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for passive listen address */ 400 int family, /* I - Address family or AF_UNSPEC */ 401 const char *service) /* I - Service name or port number */ 402{ 403 http_addrlist_t *first, /* First address in list */ 404 *addr, /* Current address in list */ 405 *temp; /* New address */ 406 _cups_globals_t *cg = _cupsGlobals(); 407 /* Global data */ 408 409 410#ifdef DEBUG 411 _cups_debug_printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, " 412 "service=\"%s\")\n", 413 hostname ? hostname : "(nil)", 414 family == AF_UNSPEC ? "UNSPEC" : 415# ifdef AF_LOCAL 416 family == AF_LOCAL ? "LOCAL" : 417# endif /* AF_LOCAL */ 418# ifdef AF_INET6 419 family == AF_INET6 ? "INET6" : 420# endif /* AF_INET6 */ 421 family == AF_INET ? "INET" : "???", service); 422#endif /* DEBUG */ 423 424#ifdef HAVE_RES_INIT 425 /* 426 * STR #2920: Initialize resolver after failure in cups-polld 427 * 428 * If the previous lookup failed, re-initialize the resolver to prevent 429 * temporary network errors from persisting. This *should* be handled by 430 * the resolver libraries, but apparently the glibc folks do not agree. 431 * 432 * We set a flag at the end of this function if we encounter an error that 433 * requires reinitialization of the resolver functions. We then call 434 * res_init() if the flag is set on the next call here or in httpAddrLookup(). 435 */ 436 437 if (cg->need_res_init) 438 { 439 res_init(); 440 441 cg->need_res_init = 0; 442 } 443#endif /* HAVE_RES_INIT */ 444 445 /* 446 * Lookup the address the best way we can... 447 */ 448 449 first = addr = NULL; 450 451#ifdef AF_LOCAL 452 if (hostname && hostname[0] == '/') 453 { 454 /* 455 * Domain socket address... 456 */ 457 458 if ((first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t))) != NULL) 459 { 460 addr = first; 461 first->addr.un.sun_family = AF_LOCAL; 462 strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path)); 463 } 464 } 465 else 466#endif /* AF_LOCAL */ 467 if (!hostname || _cups_strcasecmp(hostname, "localhost")) 468 { 469#ifdef HAVE_GETADDRINFO 470 struct addrinfo hints, /* Address lookup hints */ 471 *results, /* Address lookup results */ 472 *current; /* Current result */ 473 char ipv6[64], /* IPv6 address */ 474 *ipv6zone; /* Pointer to zone separator */ 475 int ipv6len; /* Length of IPv6 address */ 476 int error; /* getaddrinfo() error */ 477 478 479 /* 480 * Lookup the address as needed... 481 */ 482 483 memset(&hints, 0, sizeof(hints)); 484 hints.ai_family = family; 485 hints.ai_flags = hostname ? 0 : AI_PASSIVE; 486 hints.ai_socktype = SOCK_STREAM; 487 488 if (hostname && *hostname == '[') 489 { 490 /* 491 * Remove brackets from numeric IPv6 address... 492 */ 493 494 if (!strncmp(hostname, "[v1.", 4)) 495 { 496 /* 497 * Copy the newer address format which supports link-local addresses... 498 */ 499 500 strlcpy(ipv6, hostname + 4, sizeof(ipv6)); 501 if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']') 502 { 503 ipv6[ipv6len] = '\0'; 504 hostname = ipv6; 505 506 /* 507 * Convert "+zone" in address to "%zone"... 508 */ 509 510 if ((ipv6zone = strrchr(ipv6, '+')) != NULL) 511 *ipv6zone = '%'; 512 } 513 } 514 else 515 { 516 /* 517 * Copy the regular non-link-local IPv6 address... 518 */ 519 520 strlcpy(ipv6, hostname + 1, sizeof(ipv6)); 521 if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']') 522 { 523 ipv6[ipv6len] = '\0'; 524 hostname = ipv6; 525 } 526 } 527 } 528 529 if ((error = getaddrinfo(hostname, service, &hints, &results)) == 0) 530 { 531 /* 532 * Copy the results to our own address list structure... 533 */ 534 535 for (current = results; current; current = current->ai_next) 536 if (current->ai_family == AF_INET || current->ai_family == AF_INET6) 537 { 538 /* 539 * Copy the address over... 540 */ 541 542 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 543 if (!temp) 544 { 545 httpAddrFreeList(first); 546 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 547 return (NULL); 548 } 549 550 if (current->ai_family == AF_INET6) 551 memcpy(&(temp->addr.ipv6), current->ai_addr, 552 sizeof(temp->addr.ipv6)); 553 else 554 memcpy(&(temp->addr.ipv4), current->ai_addr, 555 sizeof(temp->addr.ipv4)); 556 557 /* 558 * Append the address to the list... 559 */ 560 561 if (!first) 562 first = temp; 563 564 if (addr) 565 addr->next = temp; 566 567 addr = temp; 568 } 569 570 /* 571 * Free the results from getaddrinfo()... 572 */ 573 574 freeaddrinfo(results); 575 } 576 else 577 { 578 if (error == EAI_FAIL) 579 cg->need_res_init = 1; 580 581 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gai_strerror(error), 0); 582 } 583 584#else 585 if (hostname) 586 { 587 int i; /* Looping vars */ 588 unsigned ip[4]; /* IPv4 address components */ 589 const char *ptr; /* Pointer into hostname */ 590 struct hostent *host; /* Result of lookup */ 591 struct servent *port; /* Port number for service */ 592 int portnum; /* Port number */ 593 594 595 /* 596 * Lookup the service... 597 */ 598 599 if (!service) 600 portnum = 0; 601 else if (isdigit(*service & 255)) 602 portnum = atoi(service); 603 else if ((port = getservbyname(service, NULL)) != NULL) 604 portnum = ntohs(port->s_port); 605 else if (!strcmp(service, "http")) 606 portnum = 80; 607 else if (!strcmp(service, "https")) 608 portnum = 443; 609 else if (!strcmp(service, "ipp") || !strcmp(service, "ipps")) 610 portnum = 631; 611 else if (!strcmp(service, "lpd")) 612 portnum = 515; 613 else if (!strcmp(service, "socket")) 614 portnum = 9100; 615 else 616 return (NULL); 617 618 /* 619 * This code is needed because some operating systems have a 620 * buggy implementation of gethostbyname() that does not support 621 * IPv4 addresses. If the hostname string is an IPv4 address, then 622 * sscanf() is used to extract the IPv4 components. We then pack 623 * the components into an IPv4 address manually, since the 624 * inet_aton() function is deprecated. We use the htonl() macro 625 * to get the right byte order for the address. 626 */ 627 628 for (ptr = hostname; isdigit(*ptr & 255) || *ptr == '.'; ptr ++); 629 630 if (!*ptr) 631 { 632 /* 633 * We have an IPv4 address; break it up and create an IPv4 address... 634 */ 635 636 if (sscanf(hostname, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) == 4 && 637 ip[0] <= 255 && ip[1] <= 255 && ip[2] <= 255 && ip[3] <= 255) 638 { 639 first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 640 if (!first) 641 return (NULL); 642 643 first->addr.ipv4.sin_family = AF_INET; 644 first->addr.ipv4.sin_addr.s_addr = htonl((((((((unsigned)ip[0] << 8) | 645 (unsigned)ip[1]) << 8) | 646 (unsigned)ip[2]) << 8) | 647 (unsigned)ip[3])); 648 first->addr.ipv4.sin_port = htons(portnum); 649 } 650 } 651 else if ((host = gethostbyname(hostname)) != NULL && 652# ifdef AF_INET6 653 (host->h_addrtype == AF_INET || host->h_addrtype == AF_INET6)) 654# else 655 host->h_addrtype == AF_INET) 656# endif /* AF_INET6 */ 657 { 658 for (i = 0; host->h_addr_list[i]; i ++) 659 { 660 /* 661 * Copy the address over... 662 */ 663 664 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 665 if (!temp) 666 { 667 httpAddrFreeList(first); 668 return (NULL); 669 } 670 671# ifdef AF_INET6 672 if (host->h_addrtype == AF_INET6) 673 { 674 temp->addr.ipv6.sin6_family = AF_INET6; 675 memcpy(&(temp->addr.ipv6.sin6_addr), host->h_addr_list[i], 676 sizeof(temp->addr.ipv6)); 677 temp->addr.ipv6.sin6_port = htons(portnum); 678 } 679 else 680# endif /* AF_INET6 */ 681 { 682 temp->addr.ipv4.sin_family = AF_INET; 683 memcpy(&(temp->addr.ipv4.sin_addr), host->h_addr_list[i], 684 sizeof(temp->addr.ipv4)); 685 temp->addr.ipv4.sin_port = htons(portnum); 686 } 687 688 /* 689 * Append the address to the list... 690 */ 691 692 if (!first) 693 first = temp; 694 695 if (addr) 696 addr->next = temp; 697 698 addr = temp; 699 } 700 } 701 else 702 { 703 if (h_errno == NO_RECOVERY) 704 cg->need_res_init = 1; 705 706 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, hstrerror(h_errno), 0); 707 } 708 } 709#endif /* HAVE_GETADDRINFO */ 710 } 711 712 /* 713 * Detect some common errors and handle them sanely... 714 */ 715 716 if (!addr && (!hostname || !_cups_strcasecmp(hostname, "localhost"))) 717 { 718 struct servent *port; /* Port number for service */ 719 int portnum; /* Port number */ 720 721 722 /* 723 * Lookup the service... 724 */ 725 726 if (!service) 727 portnum = 0; 728 else if (isdigit(*service & 255)) 729 portnum = atoi(service); 730 else if ((port = getservbyname(service, NULL)) != NULL) 731 portnum = ntohs(port->s_port); 732 else if (!strcmp(service, "http")) 733 portnum = 80; 734 else if (!strcmp(service, "https")) 735 portnum = 443; 736 else if (!strcmp(service, "ipp") || !strcmp(service, "ipps")) 737 portnum = 631; 738 else if (!strcmp(service, "lpd")) 739 portnum = 515; 740 else if (!strcmp(service, "socket")) 741 portnum = 9100; 742 else 743 { 744 httpAddrFreeList(first); 745 746 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown service name."), 1); 747 return (NULL); 748 } 749 750 if (hostname && !_cups_strcasecmp(hostname, "localhost")) 751 { 752 /* 753 * Unfortunately, some users ignore all of the warnings in the 754 * /etc/hosts file and delete "localhost" from it. If we get here 755 * then we were unable to resolve the name, so use the IPv6 and/or 756 * IPv4 loopback interface addresses... 757 */ 758 759#ifdef AF_INET6 760 if (family != AF_INET) 761 { 762 /* 763 * Add [::1] to the address list... 764 */ 765 766 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 767 if (!temp) 768 { 769 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 770 httpAddrFreeList(first); 771 return (NULL); 772 } 773 774 temp->addr.ipv6.sin6_family = AF_INET6; 775 temp->addr.ipv6.sin6_port = htons(portnum); 776# ifdef WIN32 777 temp->addr.ipv6.sin6_addr.u.Byte[15] = 1; 778# else 779 temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1); 780# endif /* WIN32 */ 781 782 if (!first) 783 first = temp; 784 785 addr = temp; 786 } 787 788 if (family != AF_INET6) 789#endif /* AF_INET6 */ 790 { 791 /* 792 * Add 127.0.0.1 to the address list... 793 */ 794 795 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 796 if (!temp) 797 { 798 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 799 httpAddrFreeList(first); 800 return (NULL); 801 } 802 803 temp->addr.ipv4.sin_family = AF_INET; 804 temp->addr.ipv4.sin_port = htons(portnum); 805 temp->addr.ipv4.sin_addr.s_addr = htonl(0x7f000001); 806 807 if (!first) 808 first = temp; 809 810 if (addr) 811 addr->next = temp; 812 } 813 } 814 else if (!hostname) 815 { 816 /* 817 * Provide one or more passive listening addresses... 818 */ 819 820#ifdef AF_INET6 821 if (family != AF_INET) 822 { 823 /* 824 * Add [::] to the address list... 825 */ 826 827 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 828 if (!temp) 829 { 830 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 831 httpAddrFreeList(first); 832 return (NULL); 833 } 834 835 temp->addr.ipv6.sin6_family = AF_INET6; 836 temp->addr.ipv6.sin6_port = htons(portnum); 837 838 if (!first) 839 first = temp; 840 841 addr = temp; 842 } 843 844 if (family != AF_INET6) 845#endif /* AF_INET6 */ 846 { 847 /* 848 * Add 0.0.0.0 to the address list... 849 */ 850 851 temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t)); 852 if (!temp) 853 { 854 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 855 httpAddrFreeList(first); 856 return (NULL); 857 } 858 859 temp->addr.ipv4.sin_family = AF_INET; 860 temp->addr.ipv4.sin_port = htons(portnum); 861 862 if (!first) 863 first = temp; 864 865 if (addr) 866 addr->next = temp; 867 } 868 } 869 } 870 871 /* 872 * Return the address list... 873 */ 874 875 return (first); 876} 877 878 879/* 880 * End of "$Id: http-addrlist.c 11693 2014-03-11 01:24:45Z msweet $". 881 */ 882