MEDIUM: http-ana: Add IPv6 support for forwardfor and orignialto options
A network may be specified to avoid header addition for "forwardfor" and
"orignialto" option via the "except" parameter. However, only IPv4
networks/addresses are supported. This patch adds the support of IPv6.
To do so, the net_addr structure is used to store the parameter value in the
proxy structure. And ipcmp2net() function is used to perform the comparison.
This patch should fix the issue #1145. It depends on the following commit:
* c6ce0ab MINOR: tools: Add function to compare an address to a network address
* 5587287 MINOR: tools: Add net_addr structure describing a network addess
diff --git a/src/http_ana.c b/src/http_ana.c
index d18b4cc..5536c04 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -673,12 +673,8 @@
/* Add an X-Forwarded-For header unless the source IP is
* in the 'except' network range.
*/
- if ((!sess->fe->except_mask.s_addr ||
- (((struct sockaddr_in *)cli_conn->src)->sin_addr.s_addr & sess->fe->except_mask.s_addr)
- != sess->fe->except_net.s_addr) &&
- (!s->be->except_mask.s_addr ||
- (((struct sockaddr_in *)cli_conn->src)->sin_addr.s_addr & s->be->except_mask.s_addr)
- != s->be->except_net.s_addr)) {
+ if (ipcmp2net(cli_conn->src, &sess->fe->except_xff_net) &&
+ ipcmp2net(cli_conn->src, &s->be->except_xff_net)) {
unsigned char *pn = (unsigned char *)&((struct sockaddr_in *)cli_conn->src)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
@@ -692,23 +688,26 @@
}
}
else if (cli_conn && conn_get_src(cli_conn) && cli_conn->src->ss_family == AF_INET6) {
- /* FIXME: for the sake of completeness, we should also support
- * 'except' here, although it is mostly useless in this case.
+ /* Add an X-Forwarded-For header unless the source IP is
+ * in the 'except' network range.
*/
- char pn[INET6_ADDRSTRLEN];
+ if (ipcmp2net(cli_conn->src, &sess->fe->except_xff_net) &&
+ ipcmp2net(cli_conn->src, &s->be->except_xff_net)) {
+ char pn[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6,
- (const void *)&((struct sockaddr_in6 *)(cli_conn->src))->sin6_addr,
- pn, sizeof(pn));
+ inet_ntop(AF_INET6,
+ (const void *)&((struct sockaddr_in6 *)(cli_conn->src))->sin6_addr,
+ pn, sizeof(pn));
- /* Note: we rely on the backend to get the header name to be used for
- * x-forwarded-for, because the header is really meant for the backends.
- * However, if the backend did not specify any option, we have to rely
- * on the frontend's header name.
- */
- chunk_printf(&trash, "%s", pn);
- if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
- goto return_int_err;
+ /* Note: we rely on the backend to get the header name to be used for
+ * x-forwarded-for, because the header is really meant for the backends.
+ * However, if the backend did not specify any option, we have to rely
+ * on the frontend's header name.
+ */
+ chunk_printf(&trash, "%s", pn);
+ if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
+ goto return_int_err;
+ }
}
}
@@ -717,20 +716,15 @@
* asks for it.
*/
if ((sess->fe->options | s->be->options) & PR_O_ORGTO) {
+ struct ist hdr = ist2(s->be->orgto_hdr_len ? s->be->orgto_hdr_name : sess->fe->orgto_hdr_name,
+ s->be->orgto_hdr_len ? s->be->orgto_hdr_len : sess->fe->orgto_hdr_len);
- /* FIXME: don't know if IPv6 can handle that case too. */
if (cli_conn && conn_get_dst(cli_conn) && cli_conn->dst->ss_family == AF_INET) {
/* Add an X-Original-To header unless the destination IP is
* in the 'except' network range.
*/
- if (cli_conn->dst->ss_family == AF_INET &&
- ((!sess->fe->except_mask_to.s_addr ||
- (((struct sockaddr_in *)cli_conn->dst)->sin_addr.s_addr & sess->fe->except_mask_to.s_addr)
- != sess->fe->except_to.s_addr) &&
- (!s->be->except_mask_to.s_addr ||
- (((struct sockaddr_in *)cli_conn->dst)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
- != s->be->except_to.s_addr))) {
- struct ist hdr;
+ if (ipcmp2net(cli_conn->dst, &sess->fe->except_xot_net) &&
+ ipcmp2net(cli_conn->dst, &s->be->except_xot_net)) {
unsigned char *pn = (unsigned char *)&((struct sockaddr_in *)cli_conn->dst)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
@@ -738,16 +732,33 @@
* However, if the backend did not specify any option, we have to rely
* on the frontend's header name.
*/
- if (s->be->orgto_hdr_len)
- hdr = ist2(s->be->orgto_hdr_name, s->be->orgto_hdr_len);
- else
- hdr = ist2(sess->fe->orgto_hdr_name, sess->fe->orgto_hdr_len);
-
chunk_printf(&trash, "%d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]);
if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
goto return_int_err;
}
}
+ else if (cli_conn && conn_get_dst(cli_conn) && cli_conn->dst->ss_family == AF_INET6) {
+ /* Add an X-Original-To header unless the source IP is
+ * in the 'except' network range.
+ */
+ if (ipcmp2net(cli_conn->dst, &sess->fe->except_xot_net) &&
+ ipcmp2net(cli_conn->dst, &s->be->except_xot_net)) {
+ char pn[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6,
+ (const void *)&((struct sockaddr_in6 *)(cli_conn->dst))->sin6_addr,
+ pn, sizeof(pn));
+
+ /* Note: we rely on the backend to get the header name to be used for
+ * x-forwarded-for, because the header is really meant for the backends.
+ * However, if the backend did not specify any option, we have to rely
+ * on the frontend's header name.
+ */
+ chunk_printf(&trash, "%s", pn);
+ if (unlikely(!http_add_header(htx, hdr, ist2(trash.area, trash.data))))
+ goto return_int_err;
+ }
+ }
}
/* If we have no server assigned yet and we're balancing on url_param