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]