/*
- * "$Id: http-addrlist.c 4815 2005-10-31 20:40:17Z mike $"
+ * "$Id: http-addrlist.c 7460 2008-04-16 02:19:54Z mike $"
*
* HTTP address list routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ * Copyright 2007-2008 by Apple Inc.
+ * Copyright 1997-2007 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
+ * property of Apple Inc. 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
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* Contents:
*
#include "globals.h"
#include "debug.h"
#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif /* HAVE_RESOLV_H */
/*
int *sock) /* O - Socket */
{
int val; /* Socket option value */
+#ifdef DEBUG
+ char temp[256]; /* Temporary address string */
+#endif /* DEBUG */
+
+ DEBUG_printf(("httpAddrConnect(addrlist=%p, sock=%p)\n", addrlist, sock));
+
+ if (!sock)
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
/*
* Loop through each address until we connect or run out of addresses...
* Create the socket...
*/
- if ((*sock = socket(addrlist->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
+ DEBUG_printf(("httpAddrConnect: Trying %s:%d...\n",
+ httpAddrString(&(addrlist->addr), temp, sizeof(temp)),
+ _httpAddrPort(&(addrlist->addr))));
+
+ if ((*sock = (int)socket(addrlist->addr.addr.sa_family, SOCK_STREAM,
+ 0)) < 0)
{
/*
* Don't abort yet, as this could just be an issue with the local
setsockopt(*sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
#endif /* SO_REUSEPORT */
+#ifdef SO_NOSIGPIPE
+ val = 1;
+ setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val));
+#endif /* SO_NOSIGPIPE */
+
/*
* Using TCP_NODELAY improves responsiveness, especially on systems
* with a slow loopback interface...
if (!connect(*sock, &(addrlist->addr.addr),
httpAddrLength(&(addrlist->addr))))
+ {
+ DEBUG_printf(("httpAddrConnect: Connected to %s:%d...\n",
+ httpAddrString(&(addrlist->addr), temp, sizeof(temp)),
+ _httpAddrPort(&(addrlist->addr))));
break;
+ }
+
+ DEBUG_printf(("httpAddrConnect: Unable to connect to %s:%d: %s\n",
+ httpAddrString(&(addrlist->addr), temp, sizeof(temp)),
+ _httpAddrPort(&(addrlist->addr)), strerror(errno)));
/*
* Close this socket and move to the next address...
*/
+#ifdef WIN32
closesocket(*sock);
+#else
+ close(*sock);
+#endif /* WIN32 */
+ *sock = -1;
addrlist = addrlist->next;
}
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)
+ {
+ first->addr.un.sun_family = AF_LOCAL;
+ strlcpy(first->addr.un.sun_path, hostname, sizeof(first->addr.un.sun_path));
+ }
}
else
#endif /* AF_LOCAL */
char ipv6[1024], /* 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...
freeaddrinfo(results);
}
+ else if (error == EAI_FAIL)
+ cg->need_res_init = 1;
+
#else
if (hostname)
{
# 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;
}
#endif /* HAVE_GETADDRINFO */
}
temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1);
# endif /* WIN32 */
+ if (!first)
+ first = temp;
+
addr = temp;
}
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->addr.ipv6.sin6_family = AF_INET6;
temp->addr.ipv6.sin6_port = htons(portnum);
+ if (!first)
+ first = temp;
+
addr = temp;
}
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;
}
}
}
/*
- * End of "$Id: http-addrlist.c 4815 2005-10-31 20:40:17Z mike $".
+ * End of "$Id: http-addrlist.c 7460 2008-04-16 02:19:54Z mike $".
*/