This started off as David Reid's patch which he posted this a.m.  I
renamed his apr_gethostbyname() to apr_getaddrinfo(), added fields
family and port to apr_getaddrinfo(), made some fixes, and changed the
remaining callers of apr_connect() to use the new parameter list.

Changes to the currently-committed API:

. apr_connect() takes an apr_sockaddr_t parameter instead of hostname

. apr_getaddrinfo() is new; this builds an apr_sockaddr_t representing
  the peer you wish to communicate with

Suggestions?  Concerns?

Index: lib/apr/include/apr_network_io.h
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/include/apr_network_io.h,v
retrieving revision 1.71
diff -u -r1.71 apr_network_io.h
--- lib/apr/include/apr_network_io.h    2000/11/16 14:48:50     1.71
+++ lib/apr/include/apr_network_io.h    2000/11/16 18:07:26
@@ -265,7 +265,7 @@
  *                 APR assumes that the sockaddr_in in the apr_socket is 
  *                 completely filled out.
  */
-apr_status_t apr_connect(apr_socket_t *sock, const char *hostname);
+apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa);
 
 /**
  * Get name of a machine we are currently connected to.
@@ -274,6 +274,12 @@
  * @param sock The socket to examine.
  */
 apr_status_t apr_get_hostname(char **name, apr_interface_e which, apr_socket_t 
*sock);
+
+apr_status_t apr_getaddrinfo(apr_sockaddr_t **sa, 
+                             const char *hostname,
+                             apr_int32_t family,
+                             apr_port_t port,
+                             apr_pool_t *p);
 
 /**
  * Get name of the current machine
Index: lib/apr/network_io/unix/sa_common.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/unix/sa_common.c,v
retrieving revision 1.6
diff -u -r1.6 sa_common.c
--- lib/apr/network_io/unix/sa_common.c 2000/11/16 14:48:49     1.6
+++ lib/apr/network_io/unix/sa_common.c 2000/11/16 18:07:27
@@ -171,3 +171,65 @@
     return APR_SUCCESS;
 }
 
+static void set_sockaddr_vars(apr_sockaddr_t *addr, int family)
+{
+    addr->sa.sin.sin_family = family;
+    addr->sa.sin.sin_family = family;
+
+    if (family == AF_INET) {
+        addr->sa_len = sizeof(struct sockaddr_in);
+        addr->addr_str_len = 16;
+        addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);
+        addr->ipaddr_len = sizeof(struct in_addr);
+    }
+#if APR_HAVE_IPV6
+    else if (family == AF_INET6) {
+        addr->sa_len = sizeof(struct sockaddr_in6);
+        addr->addr_str_len = 46;
+        addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
+        addr->ipaddr_len = sizeof(struct in6_addr);
+    }
+#endif
+}
+
+apr_status_t apr_getaddrinfo(apr_sockaddr_t **sa, const char *hostname, 
+                             apr_int32_t family, apr_port_t port,
+                             apr_pool_t *p)
+{
+    struct hostent *hp;
+
+    (*sa) = (apr_sockaddr_t *)apr_pcalloc(p, sizeof(apr_sockaddr_t));
+    if ((*sa) == NULL)
+        return APR_ENOMEM;
+    (*sa)->pool = p;
+    (*sa)->sa.sin.sin_family = AF_INET; /* we don't yet support IPv6 */
+    (*sa)->sa.sin.sin_port = htons(port);
+    set_sockaddr_vars(*sa, (*sa)->sa.sin.sin_family);
+
+    if (hostname != NULL) {
+#ifndef GETHOSTBYNAME_HANDLES_NAS
+        if (*hostname >= '0' && *hostname <= '9' &&
+            strspn(hostname, "0123456789.") == strlen(hostname)) {
+            (*sa)->sa.sin.sin_addr.s_addr = inet_addr(hostname);
+            (*sa)->sa_len = sizeof(struct sockaddr_in);
+        }
+        else {
+#endif
+        hp = gethostbyname(hostname);
+
+        if (!hp)  {
+            return (h_errno + APR_OS_START_SYSERR);
+        }
+
+        memcpy((char *)&(*sa)->sa.sin.sin_addr, hp->h_addr_list[0],
+               hp->h_length);
+        (*sa)->sa_len = sizeof(struct sockaddr_in);
+        (*sa)->ipaddr_len = hp->h_length;
+
+#ifndef GETHOSTBYNAME_HANDLES_NAS
+        }
+#endif
+    }
+   (*sa)->hostname = apr_pstrdup(p, hostname);
+    return APR_SUCCESS;
+}
Index: lib/apr/network_io/unix/sockets.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/unix/sockets.c,v
retrieving revision 1.56
diff -u -r1.56 sockets.c
--- lib/apr/network_io/unix/sockets.c   2000/11/16 14:48:49     1.56
+++ lib/apr/network_io/unix/sockets.c   2000/11/16 18:07:27
@@ -226,57 +226,35 @@
     return APR_SUCCESS;
 }
 
-apr_status_t apr_connect(apr_socket_t *sock, const char *hostname)
+apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
 {
-    struct hostent *hp;
-
     if ((sock->socketdes < 0) || (!sock->remote_addr)) {
         return APR_ENOTSOCK;
     }
-    if (hostname != NULL) {
-#ifndef GETHOSTBYNAME_HANDLES_NAS
-        if (*hostname >= '0' && *hostname <= '9' &&
-            strspn(hostname, "0123456789.") == strlen(hostname)) {
-            sock->remote_addr->sa.sin.sin_addr.s_addr = inet_addr(hostname);
-        }
-        else {
-#endif
-        hp = gethostbyname(hostname);
-
-        if (!hp)  {
-            return (h_errno + APR_OS_START_SYSERR);
-        }
-
-        /* XXX IPv6: move name resolution out of this function */
-        memcpy((char *)&sock->remote_addr->sa.sin.sin_addr, 
hp->h_addr_list[0], 
-               hp->h_length);
-
-#ifndef GETHOSTBYNAME_HANDLES_NAS
-        }
-#endif
-    }
 
-    if ((connect(sock->socketdes, 
-                 (const struct sockaddr *)&sock->remote_addr->sa.sin,
-                 sock->remote_addr->sa_len) < 0) &&
+    if ((connect(sock->socketdes,
+                 (const struct sockaddr *)&sa->sa.sin,
+                 sa->sa_len) < 0) &&
         (errno != EINPROGRESS)) {
         return errno;
     }
     else {
-        /* XXX IPv6 */
+        sock->remote_addr = sa;
+        /* XXX IPv6 assumes sin_port and sin6_port at same offset */
         if (sock->local_addr->sa.sin.sin_port == 0) {
             /* connect() got us an ephemeral port */
             sock->local_port_unknown = 1;
         }
-        /* XXX IPv6 */
-        if (sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
+        /* XXX IPv6 to be handled better later... */
+        if (sock->local_addr->sa.sin.sin_family == AF_INET6 ||
+            sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
             /* not bound to specific local interface; connect() had to assign
              * one for the socket
              */
             sock->local_interface_unknown = 1;
         }
 #ifndef HAVE_POLL
-       sock->connected=1;
+        sock->connected=1;
 #endif
         return APR_SUCCESS;
     }
Index: lib/apr/test/client.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/test/client.c,v
retrieving revision 1.17
diff -u -r1.17 client.c
--- lib/apr/test/client.c       2000/11/09 15:01:35     1.17
+++ lib/apr/test/client.c       2000/11/16 18:07:28
@@ -73,6 +73,7 @@
     char *dest = "127.0.0.1";
     apr_port_t local_port, remote_port;
     apr_interval_time_t read_timeout = -1;
+    apr_sockaddr_t *destsa;
 
     setbuf(stdout, NULL);
     if (argc > 1) {
@@ -115,17 +116,18 @@
         fprintf(stdout, "OK\n");
     }
 
-    fprintf(stdout, "\tClient:  Setting port for socket.......");
-    if (apr_set_port(sock, APR_REMOTE, 8021) != APR_SUCCESS) {
+    fprintf(stdout,"\tClient:  Making socket address...............");
+    if (apr_getaddrinfo(&destsa, dest, AF_INET, 8021, context) != APR_SUCCESS) 
{
         apr_close_socket(sock);
-        fprintf(stderr, "Couldn't set the port correctly\n");
+        fprintf(stdout, "Failed!\n");
+        fprintf(stdout, "Couldn't create a socket address structure for %s\n", 
dest);
         exit(-1);
     }
-    fprintf(stdout, "OK\n");           
+    fprintf(stdout,"OK\n");
 
     fprintf(stdout, "\tClient:  Connecting to socket.......");
 
-    stat = apr_connect(sock, dest);
+    stat = apr_connect(sock, destsa);
 
     if (stat != APR_SUCCESS) {
         apr_close_socket(sock);
Index: lib/apr/test/testsf.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/test/testsf.c,v
retrieving revision 1.13
diff -u -r1.13 testsf.c
--- lib/apr/test/testsf.c       2000/11/14 19:32:26     1.13
+++ lib/apr/test/testsf.c       2000/11/16 18:07:28
@@ -205,6 +205,7 @@
     apr_pollfd_t *pfd;
     apr_int32_t nsocks;
     int i;
+    apr_sockaddr_t *destsa;
 
     apr_setup(&p, &sock);
     create_testfile(p, TESTFILE);
@@ -217,15 +218,15 @@
         exit(1);
     }
 
-    rv = apr_set_port(sock, APR_REMOTE, TESTSF_PORT);
+    rv = apr_getaddrinfo(&destsa, "127.0.0.1", AF_INET, TESTSF_PORT, p);
     if (rv != APR_SUCCESS) {
-        fprintf(stderr, "apr_set_remote_port()->%d/%s\n",
+        fprintf(stderr, "apr_getaddrinfo()->%d/%s\n",
                 rv,
                 apr_strerror(rv, buf, sizeof buf));
         exit(1);
     }
 
-    rv = apr_connect(sock, "127.0.0.1");
+    rv = apr_connect(sock, destsa);
     if (rv != APR_SUCCESS) {
         fprintf(stderr, "apr_connect()->%d/%s\n", 
                 rv,
Index: main/rfc1413.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/main/rfc1413.c,v
retrieving revision 1.28
diff -u -r1.28 rfc1413.c
--- main/rfc1413.c      2000/11/09 15:09:50     1.28
+++ main/rfc1413.c      2000/11/16 18:07:30
@@ -108,8 +108,8 @@
 
 /* bind_connect - bind both ends of a socket */
 /* Ambarish fix this. Very broken */
-static int get_rfc1413(apr_socket_t *sock, const char *local_ip,
-                      const char *rmt_ip, 
+static int get_rfc1413(apr_socket_t *sock, apr_pool_t *p, 
+                       const char *local_ip, const char *rmt_ip, 
                       char user[RFC1413_USERLEN+1], server_rec *srv)
 {
     apr_port_t rmt_port, our_port;
@@ -119,6 +119,7 @@
     char *cp;
     char buffer[RFC1413_MAXDATA + 1];
     int buflen;
+    apr_sockaddr_t *destsa;
 
     /*
      * Bind the local and remote ends of the query socket to the same
@@ -138,14 +139,19 @@
        return -1;
     }
 
+    if ((status = apr_getaddrinfo(&destsa, rmt_ip, AF_INET, RFC1413_PORT, 
+                                  p)) != APR_SUCCESS) {
+        /* This should not fail since we have a numeric address string
+         * as the host. */
+        ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
+                     "rfc1413: apr_getaddrinfo() failed");
+        return -1;
+    }
 /*
  * errors from connect usually imply the remote machine doesn't support
  * the service
  */
-    apr_set_port(sock, APR_REMOTE, RFC1413_PORT);
-    apr_set_ipaddr(sock, APR_REMOTE, rmt_ip);
-                    
-    if (apr_connect(sock, NULL) != APR_SUCCESS)
+    if (apr_connect(sock, destsa) != APR_SUCCESS)
         return -1;
     apr_get_port(&sav_our_port, APR_LOCAL, sock);
     apr_get_port(&sav_rmt_port, APR_REMOTE, sock);
@@ -235,7 +241,7 @@
        conn->remote_logname = result;
     }
 
-    if (get_rfc1413(sock, conn->local_ip, conn->remote_ip, user, srv) >= 0)
+    if (get_rfc1413(sock, conn->pool, conn->local_ip, conn->remote_ip, user, 
srv) >= 0)
         result = user;
     apr_close_socket(sock);
     conn->remote_logname = result;
Index: modules/proxy/proxy_util.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/modules/proxy/proxy_util.c,v
retrieving revision 1.26
diff -u -r1.26 proxy_util.c
--- modules/proxy/proxy_util.c  2000/11/16 01:57:46     1.26
+++ modules/proxy/proxy_util.c  2000/11/16 18:07:32
@@ -1135,25 +1135,15 @@
 {
     apr_status_t rv;
     int i;
+    apr_sockaddr_t *destsa;
 
-    for (i = 0; host[i] != '\0'; i++)
-        if (!apr_isdigit(host[i]) && host[i] != '.')
-            break;
-
-    apr_set_port(sock, APR_REMOTE, port);
-    if (host[i] == '\0') {
-        apr_set_ipaddr(sock, APR_REMOTE, host);
-        host = NULL;
+    rv = apr_getaddrinfo(&destsa, host, AF_INET, port, r->pool);
+    if (rv == APR_SUCCESS) {
+        rv = apr_connect(sock, destsa);
     }
-
-    do
-    {
-        rv = apr_connect(sock, host);
-    } while (APR_STATUS_IS_EINTR(rv));
-
     if (rv != APR_SUCCESS)
     {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
             "proxy connect to %s port %d failed", host, port);
     }
     return rv;
Index: support/ab.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/support/ab.c,v
retrieving revision 1.32
diff -u -r1.32 ab.c
--- support/ab.c        2000/11/10 19:01:33     1.32
+++ support/ab.c        2000/11/16 18:07:36
@@ -482,6 +482,7 @@
 static void start_connect(struct connection *c)
 {
     apr_status_t rv;
+    apr_sockaddr_t *destsa;
 
     if(!(started < requests)) return;
 
@@ -491,14 +492,15 @@
     c->cbx = 0;
     c->gotheader = 0;
 
+    if ((rv = apr_getaddrinfo(&destsa, hostname, AF_INET, port, cntxt))
+         != APR_SUCCESS) {
+        apr_err("apr_getaddrinfo()", rv);
+    }
     if ((rv = apr_create_tcp_socket(&c->aprsock, cntxt)) != APR_SUCCESS) {
         apr_err("Socket:", rv);
     }
-    if ((rv = apr_set_port(c->aprsock, APR_REMOTE, port)) != APR_SUCCESS) {
-        apr_err("Port:", rv);
-    }
     c->start = apr_now();
-    if ((rv = apr_connect(c->aprsock, hostname)) != APR_SUCCESS) {
+    if ((rv = apr_connect(c->aprsock, destsa)) != APR_SUCCESS) {
         if (APR_STATUS_IS_EINPROGRESS(rv)) {
             c->state = STATE_CONNECTING;
             apr_add_poll_socket(readbits, c->aprsock, APR_POLLOUT);

-- 
Jeff Trawick | [EMAIL PROTECTED] | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Reply via email to