Author: rjung
Date: Sun Feb 8 14:28:10 2015
New Revision: 1658173
URL: http://svn.apache.org/r1658173
Log:
BZ 57536: AJP: Allow to configure connection
source address. This should only be used on
multi-homed hosts.
The feature is experimental.
Modified:
tomcat/jk/trunk/native/common/jk_ajp12_worker.c
tomcat/jk/trunk/native/common/jk_ajp_common.c
tomcat/jk/trunk/native/common/jk_ajp_common.h
tomcat/jk/trunk/native/common/jk_connect.c
tomcat/jk/trunk/native/common/jk_connect.h
tomcat/jk/trunk/native/common/jk_status.c
tomcat/jk/trunk/native/common/jk_util.c
tomcat/jk/trunk/native/common/jk_util.h
tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml
tomcat/jk/trunk/xdocs/reference/workers.xml
Modified: tomcat/jk/trunk/native/common/jk_ajp12_worker.c
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_ajp12_worker.c?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_ajp12_worker.c (original)
+++ tomcat/jk/trunk/native/common/jk_ajp12_worker.c Sun Feb 8 14:28:10 2015
@@ -41,6 +41,7 @@
struct ajp12_worker
{
jk_sockaddr_t worker_inet_addr;
+ jk_sockaddr_t worker_source_inet_addr;
unsigned connect_retry_attempts;
char *name;
jk_worker_t worker;
@@ -127,6 +128,9 @@ static int JK_METHOD service(jk_endpoint
attempt++) {
p->sd =
jk_open_socket(&p->worker->worker_inet_addr,
+ p->worker->worker_source_inet_addr.ipaddr_ptr !=
NULL ?
+ &p->worker->worker_source_inet_addr :
+ NULL,
JK_FALSE, 0, 0, 0, l);
jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::service, sd = %d",
@@ -187,19 +191,34 @@ static int JK_METHOD validate(jk_worker_
p->name,
AJP_DEF_HOST);
+ const char *source = jk_get_worker_host(props,
+ p->name,
+ "");
+
jk_log(l, JK_LOG_DEBUG,
- "In jk_worker_t::validate for worker %s contact is %s:%d",
+ "In jk_worker_t::validate for worker %s target is %s:%d",
p->name, host, port);
if (host) {
- if (jk_resolve(host, port, &p->worker_inet_addr, we->pool,
JK_FALSE, l)) {
- return JK_TRUE;
+ if (!jk_resolve(host, port, &p->worker_inet_addr, we->pool,
JK_FALSE, l)) {
+ jk_log(l, JK_LOG_ERROR,
+ "In jk_worker_t::validate, host '%s:%d' resolve failed",
+ host, port);
+ return JK_FALSE;
}
+ } else {
jk_log(l, JK_LOG_ERROR,
- "In jk_worker_t::validate, resolve failed");
+ "In jk_worker_t::validate, Error no host name given");
+ return JK_FALSE;
+ }
+ if (source && *source) {
+ if (!jk_resolve(source, 0, &p->worker_source_inet_addr, we->pool,
JK_FALSE, l)) {
+ p->worker_source_inet_addr.ipaddr_ptr = NULL;
+ jk_log(l, JK_LOG_WARNING,
+ "In jk_worker_t::validate, source addr '%s' resolve
failed - ignored",
+ source);
+ }
}
- jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, Error %s %d",
- host, port);
}
else {
jk_log(l, JK_LOG_ERROR,
Modified: tomcat/jk/trunk/native/common/jk_ajp_common.c
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_ajp_common.c?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_ajp_common.c (original)
+++ tomcat/jk/trunk/native/common/jk_ajp_common.c Sun Feb 8 14:28:10 2015
@@ -1040,6 +1040,9 @@ int ajp_connect_to_endpoint(ajp_endpoint
ae->last_errno = 0;
ae->sd = jk_open_socket(&ae->worker->worker_inet_addr,
+ ae->worker->worker_source_inet_addr.ipaddr_ptr !=
NULL ?
+ &ae->worker->worker_source_inet_addr :
+ NULL,
ae->worker->keepalive,
ae->worker->socket_timeout,
ae->worker->socket_connect_timeout,
@@ -2830,12 +2833,18 @@ int ajp_validate(jk_worker_t *pThis,
}
strncpy(p->host, tmp, JK_SHM_STR_SIZ);
p->prefer_ipv6 = jk_get_worker_prefer_ipv6(props, p->name, JK_FALSE);
+ tmp = jk_get_worker_source(props, p->name, "");
+ if (jk_check_attribute_length("source address", tmp, l) == JK_FALSE) {
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+ strncpy(p->source, tmp, JK_SHM_STR_SIZ);
if (p->s->h.sequence == 0) {
/* Initial setup.
*/
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
- "worker %s contact is '%s:%d'",
+ "worker %s target is '%s:%d'",
p->name, p->host, p->port);
if (p->port > 0) {
if (!jk_resolve(p->host, p->port, &p->worker_inet_addr,
@@ -2850,6 +2859,15 @@ int ajp_validate(jk_worker_t *pThis,
p->name);
}
}
+ if (p->source && *p->source) {
+ if (!jk_resolve(p->source, 0, &p->worker_source_inet_addr,
+ we->pool, p->prefer_ipv6, l)) {
+ p->worker_source_inet_addr.ipaddr_ptr = NULL;
+ jk_log(l, JK_LOG_WARNING,
+ "worker %s can't resolve source address '%s'",
+ p->name, p->source);
+ }
+ }
p->addr_sequence = 0;
p->s->addr_sequence = 0;
p->s->last_maintain_time = time(NULL);
Modified: tomcat/jk/trunk/native/common/jk_ajp_common.h
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_ajp_common.h?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_ajp_common.h (original)
+++ tomcat/jk/trunk/native/common/jk_ajp_common.h Sun Feb 8 14:28:10 2015
@@ -299,9 +299,11 @@ struct ajp_worker
JK_CRIT_SEC cs;
jk_sockaddr_t worker_inet_addr; /* Contains host and port */
+ jk_sockaddr_t worker_source_inet_addr; /* Contains source ip */
unsigned connect_retry_attempts;
char host[JK_SHM_STR_SIZ];
int port;
+ char source[JK_SHM_STR_SIZ];
int addr_sequence; /* Whether the address is resolved */
int maintain_time;
int prefer_ipv6;
Modified: tomcat/jk/trunk/native/common/jk_connect.c
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_connect.c?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_connect.c (original)
+++ tomcat/jk/trunk/native/common/jk_connect.c Sun Feb 8 14:28:10 2015
@@ -163,6 +163,7 @@ static int sononblock(jk_sock_t sd)
/** Non-blocking socket connect
* @param sd socket to connect
* @param addr address to connect to
+ * @param source optional source address
* @param timeout connect timeout in seconds
* (<=0: no timeout=blocking)
* @param l logger
@@ -171,12 +172,22 @@ static int sononblock(jk_sock_t sd)
* during blocking connect
* 0: success
*/
-static int nb_connect(jk_sock_t sd, jk_sockaddr_t *addr, int timeout,
jk_logger_t *l)
+static int nb_connect(jk_sock_t sd, jk_sockaddr_t *addr, jk_sockaddr_t *source,
+ int timeout, jk_logger_t *l)
{
int rc;
+ char buf[64];
JK_TRACE_ENTER(l);
+ if (source != NULL) {
+ if (bind(sd, (const struct sockaddr *)&source->sa.sin, source->salen))
{
+ JK_GET_SOCKET_ERRNO();
+ jk_log(l, JK_LOG_ERROR,
+ "error during source bind on socket %d [%s] (errno=%d)",
+ sd, jk_dump_hinfo(source, buf, sizeof(buf)), errno);
+ }
+ }
if (timeout <= 0) {
rc = connect(sd, (const struct sockaddr *)&addr->sa.sin, addr->salen);
JK_TRACE_EXIT(l);
@@ -237,18 +248,29 @@ static int nb_connect(jk_sock_t sd, jk_s
/** Non-blocking socket connect
* @param sd socket to connect
* @param addr address to connect to
+ * @param source optional source address
* @param timeout connect timeout in seconds
* (<=0: no timeout=blocking)
* @param l logger
* @return -1: some kind of error occured
* 0: success
*/
-static int nb_connect(jk_sock_t sd, jk_sockaddr_t *addr, int timeout,
jk_logger_t *l)
+static int nb_connect(jk_sock_t sd, jk_sockaddr_t *addr, jk_sockaddr_t *source,
+ int timeout, jk_logger_t *l)
{
int rc = 0;
+ char buf[64];
JK_TRACE_ENTER(l);
+ if (source != NULL) {
+ if (bind(sd, (const struct sockaddr *)&source->sa.sin, source->salen))
{
+ JK_GET_SOCKET_ERRNO();
+ jk_log(l, JK_LOG_ERROR,
+ "error during source bind on socket %d [%s] (errno=%d)",
+ sd, jk_dump_hinfo(source, buf, sizeof(buf)), errno);
+ }
+ }
if (timeout > 0) {
if (sononblock(sd)) {
JK_TRACE_EXIT(l);
@@ -301,17 +323,28 @@ static int nb_connect(jk_sock_t sd, jk_s
/** Non-blocking socket connect
* @param sd socket to connect
* @param addr address to connect to
+ * @param source optional source address
* @param timeout connect timeout in seconds (ignored!)
* @param l logger
* @return -1: some kind of error occured
* 0: success
*/
-static int nb_connect(jk_sock_t sd, jk_sockaddr_t *addr, int timeout,
jk_logger_t *l)
+static int nb_connect(jk_sock_t sd, jk_sockaddr_t *addr, jk_sockaddr_t *source,
+ int timeout, jk_logger_t *l)
{
int rc;
+ char buf[64];
JK_TRACE_ENTER(l);
+ if (source != NULL) {
+ if (bind(sd, (const struct sockaddr *)&source->sa.sin, source->salen))
{
+ JK_GET_SOCKET_ERRNO();
+ jk_log(l, JK_LOG_ERROR,
+ "error during source bind on socket %d [%s] (errno=%d)",
+ sd, jk_dump_hinfo(source, buf, sizeof(buf)), errno);
+ }
+ }
rc = connect(sd, (const struct sockaddr *)&addr->sa.sin, addr->salen);
JK_TRACE_EXIT(l);
return rc;
@@ -580,7 +613,8 @@ int jk_resolve(const char *host, int por
* created socket: success
* @remark Cares about errno
*/
-jk_sock_t jk_open_socket(jk_sockaddr_t *addr, int keepalive,
+jk_sock_t jk_open_socket(jk_sockaddr_t *addr, jk_sockaddr_t *source,
+ int keepalive,
int timeout, int connect_timeout,
int sock_buf, jk_logger_t *l)
{
@@ -767,11 +801,11 @@ jk_sock_t jk_open_socket(jk_sockaddr_t *
jk_dump_hinfo(addr, buf, sizeof(buf)));
/* Need more infos for BSD 4.4 and Unix 98 defines, for now only
-iSeries when Unix98 is required at compil time */
+iSeries when Unix98 is required at compile time */
#if (_XOPEN_SOURCE >= 520) && defined(AS400)
((struct sockaddr *)addr)->sa.sin.sa_len = sizeof(struct sockaddr_in);
#endif
- ret = nb_connect(sd, addr, connect_timeout, l);
+ ret = nb_connect(sd, addr, source, connect_timeout, l);
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
if (JK_IS_SOCKET_ERROR(ret)) {
JK_GET_SOCKET_ERRNO();
Modified: tomcat/jk/trunk/native/common/jk_connect.h
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_connect.h?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_connect.h (original)
+++ tomcat/jk/trunk/native/common/jk_connect.h Sun Feb 8 14:28:10 2015
@@ -43,7 +43,8 @@ void jk_clone_sockaddr(jk_sockaddr_t *ou
int jk_resolve(const char *host, int port, jk_sockaddr_t *rc, void *pool,
int prefer_ipv6, jk_logger_t *l);
-jk_sock_t jk_open_socket(jk_sockaddr_t *addr, int keepalive,
+jk_sock_t jk_open_socket(jk_sockaddr_t *addr, jk_sockaddr_t *source,
+ int keepalive,
int timeout, int connect_timeout,
int sock_buf, jk_logger_t *l);
Modified: tomcat/jk/trunk/native/common/jk_status.c
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_status.c?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_status.c (original)
+++ tomcat/jk/trunk/native/common/jk_status.c Sun Feb 8 14:28:10 2015
@@ -155,6 +155,7 @@
#define JK_STATUS_ARG_AJP_TEXT_HOST_STR "Hostname"
#define JK_STATUS_ARG_AJP_TEXT_PORT "Port"
#define JK_STATUS_ARG_AJP_TEXT_ADDR_STR "Address:Port"
+#define JK_STATUS_ARG_AJP_TEXT_SOURCE_STR "Source"
#define JK_STATUS_ARG_AJP_HEAD_CACHE_TO "Connection<br/>Pool Timeout"
#define JK_STATUS_ARG_AJP_HEAD_PING_TO "Ping<br/>Timeout"
@@ -170,6 +171,7 @@
#define JK_STATUS_ARG_AJP_HEAD_HOST_STR "Hostname"
#define JK_STATUS_ARG_AJP_HEAD_PORT "Port"
#define JK_STATUS_ARG_AJP_HEAD_ADDR_STR "Address:Port"
+#define JK_STATUS_ARG_AJP_HEAD_SOURCE_STR "Source"
#define JK_STATUS_CMD_UNKNOWN (0)
#define JK_STATUS_CMD_LIST (1)
@@ -274,6 +276,7 @@
"<th>Type</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_HOST_STR "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_ADDR_STR "</th>" \
+ "<th>"
JK_STATUS_ARG_AJP_HEAD_SOURCE_STR "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_CACHE_TO "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_CONNECT_TO "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_PREPOST_TO "</th>" \
@@ -287,6 +290,7 @@
"<td>%s</td>" \
"<td>%s</td>" \
"<td>%s</td>" \
+ "<td>%s</td>" \
"<td>%d</td>" \
"<td>%d</td>" \
"<td>%d</td>" \
@@ -379,6 +383,7 @@
"<th>Name</th><th>Type</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_HOST_STR "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_ADDR_STR "</th>" \
+ "<th>"
JK_STATUS_ARG_AJP_HEAD_SOURCE_STR "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_CACHE_TO "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_CONNECT_TO "</th>" \
"<th>"
JK_STATUS_ARG_AJP_HEAD_PREPOST_TO "</th>" \
@@ -393,6 +398,7 @@
"<td>%s</td>" \
"<td>%s</td>" \
"<td>%s</td>" \
+ "<td>%s</td>" \
"<td>%d</td>" \
"<td>%d</td>" \
"<td>%d</td>" \
@@ -1799,6 +1805,7 @@ static void display_worker_ajp_conf_deta
status_worker_type(type),
aw->host,
dump_ajp_addr(aw, buf, sizeof(buf)),
+ aw->source && *aw->source ? aw->source : "undefined",
aw->cache_timeout,
aw->connect_timeout,
aw->prepost_timeout,
@@ -1812,6 +1819,7 @@ static void display_worker_ajp_conf_deta
status_worker_type(type),
aw->host,
dump_ajp_addr(aw, buf, sizeof(buf)),
+ aw->source && *aw->source ? aw->source : "undefined",
aw->cache_timeout,
aw->connect_timeout,
aw->prepost_timeout,
@@ -1960,6 +1968,7 @@ static void display_worker_ajp_details(j
jk_print_xml_att_string(s, l, off+2, "host", aw->host);
jk_print_xml_att_int(s, l, off+2, "port", aw->port);
jk_print_xml_att_string(s, l, off+2, "address", dump_ajp_addr(aw, buf,
sizeof(buf)));
+ jk_print_xml_att_string(s, l, off+2, "source", aw->source &&
*aw->source ? aw->source : "undefined");
jk_print_xml_att_int(s, l, off+2, "connection_pool_timeout",
aw->cache_timeout);
jk_print_xml_att_int(s, l, off+2, "ping_timeout", aw->ping_timeout);
jk_print_xml_att_int(s, l, off+2, "connect_timeout",
aw->connect_timeout);
@@ -2029,6 +2038,7 @@ static void display_worker_ajp_details(j
jk_printf(s, l, " host=%s", aw->host);
jk_printf(s, l, " port=%d", aw->port);
jk_printf(s, l, " address=%s", dump_ajp_addr(aw, buf, sizeof(buf)));
+ jk_printf(s, l, " source=%s", aw->source && *aw->source ? aw->source :
"undefined");
jk_printf(s, l, " connection_pool_timeout=%d", aw->cache_timeout);
jk_printf(s, l, " ping_timeout=%d", aw->ping_timeout);
jk_printf(s, l, " connect_timeout=%d", aw->connect_timeout);
@@ -2095,6 +2105,7 @@ static void display_worker_ajp_details(j
jk_print_prop_att_string(s, l, w, ajp_name, "host", aw->host);
jk_print_prop_att_int(s, l, w, ajp_name, "port", aw->port);
jk_print_prop_att_string(s, l, w, ajp_name, "address",
dump_ajp_addr(aw, buf, sizeof(buf)));
+ jk_print_prop_att_string(s, l, w, ajp_name, "source", aw->source &&
*aw->source ? aw->source : "undefined");
jk_print_prop_att_int(s, l, w, ajp_name, "connection_pool_timeout",
aw->cache_timeout);
jk_print_prop_att_int(s, l, w, ajp_name, "ping_timeout",
aw->ping_timeout);
jk_print_prop_att_int(s, l, w, ajp_name, "connect_timeout",
aw->connect_timeout);
Modified: tomcat/jk/trunk/native/common/jk_util.c
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_util.c?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_util.c (original)
+++ tomcat/jk/trunk/native/common/jk_util.c Sun Feb 8 14:28:10 2015
@@ -45,6 +45,7 @@
#define NATIVE_LIB_OF_WORKER "native_lib"
#define REFERENCE_OF_WORKER "reference"
#define HOST_OF_WORKER "host"
+#define SOURCE_OF_WORKER "source"
#define PORT_OF_WORKER "port"
#define TYPE_OF_WORKER "type"
#define CACHE_OF_WORKER_DEPRECATED "cachesize"
@@ -183,6 +184,7 @@ static const char *unique_properties[] =
SECRET_OF_WORKER,
REFERENCE_OF_WORKER,
HOST_OF_WORKER,
+ SOURCE_OF_WORKER,
PORT_OF_WORKER,
TYPE_OF_WORKER,
CACHE_OF_WORKER_DEPRECATED,
@@ -279,6 +281,7 @@ static const char *supported_properties[
NATIVE_LIB_OF_WORKER,
REFERENCE_OF_WORKER,
HOST_OF_WORKER,
+ SOURCE_OF_WORKER,
PORT_OF_WORKER,
TYPE_OF_WORKER,
CACHE_OF_WORKER_DEPRECATED,
@@ -906,6 +909,19 @@ const char *jk_get_worker_host(jk_map_t
return jk_map_get_string(m, buf, def);
}
+
+const char *jk_get_worker_source(jk_map_t *m, const char *wname, const char
*def)
+{
+ char buf[PARAM_BUFFER_SIZE];
+
+ if (!m || !wname) {
+ return NULL;
+ }
+
+ MAKE_WORKER_PARAM(SOURCE_OF_WORKER);
+
+ return jk_map_get_string(m, buf, def);
+}
int jk_get_worker_port(jk_map_t *m, const char *wname, int def)
{
Modified: tomcat/jk/trunk/native/common/jk_util.h
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_util.h?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_util.h (original)
+++ tomcat/jk/trunk/native/common/jk_util.h Sun Feb 8 14:28:10 2015
@@ -63,6 +63,8 @@ int jk_check_attribute_length(const char
const char *jk_get_worker_host(jk_map_t *m, const char *wname, const char
*def);
+const char *jk_get_worker_source(jk_map_t *m, const char *wname, const char
*def);
+
const char *jk_get_worker_type(jk_map_t *m, const char *wname);
int jk_get_worker_port(jk_map_t *m, const char *wname, int def);
Modified: tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Sun Feb 8 14:28:10 2015
@@ -210,6 +210,11 @@
"no usable connection found, will create a new one". Tone done
from info log level to debug for the common case. (rjung)
</fix>
+ <add>
+ <bug>57536</bug>: AJP: Allow to configure connection source address.
+ This should only be used on multi-homed hosts. The feature is
+ experimental. (rjung)
+ </add>
</changelog>
</subsection>
</section>
Modified: tomcat/jk/trunk/xdocs/reference/workers.xml
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/reference/workers.xml?rev=1658173&r1=1658172&r2=1658173&view=diff
==============================================================================
--- tomcat/jk/trunk/xdocs/reference/workers.xml (original)
+++ tomcat/jk/trunk/xdocs/reference/workers.xml Sun Feb 8 14:28:10 2015
@@ -253,6 +253,14 @@ The default value depends on the worker
<b>8009</b>, while for ajp14 type of worker that value is <b>8011</b>.
</directive>
+<directive name="source" default="" required="false">
+Name or IP address used for the connection source (outgoing address).
+It should only be used on multi-homed hosts.
+<p>
+This feature is experimental and has been added in <b>jk 1.2.41</b>.
+</p>
+</directive>
+
<directive name="socket_timeout" default="0" required="false">
Socket timeout in seconds used for the communication channel between JK and
remote host.
If the remote host does not respond inside the timeout specified, JK will
generate an error,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]