You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by David Reid <dr...@jetnet.co.uk> on 2000/11/12 22:10:50 UTC

[PATCH] apr_sockaddr_t & friends

Folks,

I've been having a look at getting the apr_sockaddr_t structures added and
used throughout APR and the apache code, and in doing so have had to add
some APR functions and changed a LOT of the networking code...  the
resulting patch is bigger than I'd intended and touches more files than I'd
hoped.  The patch follows this text and can be found at
http://dev.apache.org/~dreid/sa_patch

Sendfile seems to be broken on FreeBSD (in a clean checkout it's broken as
well so it's not this patch :)) so I havn't managed to do as much checking
as I'd wished to.

whilst VirtualHosts seem to be work, the code needs a lot of attention to
get them working in a more protocol independant manner.  I think we'll need
to rework http_vhost.c following Tony's suggestion of using apr_hash and
thus allowing us to deal with more than IPv4.  That's the main reason I'm
not committing this :) Hopefully someone who knows the code well (fanf?) can
have a look and see what's required.

IPv6 support has started to be added and works in a limited fashion now.
For the adventurous in you, once applied change the line in
apr_create_tcp_socket from AF_INET to AF_INET6 and you'll have a server that
runs and will server either IPv4 or IPv6 requests. :)  Of course, the IPv6
support needs a lot more work yet.

There is a lot still to be done...  It's late and my brain is well addled
but these are a few that spring to mind...
- finish adding v6 support to APR
- rework the main apache code to remove the last vestiges of specific v4
coding
- add code safe version of inet_pton/inet_ntop for platforms that don't have
them
- http_vhost and hashing for v4 or v6

Given the above, I'm offering up the patch for public abuse and comment.  It
needs more eyes looking at it to get it to the next stage as I'm too close
to it at the moment...

It's possible to seperate out bits of this to apply in stages if that would
be preferred, or we can just go "BIG BANG"?

I'd like to get this in before we split APR out, but we'll see :)  If WW3
doesn't erupt then I'll commit Tuesday once I get home and catch up on my
mails.

david

Index: include/httpd.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/httpd.h,v
retrieving revision 1.116
diff -u -r1.116 httpd.h
--- include/httpd.h 2000/11/10 00:58:25 1.116
+++ include/httpd.h 2000/11/12 21:04:57
@@ -836,10 +836,17 @@

     /* Who is the client? */

+/* We shouldn't need these as they are cached in the socket that the
+ * structure has...
+ */
     /** local address */
+/*
     struct sockaddr_in local_addr;
+*/
     /** remote address */
+/*
     struct sockaddr_in remote_addr;
+*/
     /** Client's IP address */
     char *remote_ip;
     /** Client's DNS name, if known.  NULL if DNS hasn't been checked,
@@ -900,7 +907,7 @@
     /** The next server in the list */
     server_addr_rec *next;
     /** The bound address, for this server */
-    apr_in_addr_t host_addr;
+    apr_in_addr_t *host_addr;
     /** The bound port, for this server */
     apr_port_t host_port;
     /** The name given in <VirtualHost> */
Index: lib/apr/include/apr_network_io.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/include/apr_network_io.h,v
retrieving revision 1.68
diff -u -r1.68 apr_network_io.h
--- lib/apr/include/apr_network_io.h 2000/11/10 19:21:31 1.68
+++ lib/apr/include/apr_network_io.h 2000/11/12 21:05:02
@@ -113,6 +113,16 @@
 }
 #endif

+struct apr_in_addr_t {
+    union {
+        struct in_addr ia;
+#if APR_HAVE_IPV6
+        struct in6_addr ia6;
+#endif
+    } u;
+    int family;
+};
+
 /* Enum to tell us if we're interested in remote or local socket */
 typedef enum {
     APR_LOCAL,
@@ -132,7 +142,7 @@
 typedef struct apr_socket_t     apr_socket_t;
 typedef struct apr_pollfd_t     apr_pollfd_t;
 typedef struct apr_hdtr_t       apr_hdtr_t;
-typedef struct in_addr          apr_in_addr_t;
+typedef struct apr_in_addr_t    apr_in_addr_t;

 /* use apr_uint16_t just in case some system has a short that isn't 16
bits... */
 typedef apr_uint16_t            apr_port_t;
@@ -156,12 +166,13 @@
 #endif
     } sa;
     apr_socklen_t sa_len;          /* How big is the sockaddr we're using?
*/
+    int ipaddr_len;                /* How big is the ip address structure
we're using? */
     int addr_str_len;              /* How big should the address buffer be?
                                     * 16 for v4 or 46 for v6
                                     * used in inet_ntop...
                                     */
-     void *ipaddr_ptr;              /* This points to the IP address
-                                    * structure within the appropriate
+    void *ipaddr_ptr;              /* This points to the IP address
+                                    * structure within the appropriate
                                     * sockaddr structure.
                                     */
 } apr_sockaddr_t;
@@ -449,18 +460,12 @@
 /**
  * Return the local socket name as a BSD style struct sockaddr_in.
  * @param name The local name associated with the socket.
+ * @param which Which interface do we wnat the apr_sockaddr_t for?
  * @param sock The socket to use
  */
-apr_status_t apr_get_local_name(struct sockaddr_in **name, apr_socket_t
*sock);
+apr_status_t apr_get_name(apr_sockaddr_t **sa, apr_interface_e which,
apr_socket_t *sock);

 /**
- * Return the remote socket name as a BSD style struct sockaddr_in.
- * @param name The remote name associated with the socket.
- * @param sock The socket to use
- */
-apr_status_t apr_get_remote_name(struct sockaddr_in **name, apr_socket_t
*sock);
-
-/**
  * Setup the memory required for poll to operate properly>
  * @param new_poll The poll structure to be used.
  * @param num The number of socket descriptors to be polled.
@@ -584,7 +589,7 @@
  * @param addr The apr_in_addr_t structure to return.
  * @param hostname The hostname to lookup.
  */
-apr_status_t apr_get_inaddr(apr_in_addr_t *addr, char *hostname);
+apr_status_t apr_get_inaddr(apr_in_addr_t **addr, char *hostname,
apr_pool_t *cont);

 /**
  * Given an apr_socket_t get the apr_in_addr_t for the requested interface
@@ -592,8 +597,54 @@
  * @param which The interface to return for
  * @param sock The apr_socket_t to use
  */
-apr_status_t apr_get_socket_inaddr(apr_in_addr_t *addr, apr_interface_e
which,
+apr_status_t apr_get_socket_inaddr(apr_in_addr_t **addr, apr_interface_e
which,
                   apr_socket_t *sock);
+
+/**
+ * This returns the s_addr from an apr_in_addr_t if it's available
+ * @param saddr the return value
+ * @param ia The apr_in_addr_t structure
+ */
+apr_status_t apr_get_v4_address(apr_uint32_t *saddr, apr_in_addr_t *ia);
+
+apr_int32_t apr_inaddr_compare(apr_in_addr_t *a, apr_in_addr_t *b);
+
+apr_status_t apr_inet_ntop(char **addr, apr_in_addr_t *sa, apr_pool_t *p);
+
+/**
+ * Given an apr_socket_t, preform a reverse lookup...
+ * @param sock The apr_socket_t to preform the lookup on
+ * @tip This fundtion will first peform a hostname lookup if it has not
already been
+ *      done.
+ */
+apr_status_t apr_check_reverse_lookup(apr_socket_t *sock);
+
+/**
+ * Given an apr_socket_t, find the hostname for the specified interface and
return it
+ * in the hostname.
+ * @param sock The apr_socket_t structure to use
+ * @param which Which interface should we lookup?
+ * @param hostname The returned hostname
+ * @tip The hostname is also stored in the address structure of the
apr_socket_t.
+ */
+apr_status_t apr_gethostbyname(apr_socket_t *sock, apr_interface_e which,
const char *hostname);
+
+/**
+ * This is a replacement for inet_addr which is threadsafe
+ * @param sock The apr_socket_t into which the result will be stored
+ * @param which Which interface are we storing the address for?
+ * @param ipaddr The address in it's standard test form to convert
+ */
+apr_status_t apr_socket_inet_pton(apr_socket_t *sock, apr_interface_e which
,
+                        const char* hostname);
+
+/**
+ * This is a replacement for inet_ntoa which is threadsafe
+ * @param addr The converted string
+ * @param which The interface to convert
+ * @param sock The apr_socket_t to use for the address
+ */
+apr_status_t apr_socket_inet_ntop(char **addr, apr_interface_e which,
apr_socket_t *sock);

 #ifdef __cplusplus
 }
Index: lib/apr/network_io/unix/networkio.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/networkio.h,v
retrieving revision 1.33
diff -u -r1.33 networkio.h
--- lib/apr/network_io/unix/networkio.h 2000/09/29 04:03:20 1.33
+++ lib/apr/network_io/unix/networkio.h 2000/11/12 21:05:04
@@ -122,8 +122,8 @@
 struct apr_socket_t {
     apr_pool_t *cntxt;
     int socketdes;
-    struct sockaddr_in *local_addr;
-    struct sockaddr_in *remote_addr;
+    apr_sockaddr_t *local_addr;
+    apr_sockaddr_t *remote_addr;
     apr_socklen_t addr_len;
     apr_interval_time_t timeout;
 #ifndef HAVE_POLL
Index: lib/apr/network_io/unix/sa_common.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sa_common.c,v
retrieving revision 1.4
diff -u -r1.4 sa_common.c
--- lib/apr/network_io/unix/sa_common.c 2000/11/11 06:05:59 1.4
+++ lib/apr/network_io/unix/sa_common.c 2000/11/12 21:05:05
@@ -68,11 +68,14 @@
 apr_status_t apr_set_port(apr_socket_t *sock, apr_interface_e which,
                          apr_port_t port)
 {
-    if (which == APR_LOCAL)
-        sock->local_addr->sin_port = htons(port);
-    else if (which == APR_REMOTE)
-        sock->remote_addr->sin_port = htons(port);
-    else
+    if (which == APR_LOCAL){
+        sock->local_addr->sa.sin.sin_port = htons(port);
+        sock->local_addr->port = port;
+        sock->local_port_unknown = 0;
+    }else if (which == APR_REMOTE){
+        sock->remote_addr->sa.sin.sin_port = htons(port);
+        sock->remote_addr->port = port;
+    }else
         return APR_EINVAL;
     return APR_SUCCESS;
 }
@@ -88,10 +91,19 @@
                 return rv;
             }
         }
-
-        *port = ntohs(sock->local_addr->sin_port);
+        if (sock->local_addr->port > 0)
+            *port = sock->local_addr->port;
+        else{
+            *port = ntohs(sock->local_addr->sa.sin.sin_port);
+            sock->local_addr->port = *port;
+        }
     } else if (which == APR_REMOTE)
-        *port = ntohs(sock->remote_addr->sin_port);
+        if (sock->remote_addr->port > 0)
+            *port = sock->remote_addr->port;
+        else {
+            *port = ntohs(sock->remote_addr->sa.sin.sin_port);
+            sock->remote_addr->port = *port;
+        }
     else
         return APR_EINVAL;
     return APR_SUCCESS;
@@ -107,39 +119,49 @@
                 return rv;
             }
         }
-        *addr = apr_pstrdup(sock->cntxt,
inet_ntoa(sock->local_addr->sin_addr));
-    } else if (which == APR_REMOTE)
-        *addr = apr_pstrdup(sock->cntxt,
inet_ntoa(sock->remote_addr->sin_addr));
-    else
-        return APR_EINVAL;
+    }

-    return APR_SUCCESS;
+    return apr_socket_inet_ntop(addr, which, sock);
 }

-apr_status_t apr_get_inaddr(apr_in_addr_t *addr, char *hostname)
+/* XXX - This needs to work for IPv6 as well as IPv4 */
+apr_status_t apr_get_inaddr(apr_in_addr_t **addr, char *hostname,
apr_pool_t *cont)
 {
     struct hostent *he;
-
+
+    if ((*addr) == NULL)
+        (*addr) = (apr_in_addr_t*)apr_pcalloc(cont, sizeof(apr_in_addr_t));
+    (*addr)->family = AF_INET;
+
     if (strcmp(hostname,"*") == 0){
-        addr->s_addr = htonl(INADDR_ANY);
+        (*addr)->u.ia.s_addr = htonl(INADDR_ANY);
         return APR_SUCCESS;
     }
-    if ((addr->s_addr = apr_inet_addr(hostname)) != APR_INADDR_NONE)
+    if (strcasecmp(hostname,"_default_") == 0 ||
strcmp(hostname,"255.255.255.255") == 0){
+        /* the define of DEFAULT_VHOST_ADDR is the same as INADDR_BROADCAST
*/
+        (*addr)->u.ia.s_addr = htonl(INADDR_BROADCAST);
         return APR_SUCCESS;
+    }
+    if (((*addr)->u.ia.s_addr = apr_inet_addr(hostname)) !=
APR_INADDR_NONE)
+        return APR_SUCCESS;

     /* hmmm, it's not a numeric IP address so we need to look it up :( */
     he = gethostbyname(hostname);
     if (!he || he->h_addrtype != AF_INET || !he->h_addr_list[0])
         return (h_errno + APR_OS_START_SYSERR);

-    *addr = *(struct in_addr*)he->h_addr_list[0];
+    memcpy(&(*addr)->u, he->h_addr_list[0], he->h_length);

     return APR_SUCCESS;
 }

-apr_status_t apr_get_socket_inaddr(apr_in_addr_t *addr, apr_interface_e
which,
+apr_status_t apr_get_socket_inaddr(apr_in_addr_t **addr, apr_interface_e
which,
                         apr_socket_t *sock)
 {
+    void *ipp;
+    if (*addr == NULL)
+        (*addr)=(apr_in_addr_t*)apr_pcalloc(sock->cntxt,
sizeof(apr_in_addr_t));
+
     if (which == APR_LOCAL){
         if (sock->local_interface_unknown) {
             apr_status_t rv = get_local_addr(sock);
@@ -149,12 +171,224 @@
             }
         }

-        *addr = *(apr_in_addr_t*)&sock->local_addr->sin_addr;
+        ipp = sock->local_addr->ipaddr_ptr;
+        (*addr)->family = sock->local_addr->sa.sin.sin_family;
     } else if (which == APR_REMOTE) {
-        *addr = *(apr_in_addr_t*)&sock->remote_addr->sin_addr;
+        ipp = sock->remote_addr->ipaddr_ptr;
+        (*addr)->family = sock->remote_addr->sa.sin.sin_family;
     } else {
         return APR_EINVAL;
     }
+    if ((*addr)->family == AF_INET)
+        (*addr)->u.ia = *(struct in_addr*)ipp;
+#if APR_HAVE_IPV6
+    else if ((*addr)->family == AF_INET6)
+        (*addr)->u.ia6 = *(struct in6_addr*)ipp;
+#endif
+    return APR_SUCCESS;
+}
+
+/* iXXX - This is a horrible, horrible hack!! */
+apr_status_t apr_get_v4_address(apr_uint32_t *saddr, apr_in_addr_t *ia)
+{
+    if (ia->family == AF_INET)
+        *saddr = ia->u.ia.s_addr;
+#if APR_HAVE_IPV6
+    else if (ia->family == AF_INET6){
+        if (IN6_IS_ADDR_V4COMPAT(&ia->u.ia6)){
+            /* we have an IPv4 compatible address structure, so now we can
+             * return an IPv4 int32???
+             */
+            *saddr = ia->u.ia.s_addr;
+        }
+    }
+#endif
+    else
+        return APR_EINVAL;
+    return APR_SUCCESS;
+}
+
+apr_int32_t apr_inaddr_compare(apr_in_addr_t *a, apr_in_addr_t *b)
+{
+    if (a->family == AF_INET)
+        return memcmp(&a->u, &b->u, sizeof(struct in_addr));
+#if APR_HAVE_IPV6
+    if (a->family == AF_INET6)
+        return memcmp(&a->u, &b->u, sizeof(struct in6_addr));
+#endif
+    return -1;
+}
+
+apr_status_t apr_gethostbyname(apr_socket_t *sock, apr_interface_e which,
const char *hostname)
+{
+    apr_in_addr_t *ipp;
+    int family, errnum;
+    struct hostent *he;
+
+    if (which == APR_LOCAL){
+        ipp = sock->local_addr->ipaddr_ptr;
+        family = sock->local_addr->sa.sin.sin_family;
+    } else if (which == APR_REMOTE) {
+        ipp = sock->remote_addr->ipaddr_ptr;
+        family = sock->remote_addr->sa.sin.sin_family;
+    } else
+        return APR_EINVAL;
+
+    /* If we have getipnodebyname we'll use it... */
+#if HAVE_GETIPNODEBYNAME
+    he = getipnodebyname(hostname, family, AI_DEFAULT, &errnum);
+#else
+  #ifndef GETHOSTBYNAME_HANDLES_NAS
+    if (*hostname >= '0' && *hostname <= '9' &&
+        strspn(hostname, "0123456789.") == strlen(hostname)) {
+        apr_socket_inet_pton(sock, APR_REMOTE, hostname);
+    }
+    else {
+  #endif
+
+    he = gethostbyname(hostname);
+    errnum = h_errno;
+  #ifndef GETHOSTBYNAME_HANDLES_NAS
+    }
+  #endif
+#endif
+
+    if (!he) {
+        return (errnum + APR_OS_START_SYSERR);
+    }
+
+    memcpy(ipp, he->h_addr_list[0], he->h_length);
+
+    if (which == APR_LOCAL)
+        sock->local_addr->ipaddr_len = he->h_length;
+    else
+        sock->remote_addr->ipaddr_len = he->h_length;
+
+    return APR_SUCCESS;
+}
+
+/* XXX - This is currently just a wrapper for inet_pton if we have it
available, but
+ * we need to add our own implementation for those platforms that don't
have one.
+ * FreeBSD's might be a good candidate?
+ */
+apr_status_t apr_socket_inet_pton(apr_socket_t *sock, apr_interface_e
which,
+                        const char* hostname)
+{
+    int family;
+    void *ipp;
+    int rv;
+
+    if (which == APR_LOCAL){
+        ipp = sock->local_addr->ipaddr_ptr;
+        family = sock->local_addr->sa.sin.sin_family;
+    } else if (which == APR_REMOTE) {
+        ipp = sock->remote_addr->ipaddr_ptr;
+        family = sock->remote_addr->sa.sin.sin_family;
+    } else
+        return APR_EINVAL;
+
+#if HAVE_INET_PTON
+    if ((rv = inet_pton(family, hostname, ipp)) != 1){
+        if (rv == 0)
+            return APR_EINVAL;
+        else
+            return errno;
+    }
+#else
+    ipp = inet_addr(hostname);
+#endif
+    return APR_SUCCESS;
+}
+
+
+/* XXX - this is just a wrapper for inet_ntop on those systems that have
it, but
+ * we need to add our own implementation for those platforms that don't
have one
+ * of their own.  FreeBSD's code could be a good candidate?
+ */
+apr_status_t apr_socket_inet_ntop(char **addr, apr_interface_e which,
apr_socket_t *sock)
+{
+    int family;
+    void *ipp;
+    int strlen;
+
+    if (which == APR_LOCAL){
+        family = sock->local_addr->sa.sin.sin_family;
+        ipp = sock->local_addr->ipaddr_ptr;
+        strlen = sock->local_addr->addr_str_len;
+    } else if (which == APR_REMOTE){
+        family = sock->local_addr->sa.sin.sin_family;
+        ipp = sock->remote_addr->ipaddr_ptr;
+        strlen = sock->remote_addr->addr_str_len;
+    } else
+        return APR_EINVAL;
+
+#if HAVE_INET_NTOP
+    (*addr) = apr_pcalloc(sock->cntxt, sizeof(char*) * strlen);
+    if (inet_ntop(family, ipp, (*addr), strlen) == NULL)
+        return errno;
+#else
+    (*addr) = apr_pstrdup(sock->cntxt, inet_ntoa(family, ippi));
+#endif
+
+    return APR_SUCCESS;
+}
+
+/* XXX - this is just a wrapper for inet_ntop on those systems that have
it, but
+ * we need to add our own implementation for those platforms that don't
have one
+ * of their own.  FreeBSD's code could be a good candidate?
+ */
+apr_status_t apr_inet_ntop(char **addr, apr_in_addr_t *sa, apr_pool_t *p)
+{
+    int strlen;
+    if (sa->family == AF_INET)
+        strlen = 16;
+#if APR_HAVE_IPV6
+    else if (sa->family == AF_INET6)
+        strlen = 46;
+#endif
+    else
+        return APR_EINVAL;
+
+#if HAVE_INET_NTOP
+    (*addr) = apr_pcalloc(p, sizeof(char*) * strlen);
+    if (inet_ntop(sa->family, &sa->u, (*addr), strlen) == NULL)
+        return errno;
+#else
+    (*addr) = inet_ntoa(sa->family, sa->u.ia);
+#endif
+
     return APR_SUCCESS;
+}
+
+apr_status_t apr_check_reverse_lookup(apr_socket_t *sock)
+{
+    apr_status_t rv;
+    struct hostent *he;
+    int errnum;
+    char **haddr;
+
+    if (sock->remote_addr->hostname == NULL){
+        if ((rv = apr_get_hostname(&sock->remote_addr->hostname,
APR_REMOTE, sock)) != APR_SUCCESS)
+            return rv;
+    }
+
+#if HAVE_GETIPNODEBYNAME
+    he = getipnodebyname(sock->remote_addr->hostname,
sock->remote_addr->sa.sin.sin_family, AI_DEFAULT,
+                     &errnum);
+#else
+    he = gethostbyname(sock->remote_addr->hostname);
+    errnum = h_errno;
+#endif
+
+    if (!he)
+        return (errnum + APR_OS_START_SYSERR);
+
+    for (haddr = he->h_addr_list; *haddr; haddr++){
+        if (memcmp((apr_in_addr_t*)(*haddr), sock->remote_addr->ipaddr_ptr,
+                      sock->remote_addr->ipaddr_len) == 0)
+            return APR_SUCCESS;
+    }
+
+    return APR_EINVAL;
 }

Index: lib/apr/network_io/unix/sockaddr.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sockaddr.c,v
retrieving revision 1.19
diff -u -r1.19 sockaddr.c
--- lib/apr/network_io/unix/sockaddr.c 2000/11/09 15:01:26 1.19
+++ lib/apr/network_io/unix/sockaddr.c 2000/11/12 21:05:05
@@ -57,9 +57,9 @@

 static apr_status_t get_local_addr(apr_socket_t *sock)
 {
-    apr_socklen_t namelen = sizeof(*sock->local_addr);
+    apr_socklen_t namelen = sock->addr_len;

-    if (getsockname(sock->socketdes, (struct sockaddr *)sock->local_addr,
+    if (getsockname(sock->socketdes, (struct sockaddr
*)&sock->local_addr->sa,
                     &namelen) < 0) {
         return errno;
     }
@@ -78,9 +78,9 @@
     struct sockaddr_in* sa_ptr;

     if (which == APR_LOCAL)
-        sa_ptr = sock->local_addr;
+        sa_ptr = sock->local_addr->ipaddr_ptr;
     else if (which == APR_REMOTE)
-        sa_ptr = sock->remote_addr;
+        sa_ptr = sock->remote_addr->ipaddr_ptr;
     else
         return APR_EINVAL;

@@ -100,25 +100,24 @@
 }

 #if APR_HAVE_NETINET_IN_H
-apr_status_t apr_get_local_name(struct sockaddr_in **name, apr_socket_t
*sock)
+apr_status_t apr_get_name(apr_sockaddr_t **name, apr_interface_e which,
+                           apr_socket_t *sock)
 {
-    if (sock->local_port_unknown || sock->local_interface_unknown) {
-        apr_status_t rv = get_local_addr(sock);
-
-        if (rv != APR_SUCCESS) {
-            return rv;
+    if (which == APR_LOCAL){
+        if (sock->local_port_unknown || sock->local_interface_unknown) {
+            apr_status_t rv = get_local_addr(sock);
+
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
         }
-    }
-
-    *name = sock->local_addr;
-    return APR_SUCCESS;
-}
-
-
-
-apr_status_t apr_get_remote_name(struct sockaddr_in **name, apr_socket_t
*sock)
-{
-    *name = sock->remote_addr;
+
+        *name = sock->local_addr;
+    } else if (which == APR_REMOTE)
+        *name = sock->remote_addr;
+    else
+        return APR_EINVAL;
     return APR_SUCCESS;
 }
 #endif
+
Index: lib/apr/network_io/unix/sockets.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sockets.c,v
retrieving revision 1.54
diff -u -r1.54 sockets.c
--- lib/apr/network_io/unix/sockets.c 2000/11/02 03:02:49 1.54
+++ lib/apr/network_io/unix/sockets.c 2000/11/12 21:05:06
@@ -54,7 +54,46 @@

 #include "networkio.h"
 #include "apr_portable.h"
+#include "apr_strings.h"

+static void set_socket_vars(apr_socket_t *sock)
+{
+    /* Do we need to worry about local_addr being AF_INET and remote_addr
being AF_INET6???
+     * I've worried about it here, but this could be simplified if we don't
have to
+     * worry about it...
+     * Of course if we do then the sock->addr_len is bogus!
+     */
+    if (sock->local_addr->sa.sin.sin_family == AF_INET){
+        sock->addr_len = sizeof(struct sockaddr_in);
+        sock->local_addr->addr_str_len = 16;
+        sock->local_addr->ipaddr_ptr =
&(sock->local_addr->sa.sin.sin_addr);
+        sock->local_addr->ipaddr_len = sizeof(struct in_addr);
+    }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+        sock->addr_len = sizeof(struct sockaddr_in6);
+        sock->local_addr->addr_str_len = 46;
+        sock->local_addr->ipaddr_ptr =
&(sock->local_addr->sa.sin6.sin6_addr);
+        sock->local_addr->ipaddr_len = sizeof(struct in6_addr);
+    }
+#endif
+
+    if (sock->remote_addr->sa.sin.sin_family == AF_INET){
+        sock->addr_len = sizeof(struct sockaddr_in);
+        sock->remote_addr->addr_str_len = 16;
+        sock->remote_addr->ipaddr_ptr =
&(sock->remote_addr->sa.sin.sin_addr);
+        sock->remote_addr->ipaddr_len = sizeof(struct in_addr);
+    }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+        sock->addr_len = sizeof(struct sockaddr_in6);
+        sock->remote_addr->addr_str_len = 46;
+        sock->remote_addr->ipaddr_ptr =
&(sock->remote_addr->sa.sin6.sin6_addr);
+        sock->remote_addr->ipaddr_len = sizeof(struct in6_addr);
+    }
+#endif
+}
+
 static apr_status_t socket_cleanup(void *sock)
 {
     apr_socket_t *thesocket = sock;
@@ -69,31 +108,35 @@

 apr_status_t apr_create_tcp_socket(apr_socket_t **new, apr_pool_t *cont)
 {
+    int family = AF_INET;
+    int proto = IPPROTO_TCP;
+    int type = SOCK_STREAM;
+
     (*new) = (apr_socket_t *)apr_pcalloc(cont, sizeof(apr_socket_t));

     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
     (*new)->cntxt = cont;
-    (*new)->local_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                         sizeof(struct sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                          sizeof(struct sockaddr_in));
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                         sizeof(apr_sockaddr_t));
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                          sizeof(apr_sockaddr_t));

     if ((*new)->local_addr == NULL || (*new)->remote_addr == NULL) {
         return APR_ENOMEM;
     }

-    (*new)->socketdes = socket(AF_INET ,SOCK_STREAM, IPPROTO_TCP);
-
-    (*new)->local_addr->sin_family = AF_INET;
-    (*new)->remote_addr->sin_family = AF_INET;
+    (*new)->socketdes = socket(family ,type, proto);

-    (*new)->addr_len = sizeof(*(*new)->local_addr);
-
     if ((*new)->socketdes < 0) {
         return errno;
     }
+
+    (*new)->local_addr->sa.sin.sin_family = family;
+    (*new)->remote_addr->sa.sin.sin_family = family;
+    set_socket_vars((*new));
+
     (*new)->timeout = -1;
     apr_register_cleanup((*new)->cntxt, (void *)(*new),
                         socket_cleanup, apr_null_cleanup);
@@ -113,10 +156,10 @@

 apr_status_t apr_bind(apr_socket_t *sock)
 {
-    if (bind(sock->socketdes, (struct sockaddr *)sock->local_addr,
sock->addr_len) == -1)
+    if (bind(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa,
sock->addr_len) == -1)
         return errno;
     else {
-        if (sock->local_addr->sin_port == 0) { /* no need for ntohs() when
comparing w/ 0 */
+        if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for
ntohs() when comparing w/ 0 */
             sock->local_port_unknown = 1; /* kernel got us an ephemeral
port */
         }
         return APR_SUCCESS;
@@ -137,18 +180,22 @@
                             sizeof(apr_socket_t));

     (*new)->cntxt = connection_context;
-    (*new)->local_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                 sizeof(struct sockaddr_in));
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                 sizeof(struct apr_sockaddr_t));
+
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                 sizeof(struct apr_sockaddr_t));
+    (*new)->local_addr->sa.sin.sin_family =
sock->local_addr->sa.sin.sin_family;
+    (*new)->remote_addr->sa.sin.sin_family =
sock->remote_addr->sa.sin.sin_family;
+    set_socket_vars((*new));
+

-    (*new)->remote_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                 sizeof(struct sockaddr_in));
-    (*new)->addr_len = sizeof(struct sockaddr_in);
 #ifndef HAVE_POLL
     (*new)->connected = 1;
 #endif
     (*new)->timeout = -1;

-    (*new)->socketdes = accept(sock->socketdes, (struct sockaddr
*)(*new)->remote_addr,
+    (*new)->socketdes = accept(sock->socketdes, (struct sockaddr
*)&(*new)->remote_addr->sa,
                         &(*new)->addr_len);

     if ((*new)->socketdes < 0) {
@@ -162,16 +209,26 @@
         (*new)->local_port_unknown = 1;
     }

-    if (sock->local_interface_unknown ||
-        sock->local_addr->sin_addr.s_addr == 0) {
-        /* If the interface address inside the listening socket's
local_addr wasn't
-         * up-to-date, we don't know local interface of the connected
socket either.
-         *
-         * If the listening socket was not bound to a specific interface,
we
-         * don't know the local_addr of the connected socket.
-         */
-        (*new)->local_interface_unknown = 1;
+    if (sock->local_addr->sa.sin.sin_family == AF_INET){
+        if (sock->local_interface_unknown ||
+            sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
+            /* If the interface address inside the listening socket's
local_addr wasn't
+             * up-to-date, we don't know local interface of the connected
socket either.
+             *
+             * If the listening socket was not bound to a specific
interface, we
+             * don't know the local_addr of the connected socket.
+             */
+            (*new)->local_interface_unknown = 1;
+        }
     }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+        if (sock->local_interface_unknown ||
+            IN6_IS_ADDR_UNSPECIFIED((struct
in6_addr*)sock->local_addr->ipaddr_ptr)){
+            (*new)->local_interface_unknown = 1;
+        }
+    }
+#endif

     apr_register_cleanup((*new)->cntxt, (void *)(*new),
                         socket_cleanup, apr_null_cleanup);
@@ -180,53 +237,43 @@

 apr_status_t apr_connect(apr_socket_t *sock, const char *hostname)
 {
-    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->sin_addr.s_addr = inet_addr(hostname);
-            sock->addr_len = sizeof(*sock->remote_addr);
-        }
-        else {
-#endif
-        hp = gethostbyname(hostname);

-        if (!hp)  {
-            return (h_errno + APR_OS_START_SYSERR);
-        }
-
-        memcpy((char *)&sock->remote_addr->sin_addr, hp->h_addr_list[0],
-               hp->h_length);
-
-        sock->addr_len = sizeof(*sock->remote_addr);
-#ifndef GETHOSTBYNAME_HANDLES_NAS
-        }
-#endif
+    if (hostname != NULL) {
+        apr_status_t rv;
+        if ((rv = apr_gethostbyname(sock, APR_REMOTE, hostname)) !=
APR_SUCCESS)
+            return rv;
     }

-    if ((connect(sock->socketdes, (const struct sockaddr
*)sock->remote_addr,
+    if ((connect(sock->socketdes, (const struct sockaddr
*)&sock->remote_addr->sa,
         sock->addr_len) < 0) && (errno != EINPROGRESS)) {
         return errno;
     }
     else {
-        if (sock->local_addr->sin_port == 0) {
+        if (sock->local_addr->sa.sin.sin_port == 0) {
             /* connect() got us an ephemeral port */
             sock->local_port_unknown = 1;
         }
-        if (sock->local_addr->sin_addr.s_addr == 0) {
-            /* not bound to specific local interface; connect() had to
assign
-             * one for the socket
-             */
-            sock->local_interface_unknown = 1;
+        if (sock->local_addr->sa.sin.sin_family == AF_INET){
+            if (sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
+                sock->local_interface_unknown = 1;
+            }
         }
+#if APR_HAVE_IPV6
+        else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+            if (IN6_IS_ADDR_UNSPECIFIED((struct
in6_addr*)sock->local_addr->ipaddr_ptr)){
+                sock->local_interface_unknown = 1;
+            }
+        }
+#endif
+
 #ifndef HAVE_POLL
  sock->connected=1;
 #endif
+
+        sock->remote_addr->hostname = apr_pstrdup(sock->cntxt, hostname);
         return APR_SUCCESS;
     }
 }
@@ -254,16 +301,22 @@
     if ((*sock) == NULL) {
         (*sock) = (apr_socket_t *)apr_pcalloc(cont, sizeof(apr_socket_t));
         (*sock)->cntxt = cont;
-        (*sock)->local_addr = (struct sockaddr_in
*)apr_pcalloc((*sock)->cntxt,
-                             sizeof(struct sockaddr_in));
-        (*sock)->remote_addr = (struct sockaddr_in
*)apr_pcalloc((*sock)->cntxt,
-                              sizeof(struct sockaddr_in));
+        (*sock)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*sock)->cntxt,
+                             sizeof(struct apr_sockaddr_t));
+        (*sock)->remote_addr = (apr_sockaddr_t
*)apr_pcalloc((*sock)->cntxt,
+                              sizeof(struct apr_sockaddr_t));

         if ((*sock)->local_addr == NULL || (*sock)->remote_addr == NULL) {
             return APR_ENOMEM;
         }

-        (*sock)->addr_len = sizeof(*(*sock)->local_addr);
+        /* XXX - This is very bogus!
+         * we need to check what family socket we get...
+         */
+        (*sock)->local_addr->sa.sin.sin_family = AF_INET;
+        (*sock)->remote_addr->sa.sin.sin_family = AF_INET;
+        set_socket_vars((*sock));
+
         (*sock)->timeout = -1;
     }
     (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
Index: lib/apr/network_io/unix/sockopt.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sockopt.c,v
retrieving revision 1.36
diff -u -r1.36 sockopt.c
--- lib/apr/network_io/unix/sockopt.c 2000/11/10 16:11:13 1.36
+++ lib/apr/network_io/unix/sockopt.c 2000/11/12 21:05:06
@@ -205,26 +205,42 @@
 apr_status_t apr_get_hostname(char **name, apr_interface_e which,
apr_socket_t *sock)
 {
     struct hostent *hptr;
-    apr_in_addr_t sa_ptr;
+    apr_in_addr_t *sa_ptr = NULL;
+    int errnum;
+    int family = AF_INET;
+    int iplen;

-    if (which == APR_LOCAL)
-        sa_ptr = sock->local_addr->sin_addr;
-    else if (which == APR_REMOTE)
-        sa_ptr = sock->remote_addr->sin_addr;
-    else
+    if (which == APR_LOCAL){
+        sa_ptr = sock->local_addr->ipaddr_ptr;
+        family = sock->local_addr->sa.sin.sin_family;
+        iplen = sock->local_addr->ipaddr_len;
+    } else if (which == APR_REMOTE){
+        sa_ptr = sock->remote_addr->ipaddr_ptr;
+        family = sock->remote_addr->sa.sin.sin_family;
+        iplen = sock->remote_addr->ipaddr_len;
+    }else
         return APR_EINVAL;

-    hptr = gethostbyaddr((char *)&sa_ptr, sizeof(struct in_addr), AF_INET);
+    /* getipnodebyaddr is threadsafe and works with IPv6 so use it if we
can */
+#if HAVE_GETIPNODEBYADDR
+    hptr = getipnodebyaddr(sa_ptr, iplen, family, &errnum);
+#else
+    hptr = gethostbyaddr((char *)sa_ptr, sock->addr_len, AF_INET);
+    errnum = h_errno;
+#endif

     if (hptr != NULL) {
         *name = apr_pstrdup(sock->cntxt, hptr->h_name);
+#if HAVE_GETIPNODEBYADDR
+        freehostent(hptr);
+#endif
+
         if (*name) {
             return APR_SUCCESS;
         }
         return APR_ENOMEM;
     }

-    /* XXX - Is referencing h_errno threadsafe? */
-    return (h_errno + APR_OS_START_SYSERR);
+    return (errnum + APR_OS_START_SYSERR);
 }

Index: lib/apr/network_io/win32/sockaddr.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sockaddr.c,v
retrieving revision 1.18
diff -u -r1.18 sockaddr.c
--- lib/apr/network_io/win32/sockaddr.c 2000/11/11 06:05:59 1.18
+++ lib/apr/network_io/win32/sockaddr.c 2000/11/12 21:05:07
@@ -74,24 +74,23 @@

 /* Include this here so we have get_local_addr defined... */
 #include "../unix/sa_common.c"
-
 apr_status_t apr_set_ipaddr(apr_socket_t *sock, apr_interface_e which,
const char *addr)
 {
     u_long ipaddr;
-    struct sockaddr_in *ptr;
+    struct sockaddr_in* sa_ptr;

     if (which == APR_LOCAL)
-        ptr = sock->local_addr;
+        sa_ptr = sock->local_addr->ipaddr_ptr;
     else if (which == APR_REMOTE)
-        ptr = sock->remote_addr;
+        sa_ptr = sock->remote_addr->ipaddr_ptr;
     else
         return APR_EINVAL;
-
+
     if (!strcmp(addr, APR_ANYADDR)) {
-        ptr->sin_addr.s_addr = htonl(INADDR_ANY);
+        sa_ptr->sin_addr.s_addr = htonl(INADDR_ANY);
         return APR_SUCCESS;
     }
-
+
     ipaddr = inet_addr(addr);

     if (ipaddr == APR_INADDR_NONE) {
@@ -102,24 +101,23 @@
     return APR_SUCCESS;
 }

-apr_status_t apr_get_local_name(struct sockaddr_in **name, apr_socket_t
*sock)
+apr_status_t apr_get_name(apr_sockaddr_t **name, apr_interface_e which,
+                           apr_socket_t *sock)
 {
-    if (sock->local_port_unknown || sock->local_interface_unknown) {
-        apr_status_t rv = get_local_addr(sock);
-
-        if (rv != APR_SUCCESS) {
-            return rv;
+    if (which == APR_LOCAL){
+        if (sock->local_port_unknown || sock->local_interface_unknown) {
+            apr_status_t rv = get_local_addr(sock);
+
+            if (rv != APR_SUCCESS) {
+                return rv;
+            }
         }
-    }

-    *name = sock->local_addr;
+        *name = sock->local_addr;
+    } else if (which == APR_REMOTE)
+        *name = sock->remote_addr;
+    else
+        return APR_EINVAL;
     return APR_SUCCESS;
 }

-
-
-apr_status_t apr_get_remote_name(struct sockaddr_in **name, apr_socket_t
*sock)
-{
-    *name = sock->remote_addr;
-    return APR_SUCCESS;
-}
Index: lib/apr/network_io/win32/sockets.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sockets.c,v
retrieving revision 1.39
diff -u -r1.39 sockets.c
--- lib/apr/network_io/win32/sockets.c 2000/11/02 03:02:50 1.39
+++ lib/apr/network_io/win32/sockets.c 2000/11/12 21:05:07
@@ -59,6 +59,43 @@
 #include "apr_portable.h"
 #include <string.h>

+static void set_socket_vars(apr_socket_t *sock)
+{
+    /* Do we need to worry about local_addr being AF_INET and remote_addr
being AF_INET6???
+     * I've worried about it here, but this could be simplified if we don't
have to
+     * worry about it...
+     * Of course if we do then the sock->addr_len is bogus!
+     */
+    if (sock->local_addr->sa.sin.sin_family == AF_INET){
+        sock->addr_len = sizeof(struct sockaddr_in);
+        sock->local_addr->addr_str_len = 16;
+        sock->local_addr->ipaddr_ptr =
&(sock->local_addr->sa.sin.sin_addr);
+        sock->local_addr->ipaddr_len = sizeof(struct in_addr);
+    }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+        sock->addr_len = sizeof(struct sockaddr_in6);
+        sock->local_addr->addr_str_len = 46;
+        sock->local_addr->ipaddr_ptr =
&(sock->local_addr->sa.sin6.sin6_addr);
+        sock->local_addr->ipaddr_len = sizeof(struct in6_addr);
+    }
+#endif
+
+    if (sock->remote_addr->sa.sin.sin_family == AF_INET){
+        sock->addr_len = sizeof(struct sockaddr_in);
+        sock->remote_addr->addr_str_len = 16;
+        sock->remote_addr->ipaddr_ptr =
&(sock->remote_addr->sa.sin.sin_addr);
+        sock->remote_addr->ipaddr_len = sizeof(struct in_addr);
+    }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+        sock->addr_len = sizeof(struct sockaddr_in6);
+        sock->remote_addr->addr_str_len = 46;
+        sock->remote_addr->ipaddr_ptr =
&(sock->remote_addr->sa.sin6.sin6_addr);
+        sock->remote_addr->ipaddr_len = sizeof(struct in6_addr);
+    }
+#endif
+}

 static apr_status_t socket_cleanup(void *sock)
 {
@@ -81,10 +118,10 @@
         return APR_ENOMEM;
     }
     (*new)->cntxt = cont;
-    (*new)->local_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                                                          sizeof(struct
sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                          sizeof(struct sockaddr_in));
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                         sizeof(apr_sockaddr_t));
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                          sizeof(apr_sockaddr_t));

     if (((*new)->local_addr == NULL) || ((*new)->remote_addr == NULL)) {
         return APR_ENOMEM;
@@ -97,13 +134,12 @@
         return apr_get_netos_error();
     }

-    (*new)->local_addr->sin_family = AF_INET;
-    (*new)->remote_addr->sin_family = AF_INET;
+    (*new)->local_addr->sa.sin.sin_family = family;
+    (*new)->remote_addr->sa.sin.sin_family = family;
+    set_socket_vars((*new));

-    (*new)->addr_len = sizeof(*(*new)->local_addr);
+    (*new)->local_addr->sa.sin.sin_port = 0;

-    (*new)->local_addr->sin_port = 0;
-
     (*new)->timeout = -1;
     (*new)->disconnected = 0;

@@ -147,11 +183,11 @@

 apr_status_t apr_bind(apr_socket_t *sock)
 {
-    if (bind(sock->sock, (struct sockaddr *)sock->local_addr,
sock->addr_len) == -1) {
+    if (bind(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa,
sock->addr_len) == -1)
         return apr_get_netos_error();
     }
     else {
-        if (sock->local_addr->sin_port == 0) {
+        if (sock->local_addr->sa.sin.sin_port == 0)

             sock->local_port_unknown = 1; /* ephemeral port */
         }
         return APR_SUCCESS;
@@ -172,17 +208,21 @@
                             sizeof(apr_socket_t));

     (*new)->cntxt = connection_context;
-    (*new)->local_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                 sizeof(struct sockaddr_in));
-    (*new)->remote_addr = (struct sockaddr_in *)apr_pcalloc((*new)->cntxt,
-                 sizeof(struct sockaddr_in));
-    memcpy((*new)->local_addr, sock->local_addr, sizeof(struct
sockaddr_in));
+    (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                 sizeof(struct apr_sockaddr_t));
+
+    (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
+                 sizeof(struct apr_sockaddr_t));
+    (*new)->local_addr->sa.sin.sin_family =
sock->local_addr->sa.sin.sin_family;
+    (*new)->remote_addr->sa.sin.sin_family =
sock->remote_addr->sa.sin.sin_family;
+    set_socket_vars((*new));

-    (*new)->addr_len = sizeof(struct sockaddr_in);
+    memcpy((*new)->local_addr, sock->local_addr, sizeof(struct
apr_sockaddr_t));
+
     (*new)->timeout = -1;
     (*new)->disconnected = 0;

-    (*new)->sock = accept(sock->sock, (struct sockaddr
*)(*new)->local_addr,
+    (*new)->socketdes = accept(sock->socketdes, (struct sockaddr
*)&(*new)->remote_addr->sa,
                         &(*new)->addr_len);

     if ((*new)->sock == INVALID_SOCKET) {
@@ -196,16 +236,20 @@
         (*new)->local_port_unknown = 1;
     }

-    if (sock->local_interface_unknown ||
-        sock->local_addr->sin_addr.s_addr == 0) {
-        /* If the interface address inside the listening socket's
local_addr wasn't
-         * up-to-date, we don't know local interface of the connected
socket either.
-         *
-         * If the listening socket was not bound to a specific interface,
we
-         * don't know the local_addr of the connected socket.
-         */
-        (*new)->local_interface_unknown = 1;
+    if (sock->local_addr->sa.sin.sin_family == AF_INET){
+        if (sock->local_interface_unknown ||
+            sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
+            (*new)->local_interface_unknown = 1;
+        }
+    }
+#if APR_HAVE_IPV6
+    else if (sock->local_addr->sa.sin.sin_family == AF_INET6){
+        if (sock->local_interface_unknown ||
+            IN6_IS_ADDR_UNSPECIFIED((struct
in6_addr*)sock->local_addr->ipaddr_ptr)){
+            (*new)->local_interface_unknown = 1;
+        }
     }
+#endif

     apr_register_cleanup((*new)->cntxt, (void *)(*new),
                         socket_cleanup, apr_null_cleanup);
@@ -223,23 +267,14 @@
     }

     if (hostname != NULL) {
-        if (*hostname >= '0' && *hostname <= '9' &&
-            strspn(hostname, "0123456789.") == strlen(hostname)) {
-            sock->remote_addr->sin_addr.s_addr = inet_addr(hostname);
-        }
-        else {
-            hp = gethostbyname(hostname);
-            if (!hp)  {
-                return apr_get_netos_error();
-            }
-            memcpy((char *)&sock->remote_addr->sin_addr,
hp->h_addr_list[0], hp->h_length);
-            sock->addr_len = sizeof(*sock->remote_addr);
-        }
+        apr_status_t rv;
+        if ((rv = apr_gethostbyname(sock, APR_REMOTE, hostname)) !=
APR_SUCCESS)
+            return rv;
     }
-
+
     sock->remote_addr->sin_family = AF_INET;

-    if (connect(sock->sock, (const struct sockaddr *)sock->remote_addr,
+    if ((connect(sock->socketdes, (const struct sockaddr
*)&sock->remote_addr->sa,
                 sock->addr_len) == SOCKET_ERROR) {
         lasterror = apr_get_netos_error();
         if (lasterror != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
@@ -260,6 +295,7 @@
         /* must be using free-range port */
         sock->local_interface_unknown = 1;
     }
+    sock->remote_addr->hostname = apr_pstrdup(sock->cntxt, hostname);
     return APR_SUCCESS;
 }

@@ -289,16 +325,21 @@
     if ((*sock) == NULL) {
         (*sock) = (apr_socket_t *)apr_pcalloc(cont, sizeof(apr_socket_t));
         (*sock)->cntxt = cont;
-        (*sock)->local_addr = (struct sockaddr_in
*)apr_pcalloc((*sock)->cntxt,
-                             sizeof(struct sockaddr_in));
-        (*sock)->remote_addr = (struct sockaddr_in
*)apr_pcalloc((*sock)->cntxt,
-                              sizeof(struct sockaddr_in));
+        (*sock)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*sock)->cntxt,
+                             sizeof(struct apr_sockaddr_t));
+        (*sock)->remote_addr = (apr_sockaddr_t
*)apr_pcalloc((*sock)->cntxt,
+                              sizeof(struct apr_sockaddr_t));

         if ((*sock)->local_addr == NULL || (*sock)->remote_addr == NULL) {
             return APR_ENOMEM;
         }
-
-        (*sock)->addr_len = sizeof(*(*sock)->local_addr);
+        /* XXX - This is very bogus!
+         * we need to check what family socket we get...
+         */
+        (*sock)->local_addr->sa.sin.sin_family = AF_INET;
+        (*sock)->remote_addr->sa.sin.sin_family = AF_INET;
+        set_socket_vars((*sock));
+
         (*sock)->timeout = -1;
         (*sock)->disconnected = 0;
     }
Index: lib/apr/network_io/win32/sockopt.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sockopt.c,v
retrieving revision 1.28
diff -u -r1.28 sockopt.c
--- lib/apr/network_io/win32/sockopt.c 2000/11/10 20:17:24 1.28
+++ lib/apr/network_io/win32/sockopt.c 2000/11/12 21:05:08
@@ -204,19 +204,35 @@
 apr_status_t apr_get_hostname(char **name, apr_interface_e which,
apr_socket_t *sock)
 {
     struct hostent *hptr;
-    apr_in_addr_t sa_ptr;
+    apr_in_addr_t *sa_ptr = NULL;
+    int errnum;
+    int family = AF_INET;
+    int iplen;

-    if (which == APR_LOCAL)
-        sa_ptr = sock->local_addr->sin_addr;
-    else if (which == APR_REMOTE)
-        sa_ptr = sock->remote_addr->sin_addr;
-    else
+    if (which == APR_LOCAL){
+        sa_ptr = sock->local_addr->ipaddr_ptr;
+        family = sock->local_addr->sa.sin.sin_family;
+        iplen = sock->local_addr->ipaddr_len;
+    } else if (which == APR_REMOTE){
+        sa_ptr = sock->remote_addr->ipaddr_ptr;
+        family = sock->remote_addr->sa.sin.sin_family;
+        iplen = sock->remote_addr->ipaddr_len;
+    }else
         return APR_EINVAL;

-    hptr = gethostbyaddr((char *)&sa_ptr, sizeof(struct in_addr), AF_INET);
+    /* getipnodebyaddr is threadsafe and works with IPv6 so use it if we
can */
+#if HAVE_GETIPNODEBYADDR
+    hptr = getipnodebyaddr(sa_ptr, iplen, family, &errnum);
+#else
+    hptr = gethostbyaddr((char *)sa_ptr, sock->addr_len, AF_INET);
+    errnum = h_errno;
+#endif

     if (hptr != NULL) {
         *name = apr_pstrdup(sock->cntxt, hptr->h_name);
+#if HAVE_GETIPNODEBYADDR
+        freehostent(hptr);
+#endif
         if (*name) {
             return APR_SUCCESS;
         }
Index: lib/apr/test/client.c
===================================================================
RCS file: /home/cvs/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/12 21:05:08
@@ -142,6 +142,12 @@
     apr_get_port(&local_port, APR_LOCAL, sock);
     fprintf(stdout, "\tClient socket: %s:%u -> %s:%u\n", local_ipaddr,
local_port, remote_ipaddr, remote_port);

+    fprintf(stdout, "\tClient:  Doing reverse lookup.................");
+    if (apr_check_reverse_lookup(sock) != APR_SUCCESS)
+        fprintf(stdout,"Failed!!!\n");
+    else
+        fprintf(stdout,"OK\n");
+
     fprintf(stdout, "\tClient:  Trying to send data over socket.......");
     length = STRLEN;
     if (apr_send(sock, datasend, &length) != APR_SUCCESS) {
Index: lib/apr/test/server.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/test/server.c,v
retrieving revision 1.16
diff -u -r1.16 server.c
--- lib/apr/test/server.c 2000/11/09 15:01:35 1.16
+++ lib/apr/test/server.c 2000/11/12 21:05:09
@@ -193,7 +193,7 @@
     }
     fprintf(stdout, "OK\n");

-    fprintf(stdout, "\tServer:  Shutting down accepte socket.......");
+    fprintf(stdout, "\tServer:  Shutting down accepted socket.......");
     if (apr_shutdown(sock2, APR_SHUTDOWN_READ) != APR_SUCCESS) {
         apr_close_socket(sock);
         apr_close_socket(sock2);
Index: main/http_config.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_config.c,v
retrieving revision 1.84
diff -u -r1.84 http_config.c
--- main/http_config.c 2000/11/02 20:05:00 1.84
+++ main/http_config.c 2000/11/12 21:05:13
@@ -1645,7 +1645,7 @@
     s->next = NULL;
     s->addrs = apr_pcalloc(p, sizeof(server_addr_rec));
     /* NOT virtual host; don't match any real network interface */
-    s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
+    apr_get_inaddr(&s->addrs->host_addr, "*", p);
     s->addrs->host_port = 0; /* matches any port */
     s->addrs->virthost = ""; /* must be non-NULL */
     s->names = s->wild_names = NULL;
Index: main/http_connection.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_connection.c,v
retrieving revision 1.61
diff -u -r1.61 http_connection.c
--- main/http_connection.c 2000/11/09 15:09:50 1.61
+++ main/http_connection.c 2000/11/12 21:05:14
@@ -283,12 +283,16 @@
     conn->notes = apr_make_table(p, 5);

     conn->pool = p;
+/*
     conn->local_addr = *saddr;
+*/
     apr_get_ipaddr(&conn->local_ip, APR_LOCAL, inout);
     conn->base_server = server;
     conn->client_socket = inout;

+/*
     conn->remote_addr = *remaddr;
+*/
     apr_get_ipaddr(&conn->remote_ip, APR_REMOTE, inout);
     conn->id = id;

@@ -300,9 +304,13 @@
 conn_rec *ap_new_apr_connection(apr_pool_t *p, server_rec *server,
                                 apr_socket_t *conn_socket, long id)
 {
+
     struct sockaddr_in *sa_local, *sa_remote;
+

-    apr_get_local_name(&sa_local, conn_socket);
-    apr_get_remote_name(&sa_remote, conn_socket);
+/* XXX - Do we still need this???
+    apr_get_name(&sa_local, APR_LOCAL, conn_socket);
+    apr_get_name(&sa_remote, APR_REMOTE, conn_socket);
+*/
     return ap_new_connection(p, server, conn_socket, sa_remote, sa_local,
id);
 }
Index: main/http_core.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_core.c,v
retrieving revision 1.213
diff -u -r1.213 http_core.c
--- main/http_core.c 2000/11/10 16:11:13 1.213
+++ main/http_core.c 2000/11/12 21:05:21
@@ -578,11 +578,12 @@
     return conf->response_code_strings[error_index];
 }

-
+/* This code has now moved to APR, but it's here just in case :) */
 /* Code from Harald Hanche-Olsen <ha...@imf.unit.no> */
 static apr_inline void do_double_reverse (conn_rec *conn)
 {
     struct hostent *hptr;
+    apr_in_addr_t *ia = NULL;

     if (conn->double_reverse) {
  /* already done */
@@ -593,13 +594,16 @@
  conn->double_reverse = -1;
  return;
     }
+    /* XXX - This needs fixing for IPv6... APR?? */
     hptr = gethostbyname(conn->remote_host);
     if (hptr)

  char **haddr;
+        apr_uint32_t ipaddr;

  for (haddr = hptr->h_addr_list; *haddr; haddr++) {
-     if (((struct in_addr *)(*haddr))->s_addr
-  == conn->remote_addr.sin_addr.s_addr) {
+            apr_get_socket_inaddr(&ia, APR_REMOTE, conn->client_socket);
+     apr_get_v4_address(&ipaddr, ia);
+            if (((struct in_addr *)(*haddr))->s_addr == ipaddr){
   conn->double_reverse = 1;
   return;
      }
@@ -636,9 +640,11 @@
      ap_str_tolower(conn->remote_host);

      if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
-  do_double_reverse(conn);
-  if (conn->double_reverse != 1) {
-      conn->remote_host = NULL;
+  if (apr_check_reverse_lookup(conn->client_socket) != APR_SUCCESS){
+                    conn->double_reverse = -1;
+                    conn->remote_host = NULL;
+  } else {
+                    conn->double_reverse = 1;
   }
      }
  }
@@ -648,10 +654,12 @@
  }
     }
     if (type == REMOTE_DOUBLE_REV) {
- do_double_reverse(conn);
- if (conn->double_reverse == -1) {
+ if(apr_check_reverse_lookup(conn->client_socket) != APR_SUCCESS){
+     conn->double_reverse = -1;
      return NULL;
- }
+ } else {
+            conn->double_reverse = 1;
+        }
     }

 /*
Index: main/http_vhost.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_vhost.c,v
retrieving revision 1.38
diff -u -r1.38 http_vhost.c
--- main/http_vhost.c 2000/11/10 16:11:14 1.38
+++ main/http_vhost.c 2000/11/12 21:05:23
@@ -186,7 +186,7 @@
 static const char *get_addresses(apr_pool_t *p, const char *w_,
      server_addr_rec ***paddr, apr_port_t port)
 {
-    apr_in_addr_t my_addr;
+    apr_in_addr_t *my_addr = NULL;
     server_addr_rec *sar;
     char *t;
     int i;
@@ -210,15 +210,10 @@
  *t = 0;
     }

-    if (strcasecmp(w, "_default_") == 0
-        || strcmp(w, "255.255.255.255") == 0) {
-        my_addr.s_addr = DEFAULT_VHOST_ADDR;
-    } else {
-        if (apr_get_inaddr(&my_addr, w) != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL,
-                "Cannot resolve host name %s --- ignoring!", w);
-            return NULL;
-        }
+    if (apr_get_inaddr(&my_addr, w, p) != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL,
+            "Cannot resolve host name %s --- ignoring!", w);
+        return NULL;
     }

     sar = apr_pcalloc(p, sizeof(server_addr_rec));
@@ -372,11 +367,11 @@
     unsigned addr;

     /* scan the hash apr_table_t for an exact match first */
-    addr = server_ip->s_addr;
+    apr_get_v4_address(&addr, server_ip);
     bucket = hash_inaddr(addr);
     for (trav = iphash_table[bucket]; trav; trav = trav->next) {
  server_addr_rec *sar = trav->sar;
- if ((sar->host_addr.s_addr == addr)
+ if (apr_inaddr_compare(sar->host_addr, server_ip) == 0
      && (sar->host_port == 0 || sar->host_port == port
   || port == 0)) {
      return trav;
@@ -406,18 +401,20 @@
     name_chain *nc;
     int len;
     char buf[MAX_STRING_LEN];
-
-    if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) {
+    apr_uint32_t addr;
+    apr_get_v4_address(&addr, ic->sar->host_addr);
+
+    if (addr == DEFAULT_VHOST_ADDR) {
  len = apr_snprintf(buf, sizeof(buf), "_default_:%u",
   ic->sar->host_port);
     }
-    else if (ic->sar->host_addr.s_addr == INADDR_ANY) {
+    else if (addr == INADDR_ANY) {
  len = apr_snprintf(buf, sizeof(buf), "*:%u",
   ic->sar->host_port);
     }
     else {
  len = apr_snprintf(buf, sizeof(buf), "%pA:%u",
-  &ic->sar->host_addr, ic->sar->host_port);
+  ic->sar->host_addr, ic->sar->host_port);
     }
     if (ic->sar->host_port == 0) {
  buf[len-1] = '*';
@@ -546,10 +543,14 @@
      * occured in the config file, we'll copy it in that order.
      */
     for (sar = name_vhost_list; sar; sar = sar->next) {
- unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
- ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
+ apr_uint32_t addr;
+        unsigned bucket;
+        ipaddr_chain *ic;
+        apr_get_v4_address(&addr, sar->host_addr);
+        bucket = hash_inaddr(addr);
+ ic = new_ipaddr_chain(p, NULL, sar);

- if (sar->host_addr.s_addr != INADDR_ANY) {
+ if (addr != INADDR_ANY) {
      *iphash_table_tail[bucket] = ic;
      iphash_table_tail[bucket] = &ic->next;
  }
@@ -576,9 +577,10 @@
  has_default_vhost_addr = 0;
  for (sar = s->addrs; sar; sar = sar->next) {
      ipaddr_chain *ic;
-
-     if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
-  || sar->host_addr.s_addr == INADDR_ANY) {
+            apr_uint32_t addr;
+            apr_get_v4_address(&addr, sar->host_addr);
+     if (addr == DEFAULT_VHOST_ADDR
+  || addr == INADDR_ANY) {
   ic = find_default_server(sar->host_port);
   if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
       if (ic && ic->sar->host_port != 0) {
@@ -594,10 +596,10 @@
      }
      else {
   /* see if it matches something we've already got */
-  ic = find_ipaddr(&sar->host_addr, sar->host_port);
+  ic = find_ipaddr(sar->host_addr, sar->host_port);

   if (!ic) {
-      unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
+      unsigned bucket = hash_inaddr(addr);

       ic = new_ipaddr_chain(p, s, sar);
       ic->next = *iphash_table_tail[bucket];
@@ -640,13 +642,14 @@
       s->server_hostname = apr_pstrdup(p, (char *) h->h_name);
   }
   else {
+                    char *sname;
+                    apr_inet_ntop(&sname, s->addrs->host_addr, p);
       /* again, what can we do?  They didn't specify a
          ServerName, and their DNS isn't working. -djg */
       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
        "Failed to resolve server name "
        "for %s (check DNS) -- or specify an explicit "
-       "ServerName",
-       inet_ntoa(s->addrs->host_addr));
+       "ServerName", sname);
       s->server_hostname =
    apr_pstrdup(p, "bogus_host_without_reverse_dns");
   }
@@ -962,10 +965,12 @@
 {
     ipaddr_chain *trav;
     apr_port_t port;
+    apr_in_addr_t *ia = NULL;
     apr_get_port(&port, APR_LOCAL, conn->client_socket);
+    apr_get_socket_inaddr(&ia, APR_LOCAL, conn->client_socket);

     /* scan the hash apr_table_t for an exact match first */
-    trav = find_ipaddr(&conn->local_addr.sin_addr, port);
+    trav = find_ipaddr(ia, port);
     if (trav) {
  /* save the name_chain for later in case this is a name-vhost */
  conn->vhost_lookup_data = trav->names;
Index: modules/standard/mod_access.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_access.c,v
retrieving revision 1.21
diff -u -r1.21 mod_access.c
--- modules/standard/mod_access.c 2000/11/11 06:06:00 1.21
+++ modules/standard/mod_access.c 2000/11/12 21:05:24
@@ -318,6 +318,8 @@
     int i;
     int gothost = 0;
     const char *remotehost = NULL;
+    apr_in_addr_t *ia;
+    apr_uint32_t ipaddr;

     for (i = 0; i < a->nelts; ++i) {
  if (!(mmask & ap[i].limited))
@@ -334,8 +336,10 @@
      return 1;

  case T_IP:
-     if (ap[i].x.ip.net != APR_INADDR_NONE
-  && (r->connection->remote_addr.sin_addr.s_addr
+            apr_get_socket_inaddr(&ia, APR_REMOTE,
r->connection->client_socket);
+     apr_get_v4_address(&ipaddr, ia);
+            if (ap[i].x.ip.net != APR_INADDR_NONE
+  && (ipaddr
       & ap[i].x.ip.mask) == ap[i].x.ip.net) {
   return 1;
      }





Re: [PATCH] apr_sockaddr_t & friends

Posted by Jeff Trawick <tr...@bellsouth.net>.
"David Reid" <dr...@jetnet.co.uk> writes:

> /**
>  * Get the character network address of the IP address contained in the
> apr_sockaddr_t.
>  * @param addr The pointer to the returned string.
>  * @param sa The apr_sockaddr_t structure to use...
>  * @param p The apr_pool_t to use for memory allocations.
>  */
> apr_status_t apr_get_nas(char **addr, apr_sockaddr_t *sa, apr_pool_t *p);

We may or may not want a pool parameter here, depending on how it
should work.  If we want it to cache the numeric address string so
that apps don't need a separate field, the function would be something
like this:

  if (!sa->addr_str) {     /* gotta add this field to apr_sockaddr_t */
      sa->addr_str = apr_palloc(sa->pool, sa->addr_str_len);
      apr_inet_ntop(sa->sin.sin_family, sa->ipaddr_ptr,
                    sa->addr_str, sa->addr_str_len);
  }
  *addr = sa->addr_str;

> > I'm not sure what you mean...
> 
> I think that makes two of us.  Can you outline more of your API in detail?

for UDP?  something like this:

  apr_sendto(apr_socket_t *sock, apr_sockaddr_t *sa, apr_size_t *nbytes)
  {
      if (!sa) {
          sa = sock->remote_addr;
      }

      do {
          rc = sendto(sock->fd, &sa->sin, sa->sa_len);
      } while (rc == -1 && errno == EINTR);

      /* handle rc, nbytes, timeout here */
  }

  apr_recvfrom(apr_socket_t *sock, apr_sockaddr_t **newsa, apr_size_t *nbytes)
  {
      apr_sockaddr_t *sa;

      if (!**newsa) {
          use sock->remote_addr;
      }
      else {
          *newsa = apr_palloc(sock->pool, sock->sa_len);
          use new sa;
      }

      do {
          rc = recvfrom(sock->fd, &sa->sin, &sa->sa_len);
      } while (rc == -1 && errno == EINTR);

      /* handle rc, nbytes, timeout here */
  }

more comments on the set of routines in your current patch:

  apr_get_socket_inaddr(), apr_get_v4_address(), apr_inaddr_compare():

    replace these three routines with

      apr_get_ipaddr(apr_sockaddr_t *sa, char **ipaddr, apr_size_t *len,
                     apr_int32_t *family);

      This returns the address of the IP address within the
      sockaddr_in[6] and tells the caller the length and the family.

    I'm not sure we need the apr_in_addr_t data type at this point.

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Re: [PATCH] apr_sockaddr_t & friends

Posted by David Reid <dr...@jetnet.co.uk>.
So as I was up at 4:30am this morning I may not be totally with it, but


/**
 * Return an apr_sockaddr_t from an apr_socket_t
 * @param sa The returned apr_sockaddr_t.
 * @param which Which interface do we wnat the apr_sockaddr_t for?
 * @param sock The socket to use
 */
apr_status_t apr_get_address(apr_sockaddr_t **sa, apr_interface_e which,
apr_socket_t *sock);

/**
 * Get the character network address of the IP address contained in the
apr_sockaddr_t.
 * @param addr The pointer to the returned string.
 * @param sa The apr_sockaddr_t structure to use...
 * @param p The apr_pool_t to use for memory allocations.
 */
apr_status_t apr_get_nas(char **addr, apr_sockaddr_t *sa, apr_pool_t *p);

> I'm not sure what you mean...

I think that makes two of us.  Can you outline more of your API in detail?

> I've got the FreeBSD ones building now and will post them in a few
> minutes...

Cool.

david



Re: [PATCH] apr_sockaddr_t & friends

Posted by Jeff Trawick <tr...@bellsouth.net>.
"David Reid" <dr...@jetnet.co.uk> writes:

> >     apr_get_address() can give us one of the apr_sockaddr_t objects on
> >     a socket
> >
> >       apr_get_address(&local, APR_LOCAL, p);
> >       apr_get_address(&remote, APR_REMOTE, p);
> 
> OK. p is an apr_socket_t I'm guessing?  If so then I'm +1 for this and will
> add it...

you're right, of course..  "p" should be an apr_socket_t... for some
reason I was thinking pool instead of socket...  "p" is wrong :)

> >     apr_getaddrinfo() can do a DNS lookup on the hostname in an
> >     apr_sockaddr_t, filling in the ipaddr field in the apr_sockaddr_t
> >
> 
> Yep, this makes sense as well.
> 
> However, if we have an apr_socket_t with the remote/local apr-sockaddr_t's
> aren't we duplicating a lot of stuff?  I guess there's some step that I'm
> missing here...

I'm not sure what you mean...  

The idea was that to do stuff with the remote socket address
associated with a TCP socket you'd first call apr_get_address() to get
the address of the apr_sockaddr_t, then call other APR functions using
the apr_sockaddr_t.

For TCP the distinction isn't very important, but for UDP it makes a
huge difference since there is no single remote socket address for a UDP
socket.

For TCP or UDP, there is only one local address associated with the
socket but it makes sense to handle local the same way as remote.

> > Recommended first steps IMHO:
> >
> > . ship inet_ntop() and inet_pton() for internal APR use; stop using
> >   inet_ntoa() and inet_aton() (at least inside APR)
> 
> OK.  I guess FreeBSD's will do?  Can I just grab them or what?

I've got the FreeBSD ones building now and will post them in a few
minutes... 

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Re: [PATCH] apr_sockaddr_t & friends

Posted by David Reid <dr...@jetnet.co.uk>.
Jeff,

No worries.  I'd just like to get this lot committed so I can return to a
form of sanity (if that's possible) :)

>
> . I hope we can simplify the set of functions which manipulate some
>   form of the address before we commit it.
>
>   o apr_get_name() doesn't seem to be needed (as you suggest in a
>     comment); zap it
>
>   o apr_socket_inet_pton() is used only inside an APR routine; zap it
>     and call inet_pton() directly; we need to ship inet_pton() and
>     inet_ntop() for internal APR use so that we're thread-safe and we
>     simplify our code a bit
>
>   o Look at this set of routines:
>
>     apr_get_inaddr() - looks up a hostname?
>     apr_get_socket_inaddr() - return local or remote apr_in_addr_t?
>     apr_get_v4_address() - return IPv4 address from apr_in_addr_t?
>     apr_inaddr_compare()
>     apr_inet_ntop() - return numeric address string from apr_in_addr_t?
>     apr_gethostbyname() - do lookup on local or remote address
>     apr_socket_inet_pton() - parse hostname?
>     apr_socket_inet_ntop()
>     apr_get_hostname() - do gethostbyaddr() on one of the sockaddrs
>       for a socket
>
>     I'd rather see the apr_sockaddr_t as the one standard object apps
>     use when dealing with the addresses.  Basing operations on this
>     will make UDP support more natural, because with UDP socket
>     addresses and hostnames have to be independent of the socket since
>     multiple peers are used with a given socket.  We won't want to
>     limit ourselves to operations that use the single remote sockaddr
>     in the apr_socket_t.
>
>     very rough sketch:
>
>     apr_get_address() can give us one of the apr_sockaddr_t objects on
>     a socket
>
>       apr_get_address(&local, APR_LOCAL, p);
>       apr_get_address(&remote, APR_REMOTE, p);

OK. p is an apr_socket_t I'm guessing?  If so then I'm +1 for this and will
add it...

>
>     apr_get_nas() can give us the numeric address string for an
>     apr_sockaddr_t
>
>       apr_get_nas(&nas, local);
>
>       This will call inet_ntop() on the IP address within the local
>       apr_sockaddr_t, store the string in the apr_sockaddr_t in case
>       we're called again, and return the address of the string.

OK.  I can go for this as well :)

>
>     apr_getnameinfo() can do a reverse DNS lookup on the IP address in
>     an apr_sockaddr_t

OK.  This makes sense.

>
>       apr_getnameinfo(&dnsname, remote)
>
>     apr_getaddrinfo() can do a DNS lookup on the hostname in an
>     apr_sockaddr_t, filling in the ipaddr field in the apr_sockaddr_t
>

Yep, this makes sense as well.

However, if we have an apr_socket_t with the remote/local apr-sockaddr_t's
aren't we duplicating a lot of stuff?  I guess there's some step that I'm
missing here...

>
> Recommended first steps IMHO:
>
> . ship inet_ntop() and inet_pton() for internal APR use; stop using
>   inet_ntoa() and inet_aton() (at least inside APR)

OK.  I guess FreeBSD's will do?  Can I just grab them or what?

>
> . look at some of these starts at standardizing/simplifying the API

Yeah well...

david



Re: [PATCH] apr_sockaddr_t & friends

Posted by Jeff Trawick <tr...@bellsouth.net>.
"David Reid" <dr...@jetnet.co.uk> writes:

> Folks,
> 
> I've been having a look at getting the apr_sockaddr_t structures added and
> used throughout APR and the apache code, and in doing so have had to add
> some APR functions and changed a LOT of the networking code...  the
> resulting patch is bigger than I'd intended and touches more files than I'd
> hoped.  The patch follows this text and can be found at
> http://dev.apache.org/~dreid/sa_patch

This is a heck of a lot to swallow :)  Your work is greatly
appreciated! 

Concerns:

. I hope we can simplify the set of functions which manipulate some
  form of the address before we commit it.

  o apr_get_name() doesn't seem to be needed (as you suggest in a
    comment); zap it

  o apr_socket_inet_pton() is used only inside an APR routine; zap it
    and call inet_pton() directly; we need to ship inet_pton() and
    inet_ntop() for internal APR use so that we're thread-safe and we
    simplify our code a bit

  o Look at this set of routines:

    apr_get_inaddr() - looks up a hostname?
    apr_get_socket_inaddr() - return local or remote apr_in_addr_t?
    apr_get_v4_address() - return IPv4 address from apr_in_addr_t?
    apr_inaddr_compare() 
    apr_inet_ntop() - return numeric address string from apr_in_addr_t?
    apr_gethostbyname() - do lookup on local or remote address
    apr_socket_inet_pton() - parse hostname?
    apr_socket_inet_ntop()  
    apr_get_hostname() - do gethostbyaddr() on one of the sockaddrs
      for a socket

    I'd rather see the apr_sockaddr_t as the one standard object apps
    use when dealing with the addresses.  Basing operations on this
    will make UDP support more natural, because with UDP socket
    addresses and hostnames have to be independent of the socket since
    multiple peers are used with a given socket.  We won't want to
    limit ourselves to operations that use the single remote sockaddr
    in the apr_socket_t.

    very rough sketch:

    apr_get_address() can give us one of the apr_sockaddr_t objects on
    a socket

      apr_get_address(&local, APR_LOCAL, p);
      apr_get_address(&remote, APR_REMOTE, p);

    apr_get_nas() can give us the numeric address string for an
    apr_sockaddr_t 

      apr_get_nas(&nas, local);

      This will call inet_ntop() on the IP address within the local
      apr_sockaddr_t, store the string in the apr_sockaddr_t in case
      we're called again, and return the address of the string.

    apr_getnameinfo() can do a reverse DNS lookup on the IP address in
    an apr_sockaddr_t

      apr_getnameinfo(&dnsname, remote)

    apr_getaddrinfo() can do a DNS lookup on the hostname in an
    apr_sockaddr_t, filling in the ipaddr field in the apr_sockaddr_t


Recommended first steps IMHO:

. ship inet_ntop() and inet_pton() for internal APR use; stop using
  inet_ntoa() and inet_aton() (at least inside APR)

. look at some of these starts at standardizing/simplifying the API

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Re: [PATCH] apr_sockaddr_t & friends

Posted by rb...@covalent.net.
> > BTW, should have said that when I make the request on localhost I get an
> > entry in access_log showing it completed OK and nothing in the error_log
> > despite it having failed.  Guess that should be fixed?
> 
> Yep...
> 
> 1.3: 
> 
>   ap_send_fd_length() (called from ap_send_fd()) writes a log message
>   and sets r->connection->aborted
> 
> 2.0:
> 
>   ap_send_fd() does neither of these things

And it shouldn't.  However, someplace down the filter chain they should
happen.  I suspect this should happen in core_output_filter, but I haven't
really thought about it too hard.

Ryan

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [PATCH] apr_sockaddr_t & friends

Posted by Jeff Trawick <tr...@bellsouth.net>.
"David Reid" <dr...@jetnet.co.uk> writes:

> BTW, should have said that when I make the request on localhost I get an
> entry in access_log showing it completed OK and nothing in the error_log
> despite it having failed.  Guess that should be fixed?

Yep...

1.3: 

  ap_send_fd_length() (called from ap_send_fd()) writes a log message
  and sets r->connection->aborted

2.0:

  ap_send_fd() does neither of these things

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Re: [PATCH] apr_sockaddr_t & friends

Posted by David Reid <dr...@jetnet.co.uk>.
BTW, should have said that when I make the request on localhost I get an
entry in access_log showing it completed OK and nothing in the error_log
despite it having failed.  Guess that should be fixed?

david

----- Original Message -----
From: "David Reid" <dr...@jetnet.co.uk>
To: <ne...@apache.org>
Sent: Monday, November 13, 2000 10:39 AM
Subject: Re: [PATCH] apr_sockaddr_t & friends


> When I connect via the localhost sendfile dies as the fd passed in is -1
>   Connecting via a remote host is fine as writev is used and that seems
OK.
>
> I played with testsf and had mixed results, but it normally died.  This is
> what I did/saw.
>
> $ ./testsf server &
> $ Waiting for a client to connect...
> ./testsf client blocking
> Creating a test file...
> Opening file...OK
> Client: trying to connect...
> Processing a client...
> Client is connected!!
> Sending the file...
> apr_sendfile() updated offset with 0
> apr_sendfile() updated len with 370049
> bytes really sent: 370049
> After apr_sendfile(), the kernel file pointer is at offset 0.
> server: apr_sendfile() worked as expected!
> client: apr_sendfile() worked as expected!
> [1] 197 Exit 0                ./testsf server
> $
>
> $ ./testsf server &
> $ Waiting for a client to connect...
> ./testsf client nonblocking
> Creating a test file...
> Opening file...OK
> Client: trying to connect...
> Processing a client...
> Client is connected!!
> Sending the file...
> Calling apr_sendfile()...
> Headers:
>         15 bytes
>         5 bytes
>         80000 bytes
> File: 200000 bytes from offset 0
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 57344 bytes
> Calling apr_sendfile()...
> Headers:
>         22676 bytes
> File: 200000 bytes from offset 0
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 55444 bytes
> Calling apr_sendfile()...
> Headers:
> File: 167232 bytes from offset 32768
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 45056 bytes
> Calling apr_sendfile()...
> Headers:
> File: 122176 bytes from offset 77824
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 40960 bytes
> Calling apr_sendfile()...
> Headers:
> File: 81216 bytes from offset 118784
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 16384 bytes
> Calling apr_sendfile()...
> Headers:
> File: 64832 bytes from offset 135168
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 28672 bytes
> Calling apr_sendfile()...
> Headers:
> File: 36160 bytes from offset 163840
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->35, sent 28672 bytes
> Calling apr_sendfile()...
> Headers:
> File: 7488 bytes from offset 192512
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->0, sent 28672 bytes
> Calling apr_sendfile()...
> Headers:
> File: 0 bytes from offset 0
> Trailers:
>         68845 bytes
> apr_sendfile()->35, sent 134562560 bytes
> client problem: sent 134863764 of 370049 bytes
> client problem: rv 35
> After apr_sendfile(), the kernel file pointer is at offset 0.
> apr_recv()->20514/End of file found
> client: apr_sendfile() worked as expected!
> [1] 199 Exit 1                ./testsf server
>
> So there is a problem reported, but it does say it worked???  I think the
> problem is more with the apache code, but I'm not sure.
>
> david
>
> ----- Original Message -----
> From: "Jeff Trawick" <tr...@bellsouth.net>
> To: <ne...@apache.org>
> Sent: Monday, November 13, 2000 2:10 AM
> Subject: Re: [PATCH] apr_sockaddr_t & friends
>
>
> > "David Reid" <dr...@jetnet.co.uk> writes:
> >
> > > Sendfile seems to be broken on FreeBSD (in a clean checkout it's
broken
> as
> > > well so it's not this patch :)) so I havn't managed to do as much
> checking
> > > as I'd wished to.
> >
> > What is the symptom?  Can you see if testsf shows the problem?
> >
> >   cd lib/apr/test
> >   make testsf
> >   ./testsf server &
> >   ./testsf client blocking
> >
> >   ./testsf server &
> >   ./testsf client nonblocking
> >
> > testsf works fine on FreeBSD 3.4.
> >
> > You should see messages like this at the end:
> >
> >   server: apr_sendfile() worked as expected!
> >   client: apr_sendfile() worked as expected!
> >
> > --
> > Jeff Trawick | trawick@ibm.net | PGP public key at web site:
> >      http://www.geocities.com/SiliconValley/Park/9289/
> >           Born in Roswell... married an alien...
> >
>
>


Re: [PATCH] apr_sockaddr_t & friends

Posted by rb...@covalent.net.
> Jeff, you beat me to it.  :-)
> 
> This is a bug in the default handler.  The easy solution is to remove the
> apr_close from default handler.  The bigger job is to partially re-write
> that code to use buckets.  I was going to do this today unless somebody
> else beats me to it.

I decided to take a short break from writing and fix the bug
immediately.  I'll re-write the handler later today still, but we are
serving static pages again.

Ryan

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [PATCH] apr_sockaddr_t & friends

Posted by rb...@covalent.net.
On 13 Nov 2000, Jeff Trawick wrote:

> "David Reid" <dr...@jetnet.co.uk> writes:
> 
> > When I connect via the localhost sendfile dies as the fd passed in is -1
> >   Connecting via a remote host is fine as writev is used and that
> > seems OK.
> 
> Passing in -1 for the descriptor is certainly nasty!  It sounds like
> the file has been closed through pool cleanup.  Wasn't there a thread
> on new-httpd about that this weekend?

Jeff, you beat me to it.  :-)

This is a bug in the default handler.  The easy solution is to remove the
apr_close from default handler.  The bigger job is to partially re-write
that code to use buckets.  I was going to do this today unless somebody
else beats me to it.

Ryan

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [PATCH] apr_sockaddr_t & friends

Posted by Jeff Trawick <tr...@bellsouth.net>.
"David Reid" <dr...@jetnet.co.uk> writes:

> When I connect via the localhost sendfile dies as the fd passed in is -1
>   Connecting via a remote host is fine as writev is used and that
> seems OK.

Passing in -1 for the descriptor is certainly nasty!  It sounds like
the file has been closed through pool cleanup.  Wasn't there a thread
on new-httpd about that this weekend?

> I played with testsf and had mixed results, but it normally died.  This is
> what I did/saw.
> 
> $ ./testsf server &
> $ Waiting for a client to connect...
> ./testsf client blocking
> Creating a test file...
> Opening file...OK
> Client: trying to connect...
> Processing a client...
> Client is connected!!
> Sending the file...
> apr_sendfile() updated offset with 0
> apr_sendfile() updated len with 370049
> bytes really sent: 370049
> After apr_sendfile(), the kernel file pointer is at offset 0.
> server: apr_sendfile() worked as expected!
> client: apr_sendfile() worked as expected!
> [1] 197 Exit 0                ./testsf server
> $

blocking mode looks fine...

> 
> $ ./testsf server &
> $ Waiting for a client to connect...
> ./testsf client nonblocking
...
> Calling apr_sendfile()...
> Headers:
> File: 7488 bytes from offset 192512
> Trailers:
>         19 bytes
>         10 bytes
>         90000 bytes
> apr_sendfile()->0, sent 28672 bytes
> Calling apr_sendfile()...
> Headers:
> File: 0 bytes from offset 0
> Trailers:
>         68845 bytes
> apr_sendfile()->35, sent 134562560 bytes
> client problem: sent 134863764 of 370049 bytes

Cool!  I found the bug in apr_sendfile() for FreeBSD -- uninitialized
bytes-sent when we do writev() and it fails (EAGAIN in your case).
I'll also update testsf so that it bails out after this problem.

> client problem: rv 35
> After apr_sendfile(), the kernel file pointer is at offset 0.
> apr_recv()->20514/End of file found
> client: apr_sendfile() worked as expected!
> [1] 199 Exit 1                ./testsf server
> 
> So there is a problem reported, but it does say it worked???  I think the
> problem is more with the apache code, but I'm not sure.

There is certainly a problem...  I'll clean up the report so that it
isn't so misleading with such a failure.

Thanks!

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Re: [PATCH] apr_sockaddr_t & friends

Posted by David Reid <dr...@jetnet.co.uk>.
When I connect via the localhost sendfile dies as the fd passed in is -1
  Connecting via a remote host is fine as writev is used and that seems OK.

I played with testsf and had mixed results, but it normally died.  This is
what I did/saw.

$ ./testsf server &
$ Waiting for a client to connect...
./testsf client blocking
Creating a test file...
Opening file...OK
Client: trying to connect...
Processing a client...
Client is connected!!
Sending the file...
apr_sendfile() updated offset with 0
apr_sendfile() updated len with 370049
bytes really sent: 370049
After apr_sendfile(), the kernel file pointer is at offset 0.
server: apr_sendfile() worked as expected!
client: apr_sendfile() worked as expected!
[1] 197 Exit 0                ./testsf server
$

$ ./testsf server &
$ Waiting for a client to connect...
./testsf client nonblocking
Creating a test file...
Opening file...OK
Client: trying to connect...
Processing a client...
Client is connected!!
Sending the file...
Calling apr_sendfile()...
Headers:
        15 bytes
        5 bytes
        80000 bytes
File: 200000 bytes from offset 0
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 57344 bytes
Calling apr_sendfile()...
Headers:
        22676 bytes
File: 200000 bytes from offset 0
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 55444 bytes
Calling apr_sendfile()...
Headers:
File: 167232 bytes from offset 32768
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 45056 bytes
Calling apr_sendfile()...
Headers:
File: 122176 bytes from offset 77824
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 40960 bytes
Calling apr_sendfile()...
Headers:
File: 81216 bytes from offset 118784
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 16384 bytes
Calling apr_sendfile()...
Headers:
File: 64832 bytes from offset 135168
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 28672 bytes
Calling apr_sendfile()...
Headers:
File: 36160 bytes from offset 163840
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->35, sent 28672 bytes
Calling apr_sendfile()...
Headers:
File: 7488 bytes from offset 192512
Trailers:
        19 bytes
        10 bytes
        90000 bytes
apr_sendfile()->0, sent 28672 bytes
Calling apr_sendfile()...
Headers:
File: 0 bytes from offset 0
Trailers:
        68845 bytes
apr_sendfile()->35, sent 134562560 bytes
client problem: sent 134863764 of 370049 bytes
client problem: rv 35
After apr_sendfile(), the kernel file pointer is at offset 0.
apr_recv()->20514/End of file found
client: apr_sendfile() worked as expected!
[1] 199 Exit 1                ./testsf server

So there is a problem reported, but it does say it worked???  I think the
problem is more with the apache code, but I'm not sure.

david

----- Original Message -----
From: "Jeff Trawick" <tr...@bellsouth.net>
To: <ne...@apache.org>
Sent: Monday, November 13, 2000 2:10 AM
Subject: Re: [PATCH] apr_sockaddr_t & friends


> "David Reid" <dr...@jetnet.co.uk> writes:
>
> > Sendfile seems to be broken on FreeBSD (in a clean checkout it's broken
as
> > well so it's not this patch :)) so I havn't managed to do as much
checking
> > as I'd wished to.
>
> What is the symptom?  Can you see if testsf shows the problem?
>
>   cd lib/apr/test
>   make testsf
>   ./testsf server &
>   ./testsf client blocking
>
>   ./testsf server &
>   ./testsf client nonblocking
>
> testsf works fine on FreeBSD 3.4.
>
> You should see messages like this at the end:
>
>   server: apr_sendfile() worked as expected!
>   client: apr_sendfile() worked as expected!
>
> --
> Jeff Trawick | trawick@ibm.net | PGP public key at web site:
>      http://www.geocities.com/SiliconValley/Park/9289/
>           Born in Roswell... married an alien...
>


Re: [PATCH] apr_sockaddr_t & friends

Posted by Jeff Trawick <tr...@bellsouth.net>.
"David Reid" <dr...@jetnet.co.uk> writes:

> Sendfile seems to be broken on FreeBSD (in a clean checkout it's broken as
> well so it's not this patch :)) so I havn't managed to do as much checking
> as I'd wished to.

What is the symptom?  Can you see if testsf shows the problem?

  cd lib/apr/test
  make testsf
  ./testsf server &
  ./testsf client blocking

  ./testsf server &
  ./testsf client nonblocking

testsf works fine on FreeBSD 3.4.

You should see messages like this at the end:

  server: apr_sendfile() worked as expected!
  client: apr_sendfile() worked as expected!

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...