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...