[REORG] session: move client and server address to the stream interface

This will be needed very soon for the keep-alive.
diff --git a/src/backend.c b/src/backend.c
index f3d9f09..870947a 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -530,9 +530,9 @@
 
 			switch (s->be->lbprm.algo & BE_LB_PARM) {
 			case BE_LB_HASH_SRC:
-				if (s->cli_addr.ss_family == AF_INET)
+				if (s->req->prod->addr.c.from.ss_family == AF_INET)
 					len = 4;
-				else if (s->cli_addr.ss_family == AF_INET6)
+				else if (s->req->prod->addr.c.from.ss_family == AF_INET6)
 					len = 16;
 				else {
 					/* unknown IP family */
@@ -541,7 +541,7 @@
 				}
 		
 				s->srv = get_server_sh(s->be,
-						       (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
+						       (void *)&((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr,
 						       len);
 				break;
 
@@ -614,7 +614,7 @@
 		}
 	}
 	else if (s->be->options & PR_O_HTTP_PROXY) {
-		if (!s->srv_addr.sin_addr.s_addr) {
+		if (!s->req->cons->addr.s.to.sin_addr.s_addr) {
 			err = SRV_STATUS_NOSRV;
 			goto out;
 		}
@@ -670,9 +670,9 @@
 		if (!(s->flags & SN_ASSIGNED))
 			return SRV_STATUS_INTERNAL;
 
-		s->srv_addr = s->srv->addr;
+		s->req->cons->addr.s.to = s->srv->addr;
 
-		if (!s->srv_addr.sin_addr.s_addr) {
+		if (!s->req->cons->addr.s.to.sin_addr.s_addr) {
 			/* if the server has no address, we use the same address
 			 * the client asked, which is handy for remapping ports
 			 * locally on multiple addresses at once.
@@ -680,8 +680,8 @@
 			if (!(s->be->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
 				get_frt_addr(s);
 
-			if (s->frt_addr.ss_family == AF_INET) {
-				s->srv_addr.sin_addr = ((struct sockaddr_in *)&s->frt_addr)->sin_addr;
+			if (s->req->prod->addr.c.to.ss_family == AF_INET) {
+				s->req->cons->addr.s.to.sin_addr = ((struct sockaddr_in *)&s->req->prod->addr.c.to)->sin_addr;
 			}
 		}
 
@@ -690,27 +690,27 @@
 		if (s->srv->state & SRV_MAPPORTS) {
 			if (!(s->be->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
 				get_frt_addr(s);
-			if (s->frt_addr.ss_family == AF_INET) {
-				s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
-							     ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port));
+			if (s->req->prod->addr.c.to.ss_family == AF_INET) {
+				s->req->cons->addr.s.to.sin_port = htons(ntohs(s->req->cons->addr.s.to.sin_port) +
+							     ntohs(((struct sockaddr_in *)&s->req->prod->addr.c.to)->sin_port));
 			}
-			else if (s->frt_addr.ss_family == AF_INET6) {
-				s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
-							     ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port));
+			else if (s->req->prod->addr.c.to.ss_family == AF_INET6) {
+				s->req->cons->addr.s.to.sin_port = htons(ntohs(s->req->cons->addr.s.to.sin_port) +
+							     ntohs(((struct sockaddr_in6 *)&s->req->prod->addr.c.to)->sin6_port));
 			}
 		}
 	}
 	else if (*(int *)&s->be->dispatch_addr.sin_addr) {
 		/* connect to the defined dispatch addr */
-		s->srv_addr = s->be->dispatch_addr;
+		s->req->cons->addr.s.to = s->be->dispatch_addr;
 	}
 	else if (s->be->options & PR_O_TRANSP) {
 		/* in transparent mode, use the original dest addr if no dispatch specified */
 		if (!(s->flags & SN_FRT_ADDR_SET))
 			get_frt_addr(s);
 
-		if (s->frt_addr.ss_family == AF_INET) {
-			memcpy(&s->srv_addr, &s->frt_addr, MIN(sizeof(s->srv_addr), sizeof(s->frt_addr)));
+		if (s->req->prod->addr.c.to.ss_family == AF_INET) {
+			memcpy(&s->req->cons->addr.s.to, &s->req->prod->addr.c.to, MIN(sizeof(s->req->cons->addr.s.to), sizeof(s->req->prod->addr.c.to)));
 		}
 		/* when we support IPv6 on the backend, we may add other tests */
 		//qfprintf(stderr, "Cannot get original server address.\n");
@@ -850,7 +850,7 @@
 
 /* If an explicit source binding is specified on the server and/or backend, and
  * this source makes use of the transparent proxy, then it is extracted now and
- * assigned to the session's from_addr entry.
+ * assigned to the session's req->cons->addr.s.from entry.
  */
 static void assign_tproxy_address(struct session *s)
 {
@@ -858,18 +858,18 @@
 	if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
 		switch (s->srv->state & SRV_TPROXY_MASK) {
 		case SRV_TPROXY_ADDR:
-			s->from_addr = *(struct sockaddr_in *)&s->srv->tproxy_addr;
+			s->req->cons->addr.s.from = *(struct sockaddr_in *)&s->srv->tproxy_addr;
 			break;
 		case SRV_TPROXY_CLI:
 		case SRV_TPROXY_CIP:
 			/* FIXME: what can we do if the client connects in IPv6 or unix socket ? */
-			s->from_addr = *(struct sockaddr_in *)&s->cli_addr;
+			s->req->cons->addr.s.from = *(struct sockaddr_in *)&s->req->prod->addr.c.from;
 			break;
 		case SRV_TPROXY_DYN:
 			if (s->srv->bind_hdr_occ) {
 				/* bind to the IP in a header */
-				s->from_addr.sin_port = 0;
-				s->from_addr.sin_addr.s_addr = htonl(get_ip_from_hdr2(&s->txn.req,
+				s->req->cons->addr.s.from.sin_port = 0;
+				s->req->cons->addr.s.from.sin_addr.s_addr = htonl(get_ip_from_hdr2(&s->txn.req,
 										s->srv->bind_hdr_name,
 										s->srv->bind_hdr_len,
 										&s->txn.hdr_idx,
@@ -877,24 +877,24 @@
 			}
 			break;
 		default:
-			memset(&s->from_addr, 0, sizeof(s->from_addr));
+			memset(&s->req->cons->addr.s.from, 0, sizeof(s->req->cons->addr.s.from));
 		}
 	}
 	else if (s->be->options & PR_O_BIND_SRC) {
 		switch (s->be->options & PR_O_TPXY_MASK) {
 		case PR_O_TPXY_ADDR:
-			s->from_addr = *(struct sockaddr_in *)&s->be->tproxy_addr;
+			s->req->cons->addr.s.from = *(struct sockaddr_in *)&s->be->tproxy_addr;
 			break;
 		case PR_O_TPXY_CLI:
 		case PR_O_TPXY_CIP:
 			/* FIXME: what can we do if the client connects in IPv6 or socket unix? */
-			s->from_addr = *(struct sockaddr_in *)&s->cli_addr;
+			s->req->cons->addr.s.from = *(struct sockaddr_in *)&s->req->prod->addr.c.from;
 			break;
 		case PR_O_TPXY_DYN:
 			if (s->be->bind_hdr_occ) {
 				/* bind to the IP in a header */
-				s->from_addr.sin_port = 0;
-				s->from_addr.sin_addr.s_addr = htonl(get_ip_from_hdr2(&s->txn.req,
+				s->req->cons->addr.s.from.sin_port = 0;
+				s->req->cons->addr.s.from.sin_addr.s_addr = htonl(get_ip_from_hdr2(&s->txn.req,
 										s->be->bind_hdr_name,
 										s->be->bind_hdr_len,
 										&s->txn.hdr_idx,
@@ -902,7 +902,7 @@
 			}
 			break;
 		default:
-			memset(&s->from_addr, 0, sizeof(s->from_addr));
+			memset(&s->req->cons->addr.s.from, 0, sizeof(s->req->cons->addr.s.from));
 		}
 	}
 #endif
@@ -911,7 +911,7 @@
 
 /*
  * This function initiates a connection to the server assigned to this session
- * (s->srv, s->srv_addr). It will assign a server if none is assigned yet.
+ * (s->srv, s->req->cons->addr.s.to). It will assign a server if none is assigned yet.
  * It can return one of :
  *  - SN_ERR_NONE if everything's OK
  *  - SN_ERR_SRVTO if there are no more servers
@@ -940,8 +940,8 @@
 	assign_tproxy_address(s);
 
 	err = s->req->cons->connect(s->req->cons, s->be, s->srv,
-				    (struct sockaddr *)&s->srv_addr,
-				    (struct sockaddr *)&s->from_addr);
+				    (struct sockaddr *)&s->req->cons->addr.s.to,
+				    (struct sockaddr *)&s->req->cons->addr.s.from);
 
 	if (err != SN_ERR_NONE)
 		return err;
diff --git a/src/dumpstats.c b/src/dumpstats.c
index c24c1ef..f434cdf 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2694,23 +2694,23 @@
 		switch (sess->listener->proto->sock_family) {
 		case AF_INET:
 			inet_ntop(AF_INET,
-				  (const void *)&((struct sockaddr_in *)&sess->cli_addr)->sin_addr,
+				  (const void *)&((struct sockaddr_in *)&sess->si[0].addr.c.from)->sin_addr,
 				  pn, sizeof(pn));
 
 			chunk_printf(&msg,
 				     " source=%s:%d\n",
 				     pn,
-				     ntohs(((struct sockaddr_in *)&sess->cli_addr)->sin_port));
+				     ntohs(((struct sockaddr_in *)&sess->si[0].addr.c.from)->sin_port));
 			break;
 		case AF_INET6:
 			inet_ntop(AF_INET6,
-				  (const void *)&((struct sockaddr_in6 *)(&sess->cli_addr))->sin6_addr,
+				  (const void *)&((struct sockaddr_in6 *)(&sess->si[0].addr.c.from))->sin6_addr,
 				  pn, sizeof(pn));
 
 			chunk_printf(&msg,
 				     " source=%s:%d\n",
 				     pn,
-				     ntohs(((struct sockaddr_in6 *)&sess->cli_addr)->sin6_port));
+				     ntohs(((struct sockaddr_in6 *)&sess->si[0].addr.c.from)->sin6_port));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg,
@@ -2933,13 +2933,13 @@
 			switch (curr_sess->listener->proto->sock_family) {
 			case AF_INET:
 				inet_ntop(AF_INET,
-					  (const void *)&((struct sockaddr_in *)&curr_sess->cli_addr)->sin_addr,
+					  (const void *)&((struct sockaddr_in *)&curr_sess->si[0].addr.c.from)->sin_addr,
 					  pn, sizeof(pn));
 
 				chunk_printf(&msg,
 					     " src=%s:%d fe=%s be=%s srv=%s",
 					     pn,
-					     ntohs(((struct sockaddr_in *)&curr_sess->cli_addr)->sin_port),
+					     ntohs(((struct sockaddr_in *)&curr_sess->si[0].addr.c.from)->sin_port),
 					     curr_sess->fe->id,
 					     curr_sess->be->id,
 					     curr_sess->srv ? curr_sess->srv->id : "<none>"
@@ -2947,13 +2947,13 @@
 				break;
 			case AF_INET6:
 				inet_ntop(AF_INET6,
-					  (const void *)&((struct sockaddr_in6 *)(&curr_sess->cli_addr))->sin6_addr,
+					  (const void *)&((struct sockaddr_in6 *)(&curr_sess->si[0].addr.c.from))->sin6_addr,
 					  pn, sizeof(pn));
 
 				chunk_printf(&msg,
 					     " src=%s:%d fe=%s be=%s srv=%s",
 					     pn,
-					     ntohs(((struct sockaddr_in6 *)&curr_sess->cli_addr)->sin6_port),
+					     ntohs(((struct sockaddr_in6 *)&curr_sess->si[0].addr.c.from)->sin6_port),
 					     curr_sess->fe->id,
 					     curr_sess->be->id,
 					     curr_sess->srv ? curr_sess->srv->id : "<none>"
diff --git a/src/frontend.c b/src/frontend.c
index 7818080..6e8e1a4 100644
--- a/src/frontend.c
+++ b/src/frontend.c
@@ -50,10 +50,10 @@
  */
 void get_frt_addr(struct session *s)
 {
-	socklen_t namelen = sizeof(s->frt_addr);
+	socklen_t namelen = sizeof(s->si[0].addr.c.to);
 
-	if (get_original_dst(s->si[0].fd, (struct sockaddr_in *)&s->frt_addr, &namelen) == -1)
-		getsockname(s->si[0].fd, (struct sockaddr *)&s->frt_addr, &namelen);
+	if (get_original_dst(s->si[0].fd, (struct sockaddr_in *)&s->si[0].addr.c.to, &namelen) == -1)
+		getsockname(s->si[0].fd, (struct sockaddr *)&s->si[0].addr.c.to, &namelen);
 	s->flags |= SN_FRT_ADDR_SET;
 }
 
@@ -154,35 +154,35 @@
 				if (!(s->logs.logwait &= ~LW_CLIP))
 					s->do_log(s);
 		}
-		else if (s->cli_addr.ss_family == AF_INET) {
+		else if (s->si[0].addr.c.from.ss_family == AF_INET) {
 			char pn[INET_ADDRSTRLEN], sn[INET_ADDRSTRLEN];
 
 			if (!(s->flags & SN_FRT_ADDR_SET))
 				get_frt_addr(s);
 
-			if (inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&s->frt_addr)->sin_addr,
+			if (inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&s->si[0].addr.c.to)->sin_addr,
 				      sn, sizeof(sn)) &&
-			    inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
+			    inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr,
 				      pn, sizeof(pn))) {
 				send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
-					 pn, ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port),
-					 sn, ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port),
+					 pn, ntohs(((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_port),
+					 sn, ntohs(((struct sockaddr_in *)&s->si[0].addr.c.to)->sin_port),
 					 s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
 			}
 		}
-		else if (s->cli_addr.ss_family == AF_INET6) {
+		else if (s->si[0].addr.c.from.ss_family == AF_INET6) {
 			char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
 
 			if (!(s->flags & SN_FRT_ADDR_SET))
 				get_frt_addr(s);
 
-			if (inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&s->frt_addr)->sin6_addr,
+			if (inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&s->si[0].addr.c.to)->sin6_addr,
 				      sn, sizeof(sn)) &&
-			    inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&s->cli_addr)->sin6_addr,
+			    inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_addr,
 				      pn, sizeof(pn))) {
 				send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
-					 pn, ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
-					 sn, ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port),
+					 pn, ntohs(((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_port),
+					 sn, ntohs(((struct sockaddr_in6 *)&s->si[0].addr.c.to)->sin6_port),
 					 s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
 			}
 		}
@@ -200,25 +200,25 @@
 		if (!(s->flags & SN_FRT_ADDR_SET))
 			get_frt_addr(s);
 
-		if (s->cli_addr.ss_family == AF_INET) {
+		if (s->si[0].addr.c.from.ss_family == AF_INET) {
 			char pn[INET_ADDRSTRLEN];
 			inet_ntop(AF_INET,
-				  (const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
+				  (const void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr,
 				  pn, sizeof(pn));
 
 			len = sprintf(trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n",
 				      s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
-				      pn, ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port));
+				      pn, ntohs(((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_port));
 		}
-		else if (s->cli_addr.ss_family == AF_INET6) {
+		else if (s->si[0].addr.c.from.ss_family == AF_INET6) {
 			char pn[INET6_ADDRSTRLEN];
 			inet_ntop(AF_INET6,
-				  (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
+				  (const void *)&((struct sockaddr_in6 *)(&s->si[0].addr.c.from))->sin6_addr,
 				  pn, sizeof(pn));
 
 			len = sprintf(trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n",
 				      s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
-				      pn, ntohs(((struct sockaddr_in6 *)(&s->cli_addr))->sin6_port));
+				      pn, ntohs(((struct sockaddr_in6 *)(&s->si[0].addr.c.from))->sin6_port));
 		}
 		else {
 			len = sprintf(trash, "%08x:%s.accept(%04x)=%04x from [unix:%d]\n",
@@ -357,13 +357,13 @@
 			goto fail;
 
 		/* update the session's addresses and mark them set */
-		((struct sockaddr_in *)&s->cli_addr)->sin_family      = AF_INET;
-		((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr = htonl(src3);
-		((struct sockaddr_in *)&s->cli_addr)->sin_port        = htons(sport);
+		((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_family      = AF_INET;
+		((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr.s_addr = htonl(src3);
+		((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_port        = htons(sport);
 
-		((struct sockaddr_in *)&s->frt_addr)->sin_family      = AF_INET;
-		((struct sockaddr_in *)&s->frt_addr)->sin_addr.s_addr = htonl(dst3);
-		((struct sockaddr_in *)&s->frt_addr)->sin_port        = htons(dport);
+		((struct sockaddr_in *)&s->si[0].addr.c.to)->sin_family      = AF_INET;
+		((struct sockaddr_in *)&s->si[0].addr.c.to)->sin_addr.s_addr = htonl(dst3);
+		((struct sockaddr_in *)&s->si[0].addr.c.to)->sin_port        = htons(dport);
 		s->flags |= SN_FRT_ADDR_SET;
 
 	}
@@ -419,13 +419,13 @@
 			goto fail;
 
 		/* update the session's addresses and mark them set */
-		((struct sockaddr_in6 *)&s->cli_addr)->sin6_family      = AF_INET6;
-		memcpy(&((struct sockaddr_in6 *)&s->cli_addr)->sin6_addr, &src3, sizeof(struct in6_addr));
-		((struct sockaddr_in6 *)&s->cli_addr)->sin6_port        = htons(sport);
+		((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_family      = AF_INET6;
+		memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_addr, &src3, sizeof(struct in6_addr));
+		((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_port        = htons(sport);
 
-		((struct sockaddr_in6 *)&s->frt_addr)->sin6_family      = AF_INET6;
-		memcpy(&((struct sockaddr_in6 *)&s->frt_addr)->sin6_addr, &dst3, sizeof(struct in6_addr));
-		((struct sockaddr_in6 *)&s->frt_addr)->sin6_port        = htons(dport);
+		((struct sockaddr_in6 *)&s->si[0].addr.c.to)->sin6_family      = AF_INET6;
+		memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.c.to)->sin6_addr, &dst3, sizeof(struct in6_addr));
+		((struct sockaddr_in6 *)&s->si[0].addr.c.to)->sin6_port        = htons(dport);
 		s->flags |= SN_FRT_ADDR_SET;
 	}
 	else {
diff --git a/src/log.c b/src/log.c
index 333cbc6..b366d3b 100644
--- a/src/log.c
+++ b/src/log.c
@@ -332,13 +332,13 @@
 	if (!err && (fe->options2 & PR_O2_NOLOGNORM))
 		return;
 
-	if (s->cli_addr.ss_family == AF_INET)
+	if (s->si[0].addr.c.from.ss_family == AF_INET)
 		inet_ntop(AF_INET,
-			  (const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
+			  (const void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr,
 			  pn, sizeof(pn));
-	else if (s->cli_addr.ss_family == AF_INET6)
+	else if (s->si[0].addr.c.from.ss_family == AF_INET6)
 		inet_ntop(AF_INET6,
-			  (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
+			  (const void *)&((struct sockaddr_in6 *)(&s->si[0].addr.c.from))->sin6_addr,
 			  pn, sizeof(pn));
 
 	get_localtime(s->logs.tv_accept.tv_sec, &tm);
@@ -357,10 +357,10 @@
 	send_log(prx_log, level, "%s:%d [%02d/%s/%04d:%02d:%02d:%02d.%03d]"
 		 " %s %s/%s %ld/%ld/%s%ld %s%lld"
 		 " %c%c %d/%d/%d/%d/%s%u %ld/%ld\n",
-		 s->cli_addr.ss_family == AF_UNIX ? "unix" : pn,
-		 s->cli_addr.ss_family == AF_UNIX ? s->listener->luid : (ntohs((s->cli_addr.ss_family == AF_INET) ?
-		                                            ((struct sockaddr_in *)&s->cli_addr)->sin_port :
-		                                            ((struct sockaddr_in6 *)&s->cli_addr)->sin6_port)),
+		 s->si[0].addr.c.from.ss_family == AF_UNIX ? "unix" : pn,
+		 s->si[0].addr.c.from.ss_family == AF_UNIX ? s->listener->luid : (ntohs((s->si[0].addr.c.from.ss_family == AF_INET) ?
+		                                            ((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_port :
+		                                            ((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_port)),
 		 tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
 		 tm.tm_hour, tm.tm_min, tm.tm_sec, (int)s->logs.tv_accept.tv_usec/1000,
 		 fe->id, be->id, svid,
diff --git a/src/peers.c b/src/peers.c
index a3f1ab3..6c75465 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1138,7 +1138,7 @@
 	t->context = s;
 	t->nice = l->nice;
 
-	memcpy(&s->srv_addr, &peer->addr, sizeof(s->srv_addr));
+	memcpy(&s->si[1].addr.s.to, &peer->addr, sizeof(s->si[1].addr.s.to));
 	s->task = t;
 	s->listener = l;
 
diff --git a/src/proto_http.c b/src/proto_http.c
index a0c9b92..9693ad8 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -867,13 +867,13 @@
 		(s->req->cons->conn_retries != be->conn_retries) ||
 		txn->status >= 500;
 
-	if (s->cli_addr.ss_family == AF_INET)
+	if (s->req->prod->addr.c.from.ss_family == AF_INET)
 		inet_ntop(AF_INET,
-		          (const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
+		          (const void *)&((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr,
 		          pn, sizeof(pn));
-	else if (s->cli_addr.ss_family == AF_INET6)
+	else if (s->req->prod->addr.c.from.ss_family == AF_INET6)
 		inet_ntop(AF_INET6,
-		          (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
+		          (const void *)&((struct sockaddr_in6 *)(&s->req->prod->addr.c.from))->sin6_addr,
 		          pn, sizeof(pn));
 	else
 		snprintf(pn, sizeof(pn), "unix:%d", s->listener->luid);
@@ -916,10 +916,10 @@
 
 	w = snprintf(h, sizeof(tmpline) - (h - tmpline),
 	             " %d %03d",
-		     s->cli_addr.ss_family == AF_UNIX ? s->listener->luid :
-	                 ntohs((s->cli_addr.ss_family == AF_INET) ?
-	                       ((struct sockaddr_in *)&s->cli_addr)->sin_port :
-	                       ((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
+		     s->req->prod->addr.c.from.ss_family == AF_UNIX ? s->listener->luid :
+	                 ntohs((s->req->prod->addr.c.from.ss_family == AF_INET) ?
+	                       ((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_port :
+	                       ((struct sockaddr_in6 *)&s->req->prod->addr.c.from)->sin6_port),
 	             (int)s->logs.accept_date.tv_usec/1000);
 	if (w < 0 || w >= sizeof(tmpline) - (h - tmpline))
 		goto trunc;
@@ -1101,13 +1101,13 @@
 	if (prx_log->options2 & PR_O2_CLFLOG)
 		return http_sess_clflog(s);
 
-	if (s->cli_addr.ss_family == AF_INET)
+	if (s->req->prod->addr.c.from.ss_family == AF_INET)
 		inet_ntop(AF_INET,
-			  (const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
+			  (const void *)&((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr,
 			  pn, sizeof(pn));
-	else if (s->cli_addr.ss_family == AF_INET6)
+	else if (s->req->prod->addr.c.from.ss_family == AF_INET6)
 		inet_ntop(AF_INET6,
-			  (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
+			  (const void *)&((struct sockaddr_in6 *)(&s->req->prod->addr.c.from))->sin6_addr,
 			  pn, sizeof(pn));
 
 	get_localtime(s->logs.accept_date.tv_sec, &tm);
@@ -1172,11 +1172,11 @@
 		 "%s:%d [%02d/%s/%04d:%02d:%02d:%02d.%03d]"
 		 " %s %s/%s %d/%ld/%ld/%ld/%s%ld %d %s%lld"
 		 " %s %s %c%c%c%c %d/%d/%d/%d/%s%u %ld/%ld%s\n",
-		 (s->cli_addr.ss_family == AF_UNIX) ? "unix" : pn,
-		 (s->cli_addr.ss_family == AF_UNIX) ? s->listener->luid :
-		     ntohs((s->cli_addr.ss_family == AF_INET) ?
-		           ((struct sockaddr_in *)&s->cli_addr)->sin_port :
-		           ((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
+		 (s->req->prod->addr.c.from.ss_family == AF_UNIX) ? "unix" : pn,
+		 (s->req->prod->addr.c.from.ss_family == AF_UNIX) ? s->listener->luid :
+		     ntohs((s->req->prod->addr.c.from.ss_family == AF_INET) ?
+		           ((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_port :
+		           ((struct sockaddr_in6 *)&s->req->prod->addr.c.from)->sin6_port),
 		 tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
 		 tm.tm_hour, tm.tm_min, tm.tm_sec, (int)s->logs.accept_date.tv_usec/1000,
 		 fe->id, be->id, svid,
@@ -3465,7 +3465,7 @@
 	 * parsing incoming request.
 	 */
 	if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
-		url2sa(msg->sol + msg->sl.rq.u, msg->sl.rq.u_l, &s->srv_addr);
+		url2sa(msg->sol + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->addr.s.to);
 	}
 
 	/*
@@ -3493,19 +3493,19 @@
 	 * asks for it.
 	 */
 	if ((s->fe->options | s->be->options) & PR_O_FWDFOR) {
-		if (s->cli_addr.ss_family == AF_INET) {
+		if (s->req->prod->addr.c.from.ss_family == AF_INET) {
 			/* Add an X-Forwarded-For header unless the source IP is
 			 * in the 'except' network range.
 			 */
 			if ((!s->fe->except_mask.s_addr ||
-			     (((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr & s->fe->except_mask.s_addr)
+			     (((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
 			     != s->fe->except_net.s_addr) &&
 			    (!s->be->except_mask.s_addr ||
-			     (((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr & s->be->except_mask.s_addr)
+			     (((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
 			     != s->be->except_net.s_addr)) {
 				int len;
 				unsigned char *pn;
-				pn = (unsigned char *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr;
+				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr;
 
 				/* 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.
@@ -3526,14 +3526,14 @@
 					goto return_bad_req;
 			}
 		}
-		else if (s->cli_addr.ss_family == AF_INET6) {
+		else if (s->req->prod->addr.c.from.ss_family == AF_INET6) {
 			/* FIXME: for the sake of completeness, we should also support
 			 * 'except' here, although it is mostly useless in this case.
 			 */
 			int len;
 			char pn[INET6_ADDRSTRLEN];
 			inet_ntop(AF_INET6,
-				  (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
+				  (const void *)&((struct sockaddr_in6 *)(&s->req->prod->addr.c.from))->sin6_addr,
 				  pn, sizeof(pn));
 
 			/* Note: we rely on the backend to get the header name to be used for
@@ -3563,23 +3563,23 @@
 	if ((s->fe->options | s->be->options) & PR_O_ORGTO) {
 
 		/* FIXME: don't know if IPv6 can handle that case too. */
-		if (s->cli_addr.ss_family == AF_INET) {
+		if (s->req->prod->addr.c.from.ss_family == AF_INET) {
 			/* Add an X-Original-To header unless the destination IP is
 			 * in the 'except' network range.
 			 */
 			if (!(s->flags & SN_FRT_ADDR_SET))
 				get_frt_addr(s);
 
-			if (s->frt_addr.ss_family == AF_INET &&
+			if (s->req->prod->addr.c.to.ss_family == AF_INET &&
 			    ((!s->fe->except_mask_to.s_addr ||
-			      (((struct sockaddr_in *)&s->frt_addr)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
+			      (((struct sockaddr_in *)&s->req->prod->addr.c.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
 			      != s->fe->except_to.s_addr) &&
 			     (!s->be->except_mask_to.s_addr ||
-			      (((struct sockaddr_in *)&s->frt_addr)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
+			      (((struct sockaddr_in *)&s->req->prod->addr.c.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
 			      != s->be->except_to.s_addr))) {
 				int len;
 				unsigned char *pn;
-				pn = (unsigned char *)&((struct sockaddr_in *)&s->frt_addr)->sin_addr;
+				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->addr.c.to)->sin_addr;
 
 				/* Note: we rely on the backend to get the header name to be used for
 				 * x-original-to, because the header is really meant for the backends.
@@ -7361,7 +7361,7 @@
 	es->sid  = s->uniq_id;
 	es->srv  = s->srv;
 	es->oe   = other_end;
-	es->src  = s->cli_addr;
+	es->src  = s->req->prod->addr.c.from;
 	es->state = state;
 	es->flags = buf->flags;
 	es->ev_id = error_snapshot_id++;
@@ -7763,8 +7763,8 @@
 		return 0;
 
 	/* Parse HTTP request */
-	url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->srv_addr);
-	test->ptr = (void *)&((struct sockaddr_in *)&l4->srv_addr)->sin_addr;
+	url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->addr.s.to);
+	test->ptr = (void *)&((struct sockaddr_in *)&l4->req->cons->addr.s.to)->sin_addr;
 	test->i = AF_INET;
 
 	/*
@@ -7795,8 +7795,8 @@
 		return 0;
 
 	/* Same optimization as url_ip */
-	url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->srv_addr);
-	test->i = ntohs(((struct sockaddr_in *)&l4->srv_addr)->sin_port);
+	url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->addr.s.to);
+	test->i = ntohs(((struct sockaddr_in *)&l4->req->cons->addr.s.to)->sin_port);
 
 	if (px->options & PR_O_HTTP_PROXY)
 		l4->flags |= SN_ADDR_SET;
@@ -8016,9 +8016,9 @@
 		test->flags |= ACL_TEST_F_FETCH_MORE;
 		test->flags |= ACL_TEST_F_VOL_HDR;
 		/* Same optimization as url_ip */
-		memset(&l4->srv_addr.sin_addr, 0, sizeof(l4->srv_addr.sin_addr));
-		url2ip((char *)ctx->line + ctx->val, &l4->srv_addr.sin_addr);
-		test->ptr = (void *)&l4->srv_addr.sin_addr;
+		memset(&l4->req->cons->addr.s.to.sin_addr, 0, sizeof(l4->req->cons->addr.s.to.sin_addr));
+		url2ip((char *)ctx->line + ctx->val, &l4->req->cons->addr.s.to.sin_addr);
+		test->ptr = (void *)&l4->req->cons->addr.s.to.sin_addr;
 		test->i = AF_INET;
 		return 1;
 	}
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 6328d0a..2a74c29 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1229,11 +1229,11 @@
 acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
               struct acl_expr *expr, struct acl_test *test)
 {
-	test->i = l4->cli_addr.ss_family;
+	test->i = l4->si[0].addr.c.from.ss_family;
 	if (test->i == AF_INET)
-		test->ptr = (void *)&((struct sockaddr_in *)&l4->cli_addr)->sin_addr;
+		test->ptr = (void *)&((struct sockaddr_in *)&l4->si[0].addr.c.from)->sin_addr;
 	else if (test->i == AF_INET6)
-		test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_addr;
+		test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->si[0].addr.c.from))->sin6_addr;
 	else
 		return 0;
 
@@ -1246,10 +1246,10 @@
 pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
                   const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
 {
-	if (l4->cli_addr.ss_family != AF_INET )
+	if (l4->si[0].addr.c.from.ss_family != AF_INET )
 		return 0;
 
-	data->ip.s_addr = ((struct sockaddr_in *)&l4->cli_addr)->sin_addr.s_addr;
+	data->ip.s_addr = ((struct sockaddr_in *)&l4->si[0].addr.c.from)->sin_addr.s_addr;
 	return 1;
 }
 
@@ -1259,10 +1259,10 @@
 acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, int dir,
                 struct acl_expr *expr, struct acl_test *test)
 {
-	if (l4->cli_addr.ss_family == AF_INET)
-		test->i = ntohs(((struct sockaddr_in *)&l4->cli_addr)->sin_port);
-	else if (l4->cli_addr.ss_family == AF_INET6)
-		test->i = ntohs(((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_port);
+	if (l4->si[0].addr.c.from.ss_family == AF_INET)
+		test->i = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.from)->sin_port);
+	else if (l4->si[0].addr.c.from.ss_family == AF_INET6)
+		test->i = ntohs(((struct sockaddr_in6 *)(&l4->si[0].addr.c.from))->sin6_port);
 	else
 		return 0;
 
@@ -1279,11 +1279,11 @@
 	if (!(l4->flags & SN_FRT_ADDR_SET))
 		get_frt_addr(l4);
 
-	test->i = l4->frt_addr.ss_family;
+	test->i = l4->si[0].addr.c.to.ss_family;
 	if (test->i == AF_INET)
-		test->ptr = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr;
+		test->ptr = (void *)&((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_addr;
 	else if (test->i == AF_INET6)
-		test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->frt_addr))->sin6_addr;
+		test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->si[0].addr.c.to))->sin6_addr;
 	else
 		return 0;
 
@@ -1300,10 +1300,10 @@
 	if (!(l4->flags & SN_FRT_ADDR_SET))
 		get_frt_addr(l4);
 
-	if (l4->frt_addr.ss_family != AF_INET)
+	if (l4->si[0].addr.c.to.ss_family != AF_INET)
 		return 0;
 
-	data->ip.s_addr = ((struct sockaddr_in *)&l4->frt_addr)->sin_addr.s_addr;
+	data->ip.s_addr = ((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_addr.s_addr;
 	return 1;
 }
 
@@ -1315,10 +1315,10 @@
 	if (!(l4->flags & SN_FRT_ADDR_SET))
 		get_frt_addr(l4);
 
-	if (l4->frt_addr.ss_family == AF_INET)
-		test->i = ntohs(((struct sockaddr_in *)&l4->frt_addr)->sin_port);
-	else if (l4->frt_addr.ss_family == AF_INET6)
-		test->i = ntohs(((struct sockaddr_in6 *)(&l4->frt_addr))->sin6_port);
+	if (l4->si[0].addr.c.to.ss_family == AF_INET)
+		test->i = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_port);
+	else if (l4->si[0].addr.c.to.ss_family == AF_INET6)
+		test->i = ntohs(((struct sockaddr_in6 *)(&l4->si[0].addr.c.to))->sin6_port);
 	else
 		return 0;
 
@@ -1333,10 +1333,10 @@
 	if (!(l4->flags & SN_FRT_ADDR_SET))
 		get_frt_addr(l4);
 
-	if (l4->frt_addr.ss_family != AF_INET)
+	if (l4->si[0].addr.c.to.ss_family != AF_INET)
 		return 0;
 
-	data->integer = ntohs(((struct sockaddr_in *)&l4->frt_addr)->sin_port);
+	data->integer = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_port);
 	return 1;
 }
 
diff --git a/src/session.c b/src/session.c
index 7bcdb5d..fdf8043 100644
--- a/src/session.c
+++ b/src/session.c
@@ -95,7 +95,7 @@
 	LIST_INIT(&s->back_refs);
 
 	s->term_trace = 0;
-	s->cli_addr = *addr;
+	s->si[0].addr.c.from = *addr;
 	s->logs.accept_date = date; /* user-visible date for logging */
 	s->logs.tv_accept = now;  /* corrected date for internal use */
 	s->uniq_id = totalconn;
@@ -270,8 +270,8 @@
 	fdtab[cfd].cb[DIR_RD].b = s->req;
 	fdtab[cfd].cb[DIR_WR].f = l->proto->write;
 	fdtab[cfd].cb[DIR_WR].b = s->rep;
-	fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
-	fdinfo[cfd].peerlen  = sizeof(s->cli_addr);
+	fdinfo[cfd].peeraddr = (struct sockaddr *)&s->si[0].addr.c.from;
+	fdinfo[cfd].peerlen  = sizeof(s->si[0].addr.c.from);
 	EV_FD_SET(cfd, DIR_RD);
 
 	if (p->accept && (ret = p->accept(s)) <= 0) {