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