/*
- * "$Id: http-addrlist.c 4815 2005-10-31 20:40:17Z mike $"
+ * HTTP address list routines for CUPS.
*
- * HTTP address list routines for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2018 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
- * Copyright 1997-2005 by Easy Software Products, all rights reserved.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
- *
- * Contents:
- *
- * httpAddrConnect() - Connect to any of the addresses in the list.
- * httpAddrFreeList() - Free an address list.
- * httpAddrGetList() - Get a list of addresses for a hostname.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
* Include necessary headers...
*/
-#include "http-private.h"
-#include "globals.h"
-#include "debug.h"
-#include <stdlib.h>
+#include "cups-private.h"
+#include "debug-internal.h"
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif /* HAVE_RESOLV_H */
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif /* HAVE_POLL */
+#ifndef _WIN32
+# include <fcntl.h>
+#endif /* _WIN32 */
/*
* 'httpAddrConnect()' - Connect to any of the addresses in the list.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/macOS 10.5@ @exclude all@
*/
http_addrlist_t * /* O - Connected address or NULL on failure */
http_addrlist_t *addrlist, /* I - List of potential addresses */
int *sock) /* O - Socket */
{
- int val; /* Socket option value */
+ DEBUG_printf(("httpAddrConnect(addrlist=%p, sock=%p)", (void *)addrlist, (void *)sock));
+
+ return (httpAddrConnect2(addrlist, sock, 30000, NULL));
+}
+
+
+/*
+ * 'httpAddrConnect2()' - Connect to any of the addresses in the list with a
+ * timeout and optional cancel.
+ *
+ * @since CUPS 1.7/macOS 10.9@
+ */
+
+http_addrlist_t * /* O - Connected address or NULL on failure */
+httpAddrConnect2(
+ http_addrlist_t *addrlist, /* I - List of potential addresses */
+ int *sock, /* O - Socket */
+ int msec, /* I - Timeout in milliseconds */
+ int *cancel) /* I - Pointer to "cancel" variable */
+{
+ int val; /* Socket option value */
+#ifndef _WIN32
+ int i, j, /* Looping vars */
+ flags, /* Socket flags */
+ result; /* Result from select() or poll() */
+#endif /* !_WIN32 */
+ int remaining; /* Remaining timeout */
+ int nfds, /* Number of file descriptors */
+ fds[100]; /* Socket file descriptors */
+ http_addrlist_t *addrs[100]; /* Addresses */
+#ifndef HAVE_POLL
+ int max_fd = -1; /* Highest file descriptor */
+#endif /* !HAVE_POLL */
+#ifdef O_NONBLOCK
+# ifdef HAVE_POLL
+ struct pollfd pfds[100]; /* Polled file descriptors */
+# else
+ fd_set input_set, /* select() input set */
+ output_set, /* select() output set */
+ error_set; /* select() error set */
+ struct timeval timeout; /* Timeout */
+# endif /* HAVE_POLL */
+#endif /* O_NONBLOCK */
+#ifdef DEBUG
+# ifndef _WIN32
+ socklen_t len; /* Length of value */
+ http_addr_t peer; /* Peer address */
+# endif /* !_WIN32 */
+ char temp[256]; /* Temporary address string */
+#endif /* DEBUG */
+
+
+ DEBUG_printf(("httpAddrConnect2(addrlist=%p, sock=%p, msec=%d, cancel=%p)", (void *)addrlist, (void *)sock, msec, (void *)cancel));
+
+ if (!sock)
+ {
+ errno = EINVAL;
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
+ return (NULL);
+ }
+
+ if (cancel && *cancel)
+ return (NULL);
+ if (msec <= 0)
+ msec = INT_MAX;
/*
* Loop through each address until we connect or run out of addresses...
*/
- while (addrlist)
+ nfds = 0;
+ remaining = msec;
+
+ while (remaining > 0)
{
- /*
- * Create the socket...
- */
+ if (cancel && *cancel)
+ {
+ while (nfds > 0)
+ {
+ nfds --;
+ httpAddrClose(NULL, fds[nfds]);
+ }
+
+ return (NULL);
+ }
- if ((*sock = socket(addrlist->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
+ if (addrlist && nfds < (int)(sizeof(fds) / sizeof(fds[0])))
{
/*
- * Don't abort yet, as this could just be an issue with the local
- * system not being configured with IPv4/IPv6/domain socket enabled...
+ * Create the socket...
*/
- addrlist = addrlist->next;
- continue;
- }
+ DEBUG_printf(("2httpAddrConnect2: Trying %s:%d...", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr))));
- /*
- * Set options...
- */
+ if ((fds[nfds] = (int)socket(httpAddrFamily(&(addrlist->addr)), SOCK_STREAM, 0)) < 0)
+ {
+ /*
+ * Don't abort yet, as this could just be an issue with the local
+ * system not being configured with IPv4/IPv6/domain socket enabled.
+ *
+ * Just skip this address...
+ */
- val = 1;
-#ifdef WIN32
- setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&val,
- sizeof(val));
-#else
- setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
-#endif /* WIN32 */
+ addrlist = addrlist->next;
+ continue;
+ }
+
+ /*
+ * Set options...
+ */
+
+ val = 1;
+ setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val));
#ifdef SO_REUSEPORT
- val = 1;
- setsockopt(*sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
+ val = 1;
+ setsockopt(fds[nfds], SOL_SOCKET, SO_REUSEPORT, CUPS_SOCAST &val, sizeof(val));
#endif /* SO_REUSEPORT */
- /*
- * Using TCP_NODELAY improves responsiveness, especially on systems
- * with a slow loopback interface...
- */
+#ifdef SO_NOSIGPIPE
+ val = 1;
+ setsockopt(fds[nfds], SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
+#endif /* SO_NOSIGPIPE */
- val = 1;
-#ifdef WIN32
- setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&val,
- sizeof(val));
-#else
- setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
-#endif /* WIN32 */
+ /*
+ * Using TCP_NODELAY improves responsiveness, especially on systems
+ * with a slow loopback interface...
+ */
+
+ val = 1;
+ setsockopt(fds[nfds], IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
#ifdef FD_CLOEXEC
- /*
- * Close this socket when starting another process...
- */
+ /*
+ * Close this socket when starting another process...
+ */
- fcntl(*sock, F_SETFD, FD_CLOEXEC);
+ fcntl(fds[nfds], F_SETFD, FD_CLOEXEC);
#endif /* FD_CLOEXEC */
- /*
- * Then connect...
- */
+#ifdef O_NONBLOCK
+ /*
+ * Do an asynchronous connect by setting the socket non-blocking...
+ */
+
+ DEBUG_printf(("httpAddrConnect2: Setting non-blocking connect()"));
+
+ flags = fcntl(fds[nfds], F_GETFL, 0);
+ fcntl(fds[nfds], F_SETFL, flags | O_NONBLOCK);
+#endif /* O_NONBLOCK */
+
+ /*
+ * Then connect...
+ */
+
+ if (!connect(fds[nfds], &(addrlist->addr.addr), (socklen_t)httpAddrLength(&(addrlist->addr))))
+ {
+ DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr))));
+
+#ifdef O_NONBLOCK
+ fcntl(fds[nfds], F_SETFL, flags);
+#endif /* O_NONBLOCK */
+
+ *sock = fds[nfds];
+
+ while (nfds > 0)
+ {
+ nfds --;
+ httpAddrClose(NULL, fds[nfds]);
+ }
+
+ return (addrlist);
+ }
+
+#ifdef _WIN32
+ if (WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK)
+#else
+ if (errno != EINPROGRESS && errno != EWOULDBLOCK)
+#endif /* _WIN32 */
+ {
+ DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr)), strerror(errno)));
+ httpAddrClose(NULL, fds[nfds]);
+ addrlist = addrlist->next;
+ continue;
+ }
+
+#ifndef _WIN32
+ fcntl(fds[nfds], F_SETFL, flags);
+#endif /* !_WIN32 */
+
+#ifndef HAVE_POLL
+ if (fds[nfds] > max_fd)
+ max_fd = fds[nfds];
+#endif /* !HAVE_POLL */
+
+ addrs[nfds] = addrlist;
+ nfds ++;
+ addrlist = addrlist->next;
+ }
- if (!connect(*sock, &(addrlist->addr.addr),
- httpAddrLength(&(addrlist->addr))))
+ if (!addrlist && nfds == 0)
break;
/*
- * Close this socket and move to the next address...
+ * See if we can connect to any of the addresses so far...
*/
- closesocket(*sock);
+#ifdef O_NONBLOCK
+ DEBUG_puts("1httpAddrConnect2: Finishing async connect()");
+
+ do
+ {
+ if (cancel && *cancel)
+ {
+ /*
+ * Close this socket and return...
+ */
+
+ DEBUG_puts("1httpAddrConnect2: Canceled connect()");
+
+ while (nfds > 0)
+ {
+ nfds --;
+ httpAddrClose(NULL, fds[nfds]);
+ }
+
+ *sock = -1;
+
+ return (NULL);
+ }
+
+# ifdef HAVE_POLL
+ for (i = 0; i < nfds; i ++)
+ {
+ pfds[i].fd = fds[i];
+ pfds[i].events = POLLIN | POLLOUT;
+ }
+
+ result = poll(pfds, (nfds_t)nfds, addrlist ? 100 : remaining > 250 ? 250 : remaining);
+
+ DEBUG_printf(("1httpAddrConnect2: poll() returned %d (%d)", result, errno));
+
+# else
+ FD_ZERO(&input_set);
+ for (i = 0; i < nfds; i ++)
+ FD_SET(fds[i], &input_set);
+ output_set = input_set;
+ error_set = input_set;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = (addrlist ? 100 : remaining > 250 ? 250 : remaining) * 1000;
+
+ result = select(max_fd + 1, &input_set, &output_set, &error_set, &timeout);
+
+ DEBUG_printf(("1httpAddrConnect2: select() returned %d (%d)", result, errno));
+# endif /* HAVE_POLL */
+ }
+# ifdef _WIN32
+ while (result < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK));
+# else
+ while (result < 0 && (errno == EINTR || errno == EAGAIN));
+# endif /* _WIN32 */
- addrlist = addrlist->next;
+ if (result > 0)
+ {
+ http_addrlist_t *connaddr = NULL; /* Connected address, if any */
+
+ for (i = 0; i < nfds; i ++)
+ {
+# ifdef HAVE_POLL
+ DEBUG_printf(("pfds[%d].revents=%x\n", i, pfds[i].revents));
+ if (pfds[i].revents && !(pfds[i].revents & (POLLERR | POLLHUP)))
+# else
+ if (FD_ISSET(fds[i], &input_set) && !FD_ISSET(fds[i], &error_set))
+# endif /* HAVE_POLL */
+ {
+ *sock = fds[i];
+ connaddr = addrs[i];
+
+# ifdef DEBUG
+ len = sizeof(peer);
+ if (!getpeername(fds[i], (struct sockaddr *)&peer, &len))
+ DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", httpAddrString(&peer, temp, sizeof(temp)), httpAddrPort(&peer)));
+# endif /* DEBUG */
+
+ break;
+ }
+# ifdef HAVE_POLL
+ else if (pfds[i].revents & (POLLERR | POLLHUP))
+# else
+ else if (FD_ISSET(fds[i], &error_set))
+# endif /* HAVE_POLL */
+ {
+ /*
+ * Error on socket, remove from the "pool"...
+ */
+
+ httpAddrClose(NULL, fds[i]);
+ nfds --;
+ if (i < nfds)
+ {
+ memmove(fds + i, fds + i + 1, (size_t)(nfds - i) * (sizeof(fds[0])));
+ memmove(addrs + i, addrs + i + 1, (size_t)(nfds - i) * (sizeof(addrs[0])));
+ }
+ i --;
+ }
+ }
+
+ if (connaddr)
+ {
+ /*
+ * Connected on one address, close all of the other sockets we have so
+ * far and return...
+ */
+
+ for (j = 0; j < i; j ++)
+ httpAddrClose(NULL, fds[j]);
+
+ for (j ++; j < nfds; j ++)
+ httpAddrClose(NULL, fds[j]);
+
+ return (connaddr);
+ }
+ }
+#endif /* O_NONBLOCK */
+
+ if (addrlist)
+ remaining -= 100;
+ else
+ remaining -= 250;
+ }
+
+ while (nfds > 0)
+ {
+ nfds --;
+ httpAddrClose(NULL, fds[nfds]);
}
- return (addrlist);
+#ifdef _WIN32
+ _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, "Connection failed", 0);
+#else
+ _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, strerror(errno), 0);
+#endif /* _WIN32 */
+
+ return (NULL);
+}
+
+
+/*
+ * 'httpAddrCopyList()' - Copy an address list.
+ *
+ * @since CUPS 1.7/macOS 10.9@
+ */
+
+http_addrlist_t * /* O - New address list or @code NULL@ on error */
+httpAddrCopyList(
+ http_addrlist_t *src) /* I - Source address list */
+{
+ http_addrlist_t *dst = NULL, /* First list entry */
+ *prev = NULL, /* Previous list entry */
+ *current = NULL;/* Current list entry */
+
+
+ while (src)
+ {
+ if ((current = malloc(sizeof(http_addrlist_t))) == NULL)
+ {
+ current = dst;
+
+ while (current)
+ {
+ prev = current;
+ current = current->next;
+
+ free(prev);
+ }
+
+ return (NULL);
+ }
+
+ memcpy(current, src, sizeof(http_addrlist_t));
+
+ current->next = NULL;
+
+ if (prev)
+ prev->next = current;
+ else
+ dst = current;
+
+ prev = current;
+ src = src->next;
+ }
+
+ return (dst);
}
/*
* 'httpAddrFreeList()' - Free an address list.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/macOS 10.5@
*/
void
/*
* 'httpAddrGetList()' - Get a list of addresses for a hostname.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/macOS 10.5@
*/
http_addrlist_t * /* O - List of addresses or NULL */
http_addrlist_t *first, /* First address in list */
*addr, /* Current address in list */
*temp; /* New address */
+ _cups_globals_t *cg = _cupsGlobals();
+ /* Global data */
#ifdef DEBUG
- printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, service=\"%s\")\n",
- hostname ? hostname : "(nil)",
- family == AF_UNSPEC ? "UNSPEC" :
+ _cups_debug_printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, "
+ "service=\"%s\")\n",
+ hostname ? hostname : "(nil)",
+ family == AF_UNSPEC ? "UNSPEC" :
# ifdef AF_LOCAL
- family == AF_LOCAL ? "LOCAL" :
+ family == AF_LOCAL ? "LOCAL" :
# endif /* AF_LOCAL */
# ifdef AF_INET6
- family == AF_INET6 ? "INET6" :
+ family == AF_INET6 ? "INET6" :
# endif /* AF_INET6 */
- family == AF_INET ? "INET" : "???", service);
+ family == AF_INET ? "INET" : "???", service);
#endif /* DEBUG */
+#ifdef HAVE_RES_INIT
+ /*
+ * STR #2920: Initialize resolver after failure in cups-polld
+ *
+ * If the previous lookup failed, re-initialize the resolver to prevent
+ * temporary network errors from persisting. This *should* be handled by
+ * the resolver libraries, but apparently the glibc folks do not agree.
+ *
+ * We set a flag at the end of this function if we encounter an error that
+ * requires reinitialization of the resolver functions. We then call
+ * res_init() if the flag is set on the next call here or in httpAddrLookup().
+ */
+
+ if (cg->need_res_init)
+ {
+ res_init();
+
+ cg->need_res_init = 0;
+ }
+#endif /* HAVE_RES_INIT */
+
/*
* Lookup the address the best way we can...
*/
* Domain socket address...
*/
- first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
- first->addr.un.sun_family = AF_LOCAL;
- strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path));
+ if ((first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t))) != NULL)
+ {
+ addr = first;
+ first->addr.un.sun_family = AF_LOCAL;
+ strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path));
+ }
}
else
#endif /* AF_LOCAL */
+ if (!hostname || _cups_strcasecmp(hostname, "localhost"))
{
#ifdef HAVE_GETADDRINFO
struct addrinfo hints, /* Address lookup hints */
*results, /* Address lookup results */
*current; /* Current result */
- char ipv6[1024], /* IPv6 address */
+ char ipv6[64], /* IPv6 address */
*ipv6zone; /* Pointer to zone separator */
int ipv6len; /* Length of IPv6 address */
+ int error; /* getaddrinfo() error */
+
/*
* Lookup the address as needed...
*/
strlcpy(ipv6, hostname + 4, sizeof(ipv6));
- if ((ipv6len = strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']')
+ if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']')
{
ipv6[ipv6len] = '\0';
hostname = ipv6;
*/
strlcpy(ipv6, hostname + 1, sizeof(ipv6));
- if ((ipv6len = strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']')
+ if ((ipv6len = (int)strlen(ipv6) - 1) >= 0 && ipv6[ipv6len] == ']')
{
ipv6[ipv6len] = '\0';
hostname = ipv6;
}
}
- if (!getaddrinfo(hostname, service, &hints, &results))
+ if ((error = getaddrinfo(hostname, service, &hints, &results)) == 0)
{
/*
* Copy the results to our own address list structure...
if (!temp)
{
httpAddrFreeList(first);
+ freeaddrinfo(results);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
return (NULL);
}
freeaddrinfo(results);
}
+ else
+ {
+ if (error == EAI_FAIL)
+ cg->need_res_init = 1;
+
+# ifdef _WIN32 /* Really, Microsoft?!? */
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gai_strerrorA(error), 0);
+# else
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gai_strerror(error), 0);
+# endif /* _WIN32 */
+ }
+
#else
if (hostname)
{
portnum = 80;
else if (!strcmp(service, "https"))
portnum = 443;
- else if (!strcmp(service, "ipp"))
+ else if (!strcmp(service, "ipp") || !strcmp(service, "ipps"))
portnum = 631;
else if (!strcmp(service, "lpd"))
portnum = 515;
return (NULL);
first->addr.ipv4.sin_family = AF_INET;
- first->addr.ipv4.sin_addr.s_addr = htonl(((((((ip[0] << 8) |
- ip[1]) << 8) |
- ip[2]) << 8) | ip[3]));
+ first->addr.ipv4.sin_addr.s_addr = htonl((((((((unsigned)ip[0] << 8) |
+ (unsigned)ip[1]) << 8) |
+ (unsigned)ip[2]) << 8) |
+ (unsigned)ip[3]));
first->addr.ipv4.sin_port = htons(portnum);
}
}
# ifdef AF_INET6
if (host->h_addrtype == AF_INET6)
{
- first->addr.ipv6.sin6_family = AF_INET6;
- memcpy(&(temp->addr.ipv6), host->h_addr_list[i],
+ temp->addr.ipv6.sin6_family = AF_INET6;
+ memcpy(&(temp->addr.ipv6.sin6_addr), host->h_addr_list[i],
sizeof(temp->addr.ipv6));
temp->addr.ipv6.sin6_port = htons(portnum);
}
else
# endif /* AF_INET6 */
{
- first->addr.ipv4.sin_family = AF_INET;
- memcpy(&(temp->addr.ipv4), host->h_addr_list[i],
+ temp->addr.ipv4.sin_family = AF_INET;
+ memcpy(&(temp->addr.ipv4.sin_addr), host->h_addr_list[i],
sizeof(temp->addr.ipv4));
temp->addr.ipv4.sin_port = htons(portnum);
}
addr = temp;
}
}
+ else
+ {
+ if (h_errno == NO_RECOVERY)
+ cg->need_res_init = 1;
+
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, hstrerror(h_errno), 0);
+ }
}
#endif /* HAVE_GETADDRINFO */
}
* Detect some common errors and handle them sanely...
*/
- if (!addr && (!hostname || !strcmp(hostname, "localhost")))
+ if (!addr && (!hostname || !_cups_strcasecmp(hostname, "localhost")))
{
struct servent *port; /* Port number for service */
int portnum; /* Port number */
portnum = 80;
else if (!strcmp(service, "https"))
portnum = 443;
- else if (!strcmp(service, "ipp"))
+ else if (!strcmp(service, "ipp") || !strcmp(service, "ipps"))
portnum = 631;
else if (!strcmp(service, "lpd"))
portnum = 515;
else if (!strcmp(service, "socket"))
portnum = 9100;
else
+ {
+ httpAddrFreeList(first);
+
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown service name."), 1);
return (NULL);
+ }
- if (hostname && !strcmp(hostname, "localhost"))
+ if (hostname && !_cups_strcasecmp(hostname, "localhost"))
{
/*
* Unfortunately, some users ignore all of the warnings in the
temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
if (!temp)
{
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
httpAddrFreeList(first);
return (NULL);
}
temp->addr.ipv6.sin6_family = AF_INET6;
temp->addr.ipv6.sin6_port = htons(portnum);
-# ifdef WIN32
+# ifdef _WIN32
temp->addr.ipv6.sin6_addr.u.Byte[15] = 1;
# else
temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1);
-# endif /* WIN32 */
+# endif /* _WIN32 */
+
+ if (!first)
+ first = temp;
addr = temp;
}
temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
if (!temp)
{
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
httpAddrFreeList(first);
return (NULL);
}
temp->addr.ipv4.sin_port = htons(portnum);
temp->addr.ipv4.sin_addr.s_addr = htonl(0x7f000001);
+ if (!first)
+ first = temp;
+
if (addr)
addr->next = temp;
- else
- addr = temp;
}
}
else if (!hostname)
temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
if (!temp)
{
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
httpAddrFreeList(first);
return (NULL);
}
temp->addr.ipv6.sin6_family = AF_INET6;
temp->addr.ipv6.sin6_port = htons(portnum);
+ if (!first)
+ first = temp;
+
addr = temp;
}
temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
if (!temp)
{
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
httpAddrFreeList(first);
return (NULL);
}
temp->addr.ipv4.sin_family = AF_INET;
temp->addr.ipv4.sin_port = htons(portnum);
+ if (!first)
+ first = temp;
+
if (addr)
addr->next = temp;
- else
- addr = temp;
}
}
}
return (first);
}
-
-
-/*
- * End of "$Id: http-addrlist.c 4815 2005-10-31 20:40:17Z mike $".
- */