]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
New IPv6-capable address list stuff for STR #1313. Basically, this
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sat, 8 Oct 2005 10:10:46 +0000 (10:10 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sat, 8 Oct 2005 10:10:46 +0000 (10:10 +0000)
change deprecates the old httpGetHostByName() interface and adds a new
address list interface which supports mixed address types.

backend/lpd.c:
    - lpd_queue(): Use new httpAddrGetList() and
      httpAddrFreeList() functions.

backend/socket.c:
    - main(): Use new httpAddrConnect(), httpAddrGetList() and
      httpAddrFreeList() functions.

cups/auth.c:
    - cups_local_auth(): Fix address check for new hostaddr
      pointer.

cups/file.c:
    - cupsFileOpen(): Use new httpAddrConnect(),
      httpAddrGetList() and httpAddrFreeList() functions.

cups/globals.h:
    - Drop ip_addrs from and add ip_addr and domain_socket
      members to _cups_globals_s structure.

cups/http-addr.c:
    - httpAddrLoad(): Deleted.
    - httpGetHostByName(): Remove IPv6 and getaddrinfo() handling
      code.

cups/http-addrlist.c:
    - Added.

cups/http.c:
    - httpClose(): Free address list.
    - httpConnectEncrypt(): Use new httpAddrFreeList() and
      httpAddrGetList() functions.
    - httpReconnect(): Use new httpAddrConnect() function.

cups/http.h:
    - Change hostaddr member of http_t structure to be a
      http_addr_t *.
    - Add addrlist member to the http_t structure.
    - Add httpAddrConnect(), httpAddrFreeList(), and
      httpAddrGetList() functions.
    - Remove httpAddrLoad() function.

cups/http-private.h:
    - Add common headers.

cups/util.c:
    - cupsGetPPD2(): Fix hostaddr references.

scheduler/auth.c:
    - cupsdIsAuthorized(): Fix hostaddr references.

scheduler/client.c:
    - cupsdAcceptClient(): Use httpAddrFreeList() and
      httpAddrGetList(), and fix hostaddr references.
    - pipe_command(): Fix hostaddr references.

scheduler/client.h:
    - Add clientaddr member to cups_client_t structure.
    - Change ServerAddr to ServerAddrs list.

scheduler/conf.c:
    - get_address(): Use httpAddrFreeList() and
      httpAddrGetList().

scheduler/listen.c:
    - cupsdStartListening(): Use httpAddrFreeList() and
      httpAddrGetList().

scheduler/network.c:
    - cupsdNetIFUpdate(): Use ServerAddrs list.

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@4757 7a7537e8-13f0-0310-91df-b6672ffda945

18 files changed:
backend/lpd.c
backend/socket.c
cups/Makefile
cups/auth.c
cups/file.c
cups/globals.h
cups/http-addr.c
cups/http-addrlist.c [new file with mode: 0644]
cups/http-private.h
cups/http.c
cups/http.h
cups/util.c
scheduler/auth.c
scheduler/client.c
scheduler/client.h
scheduler/conf.c
scheduler/listen.c
scheduler/network.c

index e00a206fd47ff8c3c1941a0851bb1ccf4ba825d3..642cc513b4042dbc76e84f57fe7505695f34b764 100644 (file)
@@ -536,7 +536,6 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
          int        manual_copies,     /* I - Do copies by hand... */
          int        timeout)           /* I - Timeout... */
 {
-  int                  i;              /* Looping var */
   FILE                 *fp;            /* Job file */
   char                 localhost[255]; /* Local host name */
   int                  error;          /* Error number */
@@ -546,8 +545,9 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
   char                 control[10240], /* LPD control 'file' */
                        *cptr;          /* Pointer into control file string */
   char                 status;         /* Status byte from command */
-  http_addr_t          addr;           /* Socket address */
-  struct hostent       *hostaddr;      /* Host address */
+  char                 portname[255];  /* Port name */
+  http_addrlist_t      *addrlist,      /* Address list */
+                       *addr;          /* Socket address */
   int                  copy;           /* Copies written */
   size_t               nbytes;         /* Number of bytes written */
   off_t                        tbytes;         /* Total bytes written */
@@ -573,6 +573,19 @@ lpd_queue(const char *hostname,            /* I - Host to connect to */
   signal(SIGALRM, lpd_timeout);
 #endif /* HAVE_SIGSET */
 
+ /*
+  * Find the printer...
+  */
+
+  sprintf(portname, "%d", port);
+
+  if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
+  {
+    fprintf(stderr, "ERROR: Unable to locate printer \'%s\'!\n",
+            hostname);
+    return (CUPS_BACKEND_STOP);
+  }
+
  /*
   * Loop forever trying to print the file...
   */
@@ -583,29 +596,30 @@ lpd_queue(const char *hostname,           /* I - Host to connect to */
     * First try to reserve a port for this connection...
     */
 
-    if ((hostaddr = httpGetHostByName(hostname)) == NULL)
-    {
-      fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
-              hostname, hstrerror(h_errno));
-      return (CUPS_BACKEND_STOP);
-    }
-
     fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n",
             hostname, printer);
 
-    for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024;;)
+    for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist;;
+         addr = addr->next)
     {
      /*
       * Stop if this job has been cancelled...
       */
 
       if (abort_job)
+      {
+        httpAddrFreeList(addrlist);
+
         return (CUPS_BACKEND_FAILED);
+      }
 
      /*
       * Choose the next priviledged port...
       */
 
+      if (!addr)
+        addr = addrlist;
+
       lport --;
 
       if (lport < 721 && reserve == RESERVE_RFC1179)
@@ -623,10 +637,12 @@ lpd_queue(const char *hostname,           /* I - Host to connect to */
        * Just create a regular socket...
        */
 
-       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+       if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
        {
           perror("ERROR: Unable to create socket");
-          return (CUPS_BACKEND_FAILED);
+         sleep(1);
+
+          continue;
        }
 
         lport = 0;
@@ -638,7 +654,7 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
        * priviledged lport between 721 and 731...
        */
 
-       if ((fd = rresvport_af(&lport, hostaddr->h_addrtype)) < 0)
+       if ((fd = rresvport_af(&lport, addr->addr.addr.sa_family)) < 0)
        {
          perror("ERROR: Unable to reserve port");
          sleep(1);
@@ -651,70 +667,68 @@ lpd_queue(const char *hostname,           /* I - Host to connect to */
       * Connect to the printer or server...
       */
 
-      for (i = 0; hostaddr->h_addr_list[i]; i ++)
+      if (abort_job)
       {
-        if (abort_job)
-       {
-         close(fd);
-         return (CUPS_BACKEND_FAILED);
-       }
+        httpAddrFreeList(addrlist);
 
-        httpAddrLoad(hostaddr, port, i, &addr);
+       close(fd);
 
-       if (!connect(fd, (struct sockaddr *)&addr, sizeof(addr)))
-         break;
+       return (CUPS_BACKEND_FAILED);
       }
 
-      if (!hostaddr->h_addr_list[i])
+      if (!connect(fd, &(addr->addr.addr), httpAddrLength(&(addr->addr))))
+       break;
+
+      error = errno;
+      close(fd);
+      fd = -1;
+
+      if (addr->next)
+        continue;
+
+      if (getenv("CLASS") != NULL)
       {
-       error = errno;
-       close(fd);
-       fd = -1;
+       /*
+        * If the CLASS environment variable is set, the job was submitted
+       * to a class and not to a specific queue.  In this case, we want
+       * to abort immediately so that the job can be requeued on the next
+       * available printer in the class.
+       */
 
-       if (getenv("CLASS") != NULL)
-       {
-        /*
-          * If the CLASS environment variable is set, the job was submitted
-         * to a class and not to a specific queue.  In this case, we want
-         * to abort immediately so that the job can be requeued on the next
-         * available printer in the class.
-         */
+        fprintf(stderr, "INFO: Unable to connect to %s, queuing on next printer in class...\n",
+               hostname);
 
-          fprintf(stderr, "INFO: Unable to connect to %s, queuing on next printer in class...\n",
-                 hostname);
+        httpAddrFreeList(addrlist);
 
-        /*
-          * Sleep 5 seconds to keep the job from requeuing too rapidly...
-         */
+       /*
+        * Sleep 5 seconds to keep the job from requeuing too rapidly...
+       */
 
-         sleep(5);
+       sleep(5);
 
-          return (CUPS_BACKEND_FAILED);
-       }
+        return (CUPS_BACKEND_FAILED);
+      }
 
-       if (error == ECONNREFUSED || error == EHOSTDOWN ||
-            error == EHOSTUNREACH)
-       {
-         fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n",
-                  hostname);
-         sleep(30);
-       }
-       else if (error == EADDRINUSE)
-       {
-        /*
-         * Try on another port...
-         */
+      if (error == ECONNREFUSED || error == EHOSTDOWN ||
+          error == EHOSTUNREACH)
+      {
+       fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n",
+                hostname);
+       sleep(30);
+      }
+      else if (error == EADDRINUSE)
+      {
+       /*
+       * Try on another port...
+       */
 
-         sleep(1);
-       }
-       else
-       {
-         perror("ERROR: Unable to connect to printer; will retry in 30 seconds...");
-          sleep(30);
-       }
+       sleep(1);
       }
       else
-       break;
+      {
+       perror("ERROR: Unable to connect to printer; will retry in 30 seconds...");
+        sleep(30);
+      }
     }
 
     fprintf(stderr, "INFO: Connected to %s...\n", hostname);
@@ -727,6 +741,9 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
 
     if (stat(filename, &filestats))
     {
+      httpAddrFreeList(addrlist);
+      close(fd);
+
       perror("ERROR: unable to stat print file");
       return (CUPS_BACKEND_FAILED);
     }
@@ -735,6 +752,9 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
 
     if ((fp = fopen(filename, "rb")) == NULL)
     {
+      httpAddrFreeList(addrlist);
+      close(fd);
+
       perror("ERROR: unable to open print file for reading");
       return (CUPS_BACKEND_FAILED);
     }
@@ -746,9 +766,13 @@ lpd_queue(const char *hostname,            /* I - Host to connect to */
 
     if (lpd_command(fd, timeout, "\002%s\n",
                     printer))          /* Receive print job(s) */
+    {
+      httpAddrFreeList(addrlist);
+      close(fd);
       return (CUPS_BACKEND_FAILED);
+    }
 
-    gethostname(localhost, sizeof(localhost));
+    httpGetHostname(localhost, sizeof(localhost));
     localhost[31] = '\0'; /* RFC 1179, Section 7.2 - host name < 32 chars */
 
     snprintf(control, sizeof(control), "H%s\nP%s\nJ%s\n", localhost, user,
@@ -780,7 +804,12 @@ lpd_queue(const char *hostname,            /* I - Host to connect to */
     {
       if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
                       getpid() % 1000, localhost))
+      {
+        httpAddrFreeList(addrlist);
+       close(fd);
+
         return (CUPS_BACKEND_FAILED);
+      }
 
       fprintf(stderr, "INFO: Sending control file (%u bytes)\n",
               (unsigned)strlen(control));
@@ -822,7 +851,12 @@ lpd_queue(const char *hostname,            /* I - Host to connect to */
       if (lpd_command(fd, timeout, "\003" CUPS_LLFMT " dfA%03.3d%.15s\n",
                       CUPS_LLCAST filestats.st_size, getpid() % 1000,
                      localhost))
+      {
+        httpAddrFreeList(addrlist);
+       close(fd);
+
         return (CUPS_BACKEND_FAILED);
+      }
 
       fprintf(stderr, "INFO: Sending data file (" CUPS_LLFMT " bytes)\n",
               CUPS_LLCAST filestats.st_size);
@@ -886,7 +920,12 @@ lpd_queue(const char *hostname,            /* I - Host to connect to */
     {
       if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
                       getpid() % 1000, localhost))
+      {
+        httpAddrFreeList(addrlist);
+       close(fd);
+
         return (CUPS_BACKEND_FAILED);
+      }
 
       fprintf(stderr, "INFO: Sending control file (%lu bytes)\n",
               (unsigned long)strlen(control));
@@ -925,7 +964,11 @@ lpd_queue(const char *hostname,            /* I - Host to connect to */
     fclose(fp);
 
     if (status == 0)
+    {
+      httpAddrFreeList(addrlist);
+
       return (CUPS_BACKEND_OK);
+    }
 
    /*
     * Waiting for a retry...
@@ -934,6 +977,8 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
     sleep(30);
   }
 
+  httpAddrFreeList(addrlist);
+
  /*
   * If we get here, then the job has been cancelled...
   */
index cf4928453e4323329b8de9c2b043f56c9bfbd10b..bc27af316194fdb7593cb50a2fa292783badf302 100644 (file)
@@ -68,7 +68,6 @@ int                                   /* O - Exit status */
 main(int  argc,                                /* I - Number of command-line arguments (6 or 7) */
      char *argv[])                     /* I - Command-line arguments */
 {
-  int          i;                      /* Looping var */
   char         method[255],            /* Method in URI */
                hostname[1024],         /* Hostname */
                username[255],          /* Username info (not used) */
@@ -76,11 +75,11 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   int          fp;                     /* Print file */
   int          copies;                 /* Number of copies to print */
   int          port;                   /* Port number */
+  char         portname[255];          /* Port name */
   int          delay;                  /* Delay for retries... */
   int          fd;                     /* AppSocket */
   int          error;                  /* Error code (if any) */
-  http_addr_t  addr;                   /* Socket address */
-  struct hostent *hostaddr;            /* Host address */
+  http_addrlist_t *addrlist;           /* Address list */
   int          rbytes;                 /* Number of bytes read */
   int          wbytes;                 /* Number of bytes written */
   int          nbytes;                 /* Number of bytes read */
@@ -169,10 +168,11 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
   * Then try to connect to the remote host...
   */
 
-  if ((hostaddr = httpGetHostByName(hostname)) == NULL)
+  sprintf(portname, "%d", port);
+
+  if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
   {
-    fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
-            hostname, hstrerror(h_errno));
+    fprintf(stderr, "ERROR: Unable to locate printer \'%s\'!\n", hostname);
     return (CUPS_BACKEND_STOP);
   }
 
@@ -185,25 +185,10 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
   {
     for (delay = 5;;)
     {
-      if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-      {
-       perror("ERROR: Unable to create socket");
-       return (CUPS_BACKEND_FAILED);
-      }
-
-      for (i = 0; hostaddr->h_addr_list[i]; i ++)
-      {
-        httpAddrLoad(hostaddr, port, i, &addr);
-
-        if (!connect(fd, (struct sockaddr *)&addr, sizeof(addr)))
-         break;
-      }
-
-      if (!hostaddr->h_addr_list[i])
+      if (!httpAddrConnect(addrlist, &fd))
       {
        error = errno;
-       close(fd);
-       fd = -1;
+       fd    = -1;
 
        if (getenv("CLASS") != NULL)
        {
@@ -410,6 +395,8 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
     close(fd);
   }
 
+  httpAddrFreeList(addrlist);
+
  /*
   * Close the input file and return...
   */
index 25ed0fa62320503709d7283ae27e755ec26d9644..87cd7206f1bca60de0c22d752e9ba7711ea0d7bc 100644 (file)
@@ -44,6 +44,7 @@ LIBOBJS       =       \
                globals.o \
                http.o \
                http-addr.o \
+               http-addrlist.o \
                http-support.o \
                ipp.o \
                ipp-support.o \
index 3c72a5762fd985db3e27e92b4a0cd0cfe2aba613..c9aac4538a24ef99e3b4d3eb9d6ccc56c6005947 100644 (file)
@@ -190,7 +190,7 @@ cups_local_auth(http_t *http)               /* I - HTTP connection to server */
   * See if we are accessing localhost...
   */
 
-  if (!httpAddrLocalhost(&http->hostaddr) &&
+  if (!httpAddrLocalhost(http->hostaddr) &&
       strcasecmp(http->hostname, "localhost") != 0)
   {
     DEBUG_puts("cups_local_auth: Not a local connection!");
index 81f43a97d0f9a6a0d3e3d41bfa5a8ef41c756dd3..c7c0b2cd574cafb939dbdfc0dc0eedd86dbdec63 100644 (file)
 #include <cups/debug.h>
 #include <sys/types.h>
 
-#ifdef WIN32
-#  include <io.h>
-#  include <winsock2.h>
-#else
-#  include <unistd.h>
-#  include <fcntl.h>
-#  include <sys/socket.h>
-#  define closesocket(f) close(f)
-#endif /* WIN32 */
-
 #include "file.h"
 #ifdef HAVE_LIBZ
 #  include <zlib.h>
@@ -577,12 +567,7 @@ cupsFileOpen(const char *filename, /* I - Name of file */
   int          fd;                     /* File descriptor */
   char         hostname[1024],         /* Hostname */
                *portname;              /* Port "name" (number or service) */
-  int          port;                   /* Port number */
-  struct servent *service;             /* Service */
-  int          i;                      /* Looping var */
-  int          val;                    /* Socket value */
-  struct hostent *hostaddr;            /* Host address data */
-  http_addr_t  sockaddr;               /* Socket address */
+  http_addrlist_t *addrlist;           /* Host address list */
 
 
  /*
@@ -618,72 +603,24 @@ cupsFileOpen(const char *filename,        /* I - Name of file */
        else
          return (NULL);
 
-        if ((hostaddr = httpGetHostByName(hostname)) == NULL)
-          return (NULL);
+       /*
+        * Lookup the hostname and service...
+       */
 
-        if (isdigit(portname[0] & 255))
-         port = atoi(portname);
-       else if ((service = getservbyname(portname, NULL)) != NULL)
-         port = ntohs(service->s_port);
-       else
+        if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
          return (NULL);
 
-       for (i = 0, fd = -1; hostaddr->h_addr_list[i]; i ++)
-       {
-        /*
-         * Load the address...
-         */
-
-         httpAddrLoad(hostaddr, port, i, &sockaddr);
-
-        /*
-         * Create a socket...
-         */
-
-         if ((fd = socket(sockaddr.addr.sa_family, SOCK_STREAM, 0)) < 0)
-           continue;
-
-         val = 1;
-         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
-
-#ifdef SO_REUSEPORT
-         val = 1;
-         setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
-#endif /* SO_REUSEPORT */
-
-        /*
-         * Using TCP_NODELAY improves responsiveness, especially on systems
-         * with a slow loopback interface...  Since we write large buffers
-         * when sending print files and requests, there shouldn't be any
-         * performance penalty for this...
-         */
-
-         val = 1;
-         setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 
-
-        /*
-         * Connect to the server...
-         */
+       /*
+       * Connect to the server...
+       */
 
-#ifdef AF_INET6
-         if (sockaddr.addr.sa_family == AF_INET6)
-         {
-           if (connect(fd, (struct sockaddr *)&sockaddr,
-                       sizeof(sockaddr.ipv6)) < 0)
-           {
-             fd = -1;
-             continue;
-           }
-         }
-         else
-#endif /* AF_INET6 */
-         if (connect(fd, (struct sockaddr *)&sockaddr,
-                     sizeof(sockaddr.ipv4)) < 0)
-         {
-           fd = -1;
-           continue;
-         }
+        if (!httpAddrConnect(addrlist, &fd))
+       {
+         httpAddrFreeList(addrlist);
+         return (NULL);
        }
+
+       httpAddrFreeList(addrlist);
        break;
 
     default : /* Remove bogus compiler warning... */
index 0cabe56b8fab3ef35794202212b3cb1a2b506b33..f5ec97de25279accb560deb16e7bd914c5f787ff 100644 (file)
@@ -51,13 +51,6 @@ extern "C" {
 #  endif /* __cplusplus */
 
 
-/*
- * Constants/limits...
- */
-
-#  define CUPS_MAX_ADDRS       100     /* Limit on number of addresses... */
-
-
 /*
  * To make libcups thread safe, define thread safe globals (aka thread-
  * specific data) for the static variables used in the library.
@@ -69,10 +62,8 @@ typedef struct _cups_globals_s               /**** CUPS global state data ****/
   char                 http_date[256]; /* Date+time buffer */
 
   /* http-addr.c */
-  unsigned             ip_addrs[CUPS_MAX_ADDRS][4];
-                                       /* Packed IPv4/6 addresses */
-  char                 *ip_ptrs[CUPS_MAX_ADDRS + 1];
-                                       /* Pointer to packed address */
+  unsigned             ip_addr;        /* Packed IPv4 address */
+  char                 *ip_ptrs[2];    /* Pointer to packed address */
   struct hostent       hostent;        /* Host entry for IP address */
 #  ifdef HAVE_GETADDRINFO
   char                 hostname[1024]; /* Hostname */
@@ -118,7 +109,9 @@ typedef struct _cups_globals_s              /**** CUPS global state data ****/
   /* usersys.c */
   http_encryption_t    encryption;     /* Encryption setting */
   char                 user[65],       /* User name */
-                       server[256];    /* Server address */
+                       server[256],    /* Server address */
+                       domain_socket[256];
+                                       /* Domain socket address */
   const char           *(*password_cb)(const char *);
                                        /* Password callback */
 
index 121b47ddbbd15915ffb34fa1ca0e579b11f0433a..a0bb744a13fb65503836dd16bbdedea976b4e112 100644 (file)
  *
  *   httpAddrAny()       - Check for the "any" address.
  *   httpAddrEqual()     - Compare two addresses.
- *   httpAddrLoad()      - Load a host entry address into an HTTP address.
  *   httpAddrLocalhost() - Check for the local loopback address.
  *   httpAddrLookup()    - Lookup the hostname associated with the address.
  *   httpAddrString()    - Convert an IP address to a dotted string.
  *   httpGetHostByName() - Lookup a hostname or IP address, and return
  *                         address records for the specified name.
+ *   httpGetHostname()   - Get the FQDN for the local system.
  */
 
 /*
@@ -44,6 +44,8 @@
 
 /*
  * 'httpAddrAny()' - Check for the "any" address.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - 1 if "any", 0 otherwise */
@@ -65,6 +67,8 @@ httpAddrAny(const http_addr_t *addr)  /* I - Address to check */
 
 /*
  * 'httpAddrEqual()' - Compare two addresses.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                            /* O - 1 if equal, 0 if != */
@@ -90,6 +94,8 @@ httpAddrEqual(const http_addr_t *addr1,               /* I - First address */
 
 /*
  * 'httpAddrLength()' - Return the length of the address in bytes.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - Length in bytes */
@@ -113,61 +119,15 @@ httpAddrLength(const http_addr_t *addr)   /* I - Address */
 }
 
 
-/*
- * 'httpAddrLoad()' - Load a host entry address into an HTTP address.
- */
-
-void
-httpAddrLoad(const struct hostent *host,       /* I - Host entry */
-             int                  port,                /* I - Port number */
-             int                  n,           /* I - Index into host entry */
-            http_addr_t          *addr)        /* O - Address to load */
-{
-#ifdef AF_INET6
-  if (host->h_addrtype == AF_INET6)
-  {
-#  ifdef WIN32
-    addr->ipv6.sin6_port = htons((u_short)port);
-#  else
-    addr->ipv6.sin6_port = htons(port);
-#  endif /* WIN32 */
-
-    memcpy((char *)&(addr->ipv6.sin6_addr), host->h_addr_list[n],
-           host->h_length);
-    addr->ipv6.sin6_family = AF_INET6;
-  }
-  else
-#endif /* AF_INET6 */
-#ifdef AF_LOCAL
-  if (host->h_addrtype == AF_LOCAL)
-  {
-    addr->un.sun_family = AF_LOCAL;
-    strlcpy(addr->un.sun_path, host->h_addr_list[n], sizeof(addr->un.sun_path));
-  }
-  else
-#endif /* AF_LOCAL */
-  if (host->h_addrtype == AF_INET)
-  {
-#  ifdef WIN32
-    addr->ipv4.sin_port = htons((u_short)port);
-#  else
-    addr->ipv4.sin_port = htons(port);
-#  endif /* WIN32 */
-
-    memcpy((char *)&(addr->ipv4.sin_addr), host->h_addr_list[n],
-           host->h_length);
-    addr->ipv4.sin_family = AF_INET;
-  }
-}
-
-
 /*
  * 'httpAddrLocalhost()' - Check for the local loopback address.
+ *
+ * @since CUPS 1.2@
  */
 
 int                                    /* O - 1 if local host, 0 otherwise */
-httpAddrLocalhost(const http_addr_t *addr)
-                                       /* I - Address to check */
+httpAddrLocalhost(
+    const http_addr_t *addr)           /* I - Address to check */
 {
 #ifdef AF_INET6
   if (addr->addr.sa_family == AF_INET6 &&
@@ -198,6 +158,8 @@ httpAddrLocalhost(const http_addr_t *addr)
 
 /*
  * 'httpAddrLookup()' - Lookup the hostname associated with the address.
+ *
+ * @since CUPS 1.2@
  */
 
 char *                                         /* O - Host name */
@@ -245,6 +207,8 @@ httpAddrLookup(const http_addr_t *addr,             /* I - Address to lookup */
 
 /*
  * 'httpAddrString()' - Convert an IP address to a dotted string.
+ *
+ * @since CUPS 1.2@
  */
 
 char *                                         /* O - IP string */
@@ -289,14 +253,15 @@ httpAddrString(const http_addr_t *addr,           /* I - Address to convert */
 
 
 /*
- * 'httpGetHostByName()' - Lookup a hostname or IP address, and return
+ * 'httpGetHostByName()' - Lookup a hostname or IPv4 address, and return
  *                         address records for the specified name.
+ *
+ * @deprecated@
  */
 
 struct hostent *                       /* O - Host entry */
 httpGetHostByName(const char *name)    /* I - Hostname or IP address */
 {
-  int                  i;              /* Looping var */
   const char           *nameptr;       /* Pointer into name */
   unsigned             ip[4];          /* IP address components */
   _cups_globals_t      *cg = _cupsGlobals();
@@ -346,48 +311,6 @@ httpGetHostByName(const char *name)        /* I - Hostname or IP address */
     return (&cg->hostent);
   }
 #endif /* AF_LOCAL */
-#ifdef AF_INET6
-  if (name[0] == '[')
-  {
-   /*
-    * A raw 128-bit IPv6 address of the form "[xxxx:xxxx:xxxx:xxxx]"
-    */
-
-    cg->hostent.h_name      = (char *)name;
-    cg->hostent.h_aliases   = NULL;
-    cg->hostent.h_addrtype  = AF_INET6;
-    cg->hostent.h_length    = 16;
-    cg->hostent.h_addr_list = cg->ip_ptrs;
-    cg->ip_ptrs[0]       = (char *)(cg->ip_addrs[0]);
-    cg->ip_ptrs[1]       = NULL;
-
-    for (i = 0, nameptr = name + 1; *nameptr && i < 4; i ++)
-    {
-      if (*nameptr == ']')
-        break;
-      else if (*nameptr == ':')
-        cg->ip_addrs[0][i] = 0;
-      else
-        cg->ip_addrs[0][i] = htonl(strtoul(nameptr, (char **)&nameptr, 16));
-
-      if (*nameptr == ':' || *nameptr == ']')
-        nameptr ++;
-    }
-
-    while (i < 4)
-    {
-      cg->ip_addrs[0][i] = 0;
-      i ++;
-    }
-
-    if (*nameptr)
-      return (NULL);
-
-    DEBUG_puts("httpGetHostByName: returning IPv6 address...");
-
-    return (&cg->hostent);
-  }
-#endif /* AF_INET6 */
 
   for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++);
 
@@ -404,8 +327,8 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */
     if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255)
       return (NULL);                   /* Invalid byte ranges! */
 
-    cg->ip_addrs[0][0] = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) |
-                             ip[3]));
+    cg->ip_addr = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) |
+                         ip[3]));
 
    /*
     * Fill in the host entry and return it...
@@ -416,117 +339,17 @@ httpGetHostByName(const char *name)      /* I - Hostname or IP address */
     cg->hostent.h_addrtype  = AF_INET;
     cg->hostent.h_length    = 4;
     cg->hostent.h_addr_list = cg->ip_ptrs;
-    cg->ip_ptrs[0]       = (char *)cg->ip_addrs[0];
-    cg->ip_ptrs[1]       = NULL;
+    cg->ip_ptrs[0]          = (char *)&(cg->ip_addr);
+    cg->ip_ptrs[1]          = NULL;
 
     DEBUG_puts("httpGetHostByName: returning IPv4 address...");
 
     return (&cg->hostent);
   }
   else
-#ifdef HAVE_GETADDRINFO
   {
    /*
-    * Use the getaddrinfo() function to get the IP address for the
-    * name...
-    */
-
-    struct addrinfo    hints,          /* Address lookup hints */
-                       *results,       /* Address lookup results */
-                       *current;       /* Current result */
-    http_addr_t                *address;       /* Current address */
-
-
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_family   = PF_UNSPEC;
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_flags    = AI_CANONNAME;
-
-    if (getaddrinfo(name, NULL, &hints, &results))
-    {
-     /*
-      * If getaddrinfo() fails, try gethostbyname()...
-      */
-
-      return (gethostbyname(name));
-    }
-
-   /*
-    * Initialize hostent structure, preferring the IPv6 address...
-    */
-
-    for (current = results; current; current = current->ai_next)
-      if (current->ai_family == AF_INET6)
-        break;
-
-    if (!current)
-    {
-      for (current = results; current; current = current->ai_next)
-       if (current->ai_family == AF_INET)
-          break;
-
-      if (!current)
-      {
-       /*
-       * No IPv4 or IPv6 addresses, try gethostbyname()...
-       */
-
-        freeaddrinfo(results);
-
-       return (gethostbyname(name));
-      }
-    }
-
-    strlcpy(cg->hostname, current->ai_canonname, sizeof(cg->hostname));
-
-    cg->hostent.h_name      = cg->hostname;
-    cg->hostent.h_aliases   = NULL;
-    cg->hostent.h_addrtype  = current->ai_family;
-    cg->hostent.h_addr_list = cg->ip_ptrs;
-
-    if (current->ai_family == AF_INET6)
-      cg->hostent.h_length = 16;
-    else
-      cg->hostent.h_length = 4;
-
-   /*
-    * Convert the address info to a hostent structure...
-    */
-
-    for (i = 0, current = results;
-         i < CUPS_MAX_ADDRS && current;
-        current = current->ai_next)
-      if (current->ai_family == cg->hostent.h_addrtype)
-      {
-       /*
-        * Copy this address...
-       */
-
-        address = (http_addr_t *)(current->ai_addr);
-
-        if (current->ai_family == AF_INET)
-         memcpy((char *)cg->ip_addrs[i], (char *)&(address->ipv4.sin_addr), 4);
-       else
-         memcpy((char *)cg->ip_addrs[i], (char *)&(address->ipv6.sin6_addr), 16);
-
-       cg->ip_ptrs[i] = (char *)cg->ip_addrs[i];
-       i ++;
-      }
-
-    cg->ip_ptrs[i] = NULL;
-
-   /*
-    * Free the getaddrinfo() results and return the hostent structure...
-    */
-
-    freeaddrinfo(results);
-
-    return (&cg->hostent);
-  }
-#else
-  {
-   /*
-    * Use the gethostbyname() function to get the IP address for
+    * Use the gethostbyname() function to get the IPv4 address for
     * the name...
     */
 
@@ -534,7 +357,6 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */
 
     return (gethostbyname(name));
   }
-#endif /* HAVE_GETADDRINFO */
 }
 
 
@@ -543,6 +365,8 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */
  *
  * This function uses both gethostname() and gethostbyname() to
  * get the local hostname with domain.
+ *
+ * @since CUPS 1.2@
  */
 
 const char *                           /* O - FQDN for this system */
diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c
new file mode 100644 (file)
index 0000000..2e8f8b3
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * "$Id$"
+ *
+ *   HTTP address list routines for the Common UNIX Printing System (CUPS).
+ *
+ *   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:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "globals.h"
+#include "debug.h"
+#include <stdlib.h>
+#include "http-private.h"
+
+
+/*
+ * 'httpAddrConnect()' - Connect to any of the addresses in the list.
+ *
+ * @since CUPS 1.2@
+ */
+
+http_addrlist_t *                      /* O - Connected address or NULL on failure */
+httpAddrConnect(
+    http_addrlist_t *addrlist,         /* I - List of potential addresses */
+    int             *sock)             /* O - Socket */
+{
+  int  val;                            /* Socket option value */
+
+
+ /*
+  * Loop through each address until we connect or run out of addresses...
+  */
+
+  while (addrlist)
+  {
+   /*
+    * Create the socket...
+    */
+
+    if ((*sock = socket(addrlist->addr.addr.sa_family, 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...
+      */
+
+      addrlist = addrlist->next;
+      continue;
+    }
+
+   /*
+    * Set options...
+    */
+
+    val = 1;
+    setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+
+#ifdef SO_REUSEPORT
+    val = 1;
+    setsockopt(*sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
+#endif /* SO_REUSEPORT */
+
+   /*
+    * Using TCP_NODELAY improves responsiveness, especially on systems
+    * with a slow loopback interface...
+    */
+
+    val = 1;
+    setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 
+
+#ifdef FD_CLOEXEC
+   /*
+    * Close this socket when starting another process...
+    */
+
+    fcntl(*sock, F_SETFD, FD_CLOEXEC);
+#endif /* FD_CLOEXEC */
+
+   /*
+    * Then connect...
+    */
+
+    if (!connect(*sock, &(addrlist->addr.addr),
+                 httpAddrLength(&(addrlist->addr))))
+      break;
+
+   /*
+    * Close this socket and move to the next address...
+    */
+
+    closesocket(*sock);
+
+    addrlist = addrlist->next;
+  }
+
+  return (addrlist);
+}
+
+
+/*
+ * 'httpAddrFreeList()' - Free an address list.
+ *
+ * @since CUPS 1.2@
+ */
+
+void
+httpAddrFreeList(
+    http_addrlist_t *addrlist)         /* I - Address list to free */
+{
+  http_addrlist_t      *next;          /* Next address in list */
+
+
+ /*
+  * Free each address in the list...
+  */
+
+  while (addrlist)
+  {
+    next = addrlist->next;
+
+    free(addrlist);
+
+    addrlist = next;
+  }
+}
+
+
+/*
+ * 'httpAddrGetList()' - Get a list of address for a hostname.
+ *
+ * @since CUPS 1.2@
+ */
+
+http_addrlist_t        *                       /* O - List of addresses or NULL */
+httpAddrGetList(const char *hostname,  /* I - Hostname or IP address */
+                int        family,     /* I - Address family or AF_UNSPEC */
+               const char *service)    /* I - Service name or port number */
+{
+  http_addrlist_t      *first,         /* First address in list */
+                       *addr,          /* Current address in list */
+                       *temp;          /* New address */
+
+
+  DEBUG_printf(("httpAddrGetList(hostname=\"%s\", family=AF_%s, service=\"%s\")\n",
+                hostname, family == AF_UNSPEC ? "UNSPEC" :
+#ifdef AF_LOCAL
+                         family == AF_LOCAL ? "LOCAL" :
+#endif /* AF_LOCAL */
+#ifdef AF_INET6
+                         family == AF_INET6 ? "INET6" :
+#endif /* AF_INET6 */
+                         family == AF_INET ? "INET" : "???", service));
+
+ /*
+  * Avoid lookup delays and configuration problems when connecting
+  * to the localhost address...
+  */
+
+  if (!strcmp(hostname, "localhost"))
+    hostname = "127.0.0.1";
+
+ /*
+  * Lookup the address the best way we can...
+  */
+
+  first = addr = NULL;
+
+  if (hostname[0] == '/')
+  {
+   /*
+    * 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));
+  }
+  else
+  {
+#ifdef HAVE_GETADDRINFO
+    struct addrinfo    hints,          /* Address lookup hints */
+                       *results,       /* Address lookup results */
+                       *current;       /* Current result */
+
+
+
+   /*
+    * Lookup the address as needed...
+    */
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family   = family;
+    hints.ai_socktype = SOCK_STREAM;
+
+    if (!getaddrinfo(hostname, service, &hints, &results))
+    {
+     /*
+      * Copy the results to our own address list structure...
+      */
+
+      for (current = results; current; current = current->ai_next)
+        if (current->ai_family == AF_INET || current->ai_family == AF_INET6)
+       {
+        /*
+          * Copy the address over...
+         */
+
+         temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
+         if (!temp)
+         {
+           httpAddrFreeList(first);
+           return (NULL);
+         }
+
+          if (current->ai_family == AF_INET6)
+           memcpy(&(temp->addr.ipv6), current->ai_addr,
+                  sizeof(temp->addr.ipv6));
+         else
+           memcpy(&(temp->addr.ipv4), current->ai_addr,
+                  sizeof(temp->addr.ipv4));
+
+         /*
+         * Append the address to the list...
+         */
+
+         if (!first)
+           first = temp;
+
+         if (addr)
+           addr->next = temp;
+
+         addr = temp;
+       }
+
+     /*
+      * Free the results from getaddrinfo()...
+      */
+
+      freeaddrinfo(results);
+    }
+#else
+    int                        i;              /* Looping vars */
+    unsigned           ip[4];          /* IPv4 address components */
+    const char         *ptr;           /* Pointer into hostname */
+    struct hostent     *host;          /* Result of lookup */
+    struct servent     *port;          /* Port number for service */
+    int                        portnum;        /* Port number */
+
+
+   /*
+    * Lookup the service...
+    */
+
+    if (!service)
+      portnum = 0;
+    else if (isdigit(*service & 255))
+      portnum = atoi(service);
+    else if ((port = getservbyname(service, NULL)) != NULL)
+      portnum = ntohs(port->s_port);
+    else
+      return (NULL);
+
+   /*
+    * This code is needed because some operating systems have a
+    * buggy implementation of gethostbyname() that does not support
+    * IPv4 addresses.  If the hostname string is an IPv4 address, then
+    * sscanf() is used to extract the IPv4 components.  We then pack
+    * the components into an IPv4 address manually, since the
+    * inet_aton() function is deprecated.  We use the htonl() macro
+    * to get the right byte order for the address.
+    */
+
+    for (ptr = hostname; isdigit(*ptr & 255) || *ptr == '.'; ptr ++);
+
+    if (!*nameptr)
+    {
+     /*
+      * We have an IPv4 address; break it up and create an IPv4 address...
+      */
+
+      if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) == 4 &&
+          ip[0] <= 255 && ip[1] <= 255 && ip[2] <= 255 && ip[3] <= 255)
+      {
+       first = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
+       if (!first)
+         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_port = htons(portnum);
+      }
+    }
+    else if ((host = gethostbyname(hostname)) != NULL &&
+#ifdef AF_INET6
+             (host->h_addrtype == AF_INET || host->h_addrtype == AF_INET6))
+#else
+             host->h_addrtype == AF_INET)
+#endif /* AF_INET6 */
+    {
+      for (i = 0; host->h_addr_list[i]; i ++)
+      {
+       /*
+        * Copy the address over...
+       */
+
+       temp = (http_addrlist_t *)calloc(1, sizeof(http_addrlist_t));
+       if (!temp)
+       {
+         httpAddrFreeList(first);
+         return (NULL);
+       }
+
+#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],
+                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],
+                sizeof(temp->addr.ipv4));
+          temp->addr.ipv4.sin_port = htons(portnum);
+        }
+
+       /*
+       * Append the address to the list...
+       */
+
+       if (!first)
+         first = temp;
+
+       if (addr)
+         addr->next = temp;
+
+       addr = temp;
+      }
+    }
+#endif /* HAVE_GETADDRINFO */
+  }
+
+ /*
+  * Return the address list...
+  */
+
+  return (first);
+}
+
+
+/*
+ * End of "$Id$".
+ */
index 1ea15f2ba4abb34ed96bf750286e4c1233e2c9b0..c8dc6d432993a4f7881efb3691975be9fc943656 100644 (file)
 
 #  include "config.h"
 
+#  ifdef WIN32
+#    include <io.h>
+#    include <winsock2.h>
+#  else
+#    include <unistd.h>
+#    include <fcntl.h>
+#    include <sys/socket.h>
+#    define closesocket(f) close(f)
+#  endif /* WIN32 */
+
 #  ifdef __sun
 /*
  * Define FD_SETSIZE to CUPS_MAX_FDS on Solaris to get the correct version of
index f48dc4081c9fa652deb4213504df96ead41c9f2a..b6ce8fe8fa95bec818d144d33a2cef2b1fbafd7a 100644 (file)
@@ -235,6 +235,8 @@ httpClose(http_t *http)             /* I - Connection to close */
   if (!http)
     return;
 
+  httpAddrFreeList(http->addrlist);
+
   if (http->input_set)
     free(http->input_set);
 
@@ -290,9 +292,9 @@ httpConnectEncrypt(
     int               port,            /* I - Port number */
     http_encryption_t encryption)      /* I - Type of encryption to use */
 {
-  int                  i;              /* Looping var */
   http_t               *http;          /* New HTTP connection */
-  struct hostent       *hostaddr;      /* Host address data */
+  http_addrlist_t      *addrlist;      /* Host address data */
+  char                 service[255];   /* Service name */
 
 
   DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)\n",
@@ -307,31 +309,9 @@ httpConnectEncrypt(
   * Lookup the host...
   */
 
-  if ((hostaddr = httpGetHostByName(host)) == NULL)
-  {
-   /*
-    * This hack to make users that don't have a localhost entry in
-    * their hosts file or DNS happy...
-    */
-
-    if (strcasecmp(host, "localhost") != 0)
-      return (NULL);
-    else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL)
-      return (NULL);
-  }
+  sprintf(service, "%d", port);
 
- /*
-  * Verify that it is an IPv4, IPv6, or domain address...
-  */
-
-  if ((hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4)
-#ifdef AF_INET6
-      && (hostaddr->h_addrtype != AF_INET6 || hostaddr->h_length != 16)
-#endif /* AF_INET6 */
-#ifdef AF_LOCAL
-      && (hostaddr->h_addrtype != AF_LOCAL)
-#endif /* AF_LOCAL */
-      )
+  if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
     return (NULL);
 
  /*
@@ -362,27 +342,23 @@ httpConnectEncrypt(
 
   strlcpy(http->hostname, host, sizeof(http->hostname));
 
-  for (i = 0; hostaddr->h_addr_list[i]; i ++)
-  {
-   /*
-    * Load the address...
-    */
-
-    httpAddrLoad(hostaddr, port, i, &(http->hostaddr));
+ /*
+  * Connect to the remote system...
+  */
 
-   /*
-    * Connect to the remote system...
-    */
+  http->addrlist = addrlist;
 
-    if (!httpReconnect(http))
-      return (http);
-  }
+  if (!httpReconnect(http))
+    return (http);
 
  /*
   * Could not connect to any known address - bail out!
   */
 
+  httpAddrFreeList(addrlist);
+
   free(http);
+
   return (NULL);
 }
 
@@ -1532,8 +1508,7 @@ httpRead(http_t *http,                    /* I - HTTP data */
 int                                    /* O - 0 on success, non-zero on failure */
 httpReconnect(http_t *http)            /* I - HTTP data */
 {
-  int          val;                    /* Socket option value */
-  int          status;                 /* Connect status */
+  http_addrlist_t      *addr;          /* Connected address */
 
 
   DEBUG_printf(("httpReconnect(http=%p)\n", http));
@@ -1557,69 +1532,16 @@ httpReconnect(http_t *http)             /* I - HTTP data */
     close(http->fd);
 #endif /* WIN32 */
 
- /*
-  * Create the socket and set options to allow reuse.
-  */
-
-  if ((http->fd = socket(http->hostaddr.addr.sa_family, SOCK_STREAM, 0)) < 0)
-  {
-#ifdef WIN32
-    http->error  = WSAGetLastError();
-#else
-    http->error  = errno;
-#endif /* WIN32 */
-    http->status = HTTP_ERROR;
-    return (-1);
-  }
-
-#ifdef FD_CLOEXEC
-  fcntl(http->fd, F_SETFD, FD_CLOEXEC);        /* Close this socket when starting *
-                                        * other processes...              */
-#endif /* FD_CLOEXEC */
-
-  val = 1;
-  setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
-
-#ifdef SO_REUSEPORT
-  val = 1;
-  setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
-#endif /* SO_REUSEPORT */
-
- /*
-  * Using TCP_NODELAY improves responsiveness, especially on systems
-  * with a slow loopback interface...  Since we write large buffers
-  * when sending print files and requests, there shouldn't be any
-  * performance penalty for this...
-  */
-
-  val = 1;
-#ifdef WIN32
-  setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); 
-#else
-  setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 
-#endif /* WIN32 */
-
  /*
   * Connect to the server...
   */
 
-#ifdef AF_INET6
-  if (http->hostaddr.addr.sa_family == AF_INET6)
-    status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
-                     sizeof(http->hostaddr.ipv6));
-  else
-#endif /* AF_INET6 */
-#ifdef AF_LOCAL
-  if (http->hostaddr.addr.sa_family == AF_LOCAL)
-    status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
-                     SUN_LEN(&(http->hostaddr.un)));
-  else
-#endif /* AF_LOCAL */
-  status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
-                   sizeof(http->hostaddr.ipv4));
-
-  if (status < 0)
+  if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
   {
+   /*
+    * Unable to connect...
+    */
+
 #ifdef WIN32
     http->error  = WSAGetLastError();
 #else
@@ -1627,19 +1549,12 @@ httpReconnect(http_t *http)             /* I - HTTP data */
 #endif /* WIN32 */
     http->status = HTTP_ERROR;
 
-#ifdef WIN32
-    closesocket(http->fd);
-#else
-    close(http->fd);
-#endif
-
-    http->fd = -1;
-
     return (-1);
   }
 
-  http->error  = 0;
-  http->status = HTTP_CONTINUE;
+  http->hostaddr = &(addr->addr);
+  http->error    = 0;
+  http->status   = HTTP_CONTINUE;
 
 #ifdef HAVE_SSL
   if (http->encryption == HTTP_ENCRYPT_ALWAYS)
index 23151a598212ebdca7bccf392cb32c9a263e52d3..6ad56420e72d79f5faad58a442bcb7e3b09f4e20 100644 (file)
@@ -74,7 +74,7 @@ extern "C" {
  * core structure and union names, so the same defines or code
  * can't be used on all platforms.
  *
- * The following will likely need tweeking on new platforms that
+ * The following will likely need tweaking on new platforms that
  * support IPv6 - the "s6_addr32" define maps to the 32-bit integer
  * array in the in6_addr union, which is named differently on various
  * platforms.
@@ -100,186 +100,152 @@ extern "C" {
 
 
 /*
- * HTTP state values...
+ * Types and structures...
  */
 
-typedef enum                   /* States are server-oriented */
+typedef enum http_state_e              /**** HTTP state values; states
+                                        **** are server-oriented...
+                                        ****/
 {
-  HTTP_WAITING,                        /* Waiting for command */
-  HTTP_OPTIONS,                        /* OPTIONS command, waiting for blank line */
-  HTTP_GET,                    /* GET command, waiting for blank line */
-  HTTP_GET_SEND,               /* GET command, sending data */
-  HTTP_HEAD,                   /* HEAD command, waiting for blank line */
-  HTTP_POST,                   /* POST command, waiting for blank line */
-  HTTP_POST_RECV,              /* POST command, receiving data */
-  HTTP_POST_SEND,              /* POST command, sending data */
-  HTTP_PUT,                    /* PUT command, waiting for blank line */
-  HTTP_PUT_RECV,               /* PUT command, receiving data */
-  HTTP_DELETE,                 /* DELETE command, waiting for blank line */
-  HTTP_TRACE,                  /* TRACE command, waiting for blank line */
-  HTTP_CLOSE,                  /* CLOSE command, waiting for blank line */
-  HTTP_STATUS                  /* Command complete, sending status */
+  HTTP_WAITING,                                /* Waiting for command */
+  HTTP_OPTIONS,                                /* OPTIONS command, waiting for blank line */
+  HTTP_GET,                            /* GET command, waiting for blank line */
+  HTTP_GET_SEND,                       /* GET command, sending data */
+  HTTP_HEAD,                           /* HEAD command, waiting for blank line */
+  HTTP_POST,                           /* POST command, waiting for blank line */
+  HTTP_POST_RECV,                      /* POST command, receiving data */
+  HTTP_POST_SEND,                      /* POST command, sending data */
+  HTTP_PUT,                            /* PUT command, waiting for blank line */
+  HTTP_PUT_RECV,                       /* PUT command, receiving data */
+  HTTP_DELETE,                         /* DELETE command, waiting for blank line */
+  HTTP_TRACE,                          /* TRACE command, waiting for blank line */
+  HTTP_CLOSE,                          /* CLOSE command, waiting for blank line */
+  HTTP_STATUS                          /* Command complete, sending status */
 } http_state_t;
 
-
-/*
- * HTTP version numbers...
- */
-
-typedef enum
+typedef enum http_version_e            /**** HTTP version numbers ****/
 {
-  HTTP_0_9 = 9,                        /* HTTP/0.9 */
-  HTTP_1_0 = 100,              /* HTTP/1.0 */
-  HTTP_1_1 = 101               /* HTTP/1.1 */
+  HTTP_0_9 = 9,                                /* HTTP/0.9 */
+  HTTP_1_0 = 100,                      /* HTTP/1.0 */
+  HTTP_1_1 = 101                       /* HTTP/1.1 */
 } http_version_t;
 
-
-/*
- * HTTP keep-alive values...
- */
-
-typedef enum
+typedef enum http_keepalive_e          /**** HTTP keep-alive values ****/
 {
-  HTTP_KEEPALIVE_OFF = 0,
-  HTTP_KEEPALIVE_ON
+  HTTP_KEEPALIVE_OFF = 0,              /* No keep alive support */
+  HTTP_KEEPALIVE_ON                    /* Use keep alive */
 } http_keepalive_t;
 
-
-/*
- * HTTP transfer encoding values...
- */
-
-typedef enum
+typedef enum http_encoding_e           /**** HTTP transfer encoding values ****/
 {
-  HTTP_ENCODE_LENGTH,          /* Data is sent with Content-Length */
-  HTTP_ENCODE_CHUNKED          /* Data is chunked */
+  HTTP_ENCODE_LENGTH,                  /* Data is sent with Content-Length */
+  HTTP_ENCODE_CHUNKED                  /* Data is chunked */
 } http_encoding_t;
 
-
-/*
- * HTTP encryption values...
- */
-
-typedef enum
+typedef enum http_encryption_e         /**** HTTP encryption values ****/
 {
-  HTTP_ENCRYPT_IF_REQUESTED,   /* Encrypt if requested (TLS upgrade) */
-  HTTP_ENCRYPT_NEVER,          /* Never encrypt */
-  HTTP_ENCRYPT_REQUIRED,       /* Encryption is required (TLS upgrade) */
-  HTTP_ENCRYPT_ALWAYS          /* Always encrypt (SSL) */
+  HTTP_ENCRYPT_IF_REQUESTED,           /* Encrypt if requested (TLS upgrade) */
+  HTTP_ENCRYPT_NEVER,                  /* Never encrypt */
+  HTTP_ENCRYPT_REQUIRED,               /* Encryption is required (TLS upgrade) */
+  HTTP_ENCRYPT_ALWAYS                  /* Always encrypt (SSL) */
 } http_encryption_t;
 
-
-/*
- * HTTP authentication types...
- */
-
-typedef enum
+typedef enum http_auth_e               /**** HTTP authentication types ****/
 {
-  HTTP_AUTH_NONE,              /* No authentication in use */
-  HTTP_AUTH_BASIC,             /* Basic authentication in use */
-  HTTP_AUTH_MD5,               /* Digest authentication in use */
-  HTTP_AUTH_MD5_SESS,          /* MD5-session authentication in use */
-  HTTP_AUTH_MD5_INT,           /* Digest authentication in use for body */
-  HTTP_AUTH_MD5_SESS_INT       /* MD5-session authentication in use for body */
+  HTTP_AUTH_NONE,                      /* No authentication in use */
+  HTTP_AUTH_BASIC,                     /* Basic authentication in use */
+  HTTP_AUTH_MD5,                       /* Digest authentication in use */
+  HTTP_AUTH_MD5_SESS,                  /* MD5-session authentication in use */
+  HTTP_AUTH_MD5_INT,                   /* Digest authentication in use for body */
+  HTTP_AUTH_MD5_SESS_INT               /* MD5-session authentication in use for body */
 } http_auth_t;
 
-
-/*
- * HTTP status codes...
- */
-
-typedef enum
+typedef enum http_status_e             /**** HTTP status codes ****/
 {
-  HTTP_ERROR = -1,             /* An error response from httpXxxx() */
-
-  HTTP_CONTINUE = 100,         /* Everything OK, keep going... */
-  HTTP_SWITCHING_PROTOCOLS,    /* HTTP upgrade to TLS/SSL */
-
-  HTTP_OK = 200,               /* OPTIONS/GET/HEAD/POST/TRACE command was successful */
-  HTTP_CREATED,                        /* PUT command was successful */
-  HTTP_ACCEPTED,               /* DELETE command was successful */
-  HTTP_NOT_AUTHORITATIVE,      /* Information isn't authoritative */
-  HTTP_NO_CONTENT,             /* Successful command, no new data */
-  HTTP_RESET_CONTENT,          /* Content was reset/recreated */
-  HTTP_PARTIAL_CONTENT,                /* Only a partial file was recieved/sent */
-
-  HTTP_MULTIPLE_CHOICES = 300, /* Multiple files match request */
-  HTTP_MOVED_PERMANENTLY,      /* Document has moved permanently */
-  HTTP_MOVED_TEMPORARILY,      /* Document has moved temporarily */
-  HTTP_SEE_OTHER,              /* See this other link... */
-  HTTP_NOT_MODIFIED,           /* File not modified */
-  HTTP_USE_PROXY,              /* Must use a proxy to access this URI */
-
-  HTTP_BAD_REQUEST = 400,      /* Bad request */
-  HTTP_UNAUTHORIZED,           /* Unauthorized to access host */
-  HTTP_PAYMENT_REQUIRED,       /* Payment required */
-  HTTP_FORBIDDEN,              /* Forbidden to access this URI */
-  HTTP_NOT_FOUND,              /* URI was not found */
-  HTTP_METHOD_NOT_ALLOWED,     /* Method is not allowed */
-  HTTP_NOT_ACCEPTABLE,         /* Not Acceptable */
-  HTTP_PROXY_AUTHENTICATION,   /* Proxy Authentication is Required */
-  HTTP_REQUEST_TIMEOUT,                /* Request timed out */
-  HTTP_CONFLICT,               /* Request is self-conflicting */
-  HTTP_GONE,                   /* Server has gone away */
-  HTTP_LENGTH_REQUIRED,                /* A content length or encoding is required */
-  HTTP_PRECONDITION,           /* Precondition failed */
-  HTTP_REQUEST_TOO_LARGE,      /* Request entity too large */
-  HTTP_URI_TOO_LONG,           /* URI too long */
-  HTTP_UNSUPPORTED_MEDIATYPE,  /* The requested media type is unsupported */
-  HTTP_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */
-
-  HTTP_SERVER_ERROR = 500,     /* Internal server error */
-  HTTP_NOT_IMPLEMENTED,                /* Feature not implemented */
-  HTTP_BAD_GATEWAY,            /* Bad gateway */
-  HTTP_SERVICE_UNAVAILABLE,    /* Service is unavailable */
-  HTTP_GATEWAY_TIMEOUT,                /* Gateway connection timed out */
-  HTTP_NOT_SUPPORTED           /* HTTP version not supported */
+  HTTP_ERROR = -1,                     /* An error response from httpXxxx() */
+
+  HTTP_CONTINUE = 100,                 /* Everything OK, keep going... */
+  HTTP_SWITCHING_PROTOCOLS,            /* HTTP upgrade to TLS/SSL */
+
+  HTTP_OK = 200,                       /* OPTIONS/GET/HEAD/POST/TRACE command was successful */
+  HTTP_CREATED,                                /* PUT command was successful */
+  HTTP_ACCEPTED,                       /* DELETE command was successful */
+  HTTP_NOT_AUTHORITATIVE,              /* Information isn't authoritative */
+  HTTP_NO_CONTENT,                     /* Successful command, no new data */
+  HTTP_RESET_CONTENT,                  /* Content was reset/recreated */
+  HTTP_PARTIAL_CONTENT,                        /* Only a partial file was recieved/sent */
+
+  HTTP_MULTIPLE_CHOICES = 300,         /* Multiple files match request */
+  HTTP_MOVED_PERMANENTLY,              /* Document has moved permanently */
+  HTTP_MOVED_TEMPORARILY,              /* Document has moved temporarily */
+  HTTP_SEE_OTHER,                      /* See this other link... */
+  HTTP_NOT_MODIFIED,                   /* File not modified */
+  HTTP_USE_PROXY,                      /* Must use a proxy to access this URI */
+
+  HTTP_BAD_REQUEST = 400,              /* Bad request */
+  HTTP_UNAUTHORIZED,                   /* Unauthorized to access host */
+  HTTP_PAYMENT_REQUIRED,               /* Payment required */
+  HTTP_FORBIDDEN,                      /* Forbidden to access this URI */
+  HTTP_NOT_FOUND,                      /* URI was not found */
+  HTTP_METHOD_NOT_ALLOWED,             /* Method is not allowed */
+  HTTP_NOT_ACCEPTABLE,                 /* Not Acceptable */
+  HTTP_PROXY_AUTHENTICATION,           /* Proxy Authentication is Required */
+  HTTP_REQUEST_TIMEOUT,                        /* Request timed out */
+  HTTP_CONFLICT,                       /* Request is self-conflicting */
+  HTTP_GONE,                           /* Server has gone away */
+  HTTP_LENGTH_REQUIRED,                        /* A content length or encoding is required */
+  HTTP_PRECONDITION,                   /* Precondition failed */
+  HTTP_REQUEST_TOO_LARGE,              /* Request entity too large */
+  HTTP_URI_TOO_LONG,                   /* URI too long */
+  HTTP_UNSUPPORTED_MEDIATYPE,          /* The requested media type is unsupported */
+  HTTP_UPGRADE_REQUIRED = 426,         /* Upgrade to SSL/TLS required */
+
+  HTTP_SERVER_ERROR = 500,             /* Internal server error */
+  HTTP_NOT_IMPLEMENTED,                        /* Feature not implemented */
+  HTTP_BAD_GATEWAY,                    /* Bad gateway */
+  HTTP_SERVICE_UNAVAILABLE,            /* Service is unavailable */
+  HTTP_GATEWAY_TIMEOUT,                        /* Gateway connection timed out */
+  HTTP_NOT_SUPPORTED                   /* HTTP version not supported */
 } http_status_t;
 
-
-/*
- * HTTP field names...
- */
-
-typedef enum
+typedef enum http_field_e              /**** HTTP field names ****/
 {
-  HTTP_FIELD_UNKNOWN = -1,
-  HTTP_FIELD_ACCEPT_LANGUAGE,
-  HTTP_FIELD_ACCEPT_RANGES,
-  HTTP_FIELD_AUTHORIZATION,
-  HTTP_FIELD_CONNECTION,
-  HTTP_FIELD_CONTENT_ENCODING,
-  HTTP_FIELD_CONTENT_LANGUAGE,
-  HTTP_FIELD_CONTENT_LENGTH,
-  HTTP_FIELD_CONTENT_LOCATION,
-  HTTP_FIELD_CONTENT_MD5,
-  HTTP_FIELD_CONTENT_RANGE,
-  HTTP_FIELD_CONTENT_TYPE,
-  HTTP_FIELD_CONTENT_VERSION,
-  HTTP_FIELD_DATE,
-  HTTP_FIELD_HOST,
-  HTTP_FIELD_IF_MODIFIED_SINCE,
-  HTTP_FIELD_IF_UNMODIFIED_SINCE,
-  HTTP_FIELD_KEEP_ALIVE,
-  HTTP_FIELD_LAST_MODIFIED,
-  HTTP_FIELD_LINK,
-  HTTP_FIELD_LOCATION,
-  HTTP_FIELD_RANGE,
-  HTTP_FIELD_REFERER,
-  HTTP_FIELD_RETRY_AFTER,
-  HTTP_FIELD_TRANSFER_ENCODING,
-  HTTP_FIELD_UPGRADE,
-  HTTP_FIELD_USER_AGENT,
-  HTTP_FIELD_WWW_AUTHENTICATE,
-  HTTP_FIELD_MAX
+  HTTP_FIELD_UNKNOWN = -1,             /* Unknown field */
+  HTTP_FIELD_ACCEPT_LANGUAGE,          /* Accept-Language field */
+  HTTP_FIELD_ACCEPT_RANGES,            /* Accept-Ranges field */
+  HTTP_FIELD_AUTHORIZATION,            /* Authorization field */
+  HTTP_FIELD_CONNECTION,               /* Connection field */
+  HTTP_FIELD_CONTENT_ENCODING,         /* Content-Encoding field */
+  HTTP_FIELD_CONTENT_LANGUAGE,         /* Content-Language field */
+  HTTP_FIELD_CONTENT_LENGTH,           /* Content-Length field */
+  HTTP_FIELD_CONTENT_LOCATION,         /* Content-Location field */
+  HTTP_FIELD_CONTENT_MD5,              /* Content-MD5 field */
+  HTTP_FIELD_CONTENT_RANGE,            /* Content-Range field */
+  HTTP_FIELD_CONTENT_TYPE,             /* Content-Type field */
+  HTTP_FIELD_CONTENT_VERSION,          /* Content-Version field */
+  HTTP_FIELD_DATE,                     /* Date field */
+  HTTP_FIELD_HOST,                     /* Host field */
+  HTTP_FIELD_IF_MODIFIED_SINCE,                /* If-Modified-Since field */
+  HTTP_FIELD_IF_UNMODIFIED_SINCE,      /* If-Unmodified-Since field */
+  HTTP_FIELD_KEEP_ALIVE,               /* Keep-Alive field */
+  HTTP_FIELD_LAST_MODIFIED,            /* Last-Modified field */
+  HTTP_FIELD_LINK,                     /* Link field */
+  HTTP_FIELD_LOCATION,                 /* Location field */
+  HTTP_FIELD_RANGE,                    /* Range field */
+  HTTP_FIELD_REFERER,                  /* Referer field */
+  HTTP_FIELD_RETRY_AFTER,              /* Retry-After field */
+  HTTP_FIELD_TRANSFER_ENCODING,                /* Transfer-Encoding field */
+  HTTP_FIELD_UPGRADE,                  /* Upgrade field */
+  HTTP_FIELD_USER_AGENT,               /* User-Agent field */
+  HTTP_FIELD_WWW_AUTHENTICATE,         /* WWW-Authenticate field */
+  HTTP_FIELD_MAX                       /* Maximum field index */
 } http_field_t;
 
-
-/*
- * HTTP address structure (makes using IPv6 a little easier and more portable.)
- */  
-
-typedef union
+typedef union http_addr_u              /**** Socket address union, which
+                                        **** makes using IPv6 and other
+                                        **** address types easier and
+                                        **** more portable. @since CUPS 1.2@
+                                        ****/
 {
   struct sockaddr      addr;           /* Base structure for family value */
   struct sockaddr_in   ipv4;           /* IPv4 address */
@@ -289,14 +255,20 @@ typedef union
 #ifdef AF_LOCAL
   struct sockaddr_un   un;             /* Domain socket file */
 #endif /* AF_LOCAL */
-  char                 pad[128];       /* Pad to ensure binary compatibility */
+  char                 pad[256];       /* Padding to ensure binary compatibility */
 } http_addr_t;
 
-/*
- * HTTP connection structure...
- */
+typedef struct http_addrlist_s         /**** Socket address list, which is
+                                        **** used to enumerate all of the
+                                        **** addresses that are associated
+                                        **** with a hostname. @since CUPS 1.2@
+                                        ****/
+{
+  struct http_addrlist_s *next;                /* Pointer to next address in list */
+  http_addr_t          addr;           /* Address */
+} http_addrlist_t;
 
-typedef struct
+typedef struct http_s                  /**** HTTP connection structure. ****/
 {
   int                  fd;             /* File descriptor for this socket */
   int                  blocking;       /* To block or not to block */
@@ -306,14 +278,14 @@ typedef struct
   http_status_t                status;         /* Status of last request */
   http_version_t       version;        /* Protocol version */
   http_keepalive_t     keep_alive;     /* Keep-alive supported? */
-  struct sockaddr_in   oldaddr;        /* Address of connected host */
+  struct sockaddr_in   _hostaddr;      /* Address of connected host @deprecated@ */
   char                 hostname[HTTP_MAX_HOST],
                                        /* Name of connected host */
                        fields[HTTP_FIELD_MAX][HTTP_MAX_VALUE];
                                        /* Field values */
   char                 *data;          /* Pointer to data buffer */
   http_encoding_t      data_encoding;  /* Chunked or not */
-  int                  _data_remaining;/* Number of bytes left (deprecated) */
+  int                  _data_remaining;/* Number of bytes left @deprecated@ */
   int                  used;           /* Number of bytes used in buffer */
   char                 buffer[HTTP_MAX_BUFFER];
                                        /* Buffer for incoming data */
@@ -327,23 +299,22 @@ typedef struct
   void                 *tls;           /* TLS state information */
   http_encryption_t    encryption;     /* Encryption requirements */
   /**** New in CUPS 1.1.19 ****/
-  fd_set               *input_set;     /* select() set for httpWait() */
-  http_status_t                expect;         /* Expect: header */
-  char                 *cookie;        /* Cookie value(s) */
+  fd_set               *input_set;     /* select() set for httpWait() @since CUPS 1.1.19@ */
+  http_status_t                expect;         /* Expect: header @since CUPS 1.1.19@ */
+  char                 *cookie;        /* Cookie value(s) @since CUPS 1.1.19@ */
   /**** New in CUPS 1.1.20 ****/
   char                 authstring[HTTP_MAX_VALUE],
-                                       /* Current Authentication value */
+                                       /* Current Authentication value @since CUPS 1.1.20@ */
                        userpass[HTTP_MAX_VALUE];
-                                       /* Username:password string */
-  int                  digest_tries;   /* Number of tries for digest auth */
+                                       /* Username:password string @since CUPS 1.1.20@ */
+  int                  digest_tries;   /* Number of tries for digest auth @since CUPS 1.1.20@ */
   /**** New in CUPS 1.2 ****/
-  http_addr_t          hostaddr;       /* Host address and port */
-  int                  wused;          /* Write buffer bytes used */
-  off_t                        data_remaining; /* Number of bytes left */
+  http_addr_t          *hostaddr;      /* Current host address and port @since CUPS 1.2@ */
+  http_addrlist_t      *addrlist;      /* List of valid addresses @since CUPS 1.2@ */
+  int                  wused;          /* Write buffer bytes used @since CUPS 1.2@ */
+  off_t                        data_remaining; /* Number of bytes left @since CUPS 1.2@ */
 } http_t;
 
-/**** New in CUPS 1.1.20+ ****/
-extern int             httpWriteFlush(http_t *http);
 
 /*
  * Prototypes...
@@ -417,11 +388,13 @@ extern void               httpSeparate2(const char *uri,
 
 /**** New in CUPS 1.2 ****/
 extern int             httpAddrAny(const http_addr_t *addr);
+extern http_addrlist_t *httpAddrConnect(http_addrlist_t *addrlist, int *sock);
 extern int             httpAddrEqual(const http_addr_t *addr1,
                                      const http_addr_t *addr2);
+extern void            httpAddrFreeList(http_addrlist_t *addrlist);
+extern http_addrlist_t *httpAddrGetList(const char *hostname, int family,
+                                        const char *service);
 extern int             httpAddrLength(const http_addr_t *addr);
-extern void            httpAddrLoad(const struct hostent *host, int port,
-                                    int n, http_addr_t *addr);
 extern int             httpAddrLocalhost(const http_addr_t *addr);
 extern char            *httpAddrLookup(const http_addr_t *addr,
                                         char *name, int namelen);
index 35d8d0eb8bbe8315ebb62848a5f9c46a4a4b4692..adcfbc2ac30e47b3136f69931d28769d26d285b9 100644 (file)
@@ -1089,12 +1089,12 @@ cupsGetPPD2(http_t     *http,           /* I - HTTP connection */
   */
 
 #ifdef AF_INET6
-  if (http->hostaddr.addr.sa_family == AF_INET6)
-    http_port = ntohs(http->hostaddr.ipv6.sin6_port);
+  if (http->hostaddr->addr.sa_family == AF_INET6)
+    http_port = ntohs(http->hostaddr->ipv6.sin6_port);
   else
 #endif /* AF_INET6 */
-  if (http->hostaddr.addr.sa_family == AF_INET)
-    http_port = ntohs(http->hostaddr.ipv4.sin_port);
+  if (http->hostaddr->addr.sa_family == AF_INET)
+    http_port = ntohs(http->hostaddr->ipv4.sin_port);
   else
     http_port = ippPort(); 
 
index e576b3f00e808732a8825ab1e849975871646338..a14439a54b956b1d9b217011474c28d0173e5b4b 100644 (file)
@@ -1113,20 +1113,20 @@ cupsdIsAuthorized(cupsd_client_t *con,  /* I - Connection */
   */
 
 #ifdef AF_INET6
-  if (con->http.hostaddr.addr.sa_family == AF_INET6)
+  if (con->http.hostaddr->addr.sa_family == AF_INET6)
   {
    /*
     * Copy IPv6 address...
     */
 
-    address[0] = ntohl(con->http.hostaddr.ipv6.sin6_addr.s6_addr32[0]);
-    address[1] = ntohl(con->http.hostaddr.ipv6.sin6_addr.s6_addr32[1]);
-    address[2] = ntohl(con->http.hostaddr.ipv6.sin6_addr.s6_addr32[2]);
-    address[3] = ntohl(con->http.hostaddr.ipv6.sin6_addr.s6_addr32[3]);
+    address[0] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[0]);
+    address[1] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[1]);
+    address[2] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[2]);
+    address[3] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[3]);
   }
   else
 #endif /* AF_INET6 */
-  if (con->http.hostaddr.addr.sa_family == AF_INET)
+  if (con->http.hostaddr->addr.sa_family == AF_INET)
   {
    /*
     * Copy IPv4 address...
@@ -1135,7 +1135,7 @@ cupsdIsAuthorized(cupsd_client_t *con,    /* I - Connection */
     address[0] = 0;
     address[1] = 0;
     address[2] = 0;
-    address[3] = ntohl(con->http.hostaddr.ipv4.sin_addr.s_addr);
+    address[3] = ntohl(con->http.hostaddr->ipv4.sin_addr.s_addr);
   }
   else
     memset(address, 0, sizeof(address));
index b7ac039d9be79209a072e4f2ed60297450ec4133..703a62b121d093a54b9ba07b2e9f707e12c8cb05 100644 (file)
@@ -86,7 +86,8 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
   int                  count;          /* Count of connections on a host */
   int                  val;            /* Parameter value */
   cupsd_client_t       *con;           /* New client pointer */
-  const struct hostent *host;          /* Host entry for address */
+  http_addrlist_t      *addrlist,      /* List of adddresses for host */
+                       *addr;          /* Current address */
   char                 *hostname;      /* Hostname for address */
   http_addr_t          temp;           /* Temporary address variable */
   static time_t                last_dos = 0;   /* Time of last DoS attack */
@@ -112,6 +113,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
   memset(con, 0, sizeof(cupsd_client_t));
   con->http.activity = time(NULL);
   con->file          = -1;
+  con->http.hostaddr = &(con->clientaddr);
 
  /*
   * Accept the client and get the remote address...
@@ -119,7 +121,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
 
   val = sizeof(struct sockaddr_in);
 
-  if ((con->http.fd = accept(lis->fd, (struct sockaddr *)&(con->http.hostaddr),
+  if ((con->http.fd = accept(lis->fd, (struct sockaddr *)con->http.hostaddr,
                              &val)) < 0)
   {
     cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to accept client connection - %s.",
@@ -129,18 +131,18 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
 
 #ifdef AF_INET6
   if (lis->address.addr.sa_family == AF_INET6)
-    con->http.hostaddr.ipv6.sin6_port = lis->address.ipv6.sin6_port;
+    con->http.hostaddr->ipv6.sin6_port = lis->address.ipv6.sin6_port;
   else
 #endif /* AF_INET6 */
   if (lis->address.addr.sa_family == AF_INET)
-    con->http.hostaddr.ipv4.sin_port = lis->address.ipv4.sin_port;
+    con->http.hostaddr->ipv4.sin_port = lis->address.ipv4.sin_port;
 
  /*
   * Check the number of clients on the same address...
   */
 
   for (i = 0, count = 0; i < NumClients; i ++)
-    if (httpAddrEqual(&(Clients[i].http.hostaddr), &(con->http.hostaddr)))
+    if (httpAddrEqual(Clients[i].http.hostaddr, con->http.hostaddr))
     {
       count ++;
       if (count >= MaxClientsPerHost)
@@ -170,7 +172,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
   * Get the hostname or format the IP address as needed...
   */
 
-  if (httpAddrLocalhost(&(con->http.hostaddr)))
+  if (httpAddrLocalhost(con->http.hostaddr))
   {
    /*
     * Map accesses from the loopback interface to "localhost"...
@@ -179,23 +181,30 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
     strlcpy(con->http.hostname, "localhost", sizeof(con->http.hostname));
     hostname = con->http.hostname;
   }
-  else if (httpAddrEqual(&(con->http.hostaddr), &ServerAddr))
+  else
   {
    /*
     * Map accesses from the same host to the server name.
     */
 
-    strlcpy(con->http.hostname, ServerName, sizeof(con->http.hostname));
-    hostname = con->http.hostname;
-  }
-  else if (HostNameLookups)
-    hostname = httpAddrLookup(&(con->http.hostaddr), con->http.hostname,
-                              sizeof(con->http.hostname));
-  else
-  {
-    hostname = NULL;
-    httpAddrString(&(con->http.hostaddr), con->http.hostname,
-                   sizeof(con->http.hostname));
+    for (addr = ServerAddrs; addr; addr = addr->next)
+      if (httpAddrEqual(con->http.hostaddr, &(addr->addr)))
+        break;
+
+    if (addr)
+    {
+      strlcpy(con->http.hostname, ServerName, sizeof(con->http.hostname));
+      hostname = con->http.hostname;
+    }
+    else if (HostNameLookups)
+      hostname = httpAddrLookup(con->http.hostaddr, con->http.hostname,
+                                sizeof(con->http.hostname));
+    else
+    {
+      hostname = NULL;
+      httpAddrString(con->http.hostaddr, con->http.hostname,
+                     sizeof(con->http.hostname));
+    }
   }
 
   if (hostname == NULL && HostNameLookups == 2)
@@ -226,40 +235,22 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
     * Do double lookups as needed...
     */
 
-    if ((host = httpGetHostByName(con->http.hostname)) != NULL)
+    if ((addrlist = httpAddrGetList(con->http.hostname, AF_UNSPEC, NULL)) != NULL)
     {
      /*
       * See if the hostname maps to the same IP address...
       */
 
-      if (host->h_addrtype != con->http.hostaddr.addr.sa_family)
-      {
-       /*
-        * Not the right type of address...
-       */
-
-       host = NULL;
-      }
-      else
-      {
-       /*
-        * Compare all of the addresses against this one...
-       */
-
-       for (i = 0; host->h_addr_list[i]; i ++)
-       {
-         httpAddrLoad(host, 0, i, &temp);
-
-          if (httpAddrEqual(&(con->http.hostaddr), &temp))
-           break;
-        }
-
-        if (!host->h_addr_list[i])
-         host = NULL;
-      }
+      for (addr = addrlist; addr; addr = addr->next)
+        if (httpAddrEqual(con->http.hostaddr, &(addr->addr)))
+          break;
     }
+    else
+      addr = NULL;
+
+    httpAddrFreeList(addrlist);
 
-    if (host == NULL)
+    if (!addr)
     {
      /*
       * Can't have a hostname that doesn't resolve to the same IP address
@@ -284,21 +275,21 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
   }
 
 #ifdef AF_INET6
-  if (con->http.hostaddr.addr.sa_family == AF_INET6)
+  if (con->http.hostaddr->addr.sa_family == AF_INET6)
     cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s:%d (IPv6)",
                     con->http.fd, con->http.hostname,
-                   ntohs(con->http.hostaddr.ipv6.sin6_port));
+                   ntohs(con->http.hostaddr->ipv6.sin6_port));
   else
 #endif /* AF_INET6 */
 #ifdef AF_LOCAL
-  if (con->http.hostaddr.addr.sa_family == AF_LOCAL)
+  if (con->http.hostaddr->addr.sa_family == AF_LOCAL)
     cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s (Domain)",
                     con->http.fd, con->http.hostname);
   else
 #endif /* AF_LOCAL */
   cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s:%d (IPv4)",
                   con->http.fd, con->http.hostname,
-                 ntohs(con->http.hostaddr.ipv4.sin_port));
+                 ntohs(con->http.hostaddr->ipv4.sin_port));
 
  /*
   * Get the local address the client connected to...
@@ -3265,7 +3256,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
     strcpy(lang, "LANG=C");
 
   strcpy(remote_addr, "REMOTE_ADDR=");
-  httpAddrString(&(con->http.hostaddr), remote_addr + 12,
+  httpAddrString(con->http.hostaddr, remote_addr + 12,
                  sizeof(remote_addr) - 12);
 
   snprintf(remote_host, sizeof(remote_host), "REMOTE_HOST=%s",
index 1dce052a2bad4380e1ed29fa93a9b6f1f07e74af..aa22b6536114b170499bca72d81335f37e1629e2 100644 (file)
@@ -52,6 +52,7 @@ struct cupsd_client_s
 #ifdef HAVE_SSL
   int                  auto_ssl;       /* Automatic test for SSL/TLS */
 #endif /* HAVE_SSL */
+  http_addr_t          clientaddr;     /* Client address */
   char                 servername[256];/* Server name for connection */
   int                  serverport;     /* Server port for connection */
 };
@@ -83,13 +84,14 @@ VAR http_encryption_t       LocalEncryption VALUE(HTTP_ENCRYPT_IF_REQUESTED);
                                        /* Local port encryption to use */
 VAR int                        NumListeners    VALUE(0);
                                        /* Number of listening sockets */
-VAR cupsd_listener_t           *Listeners      VALUE(NULL);
+VAR cupsd_listener_t   *Listeners      VALUE(NULL);
                                        /* Listening sockets */
 VAR int                        NumClients      VALUE(0);
                                        /* Number of HTTP clients */
-VAR cupsd_client_t             *Clients        VALUE(NULL);
+VAR cupsd_client_t     *Clients        VALUE(NULL);
                                        /* HTTP clients */
-VAR http_addr_t                ServerAddr;     /* Server address */
+VAR http_addrlist_t    *ServerAddrs    VALUE(NULL);
+                                       /* Server address(es) */
 VAR char               *ServerHeader   VALUE(NULL);
                                        /* Server header in requests */
 VAR int                        CGIPipes[2]     VALUE2(-1,-1);
index 741bd5860aa54b9e3f29cb10cd3ab562a380531a..59fa858089d0b2452b2999908da6436e1b0a3803 100644 (file)
@@ -1035,11 +1035,11 @@ get_address(const char  *value,         /* I - Value string */
            int         deffamily,      /* I - Default family */
             http_addr_t *address)      /* O - Socket address */
 {
-  char                 hostname[256],  /* Hostname or IP */
-                       portname[256],  /* Port number or name */
-                       *ptr;           /* Pointer into hostname string */
-  struct hostent       *host;          /* Host address */
-  struct servent       *port;          /* Port number */  
+  char                 hostname[1024], /* Hostname or IP */
+                       *portname;      /* Port number or name */
+  http_addrlist_t      *addrlist;      /* Address list */
+  int                  portnum;        /* Port number */
+  struct servent       *service;       /* Service entry */
 
 
  /*
@@ -1103,24 +1103,22 @@ get_address(const char  *value,         /* I - Value string */
 
   strlcpy(hostname, value, sizeof(hostname));
 
-  if ((ptr = strrchr(hostname, ':')) != NULL)
-  {
-   /*
-    * Copy hostname and port separately...
-    */
-
-    *ptr++ = '\0';
-
-    strlcpy(portname, ptr, sizeof(portname));
-  }
+  if ((portname = strrchr(hostname, ':')) != NULL)
+    *portname++ = '\0';
   else if (isdigit(value[0] & 255))
   {
    /*
     * Port number...
     */
 
-    hostname[0] = '\0';
-    strlcpy(portname, value, sizeof(portname));
+#ifdef AF_INET6
+    if (deffamily == AF_INET6)
+      address->ipv6.sin6_port = htons(atoi(value));
+    else
+#endif /* AF_INET6 */
+    address->ipv4.sin_port = htons(atoi(value));
+
+    return (1);
   }
   else
   {
@@ -1128,7 +1126,7 @@ get_address(const char  *value,           /* I - Value string */
     * Hostname by itself...
     */
 
-    portname[0] = '\0';
+    portname = NULL;
   }
 
  /*
@@ -1137,45 +1135,46 @@ get_address(const char  *value,         /* I - Value string */
 
   if (hostname[0] && strcmp(hostname, "*"))
   {
-    if ((host = httpGetHostByName(hostname)) == NULL)
+    if ((addrlist = httpAddrGetList(hostname, deffamily, portname)) == NULL)
     {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "httpGetHostByName(\"%s\") failed - %s!",
-                      hostname, hstrerror(h_errno));
+      cupsdLogMessage(CUPSD_LOG_ERROR, "Hostname lookup for \"%s\" failed!",
+                      hostname);
       return (0);
     }
 
-    httpAddrLoad(host, defport, 0, address);
-  }
+    memcpy(address, &(addrlist->addr), httpAddrLength(&(addrlist->addr)));
 
-  if (portname[0] != '\0')
-  {
-    if (isdigit(portname[0] & 255))
+    if (!portname)
     {
 #ifdef AF_INET6
       if (address->addr.sa_family == AF_INET6)
-        address->ipv6.sin6_port = htons(atoi(portname));
+       address->ipv6.sin6_port = htons(atoi(value));
       else
 #endif /* AF_INET6 */
-      address->ipv4.sin_port = htons(atoi(portname));
+      address->ipv4.sin_port = htons(atoi(value));
     }
+
+    httpAddrFreeList(addrlist);
+  }
+  else if (portname)
+  {
+    if (isdigit(*portname & 255))
+      portnum = atoi(portname);
+    else if ((service = getservbyname(portname, NULL)) != NULL)
+      portnum = ntohs(service->s_port);
     else
     {
-      if ((port = getservbyname(portname, NULL)) == NULL)
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR, "getservbyname(\"%s\") failed - %s!",
-                       portname, strerror(errno));
-        return (0);
-      }
-      else
-      {
+      cupsdLogMessage(CUPSD_LOG_ERROR, "Service lookup for \"%s\" failed!",
+                      portname);
+      return (0);
+    }
+
 #ifdef AF_INET6
-       if (address->addr.sa_family == AF_INET6)
-          address->ipv6.sin6_port = htons(port->s_port);
-       else
+    if (deffamily == AF_INET6)
+      address->ipv6.sin6_port = htons(portnum);
+    else
 #endif /* AF_INET6 */
-       address->ipv4.sin_port = htons(port->s_port);
-      }
-    }
+    address->ipv4.sin_port = htons(portnum);
   }
 
   return (1);
index 45272d233071ff3aad57a3033eaec1d2a2817b34..5faf5caa435b411b629c2604984d2cfb02e518c4 100644 (file)
@@ -109,7 +109,6 @@ cupsdStartListening(void)
                        p,              /* Port number */
                        val;            /* Parameter value */
   cupsd_listener_t     *lis;           /* Current listening socket */
-  struct hostent       *host;          /* Host entry for server address */
   char                 s[256];         /* String addresss */
   const char           *have_domain;   /* Have a domain socket? */
   static const char * const encryptions[] =
@@ -128,27 +127,18 @@ cupsdStartListening(void)
   * Get the server's IP address...
   */
 
-  memset(&ServerAddr, 0, sizeof(ServerAddr));
+  if (ServerAddrs)
+    httpAddrFreeList(ServerAddrs);
 
-  if ((host = httpGetHostByName(ServerName)) != NULL)
-  {
-   /*
-    * Found the server's address!
-    */
-
-    httpAddrLoad(host, 0, 0, &ServerAddr);
-  }
-  else
+  if ((ServerAddrs = httpAddrGetList(ServerName, AF_UNSPEC, NULL)) == NULL)
   {
    /*
     * Didn't find it!  Use an address of 0...
     */
 
     cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "cupsdStartListening: Unable to find IP address for server name \"%s\" - %s\n",
-                    ServerName, hstrerror(h_errno));
-
-    ServerAddr.ipv4.sin_family = AF_INET;
+                    "cupsdStartListening: Unable to find IP address for server name \"%s\"!\n",
+                    ServerName);
   }
 
  /*
index f8fd6b3794a4e7436a8d22101586d52a656c67d3..8bc4bb088a3b610f1889cb0a55ab6cd21ee0c646 100644 (file)
@@ -143,6 +143,7 @@ cupsdNetIFUpdate(void)
   cupsd_netif_t                *temp;          /* Current interface */
   struct ifaddrs       *addrs,         /* Interface address list */
                        *addr;          /* Current interface address */
+  http_addrlist_t      *saddr;         /* Current server address */
 
 
  /*
@@ -294,11 +295,18 @@ cupsdNetIFUpdate(void)
 
       if (httpAddrLocalhost(&(temp->address)))
         strcpy(temp->hostname, "localhost");
-      else if (httpAddrEqual(&(temp->address), &ServerAddr))
-        strlcpy(temp->hostname, ServerName, sizeof(temp->hostname));
       else
-        httpAddrString(&(temp->address), temp->hostname,
-                      sizeof(temp->hostname));
+      {
+        for (saddr = ServerAddrs; saddr; saddr = saddr->next)
+         if (httpAddrEqual(&(temp->address), &(saddr->addr)))
+           break;
+
+       if (saddr)
+          strlcpy(temp->hostname, ServerName, sizeof(temp->hostname));
+       else
+          httpAddrString(&(temp->address), temp->hostname,
+                        sizeof(temp->hostname));
+      }
     }
   }