The following patch makes the following changes to APR and all callers in the apache-2.0 CVS repository:
1) change apr_bind() to take apr_sockaddr_t as second parameter, for specifying the local socket address to bind to 2) add apr_get_sockaddr() function for retrieving the local or remote apr_sockaddr_t associated with a function 3) tweak apr_getaddrinfo() to handle certain AF_INET6 usage a little better Concerns? Would anybody like to see this patch before the next alpha? Where is the API going from here? (mostly IMHO :) ) . more helper functions are needed for dealing with sockaddrs and IP addresses (non-disruptive) . apr_sendto() and apr_recvfrom() are needed to support normal UDP idioms (non-disruptive) . apr_get_port(), apr_set_port(), apr_get_ipaddr(), apr_set_ipaddr() should take apr_sockaddr_t as a parameter, not apr_socket_t+APR_LOCAL/APR_REMOTE; (a little disruptive, but really a trivial change for apps) . apr_create_tcp_socket() can go away (a little disruptive, but really a trivial change for apps) . change apr_get_hostname() to apr_getnameinfo(), make it take apr_sockaddr_t instead of apr_socket_t+APR_LOCAL/APR_REMOTE, let it cache result in apr_sockaddr_t (a little disruptive, but really a trivial change for apps) . get rid of apr_get_remote_name() and apr_get_local_name(); if an app wants to deal with the native sockaddr structure directly, they can call apr_get_sockaddr() and look in the returned apr_sockaddr_t for the native structure (a little disruptive, but really a trivial change for apps) . get rid of apr_get_inaddr(); apr_getaddrinfo() does that work + more (a little disruptive, but really a trivial change for apps) . get rid of apr_get_socket_inaddr(); if an app wants to deal with the native IP address structure directly, they can call apr_get_sockaddr() and look in the returned apr_sockaddr_t for the native structure (a little disruptive, but really a trivial change for apps) . decide what to do about apr_make_os_sock(): should it play the AF_INET/AF_INET6 game and make a socket really work? currently, such a socket is not fully functional even for AF_INET; this isn't terrible, because we save syscalls, and such sockets are usually built only for use with apr_poll() Where are the internals going from here? . apr_getaddrinfo() needs to be changed support IPv6 (when the platform provides getipnodebyname() or getaddrinfo()) . test better with AF_INET6 and/or UDP to make sure those work properly and support expected idioms . it is high time to get more commonality in the codebase Index: lib/apr/aprlib.def =================================================================== RCS file: /home/cvspublic/apache-2.0/src/lib/apr/aprlib.def,v retrieving revision 1.42 diff -u -r1.42 aprlib.def --- lib/apr/aprlib.def 2000/11/17 03:45:03 1.42 +++ lib/apr/aprlib.def 2000/11/17 18:59:25 @@ -51,6 +51,7 @@ ; ; apr_network_io.h + apr_get_sockaddr @44 apr_getaddrinfo @45 apr_create_socket @46 apr_create_tcp_socket @47 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.72 diff -u -r1.72 apr_network_io.h --- lib/apr/include/apr_network_io.h 2000/11/17 03:45:01 1.72 +++ lib/apr/include/apr_network_io.h 2000/11/17 18:59:27 @@ -232,10 +232,11 @@ /** * Bind the socket to its associated port * @param sock The socket to bind - * @tip This is where we will find out if there is any other process + * @param sa The socket address to bind to + * @tip This may be where we will find out if there is any other process * using the selected port. */ -apr_status_t apr_bind(apr_socket_t *sock); +apr_status_t apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa); /** * Listen to a bound socket for connections. @@ -440,6 +441,14 @@ * @param on Socket option returned on the call. */ apr_status_t apr_getsocketopt(apr_socket_t *sock, apr_int32_t opt, apr_int32_t* on); + +/** + * 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_sockaddr(apr_sockaddr_t **sa, apr_interface_e which, apr_socket_t *sock); /** * Associate a port with a socket. Index: lib/apr/network_io/os2/sockets.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/os2/sockets.c,v retrieving revision 1.32 diff -u -r1.32 sockets.c --- lib/apr/network_io/os2/sockets.c 2000/11/17 03:45:03 1.32 +++ lib/apr/network_io/os2/sockets.c 2000/11/17 18:59:27 @@ -189,14 +189,16 @@ -apr_status_t apr_bind(apr_socket_t *sock) +apr_status_t apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa) { if (bind(sock->socketdes, - (struct sockaddr *)&sock->local_addr->sa, - sock->local_addr->sa_len) == -1) + (struct sockaddr *)&sa->sa, + sa->sa_len) == -1) return APR_OS2_STATUS(sock_errno()); - else + else { + sock->local_sa = sa; return APR_SUCCESS; + } } apr_status_t apr_listen(apr_socket_t *sock, apr_int32_t backlog) 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.7 diff -u -r1.7 sa_common.c --- lib/apr/network_io/unix/sa_common.c 2000/11/17 03:45:01 1.7 +++ lib/apr/network_io/unix/sa_common.c 2000/11/17 18:59:27 @@ -191,6 +191,22 @@ #endif } +apr_status_t apr_get_sockaddr(apr_sockaddr_t **sa, apr_interface_e which, apr_socket_t *sock) +{ + if (which == APR_LOCAL) { + *sa = sock->local_addr; + } + else if (which == APR_REMOTE) { + *sa = sock->remote_addr; + } + else { + *sa = NULL; + return APR_EINVAL; + } + return APR_SUCCESS; + +} + apr_status_t apr_getaddrinfo(apr_sockaddr_t **sa, const char *hostname, apr_int32_t family, apr_port_t port, apr_int32_t flags, apr_pool_t *p) @@ -201,7 +217,12 @@ if ((*sa) == NULL) return APR_ENOMEM; (*sa)->pool = p; - (*sa)->sa.sin.sin_family = AF_INET; /* we don't yet support IPv6 */ + if (family == AF_UNSPEC) { + (*sa)->sa.sin.sin_family = AF_INET; /* we don't yet support IPv6 here */ + } + else { + (*sa)->sa.sin.sin_family = family; + } (*sa)->sa.sin.sin_port = htons(port); set_sockaddr_vars(*sa, (*sa)->sa.sin.sin_family); 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.57 diff -u -r1.57 sockets.c --- lib/apr/network_io/unix/sockets.c 2000/11/17 03:45:01 1.57 +++ lib/apr/network_io/unix/sockets.c 2000/11/17 18:59:28 @@ -162,12 +162,14 @@ return socket_cleanup(thesocket); } -apr_status_t apr_bind(apr_socket_t *sock) +apr_status_t apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa) { if (bind(sock->socketdes, - (struct sockaddr *)&sock->local_addr->sa, sock->local_addr->sa_len) == -1) + (struct sockaddr *)&sa->sa, sa->sa_len) == -1) { return errno; + } else { + sock->local_addr = sa; /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 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 */ Index: lib/apr/network_io/win32/sockets.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/win32/sockets.c,v retrieving revision 1.42 diff -u -r1.42 sockets.c --- lib/apr/network_io/win32/sockets.c 2000/11/17 03:45:03 1.42 +++ lib/apr/network_io/win32/sockets.c 2000/11/17 18:59:28 @@ -196,14 +196,15 @@ return socket_cleanup(thesocket); } -apr_status_t apr_bind(apr_socket_t *sock) +apr_status_t apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa) { if (bind(sock->sock, - (struct sockaddr *)&sock->local_addr->sa, - sock->local_addr->sa_len) == -1) { + (struct sockaddr *)&sa->sa, + sa->sa_len) == -1) { return apr_get_netos_error(); } else { + sock->local_addr = sa; if (sock->local_addr->sa.sin.sin_port == 0) { sock->local_port_unknown = 1; /* ephemeral port */ } Index: lib/apr/test/server.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/lib/apr/test/server.c,v retrieving revision 1.18 diff -u -r1.18 server.c --- lib/apr/test/server.c 2000/11/16 14:48:50 1.18 +++ lib/apr/test/server.c 2000/11/17 18:59:28 @@ -71,6 +71,10 @@ char datarecv[STRLEN] = "Recv data test"; char *local_ipaddr, *remote_ipaddr; apr_port_t local_port, remote_port; + apr_sockaddr_t *localsa; + apr_status_t stat; + int family; + char buf[128]; fprintf(stdout, "Initializing........."); if (apr_initialize() != APR_SUCCESS) { @@ -94,6 +98,18 @@ } fprintf(stdout, "OK\n"); + fprintf(stdout, "\tServer: Grabbing local socket address........"); + if (apr_get_sockaddr(&localsa, APR_LOCAL, sock) != APR_SUCCESS) { + fprintf(stderr, "Couldn't grab local address\n"); + exit(-1); + } + fprintf(stdout, "OK\n"); + + /* APR chose the address family of socket for us, so we need to build a + * socket address later for the same address family. + */ + family = localsa->sa.sin.sin_family; + fprintf(stdout, "\tServer: Setting socket option NONBLOCK......."); if (apr_setsocketopt(sock, APR_SO_NONBLOCK, 1) != APR_SUCCESS) { apr_close_socket(sock); @@ -110,18 +126,20 @@ } fprintf(stdout, "OK\n"); - fprintf(stdout, "\tServer: Setting port for socket......."); - if (apr_set_port(sock, APR_LOCAL, 8021) != APR_SUCCESS) { + fprintf(stdout, "\tServer: Building local socket address........."); + if (apr_getaddrinfo(&localsa, NULL, family, 8021, 0, context) + != APR_SUCCESS) { apr_close_socket(sock); - fprintf(stderr, "Couldn't set the port correctly\n"); + fprintf(stderr, "Couldn't build the socket address correctly\n"); exit(-1); } fprintf(stdout, "OK\n"); fprintf(stdout, "\tServer: Binding socket to port......."); - if (apr_bind(sock) != APR_SUCCESS) { + if ((stat = apr_bind(sock, localsa)) != APR_SUCCESS) { apr_close_socket(sock); - fprintf(stderr, "Could not bind\n"); + fprintf(stderr, "Could not bind: %s\n", + apr_strerror(stat, buf, sizeof buf)); exit(-1); } fprintf(stdout, "OK\n"); Index: lib/apr/test/testsf.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/lib/apr/test/testsf.c,v retrieving revision 1.14 diff -u -r1.14 testsf.c --- lib/apr/test/testsf.c 2000/11/17 03:45:01 1.14 +++ lib/apr/test/testsf.c 2000/11/17 18:59:29 @@ -90,7 +90,7 @@ typedef enum {BLK, NONBLK, TIMEOUT} client_socket_mode_t; -static void apr_setup(apr_pool_t **p, apr_socket_t **sock) +static void apr_setup(apr_pool_t **p, apr_socket_t **sock, int *family) { char buf[120]; apr_status_t rv; @@ -114,13 +114,26 @@ } *sock = NULL; - rv = apr_create_tcp_socket(sock, *p); + rv = apr_create_socket(sock, *family, SOCK_STREAM, *p); if (rv != APR_SUCCESS) { fprintf(stderr, "apr_create_tcp_socket()->%d/%s\n", rv, apr_strerror(rv, buf, sizeof buf)); exit(1); } + + if (*family == AF_UNSPEC) { + apr_sockaddr_t *localsa; + + rv = apr_get_sockaddr(&localsa, APR_LOCAL, *sock); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_get_sockaddr()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + *family = localsa->sa.sin.sin_family; + } } static void create_testfile(apr_pool_t *p, const char *fname) @@ -205,9 +218,11 @@ apr_pollfd_t *pfd; apr_int32_t nsocks; int i; + int family; apr_sockaddr_t *destsa; - apr_setup(&p, &sock); + family = AF_INET; + apr_setup(&p, &sock, &family); create_testfile(p, TESTFILE); rv = apr_open(&f, TESTFILE, APR_READ, 0, p); @@ -218,7 +233,7 @@ exit(1); } - rv = apr_getaddrinfo(&destsa, "127.0.0.1", AF_INET, TESTSF_PORT, 0, p); + rv = apr_getaddrinfo(&destsa, "127.0.0.1", family, TESTSF_PORT, 0, p); if (rv != APR_SUCCESS) { fprintf(stderr, "apr_getaddrinfo()->%d/%s\n", rv, @@ -493,26 +508,29 @@ int i; apr_socket_t *newsock = NULL; apr_ssize_t bytes_read; + apr_sockaddr_t *localsa; + int family; - apr_setup(&p, &sock); + family = AF_UNSPEC; + apr_setup(&p, &sock, &family); - rv = apr_set_port(sock, APR_LOCAL, TESTSF_PORT); + rv = apr_setsocketopt(sock, APR_SO_REUSEADDR, 1); if (rv != APR_SUCCESS) { - fprintf(stderr, "apr_set_local_port()->%d/%s\n", + fprintf(stderr, "apr_setsocketopt()->%d/%s\n", rv, apr_strerror(rv, buf, sizeof buf)); exit(1); } - rv = apr_setsocketopt(sock, APR_SO_REUSEADDR, 1); + rv = apr_getaddrinfo(&localsa, NULL, family, TESTSF_PORT, 0, p); if (rv != APR_SUCCESS) { - fprintf(stderr, "apr_setsocketopt()->%d/%s\n", + fprintf(stderr, "apr_getaddrinfo()->%d/%s\n", rv, apr_strerror(rv, buf, sizeof buf)); exit(1); } - rv = apr_bind(sock); + rv = apr_bind(sock, localsa); if (rv != APR_SUCCESS) { fprintf(stderr, "apr_bind()->%d/%s\n", rv, Index: main/listen.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/main/listen.c,v retrieving revision 1.36 diff -u -r1.36 listen.c --- main/listen.c 2000/11/09 19:38:26 1.36 +++ main/listen.c 2000/11/17 18:59:29 @@ -85,12 +85,22 @@ apr_status_t stat; apr_port_t port; char *ipaddr; + apr_sockaddr_t *localsa; apr_get_port(&port, APR_LOCAL, s); apr_get_ipaddr(&ipaddr, APR_LOCAL, s); apr_snprintf(addr, sizeof(addr), "address %s port %u", ipaddr, (unsigned) port); + stat = apr_getaddrinfo(&localsa, ipaddr, AF_INET, port, 0, p); + if (stat != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, stat, NULL, + "make_sock: for %s/%hu, apr_getaddrinfo() failed", + ipaddr, port); + apr_close_socket(s); + return stat; + } + stat = apr_setsocketopt(s, APR_SO_REUSEADDR, one); if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) { ap_log_error(APLOG_MARK, APLOG_CRIT, stat, NULL, @@ -140,7 +150,7 @@ ap_sock_disable_nagle(s); #endif - if ((stat = apr_bind(s)) != APR_SUCCESS) { + if ((stat = apr_bind(s, localsa)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, stat, NULL, "make_sock: could not bind to %s", addr); apr_close_socket(s); Index: main/rfc1413.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/main/rfc1413.c,v retrieving revision 1.29 diff -u -r1.29 rfc1413.c --- main/rfc1413.c 2000/11/17 03:45:02 1.29 +++ main/rfc1413.c 2000/11/17 18:59:30 @@ -119,7 +119,7 @@ char *cp; char buffer[RFC1413_MAXDATA + 1]; int buflen; - apr_sockaddr_t *destsa; + apr_sockaddr_t *localsa, *destsa; /* * Bind the local and remote ends of the query socket to the same @@ -130,10 +130,16 @@ * addresses from the query socket. */ - apr_set_port(sock, APR_LOCAL, ANY_PORT); - apr_set_ipaddr(sock, APR_LOCAL, local_ip); + if ((status = apr_getaddrinfo(&localsa, local_ip, AF_INET, 0, 0, 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; + } - if ((status = apr_bind(sock)) != APR_SUCCESS) { + if ((status = apr_bind(sock, localsa)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv, "bind: rfc1413: Error binding to local port"); return -1; Index: modules/proxy/proxy_ftp.c =================================================================== RCS file: /home/cvspublic/apache-2.0/src/modules/proxy/proxy_ftp.c,v retrieving revision 1.23 diff -u -r1.23 proxy_ftp.c --- modules/proxy/proxy_ftp.c 2000/11/16 01:57:46 1.23 +++ modules/proxy/proxy_ftp.c 2000/11/17 18:59:31 @@ -873,8 +873,6 @@ } apr_get_port(&npport, APR_LOCAL, sock); apr_get_ipaddr(&npaddr, APR_LOCAL, sock); - apr_set_port(dsock, APR_LOCAL, npport); - apr_set_ipaddr(dsock, APR_LOCAL, npaddr); if (apr_setsocketopt(dsock, APR_SO_REUSEADDR, one) != APR_SUCCESS) { #ifndef _OSD_POSIX /* BS2000 has this option "always on" */ @@ -886,7 +884,15 @@ #endif /*_OSD_POSIX*/ } - if (apr_bind(dsock) != APR_SUCCESS) { + if (apr_getaddrinfo(&localsa, npaddr, AF_INET, npport, 0, r->pool) + != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error creating local socket address"); + ap_bclose(f); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (apr_bind(dsock, localsa) != APR_SUCCESS) { char buff[22]; apr_snprintf(buff, sizeof(buff), "%s:%d", npaddr, npport); Index: support/httpd.exp =================================================================== RCS file: /home/cvspublic/apache-2.0/src/support/httpd.exp,v retrieving revision 1.12 diff -u -r1.12 httpd.exp --- support/httpd.exp 2000/11/17 03:45:02 1.12 +++ support/httpd.exp 2000/11/17 18:59:33 @@ -425,6 +425,7 @@ apr_get_port apr_get_remote_name apr_get_revents +apr_get_sockaddr apr_get_socket_inaddr apr_get_socketdata apr_get_thread_private -- Jeff Trawick | [EMAIL PROTECTED] | PGP public key at web site: http://www.geocities.com/SiliconValley/Park/9289/ Born in Roswell... married an alien...