]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/http-addrlist.c
Merge changes from CUPS 1.4svn-r7932.
[thirdparty/cups.git] / cups / http-addrlist.c
index ed61944714f7917f1541414aecba9b2b752f5b75..52b5aeca9c075304be94bac2313d51b679b0c948 100644 (file)
@@ -1,25 +1,16 @@
 /*
- * "$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 */
 
 
 /*
@@ -50,7 +45,18 @@ httpAddrConnect(
     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...
@@ -62,7 +68,12 @@ httpAddrConnect(
     * 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
@@ -90,6 +101,11 @@ httpAddrConnect(
     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...
@@ -117,14 +133,28 @@ httpAddrConnect(
 
     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;
   }
 
@@ -174,21 +204,46 @@ httpAddrGetList(const char *hostname,     /* I - Hostname, IP address, or NULL for p
   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...
   */
@@ -202,9 +257,11 @@ httpAddrGetList(const char *hostname,      /* I - Hostname, IP address, or NULL for p
     * 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 */
@@ -216,6 +273,8 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
     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...
@@ -239,7 +298,7 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
        */
 
        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;
@@ -259,7 +318,7 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
        */
 
        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;
@@ -267,7 +326,7 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
       }
     }
 
-    if (!getaddrinfo(hostname, service, &hints, &results))
+    if ((error = getaddrinfo(hostname, service, &hints, &results)) == 0)
     {
      /*
       * Copy the results to our own address list structure...
@@ -313,6 +372,9 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
 
       freeaddrinfo(results);
     }
+    else if (error == EAI_FAIL)
+      cg->need_res_init = 1;
+
 #else
     if (hostname)
     {
@@ -402,16 +464,16 @@ httpAddrGetList(const char *hostname,     /* I - Hostname, IP address, or NULL for p
 #  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);
           }
@@ -429,6 +491,8 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
          addr = temp;
        }
       }
+      else if (h_errno == NO_RECOVERY)
+        cg->need_res_init = 1;
     }
 #endif /* HAVE_GETADDRINFO */
   }
@@ -497,6 +561,9 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
        temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1);
 #  endif /* WIN32 */
 
+        if (!first)
+          first = temp;
+
         addr = temp;
       }
 
@@ -518,10 +585,11 @@ httpAddrGetList(const char *hostname,     /* I - Hostname, IP address, or NULL for p
        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)
@@ -547,6 +615,9 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
         temp->addr.ipv6.sin6_family = AF_INET6;
        temp->addr.ipv6.sin6_port   = htons(portnum);
 
+        if (!first)
+          first = temp;
+
         addr = temp;
       }
 
@@ -567,10 +638,11 @@ httpAddrGetList(const char *hostname,     /* I - Hostname, IP address, or NULL for p
         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;
       }
     }
   }
@@ -584,5 +656,5 @@ httpAddrGetList(const char *hostname,       /* I - Hostname, IP address, or NULL for p
 
 
 /*
- * 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 $".
  */