Dear developers.
I made the mod_jk patch to support ipv6 between mod_jk and Tomcat.
The detection of getaddrinfo() and implementation of jk_resolve()
referred to APR.
This patch was tested in the following environments (Do not compile in
other OS's).
1.RHEL4/5 with Apache 2.x
Link-Local address cannot be used.
2.Windows XP Pro with IIS 5.1
isapi_redirector.dll was constructed by VS 2005 Express + PSDK.
when constructing the isapi_redirector.dll, '/D "HAVE_IPV6"' and
'/D "HAVE_GETADDRINFO"' were specified.
My best regards.
Index: mod_jk/native/iis/jk_isapi_plugin.c
===================================================================
--- mod_jk/native/iis/jk_isapi_plugin.c (revision 598096)
+++ mod_jk/native/iis/jk_isapi_plugin.c (working copy)
@@ -27,10 +27,6 @@
// This define is needed to include wincrypt,h, needed to get client
certificates
#define _WIN32_WINNT 0x0400
-#include <httpext.h>
-#include <httpfilt.h>
-#include <wininet.h>
-
#include "jk_global.h"
#include "jk_url.h"
#include "jk_util.h"
@@ -43,6 +39,10 @@
#include "jk_ajp13.h"
#include "pcre.h"
+#include <httpext.h>
+#include <httpfilt.h>
+#include <wininet.h>
+
#ifndef POSIX_MALLOC_THRESHOLD
#define POSIX_MALLOC_THRESHOLD (10)
#endif
Index: mod_jk/native/configure.in
===================================================================
--- mod_jk/native/configure.in (revision 598096)
+++ mod_jk/native/configure.in (working copy)
@@ -263,6 +263,44 @@
AC_SUBST(uint64_t_hex_fmt)
AC_SUBST(pid_t_fmt)
+dnl check for getaddrinfo.
+AC_DEFUN([JK_CHECK_WORKING_GETADDRINFO],[
+ AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[
+ AC_TRY_RUN( [
+#include <netdb.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main(void) {
+ struct addrinfo hints, *ai;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo("127.0.0.1", NULL, &hints, &ai);
+ if (error) {
+ exit(1);
+ }
+ if (ai->ai_addr->sa_family != AF_INET) {
+ exit(1);
+ }
+ exit(0);
+}
+],[
+ ac_cv_working_getaddrinfo="yes"
+],[
+ ac_cv_working_getaddrinfo="no"
+],[
+ ac_cv_working_getaddrinfo="yes"
+])])
+if test "$ac_cv_working_getaddrinfo" = "yes"; then
+ AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works well
enough for APR])
+fi
+])
+JK_CHECK_WORKING_GETADDRINFO
+
dnl check for snprintf and vsnprintf.
AC_CHECK_FUNC(snprintf, AC_DEFINE(HAVE_SNPRINTF,1,[Have snprintf()]))
AC_CHECK_FUNC(vsnprintf, AC_DEFINE(HAVE_VSNPRINTF,1,[Have vsnprintf()]))
Index: mod_jk/native/common/jk_ajp_common.c
===================================================================
--- mod_jk/native/common/jk_ajp_common.c (revision 598096)
+++ mod_jk/native/common/jk_ajp_common.c (working copy)
@@ -852,7 +852,7 @@
int ajp_connect_to_endpoint(ajp_endpoint_t * ae, jk_logger_t *l)
{
- char buf[32];
+ char buf[JK_DUMP_BUF];
int rc = JK_TRUE;
JK_TRACE_ENTER(l);
Index: mod_jk/native/common/jk_ajp_common.h
===================================================================
--- mod_jk/native/common/jk_ajp_common.h (revision 598096)
+++ mod_jk/native/common/jk_ajp_common.h (working copy)
@@ -232,7 +232,7 @@
struct ajp_worker
{
- struct sockaddr_in worker_inet_addr; /* Contains host and port */
+ struct jk_sockaddr_in worker_inet_addr; /* Contains host and port */
unsigned connect_retry_attempts;
const char *name;
const char *host;
Index: mod_jk/native/common/jk_connect.c
===================================================================
--- mod_jk/native/common/jk_connect.c (revision 598096)
+++ mod_jk/native/common/jk_connect.c (working copy)
@@ -35,7 +35,6 @@
#include "apr_errno.h"
#include "apr_general.h"
#include "apr_pools.h"
-static apr_pool_t *jk_apr_pool = NULL;
#endif
#ifdef HAVE_SYS_FILIO_H
@@ -117,15 +116,15 @@
#if defined (WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
/* WIN32 implementation */
-static int nb_connect(jk_sock_t sock, struct sockaddr *addr, int timeout)
+static int nb_connect(jk_sock_t sock, struct jk_sockaddr_in *addr, int timeout)
{
int rc;
if (timeout <= 0)
- return connect(sock, addr, sizeof(struct sockaddr_in));
+ return connect(sock, (const struct sockaddr *)&addr->sa.sin,
addr->salen);
if ((rc = sononblock(sock)))
return -1;
- if (connect(sock, addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
+ if (connect(sock, (const struct sockaddr *)&addr->sa.sin, addr->salen) ==
SOCKET_ERROR) {
struct timeval tv;
fd_set wfdset, efdset;
@@ -167,7 +166,7 @@
#elif !defined(NETWARE)
/* POSIX implementation */
-static int nb_connect(jk_sock_t sock, struct sockaddr *addr, int timeout)
+static int nb_connect(jk_sock_t sock, struct jk_sockaddr_in *addr, int timeout)
{
int rc = 0;
@@ -176,7 +175,7 @@
return -1;
}
do {
- rc = connect(sock, addr, sizeof(struct sockaddr_in));
+ rc = connect(sock, (const struct sockaddr *)&addr->sa.sin,
addr->salen);
} while (rc == -1 && errno == EINTR);
if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY)
@@ -216,9 +215,9 @@
}
#else
/* NETWARE implementation - blocking for now */
-static int nb_connect(jk_sock_t sock, struct sockaddr *addr, int timeout)
+static int nb_connect(jk_sock_t sock, struct jk_sockaddr_in *addr, int timeout)
{
- return connect(sock, addr, sizeof(struct sockaddr_in));
+ return connect(sock, (const struct sockaddr *)&addr->sa.sin, addr->salen);
}
#endif
@@ -245,16 +244,35 @@
/** resolve the host IP */
-int jk_resolve(const char *host, int port, struct sockaddr_in *rc)
+int jk_resolve(const char *host, int port, struct jk_sockaddr_in *rc)
{
- int x;
- struct in_addr laddr;
+ int ret = JK_FALSE;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints, *res;
- memset(rc, 0, sizeof(struct sockaddr_in));
+ memset(rc, 0, sizeof(struct jk_sockaddr_in));
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = AF_UNSPEC;
- rc->sin_port = htons((short)port);
- rc->sin_family = AF_INET;
+ if (getaddrinfo(host, NULL, &hints, &res) == 0) {
+ rc->family = res->ai_family;
+ rc->salen = res->ai_addrlen;
+ memcpy(&(rc->sa), res->ai_addr, res->ai_addrlen);
+ rc->sa.sin.sin_port = htons((short)port);
+ freeaddrinfo(res);
+ ret = JK_TRUE;
+ }
+#else /* HAVE_GETADDR_INFO */
+ int x;
+ struct in_addr laddr;
+
+ memset(rc, 0, sizeof(struct jk_sockaddr_in));
+ rc->family = rc->sa.sin.sin_family = AF_INET;
+ rc->salen = sizeof(struct sockaddr_in);
+ rc->sa.sin.sin_port = htons((short)port);
+
/* Check if we only have digits in the string */
for (x = 0; host[x] != '\0'; x++) {
if (!isdigit((int)(host[x])) && host[x] != '.') {
@@ -265,67 +283,34 @@
/* If we found also characters we shoud make name to IP resolution */
if (host[x] != '\0') {
-#ifdef HAVE_APR
- apr_sockaddr_t *remote_sa, *temp_sa;
- char *remote_ipaddr;
-
- if (!jk_apr_pool) {
- if (apr_pool_create(&jk_apr_pool, NULL) != APR_SUCCESS)
- return JK_FALSE;
- }
- if (apr_sockaddr_info_get
- (&remote_sa, host, APR_UNSPEC, (apr_port_t) port, 0, jk_apr_pool)
- != APR_SUCCESS)
- return JK_FALSE;
-
- /* Since we are only handling AF_INET (IPV4) address (in_addr_t) */
- /* make sure we find one of those. */
- temp_sa = remote_sa;
- while ((NULL != temp_sa) && (AF_INET != temp_sa->family))
- temp_sa = temp_sa->next;
-
- /* if temp_sa is set, we have a valid address otherwise, just return */
- if (NULL != temp_sa)
- remote_sa = temp_sa;
- else
- return JK_FALSE;
-
- apr_sockaddr_ip_get(&remote_ipaddr, remote_sa);
-
- laddr.s_addr = jk_inet_addr(remote_ipaddr);
-
-#else /* HAVE_APR */
-
- /* XXX : WARNING : We should really use gethostbyname_r in
multi-threaded env */
- /* Fortunatly when APR is available, ie under Apache 2.0, we use it */
#if defined(NETWARE) && !defined(__NOVELL_LIBC__)
struct hostent *hoste = gethostbyname((char*)host);
#else
struct hostent *hoste = gethostbyname(host);
#endif
- if (!hoste) {
- return JK_FALSE;
+ if (hoste) {
+ laddr = *((struct in_addr *)hoste->h_addr_list[0]);
+ ret = JK_TRUE;
}
-
- laddr = *((struct in_addr *)hoste->h_addr_list[0]);
-
-#endif /* HAVE_APR */
}
else {
/* If we found only digits we use inet_addr() */
laddr.s_addr = jk_inet_addr(host);
+ ret = JK_TRUE;
}
- memcpy(&(rc->sin_addr), &laddr, sizeof(laddr));
+ if ( ret == JK_TRUE )
+ memcpy(&(rc->sa.sin.sin_addr), &laddr, sizeof(laddr));
- return JK_TRUE;
+#endif /* HAVE_GETADDR_INFO */
+ return ret;
}
/** connect to Tomcat */
-jk_sock_t jk_open_socket(struct sockaddr_in *addr, int keepalive,
+jk_sock_t jk_open_socket(struct jk_sockaddr_in *addr, int keepalive,
int timeout, int sock_buf, jk_logger_t *l)
{
- char buf[32];
+ char buf[JK_DUMP_BUF];
jk_sock_t sock;
int set = 1;
int ret = 0;
@@ -335,7 +320,7 @@
JK_TRACE_ENTER(l);
- sock = socket(AF_INET, SOCK_STREAM, 0);
+ sock = socket(addr->family, SOCK_STREAM, 0);
if (!IS_VALID_SOCKET(sock)) {
JK_GET_SOCKET_ERRNO();
jk_log(l, JK_LOG_ERROR,
@@ -456,12 +441,13 @@
"trying to connect socket %d to %s", sock,
jk_dump_hinfo(addr, buf));
+
/* Need more infos for BSD 4.4 and Unix 98 defines, for now only
iSeries when Unix98 is required at compil time */
#if (_XOPEN_SOURCE >= 520) && defined(AS400)
- ((struct sockaddr *)addr)->sa_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr)(addr->sa.sin)).sa_len = addr->salen;
#endif
- ret = nb_connect(sock, (struct sockaddr *)addr, timeout);
+ ret = nb_connect(sock, addr, timeout);
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
if (ret == SOCKET_ERROR) {
errno = WSAGetLastError() - WSABASEERR;
@@ -641,14 +627,24 @@
* dump a sockaddr_in in A.B.C.D:P in ASCII buffer
*
*/
-char *jk_dump_hinfo(struct sockaddr_in *saddr, char *buf)
+char *jk_dump_hinfo(struct jk_sockaddr_in *saddr, char *buf)
{
- unsigned long laddr = (unsigned long)htonl(saddr->sin_addr.s_addr);
- unsigned short lport = (unsigned short)htons(saddr->sin_port);
+ unsigned short lport = (unsigned short)htons(saddr->sa.sin.sin_port);
+ if (saddr->family == AF_INET) {
+ unsigned long laddr = (unsigned
long)htonl(saddr->sa.sin.sin_addr.s_addr);
- sprintf(buf, "%d.%d.%d.%d:%d",
- (int)(laddr >> 24), (int)((laddr >> 16) & 0xff),
- (int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport);
+ sprintf(buf, "%d.%d.%d.%d:%d",
+ (int)(laddr >> 24), (int)((laddr >> 16) & 0xff),
+ (int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport);
+#ifdef HAVE_IPV6
+ } else {
+ unsigned short *laddr = (unsigned short *)&(saddr->sa.sin6.sin6_addr);
+ sprintf(buf, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
+ htons(*laddr), htons(*(laddr+1)), htons(*(laddr+2)),
+ htons(*(laddr+3)), htons(*(laddr+4)), htons(*(laddr+5)),
+ htons(*(laddr+6)), htons(*(laddr+7)), (int)lport);
+#endif /* HAVE_IPV6 */
+ }
return buf;
}
Index: mod_jk/native/common/jk_connect.h
===================================================================
--- mod_jk/native/common/jk_connect.h (revision 598096)
+++ mod_jk/native/common/jk_connect.h (working copy)
@@ -39,9 +39,9 @@
#define JK_SOCKET_EOF (-2)
#define JK_SOCKET_ERROR (-3)
-int jk_resolve(const char *host, int port, struct sockaddr_in *rc);
+int jk_resolve(const char *host, int port, struct jk_sockaddr_in *rc);
-jk_sock_t jk_open_socket(struct sockaddr_in *addr, int keepalive,
+jk_sock_t jk_open_socket(struct jk_sockaddr_in *addr, int keepalive,
int timeout, int sock_buf, jk_logger_t *l);
int jk_close_socket(jk_sock_t s);
@@ -52,11 +52,10 @@
int jk_tcp_socket_recvfull(jk_sock_t sd, unsigned char *b, int len);
-char *jk_dump_hinfo(struct sockaddr_in *saddr, char *buf);
+char *jk_dump_hinfo(struct jk_sockaddr_in *saddr, char *buf);
int jk_is_socket_connected(jk_sock_t sd);
-
/***
* i5/OS V5R4 need ASCII<->EBCDIC translation for inet_addr() call
*/
Index: mod_jk/native/common/jk_ajp12_worker.c
===================================================================
--- mod_jk/native/common/jk_ajp12_worker.c (revision 598096)
+++ mod_jk/native/common/jk_ajp12_worker.c (working copy)
@@ -40,7 +40,7 @@
struct ajp12_worker
{
- struct sockaddr_in worker_inet_addr;
+ struct jk_sockaddr_in worker_inet_addr;
unsigned connect_retry_attempts;
char *name;
jk_worker_t worker;
Index: mod_jk/native/common/jk_status.c
===================================================================
--- mod_jk/native/common/jk_status.c (revision 598096)
+++ mod_jk/native/common/jk_status.c (working copy)
@@ -1343,7 +1343,7 @@
lb_worker_t *lb,
jk_logger_t *l)
{
- char buf[32];
+ char buf[JK_DUMP_BUF];
char buf_rd[32];
char buf_wr[32];
int cmd;
@@ -1754,7 +1754,7 @@
ajp_worker_t *aw,
jk_logger_t *l)
{
- char buf[32];
+ char buf[JK_DUMP_BUF];
int cmd;
int mime;
int single = 0;
Index: mod_jk/native/common/jk_global.h
===================================================================
--- mod_jk/native/common/jk_global.h (revision 598096)
+++ mod_jk/native/common/jk_global.h (working copy)
@@ -371,6 +371,23 @@
#define strcasecmp(a,b) apr_strnatcasecmp(a,b)
#endif
+#ifdef HAVE_APR
+#define HAVE_IPV6 APR_HAVE_IPV6
+#endif
+
+#define JK_DUMP_BUF 48
+
+struct jk_sockaddr_in {
+ unsigned short int family;
+ int salen;
+ union {
+ struct sockaddr_in sin;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 sin6;
+#endif /* HAVE_IPV6 */
+ } sa;
+};
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]